use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
ElisionFailureInfo, ElidedLifetime};
-use rscope::{AnonTypeScope, MaybeWithAnonTypes};
+use rscope::{AnonTypeScope, MaybeWithAnonTypes, ExplicitRscope};
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FxHashSet};
/// This type must not appear anywhere in other converted types.
const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0));
-pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- lifetime: &hir::Lifetime)
- -> &'tcx ty::Region {
- let r = match tcx.named_region_map.defs.get(&lifetime.id) {
- None => {
- // should have been recorded by the `resolve_lifetime` pass
- span_bug!(lifetime.span, "unresolved lifetime");
- }
-
- Some(&rl::DefStaticRegion) => {
- ty::ReStatic
- }
-
- Some(&rl::DefLateBoundRegion(debruijn, id)) => {
- // If this region is declared on a function, it will have
- // an entry in `late_bound`, but if it comes from
- // `for<'a>` in some type or something, it won't
- // necessarily have one. In that case though, we won't be
- // changed from late to early bound, so we can just
- // substitute false.
- let issue_32330 = tcx.named_region_map
- .late_bound
- .get(&id)
- .cloned()
- .unwrap_or(ty::Issue32330::WontChange);
- ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id),
- lifetime.name,
- issue_32330))
- }
-
- Some(&rl::DefEarlyBoundRegion(index, _)) => {
- ty::ReEarlyBound(ty::EarlyBoundRegion {
- index: index,
- name: lifetime.name
- })
- }
-
- Some(&rl::DefFreeRegion(scope, id)) => {
- // As in DefLateBoundRegion above, could be missing for some late-bound
- // regions, but also for early-bound regions.
- let issue_32330 = tcx.named_region_map
- .late_bound
- .get(&id)
- .cloned()
- .unwrap_or(ty::Issue32330::WontChange);
- ty::ReFree(ty::FreeRegion {
- scope: scope.to_code_extent(&tcx.region_maps),
- bound_region: ty::BrNamed(tcx.map.local_def_id(id),
- lifetime.name,
- issue_32330)
- })
-
- // (*) -- not late-bound, won't change
- }
- };
-
- debug!("ast_region_to_region(lifetime={:?} id={}) yields {:?}",
- lifetime,
- lifetime.id,
- r);
-
- tcx.mk_region(r)
-}
-
fn report_elision_failure(
tcx: TyCtxt,
db: &mut DiagnosticBuilder,
} = info;
let help_name = if let Some(body) = parent {
- let arg = &tcx.map.body(body).arguments[index];
- format!("`{}`", tcx.map.node_to_pretty_string(arg.pat.id))
+ let arg = &tcx.hir.body(body).arguments[index];
+ format!("`{}`", tcx.hir.node_to_pretty_string(arg.pat.id))
} else {
format!("argument {}", index + 1)
};
}
impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
- pub fn opt_ast_region_to_region(&self,
+ pub fn ast_region_to_region(&self, lifetime: &hir::Lifetime) -> &'tcx ty::Region {
+ self.opt_ast_region_to_region(&ExplicitRscope, lifetime.span, Some(lifetime), None)
+ }
+
+ fn try_opt_ast_region_to_region(&self,
rscope: &RegionScope,
default_span: Span,
- opt_lifetime: &Option<hir::Lifetime>) -> &'tcx ty::Region
+ opt_lifetime: Option<&hir::Lifetime>,
+ def: Option<&ty::RegionParameterDef>)
+ -> Result<&'tcx ty::Region, Option<Vec<ElisionFailureInfo>>>
{
- let r = match *opt_lifetime {
- Some(ref lifetime) => {
- ast_region_to_region(self.tcx(), lifetime)
+ let tcx = self.tcx();
+ let name = opt_lifetime.map(|l| l.name);
+ let resolved = opt_lifetime.and_then(|l| tcx.named_region_map.defs.get(&l.id));
+ let r = tcx.mk_region(match resolved {
+ Some(&rl::DefStaticRegion) => {
+ ty::ReStatic
}
- None => self.tcx().mk_region(match rscope.anon_regions(default_span, 1) {
- Ok(rs) => rs[0],
- Err(params) => {
- let ampersand_span = Span { hi: default_span.lo, ..default_span};
+ Some(&rl::DefLateBoundRegion(debruijn, id)) => {
+ // If this region is declared on a function, it will have
+ // an entry in `late_bound`, but if it comes from
+ // `for<'a>` in some type or something, it won't
+ // necessarily have one. In that case though, we won't be
+ // changed from late to early bound, so we can just
+ // substitute false.
+ let issue_32330 = tcx.named_region_map
+ .late_bound
+ .get(&id)
+ .cloned()
+ .unwrap_or(ty::Issue32330::WontChange);
+ ty::ReLateBound(debruijn, ty::BrNamed(tcx.hir.local_def_id(id),
+ name.unwrap(),
+ issue_32330))
+ }
- let mut err = struct_span_err!(self.tcx().sess, ampersand_span, E0106,
- "missing lifetime specifier");
- err.span_label(ampersand_span, &format!("expected lifetime parameter"));
+ Some(&rl::DefEarlyBoundRegion(index, _)) => {
+ ty::ReEarlyBound(ty::EarlyBoundRegion {
+ index: index,
+ name: name.unwrap()
+ })
+ }
- if let Some(params) = params {
- report_elision_failure(self.tcx(), &mut err, params);
- }
- err.emit();
- ty::ReStatic
- }
- })
- };
+ Some(&rl::DefFreeRegion(scope, id)) => {
+ // As in DefLateBoundRegion above, could be missing for some late-bound
+ // regions, but also for early-bound regions.
+ let issue_32330 = tcx.named_region_map
+ .late_bound
+ .get(&id)
+ .cloned()
+ .unwrap_or(ty::Issue32330::WontChange);
+ ty::ReFree(ty::FreeRegion {
+ scope: scope.to_code_extent(&tcx.region_maps),
+ bound_region: ty::BrNamed(tcx.hir.local_def_id(id),
+ name.unwrap(),
+ issue_32330)
+ })
+
+ // (*) -- not late-bound, won't change
+ }
+
+ None => rscope.anon_region(default_span, def)?
+ });
debug!("opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}",
opt_lifetime,
r);
- r
+ Ok(r)
+ }
+
+ pub fn opt_ast_region_to_region(&self,
+ rscope: &RegionScope,
+ default_span: Span,
+ opt_lifetime: Option<&hir::Lifetime>,
+ def: Option<&ty::RegionParameterDef>) -> &'tcx ty::Region
+ {
+ let tcx = self.tcx();
+ self.try_opt_ast_region_to_region(rscope, default_span, opt_lifetime, def)
+ .unwrap_or_else(|params| {
+ let ampersand_span = Span { hi: default_span.lo, ..default_span};
+
+ let mut err = struct_span_err!(tcx.sess, ampersand_span, E0106,
+ "missing lifetime specifier");
+ err.span_label(ampersand_span, &format!("expected lifetime parameter"));
+
+ if let Some(params) = params {
+ report_elision_failure(tcx, &mut err, params);
+ }
+ err.emit();
+ tcx.mk_region(ty::ReStatic)
+ })
}
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
};
let expected_num_region_params = decl_generics.regions.len();
let supplied_num_region_params = lifetimes.len();
- let regions = if expected_num_region_params == supplied_num_region_params {
- lifetimes.iter().map(|l| *ast_region_to_region(tcx, l)).collect()
- } else {
- let anon_regions =
- rscope.anon_regions(span, expected_num_region_params);
-
- if supplied_num_region_params != 0 || anon_regions.is_err() {
+ let mut reported_lifetime_count_mismatch = false;
+ let mut report_lifetime_count_mismatch = || {
+ if !reported_lifetime_count_mismatch {
+ reported_lifetime_count_mismatch = true;
+ let all_infer = lifetimes.iter().all(|lt| lt.is_elided());
+ let supplied = if all_infer { 0 } else { supplied_num_region_params };
report_lifetime_number_error(tcx, span,
- supplied_num_region_params,
+ supplied,
expected_num_region_params);
}
-
- match anon_regions {
- Ok(anon_regions) => anon_regions,
- Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect()
- }
};
+ if expected_num_region_params != supplied_num_region_params {
+ report_lifetime_count_mismatch();
+ }
+
// If a self-type was declared, one should be provided.
assert_eq!(decl_generics.has_self, self_ty.is_some());
let mut output_assoc_binding = None;
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - self_ty.is_some() as usize;
- tcx.mk_region(regions[i])
+ let l = lifetimes.get(i);
+ self.try_opt_ast_region_to_region(rscope, span, l, Some(def)).unwrap_or_else(|_| {
+ report_lifetime_count_mismatch();
+ tcx.mk_region(ty::ReStatic)
+ })
}, |def, substs| {
let i = def.index as usize;
}
_ => {
span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
- self.tcx().map.node_to_pretty_string(trait_ref.ref_id));
+ self.tcx().hir.node_to_pretty_string(trait_ref.ref_id));
}
}
}
let bound_span = self.tcx().associated_items(bound.def_id()).find(|item| {
item.kind == ty::AssociatedKind::Type && item.name == assoc_name
})
- .and_then(|item| self.tcx().map.span_if_local(item.def_id));
+ .and_then(|item| self.tcx().hir.span_if_local(item.def_id));
if let Some(span) = bound_span {
err.span_label(span, &format!("ambiguous `{}` from `{}`",
}
}
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
- let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
+ let trait_node_id = tcx.hir.as_local_node_id(trait_did).unwrap();
match self.find_bound_for_assoc_item(trait_node_id,
keywords::SelfType.name(),
assoc_name,
}
}
(&ty::TyParam(_), Def::TyParam(param_did)) => {
- let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
+ let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
let param_name = tcx.type_parameter_def(param_node_id).name;
match self.find_bound_for_assoc_item(param_node_id,
param_name,
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(&path.segments);
- let node_id = tcx.map.as_local_node_id(did).unwrap();
+ let node_id = tcx.hir.as_local_node_id(did).unwrap();
let param = tcx.ty_param_defs.borrow().get(&node_id)
.map(ty::ParamTy::for_def);
if let Some(p) = param {
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(&path.segments);
- let ty = tcx.item_type(def_id);
- if let Some(free_substs) = self.get_free_substs() {
- ty.subst(tcx, free_substs)
+
+ // FIXME: Self type is not always computed when we are here because type parameter
+ // bounds may affect Self type and have to be converted before it.
+ let ty = if def_id.is_local() {
+ tcx.item_types.borrow().get(&def_id).cloned()
} else {
- ty
+ Some(tcx.item_type(def_id))
+ };
+ if let Some(ty) = ty {
+ if let Some(free_substs) = self.get_free_substs() {
+ ty.subst(tcx, free_substs)
+ } else {
+ ty
+ }
+ } else {
+ tcx.sess.span_err(span, "`Self` type is used before it's determined");
+ tcx.types.err
}
}
Def::SelfTy(Some(_), None) => {
})
}
hir::TyRptr(ref region, ref mt) => {
- let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region);
+ let r = self.opt_ast_region_to_region(rscope, ast_ty.span, Some(region), None);
debug!("TyRef r={:?}", r);
let rscope1 =
&ObjectLifetimeDefaultRscope::new(
use collect::{compute_bounds, SizedByDefault};
// Create the anonymized type.
- let def_id = tcx.map.local_def_id(ast_ty.id);
+ let def_id = tcx.hir.local_def_id(ast_ty.id);
if let Some(anon_scope) = rscope.anon_type_scope() {
let substs = anon_scope.fresh_substs(self, ast_ty.span);
- let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
+ let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs);
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
let bounds = compute_bounds(self, ty, bounds,
if let Some(&r) = explicit_region_bounds.get(0) {
// Explicitly specified region bound. Use that.
- return Some(ast_region_to_region(tcx, r));
+ return Some(self.ast_region_to_region(r));
}
if let Some(principal) = existential_predicates.principal() {