Skip to content

Commit f79feba

Browse files
committed
rustc_typeck: pass all lifetimes through AstConv::opt_ast_region_to_region.
1 parent 4f559f8 commit f79feba

File tree

4 files changed

+129
-130
lines changed

4 files changed

+129
-130
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 100 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use require_c_abi_if_variadic;
6464
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
6565
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
6666
ElisionFailureInfo, ElidedLifetime};
67-
use rscope::{AnonTypeScope, MaybeWithAnonTypes};
67+
use rscope::{AnonTypeScope, MaybeWithAnonTypes, ExplicitRscope};
6868
use util::common::{ErrorReported, FN_OUTPUT_NAME};
6969
use util::nodemap::{NodeMap, FxHashSet};
7070

@@ -161,70 +161,6 @@ struct ConvertedBinding<'tcx> {
161161
/// This type must not appear anywhere in other converted types.
162162
const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0));
163163

164-
pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
165-
lifetime: &hir::Lifetime)
166-
-> &'tcx ty::Region {
167-
let r = match tcx.named_region_map.defs.get(&lifetime.id) {
168-
None => {
169-
// should have been recorded by the `resolve_lifetime` pass
170-
span_bug!(lifetime.span, "unresolved lifetime");
171-
}
172-
173-
Some(&rl::DefStaticRegion) => {
174-
ty::ReStatic
175-
}
176-
177-
Some(&rl::DefLateBoundRegion(debruijn, id)) => {
178-
// If this region is declared on a function, it will have
179-
// an entry in `late_bound`, but if it comes from
180-
// `for<'a>` in some type or something, it won't
181-
// necessarily have one. In that case though, we won't be
182-
// changed from late to early bound, so we can just
183-
// substitute false.
184-
let issue_32330 = tcx.named_region_map
185-
.late_bound
186-
.get(&id)
187-
.cloned()
188-
.unwrap_or(ty::Issue32330::WontChange);
189-
ty::ReLateBound(debruijn, ty::BrNamed(tcx.hir.local_def_id(id),
190-
lifetime.name,
191-
issue_32330))
192-
}
193-
194-
Some(&rl::DefEarlyBoundRegion(index, _)) => {
195-
ty::ReEarlyBound(ty::EarlyBoundRegion {
196-
index: index,
197-
name: lifetime.name
198-
})
199-
}
200-
201-
Some(&rl::DefFreeRegion(scope, id)) => {
202-
// As in DefLateBoundRegion above, could be missing for some late-bound
203-
// regions, but also for early-bound regions.
204-
let issue_32330 = tcx.named_region_map
205-
.late_bound
206-
.get(&id)
207-
.cloned()
208-
.unwrap_or(ty::Issue32330::WontChange);
209-
ty::ReFree(ty::FreeRegion {
210-
scope: scope.to_code_extent(&tcx.region_maps),
211-
bound_region: ty::BrNamed(tcx.hir.local_def_id(id),
212-
lifetime.name,
213-
issue_32330)
214-
})
215-
216-
// (*) -- not late-bound, won't change
217-
}
218-
};
219-
220-
debug!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
221-
lifetime,
222-
lifetime.id,
223-
r);
224-
225-
tcx.mk_region(r)
226-
}
227-
228164
fn report_elision_failure(
229165
tcx: TyCtxt,
230166
db: &mut DiagnosticBuilder,
@@ -296,38 +232,98 @@ fn report_elision_failure(
296232
}
297233

298234
impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
299-
pub fn opt_ast_region_to_region(&self,
235+
pub fn ast_region_to_region(&self, lifetime: &hir::Lifetime) -> &'tcx ty::Region {
236+
self.opt_ast_region_to_region(&ExplicitRscope, lifetime.span, Some(lifetime), None)
237+
}
238+
239+
fn try_opt_ast_region_to_region(&self,
300240
rscope: &RegionScope,
301241
default_span: Span,
302-
opt_lifetime: &Option<hir::Lifetime>) -> &'tcx ty::Region
242+
opt_lifetime: Option<&hir::Lifetime>,
243+
def: Option<&ty::RegionParameterDef>)
244+
-> Result<&'tcx ty::Region, Option<Vec<ElisionFailureInfo>>>
303245
{
304-
let r = match *opt_lifetime {
305-
Some(ref lifetime) => {
306-
ast_region_to_region(self.tcx(), lifetime)
246+
let tcx = self.tcx();
247+
let name = opt_lifetime.map(|l| l.name);
248+
let resolved = opt_lifetime.and_then(|l| tcx.named_region_map.defs.get(&l.id));
249+
let r = tcx.mk_region(match resolved {
250+
Some(&rl::DefStaticRegion) => {
251+
ty::ReStatic
307252
}
308253

309-
None => {
310-
self.tcx().mk_region(rscope.anon_region(default_span).unwrap_or_else(|params| {
311-
let ampersand_span = Span { hi: default_span.lo, ..default_span};
254+
Some(&rl::DefLateBoundRegion(debruijn, id)) => {
255+
// If this region is declared on a function, it will have
256+
// an entry in `late_bound`, but if it comes from
257+
// `for<'a>` in some type or something, it won't
258+
// necessarily have one. In that case though, we won't be
259+
// changed from late to early bound, so we can just
260+
// substitute false.
261+
let issue_32330 = tcx.named_region_map
262+
.late_bound
263+
.get(&id)
264+
.cloned()
265+
.unwrap_or(ty::Issue32330::WontChange);
266+
ty::ReLateBound(debruijn, ty::BrNamed(tcx.hir.local_def_id(id),
267+
name.unwrap(),
268+
issue_32330))
269+
}
270+
271+
Some(&rl::DefEarlyBoundRegion(index, _)) => {
272+
ty::ReEarlyBound(ty::EarlyBoundRegion {
273+
index: index,
274+
name: name.unwrap()
275+
})
276+
}
312277

313-
let mut err = struct_span_err!(self.tcx().sess, ampersand_span, E0106,
314-
"missing lifetime specifier");
315-
err.span_label(ampersand_span, &format!("expected lifetime parameter"));
278+
Some(&rl::DefFreeRegion(scope, id)) => {
279+
// As in DefLateBoundRegion above, could be missing for some late-bound
280+
// regions, but also for early-bound regions.
281+
let issue_32330 = tcx.named_region_map
282+
.late_bound
283+
.get(&id)
284+
.cloned()
285+
.unwrap_or(ty::Issue32330::WontChange);
286+
ty::ReFree(ty::FreeRegion {
287+
scope: scope.to_code_extent(&tcx.region_maps),
288+
bound_region: ty::BrNamed(tcx.hir.local_def_id(id),
289+
name.unwrap(),
290+
issue_32330)
291+
})
316292

317-
if let Some(params) = params {
318-
report_elision_failure(self.tcx(), &mut err, params);
319-
}
320-
err.emit();
321-
ty::ReStatic
322-
}))
293+
// (*) -- not late-bound, won't change
323294
}
324-
};
295+
296+
None => rscope.anon_region(default_span, def)?
297+
});
325298

326299
debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
327300
opt_lifetime,
328301
r);
329302

330-
r
303+
Ok(r)
304+
}
305+
306+
pub fn opt_ast_region_to_region(&self,
307+
rscope: &RegionScope,
308+
default_span: Span,
309+
opt_lifetime: Option<&hir::Lifetime>,
310+
def: Option<&ty::RegionParameterDef>) -> &'tcx ty::Region
311+
{
312+
let tcx = self.tcx();
313+
self.try_opt_ast_region_to_region(rscope, default_span, opt_lifetime, def)
314+
.unwrap_or_else(|params| {
315+
let ampersand_span = Span { hi: default_span.lo, ..default_span};
316+
317+
let mut err = struct_span_err!(tcx.sess, ampersand_span, E0106,
318+
"missing lifetime specifier");
319+
err.span_label(ampersand_span, &format!("expected lifetime parameter"));
320+
321+
if let Some(params) = params {
322+
report_elision_failure(tcx, &mut err, params);
323+
}
324+
err.emit();
325+
tcx.mk_region(ty::ReStatic)
326+
})
331327
}
332328

333329
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
@@ -408,25 +404,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
408404
};
409405
let expected_num_region_params = decl_generics.regions.len();
410406
let supplied_num_region_params = lifetimes.len();
411-
let regions = if expected_num_region_params == supplied_num_region_params {
412-
lifetimes.iter().map(|l| *ast_region_to_region(tcx, l)).collect()
413-
} else {
414-
let anon_regions = (0..expected_num_region_params).map(|_| {
415-
rscope.anon_region(span)
416-
}).collect::<Result<Vec<_>, _>>();
417-
418-
if supplied_num_region_params != 0 || anon_regions.is_err() {
407+
let has_exact_lifetimes = expected_num_region_params == supplied_num_region_params;
408+
let mut can_report_lifetime_count_mismatch = !has_exact_lifetimes;
409+
let mut maybe_report_lifetime_count_mismatch = || {
410+
if can_report_lifetime_count_mismatch {
411+
can_report_lifetime_count_mismatch = false;
419412
report_lifetime_number_error(tcx, span,
420413
supplied_num_region_params,
421414
expected_num_region_params);
422415
}
423-
424-
match anon_regions {
425-
Ok(anon_regions) => anon_regions,
426-
Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect()
427-
}
428416
};
429417

418+
if supplied_num_region_params != 0 {
419+
maybe_report_lifetime_count_mismatch();
420+
}
421+
430422
// If a self-type was declared, one should be provided.
431423
assert_eq!(decl_generics.has_self, self_ty.is_some());
432424

@@ -452,7 +444,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
452444
let mut output_assoc_binding = None;
453445
let substs = Substs::for_item(tcx, def_id, |def, _| {
454446
let i = def.index as usize - self_ty.is_some() as usize;
455-
tcx.mk_region(regions[i])
447+
let l = if has_exact_lifetimes {
448+
Some(&lifetimes[i])
449+
} else {
450+
None
451+
};
452+
self.try_opt_ast_region_to_region(rscope, span, l, Some(def)).unwrap_or_else(|_| {
453+
maybe_report_lifetime_count_mismatch();
454+
tcx.mk_region(ty::ReStatic)
455+
})
456456
}, |def, substs| {
457457
let i = def.index as usize;
458458

@@ -1472,7 +1472,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
14721472
})
14731473
}
14741474
hir::TyRptr(ref region, ref mt) => {
1475-
let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region);
1475+
let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region.as_ref(), None);
14761476
debug!("TyRef r={:?}", r);
14771477
let rscope1 =
14781478
&ObjectLifetimeDefaultRscope::new(
@@ -1823,7 +1823,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18231823

18241824
if let Some(&r) = explicit_region_bounds.get(0) {
18251825
// Explicitly specified region bound. Use that.
1826-
return Some(ast_region_to_region(tcx, r));
1826+
return Some(self.ast_region_to_region(r));
18271827
}
18281828

18291829
if let Some(principal) = existential_predicates.principal() {

src/librustc_typeck/check/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub use self::Expectation::*;
8080
pub use self::compare_method::{compare_impl_method, compare_const_impl};
8181
use self::TupleArgumentsFlag::*;
8282

83-
use astconv::{AstConv, ast_region_to_region};
83+
use astconv::AstConv;
8484
use dep_graph::DepNode;
8585
use fmt_macros::{Parser, Piece, Position};
8686
use hir::def::{Def, CtorKind};
@@ -1466,9 +1466,13 @@ impl<'a, 'gcx, 'tcx> RegionScope for FnCtxt<'a, 'gcx, 'tcx> {
14661466
*self.next_region_var(infer::MiscVariable(span))
14671467
}
14681468

1469-
fn anon_region(&self, span: Span)
1469+
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
14701470
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
1471-
Ok(*self.next_region_var(infer::MiscVariable(span)))
1471+
let v = match def {
1472+
Some(def) => infer::EarlyBoundRegion(span, def.name),
1473+
None => infer::MiscVariable(span)
1474+
};
1475+
Ok(*self.next_region_var(v))
14721476
}
14731477
}
14741478

@@ -4404,11 +4408,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44044408
None => &[]
44054409
};
44064410

4407-
if let Some(ast_lifetime) = lifetimes.get(i) {
4408-
ast_region_to_region(self.tcx, ast_lifetime)
4409-
} else {
4410-
self.region_var_for_def(span, def)
4411-
}
4411+
AstConv::opt_ast_region_to_region(self, self, span, lifetimes.get(i), Some(def))
44124412
}, |def, substs| {
44134413
let mut i = def.index as usize;
44144414

src/librustc_typeck/collect.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ There are some shortcomings in this design:
5757
5858
*/
5959

60-
use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
60+
use astconv::{AstConv, Bounds, PartitionedBounds, partition_bounds};
6161
use lint;
6262
use constrained_type_params as ctp;
6363
use middle::lang_items::SizedTraitLangItem;
@@ -1472,7 +1472,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
14721472
index: own_start + i as u32,
14731473
def_id: tcx.hir.local_def_id(l.lifetime.id),
14741474
bounds: l.bounds.iter().map(|l| {
1475-
ast_region_to_region(tcx, l)
1475+
AstConv::ast_region_to_region(&ccx.icx(&()), l)
14761476
}).collect(),
14771477
pure_wrt_drop: l.pure_wrt_drop,
14781478
}
@@ -1765,7 +1765,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
17651765
name: param.lifetime.name
17661766
}));
17671767
for bound in &param.bounds {
1768-
let bound_region = ast_region_to_region(ccx.tcx, bound);
1768+
let bound_region = AstConv::ast_region_to_region(&ccx.icx(&()), bound);
17691769
let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
17701770
predicates.push(outlives.to_predicate());
17711771
}
@@ -1816,7 +1816,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
18161816
}
18171817

18181818
&hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
1819-
let region = ast_region_to_region(tcx, lifetime);
1819+
let region = AstConv::ast_region_to_region(&ccx.icx(&()), lifetime);
18201820
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
18211821
predicates.push(ty::Predicate::TypeOutlives(pred))
18221822
}
@@ -1825,9 +1825,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
18251825
}
18261826

18271827
&hir::WherePredicate::RegionPredicate(ref region_pred) => {
1828-
let r1 = ast_region_to_region(tcx, &region_pred.lifetime);
1828+
let r1 = AstConv::ast_region_to_region(&ccx.icx(&()), &region_pred.lifetime);
18291829
for bound in &region_pred.bounds {
1830-
let r2 = ast_region_to_region(tcx, bound);
1830+
let r2 = AstConv::ast_region_to_region(&ccx.icx(&()), bound);
18311831
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
18321832
predicates.push(ty::Predicate::RegionOutlives(pred))
18331833
}
@@ -1935,7 +1935,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
19351935
hir::TraitTyParamBound(..) =>
19361936
None,
19371937
hir::RegionTyParamBound(ref lifetime) =>
1938-
Some(ast_region_to_region(ccx.tcx, lifetime)),
1938+
Some(AstConv::ast_region_to_region(&ccx.icx(&()), lifetime)),
19391939
}
19401940
})
19411941
.collect()
@@ -1981,7 +1981,6 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
19811981
span: Span)
19821982
-> Bounds<'tcx>
19831983
{
1984-
let tcx = astconv.tcx();
19851984
let PartitionedBounds {
19861985
trait_bounds,
19871986
region_bounds
@@ -1998,7 +1997,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
19981997
}).collect();
19991998

20001999
let region_bounds = region_bounds.into_iter().map(|r| {
2001-
ast_region_to_region(tcx, r)
2000+
astconv.ast_region_to_region(r)
20022001
}).collect();
20032002

20042003
trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
@@ -2040,7 +2039,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
20402039
.collect()
20412040
}
20422041
hir::RegionTyParamBound(ref lifetime) => {
2043-
let region = ast_region_to_region(astconv.tcx(), lifetime);
2042+
let region = astconv.ast_region_to_region(lifetime);
20442043
let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
20452044
vec![ty::Predicate::TypeOutlives(pred)]
20462045
}

0 commit comments

Comments
 (0)