Skip to content

Commit dc38e16

Browse files
committed
Generalize the ty::substs struct so that it can represent
multiple lifetime parameters, and not just one. Also add an option for erasing lifetimes, which makes trans code somewhat simpler and cleaner.
1 parent 5102853 commit dc38e16

File tree

19 files changed

+304
-179
lines changed

19 files changed

+304
-179
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ fn parse_trait_store(st: &mut PState) -> ty::TraitStore {
186186
}
187187

188188
fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
189-
let self_r = parse_opt(st, |st| parse_region(st) );
189+
let regions = parse_region_substs(st, |x,y| conv(x,y));
190190

191191
let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
192192

@@ -196,12 +196,28 @@ fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
196196
st.pos = st.pos + 1u;
197197

198198
return ty::substs {
199-
self_r: self_r,
199+
regions: regions,
200200
self_ty: self_ty,
201201
tps: params
202202
};
203203
}
204204

205+
fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
206+
match next(st) {
207+
'e' => ty::ErasedRegions,
208+
'n' => {
209+
let mut regions = opt_vec::Empty;
210+
while peek(st) != '.' {
211+
let r = parse_region(st);
212+
regions.push(r);
213+
}
214+
assert_eq!(next(st), '.');
215+
ty::NonerasedRegions(regions)
216+
}
217+
_ => fail!("parse_bound_region: bad input")
218+
}
219+
}
220+
205221
fn parse_bound_region(st: &mut PState) -> ty::bound_region {
206222
match next(st) {
207223
's' => ty::br_self,

src/librustc/metadata/tyencode.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,28 @@ fn enc_opt<T>(w: @io::Writer, t: Option<T>, enc_f: &fn(T)) {
120120
}
121121

122122
fn enc_substs(w: @io::Writer, cx: @ctxt, substs: &ty::substs) {
123-
do enc_opt(w, substs.self_r) |r| { enc_region(w, cx, r) }
123+
enc_region_substs(w, cx, &substs.regions);
124124
do enc_opt(w, substs.self_ty) |t| { enc_ty(w, cx, t) }
125125
w.write_char('[');
126126
for substs.tps.iter().advance |t| { enc_ty(w, cx, *t); }
127127
w.write_char(']');
128128
}
129129

130+
fn enc_region_substs(w: @io::Writer, cx: @ctxt, substs: &ty::RegionSubsts) {
131+
match *substs {
132+
ty::ErasedRegions => {
133+
w.write_char('e');
134+
}
135+
ty::NonerasedRegions(ref regions) => {
136+
w.write_char('n');
137+
for regions.iter().advance |&r| {
138+
enc_region(w, cx, r);
139+
}
140+
w.write_char('.');
141+
}
142+
}
143+
}
144+
130145
fn enc_region(w: @io::Writer, cx: @ctxt, r: ty::Region) {
131146
match r {
132147
ty::re_bound(br) => {

src/librustc/middle/kind.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use util::ppaux::UserString;
1919
use syntax::ast::*;
2020
use syntax::attr;
2121
use syntax::codemap::span;
22+
use syntax::opt_vec;
2223
use syntax::print::pprust::expr_to_str;
2324
use syntax::{visit, ast_util};
2425

@@ -83,7 +84,7 @@ fn check_struct_safe_for_destructor(cx: Context,
8384
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
8485
if !struct_tpt.generics.has_type_params() {
8586
let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
86-
self_r: None,
87+
regions: ty::NonerasedRegions(opt_vec::Empty),
8788
self_ty: None,
8889
tps: ~[]
8990
});

src/librustc/middle/subst.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313

1414
use middle::ty;
15+
use syntax::opt_vec::OptVec;
1516
use util::ppaux::Repr;
1617

1718
///////////////////////////////////////////////////////////////////////////
@@ -79,6 +80,12 @@ impl<T:Subst> Subst for ~[T] {
7980
}
8081
}
8182

83+
impl<T:Subst> Subst for OptVec<T> {
84+
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> OptVec<T> {
85+
self.map(|t| t.subst(tcx, substs))
86+
}
87+
}
88+
8289
impl<T:Subst + 'static> Subst for @T {
8390
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @T {
8491
match self {
@@ -105,13 +112,26 @@ impl Subst for ty::TraitRef {
105112
impl Subst for ty::substs {
106113
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::substs {
107114
ty::substs {
108-
self_r: self.self_r.subst(tcx, substs),
115+
regions: self.regions.subst(tcx, substs),
109116
self_ty: self.self_ty.map(|typ| typ.subst(tcx, substs)),
110117
tps: self.tps.map(|typ| typ.subst(tcx, substs))
111118
}
112119
}
113120
}
114121

122+
impl Subst for ty::RegionSubsts {
123+
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::RegionSubsts {
124+
match *self {
125+
ty::ErasedRegions => {
126+
ty::ErasedRegions
127+
}
128+
ty::NonerasedRegions(ref regions) => {
129+
ty::NonerasedRegions(regions.subst(tcx, substs))
130+
}
131+
}
132+
}
133+
}
134+
115135
impl Subst for ty::BareFnTy {
116136
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::BareFnTy {
117137
ty::fold_bare_fn_ty(self, |t| t.subst(tcx, substs))
@@ -158,15 +178,18 @@ impl Subst for ty::Region {
158178
// will most likely disappear.
159179
match self {
160180
&ty::re_bound(ty::br_self) => {
161-
match substs.self_r {
162-
None => {
163-
tcx.sess.bug(
164-
fmt!("ty::Region#subst(): \
165-
Reference to self region when \
166-
given substs with no self region: %s",
167-
substs.repr(tcx)));
181+
match substs.regions {
182+
ty::ErasedRegions => ty::re_static,
183+
ty::NonerasedRegions(ref regions) => {
184+
if regions.len() != 1 {
185+
tcx.sess.bug(
186+
fmt!("ty::Region#subst(): \
187+
Reference to self region when \
188+
given substs with no self region: %s",
189+
substs.repr(tcx)));
190+
}
191+
*regions.get(0)
168192
}
169-
Some(self_r) => self_r
170193
}
171194
}
172195
_ => *self

src/librustc/middle/trans/base.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,8 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
517517
did
518518
};
519519
assert_eq!(did.crate, ast::local_crate);
520-
let tsubsts = ty::substs { self_r: None, self_ty: None,
520+
let tsubsts = ty::substs {regions: ty::ErasedRegions,
521+
self_ty: None,
521522
tps: /*bad*/ substs.to_owned() };
522523
let (val, _) = monomorphize::monomorphic_fn(ccx,
523524
did,

src/librustc/middle/trans/callee.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,15 +284,10 @@ pub fn trans_fn_ref_with_vtables(
284284
// Polytype of the function item (may have type params)
285285
let fn_tpt = ty::lookup_item_type(tcx, def_id);
286286

287-
// For simplicity, we want to use the Subst trait when composing
288-
// substitutions for default methods. The subst trait does
289-
// substitutions with regions, though, so we put a dummy self
290-
// region parameter in to keep it from failing. This is a hack.
291-
let substs = ty::substs { self_r: Some(ty::re_empty),
287+
let substs = ty::substs { regions: ty::ErasedRegions,
292288
self_ty: None,
293289
tps: /*bad*/ type_params.to_owned() };
294290

295-
296291
// We need to do a bunch of special handling for default methods.
297292
// We need to modify the def_id and our substs in order to monomorphize
298293
// the function.

src/librustc/middle/trans/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ pub fn find_vtable(tcx: ty::ctxt,
11141114

11151115
pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
11161116
substs {
1117-
self_r: Some(ty::re_bound(ty::br_self)),
1117+
regions: ty::ErasedRegions,
11181118
self_ty: None,
11191119
tps: tps
11201120
}

src/librustc/middle/trans/type_of.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use util::ppaux;
1717
use middle::trans::type_::Type;
1818

1919
use syntax::ast;
20+
use syntax::opt_vec;
2021

2122
pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: &ty::t) -> bool {
2223
!ty::type_is_immediate(ccx.tcx, *arg_ty)
@@ -312,7 +313,8 @@ pub fn llvm_type_name(cx: &CrateContext,
312313
a_struct => { "struct" }
313314
an_enum => { "enum" }
314315
};
315-
let tstr = ppaux::parameterized(cx.tcx, ty::item_path_str(cx.tcx, did), None, tps);
316+
let tstr = ppaux::parameterized(cx.tcx, ty::item_path_str(cx.tcx, did),
317+
&ty::NonerasedRegions(opt_vec::Empty), tps);
316318
if did.crate == 0 {
317319
fmt!("%s.%s", name, tstr)
318320
} else {

src/librustc/middle/ty.rs

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,15 @@ pub enum bound_region {
486486
br_cap_avoid(ast::node_id, @bound_region),
487487
}
488488

489-
type opt_region = Option<Region>;
489+
/**
490+
* Represents the values to use when substituting lifetime parameters.
491+
* If the value is `ErasedRegions`, then this subst is occurring during
492+
* trans, and all region parameters will be replaced with `ty::re_static`. */
493+
#[deriving(Clone, Eq, IterBytes)]
494+
pub enum RegionSubsts {
495+
ErasedRegions,
496+
NonerasedRegions(OptVec<ty::Region>)
497+
}
490498

491499
/**
492500
* The type substs represents the kinds of things that can be substituted to
@@ -507,9 +515,9 @@ type opt_region = Option<Region>;
507515
* always substituted away to the implementing type for a trait. */
508516
#[deriving(Clone, Eq, IterBytes)]
509517
pub struct substs {
510-
self_r: opt_region,
511518
self_ty: Option<ty::t>,
512-
tps: ~[t]
519+
tps: ~[t],
520+
regions: RegionSubsts,
513521
}
514522

515523
mod primitives {
@@ -948,7 +956,14 @@ fn mk_t(cx: ctxt, st: sty) -> t {
948956
fn sflags(substs: &substs) -> uint {
949957
let mut f = 0u;
950958
for substs.tps.iter().advance |tt| { f |= get(*tt).flags; }
951-
for substs.self_r.iter().advance |r| { f |= rflags(*r) }
959+
match substs.regions {
960+
ErasedRegions => {}
961+
NonerasedRegions(ref regions) => {
962+
for regions.iter().advance |r| {
963+
f |= rflags(*r)
964+
}
965+
}
966+
}
952967
return f;
953968
}
954969
match &st {
@@ -1286,7 +1301,7 @@ pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy {
12861301

12871302
fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
12881303
fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1289-
substs {self_r: substs.self_r,
1304+
substs {regions: substs.regions.clone(),
12901305
self_ty: substs.self_ty.map(|t| fldop(*t)),
12911306
tps: substs.tps.map(|t| fldop(*t))}
12921307
}
@@ -1378,8 +1393,15 @@ pub fn fold_regions_and_ty(
13781393
fldr: &fn(r: Region) -> Region,
13791394
fldt: &fn(t: t) -> t)
13801395
-> substs {
1396+
let regions = match substs.regions {
1397+
ErasedRegions => ErasedRegions,
1398+
NonerasedRegions(ref regions) => {
1399+
NonerasedRegions(regions.map(|r| fldr(*r)))
1400+
}
1401+
};
1402+
13811403
substs {
1382-
self_r: substs.self_r.map(|r| fldr(*r)),
1404+
regions: regions,
13831405
self_ty: substs.self_ty.map(|t| fldt(*t)),
13841406
tps: substs.tps.map(|t| fldt(*t))
13851407
}
@@ -1478,8 +1500,13 @@ pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
14781500
}
14791501

14801502
pub fn substs_is_noop(substs: &substs) -> bool {
1503+
let regions_is_noop = match substs.regions {
1504+
ErasedRegions => false, // may be used to canonicalize
1505+
NonerasedRegions(ref regions) => regions.is_empty()
1506+
};
1507+
14811508
substs.tps.len() == 0u &&
1482-
substs.self_r.is_none() &&
1509+
regions_is_noop &&
14831510
substs.self_ty.is_none()
14841511
}
14851512

@@ -4227,30 +4254,33 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
42274254
})
42284255
}
42294256

4230-
ty_enum(did, ref r) =>
4231-
match (*r).self_r {
4232-
Some(_) =>
4233-
// Use re_static since trans doesn't care about regions
4234-
mk_enum(cx, did,
4235-
substs {
4236-
self_r: Some(ty::re_static),
4237-
self_ty: None,
4238-
tps: (*r).tps.clone()
4239-
}),
4240-
None =>
4257+
ty_enum(did, ref r) => {
4258+
match (*r).regions {
4259+
NonerasedRegions(_) => {
4260+
// trans doesn't care about regions
4261+
mk_enum(cx, did, substs {regions: ty::ErasedRegions,
4262+
self_ty: None,
4263+
tps: (*r).tps.clone()})
4264+
}
4265+
ErasedRegions => {
42414266
t
4242-
},
4267+
}
4268+
}
4269+
}
42434270

4244-
ty_struct(did, ref r) =>
4245-
match (*r).self_r {
4246-
Some(_) =>
4247-
// Ditto.
4248-
mk_struct(cx, did, substs {self_r: Some(ty::re_static),
4249-
self_ty: None,
4250-
tps: (*r).tps.clone()}),
4251-
None =>
4252-
t
4253-
},
4271+
ty_struct(did, ref r) => {
4272+
match (*r).regions {
4273+
NonerasedRegions(_) => {
4274+
// Ditto.
4275+
mk_struct(cx, did, substs {regions: ty::ErasedRegions,
4276+
self_ty: None,
4277+
tps: (*r).tps.clone()})
4278+
}
4279+
ErasedRegions => {
4280+
t
4281+
}
4282+
}
4283+
}
42544284

42554285
_ =>
42564286
t
@@ -4434,7 +4464,7 @@ pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
44344464
Err(s) => { return Err(s); }
44354465
};
44364466
let substs = substs {
4437-
self_r: None,
4467+
regions: ty::NonerasedRegions(opt_vec::Empty),
44384468
self_ty: None,
44394469
tps: ~[]
44404470
};

0 commit comments

Comments
 (0)