Cleanups and comments
This commit is contained in:
parent
0c98dc66fd
commit
7108918db6
7 changed files with 216 additions and 267 deletions
|
@ -504,7 +504,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
|
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
|
||||||
let closure_kind_ty = closure_substs.as_closure().kind_ty();
|
let closure_kind_ty = closure_substs.as_closure().kind_ty();
|
||||||
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
|
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
|
||||||
debug_assert!(!closure_ty.has_escaping_bound_vars());
|
|
||||||
let env_ty = match closure_kind {
|
let env_ty = match closure_kind {
|
||||||
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
|
ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
|
||||||
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
|
ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc_middle::traits;
|
use rustc_middle::traits;
|
||||||
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
|
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@ fn custom_coerce_unsize_info<'tcx>(
|
||||||
) -> CustomCoerceUnsized {
|
) -> CustomCoerceUnsized {
|
||||||
let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
|
let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
|
||||||
|
|
||||||
debug_assert!(!source_ty.has_escaping_bound_vars());
|
|
||||||
debug_assert!(!target_ty.has_escaping_bound_vars());
|
|
||||||
let trait_ref = ty::Binder::dummy(ty::TraitRef {
|
let trait_ref = ty::Binder::dummy(ty::TraitRef {
|
||||||
def_id,
|
def_id,
|
||||||
substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
|
substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
|
||||||
|
|
|
@ -34,7 +34,6 @@ use tracing::debug;
|
||||||
|
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
crate mod lifetimes;
|
crate mod lifetimes;
|
||||||
crate mod supertraits;
|
|
||||||
|
|
||||||
type Res = def::Res<NodeId>;
|
type Res = def::Res<NodeId>;
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,12 @@ struct NamedRegionMap {
|
||||||
// (b) it DOES appear in the arguments.
|
// (b) it DOES appear in the arguments.
|
||||||
late_bound: HirIdSet,
|
late_bound: HirIdSet,
|
||||||
|
|
||||||
|
// Maps relevant hir items to the bound vars on them. These include:
|
||||||
|
// - function defs
|
||||||
|
// - function pointers
|
||||||
|
// - closures
|
||||||
|
// - trait refs
|
||||||
|
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
|
||||||
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
|
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +177,16 @@ crate struct LifetimeContext<'a, 'tcx> {
|
||||||
/// any bound var information.
|
/// any bound var information.
|
||||||
///
|
///
|
||||||
/// So, if we encounter a quantifier at the outer scope, we set
|
/// So, if we encounter a quantifier at the outer scope, we set
|
||||||
/// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter
|
/// `trait_ref_hack` to the hir id of the bounded type (and introduce a scope).
|
||||||
/// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`,
|
/// Then, if we encounter a quantifier at the inner scope, then we know to
|
||||||
/// then we introduce the scope at the inner quantifier.
|
/// emit an error. Importantly though, we do have to track the lifetimes
|
||||||
trait_ref_hack: Option<(Vec<ty::BoundVariableKind>, u32)>,
|
/// defined on the outer scope (i.e. the bounded ty), since we continue
|
||||||
|
/// to type check after emitting an error; we therefore assume that the bound
|
||||||
|
/// vars on the inner trait refs come from both quantifiers.
|
||||||
|
///
|
||||||
|
/// If we encounter a quantifier in the inner scope `trait_ref_hack` being
|
||||||
|
/// `None`, then we just introduce the scope at the inner quantifier as normal.
|
||||||
|
trait_ref_hack: Option<hir::HirId>,
|
||||||
|
|
||||||
/// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
|
/// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
|
||||||
is_in_fn_syntax: bool,
|
is_in_fn_syntax: bool,
|
||||||
|
@ -232,11 +244,9 @@ enum Scope<'a> {
|
||||||
/// of the resulting opaque type.
|
/// of the resulting opaque type.
|
||||||
opaque_type_parent: bool,
|
opaque_type_parent: bool,
|
||||||
|
|
||||||
/// We need to keep track of the number of named late bound vars, since
|
/// True only if this `Binder` scope is from the quantifiers on a
|
||||||
/// we may have elided lifetimes that have an index starting *after*
|
/// `PolyTraitRef`. This is necessary for `assocated_type_bounds`, which
|
||||||
/// these.
|
/// requires binders of nested trait refs to be merged.
|
||||||
named_late_bound_vars: u32,
|
|
||||||
|
|
||||||
from_poly_trait_ref: bool,
|
from_poly_trait_ref: bool,
|
||||||
|
|
||||||
/// The late bound vars for a given item are stored by `HirId` to be
|
/// The late bound vars for a given item are stored by `HirId` to be
|
||||||
|
@ -304,7 +314,6 @@ enum Scope<'a> {
|
||||||
/// vars from both `for<...>`s *do* share the same binder level.
|
/// vars from both `for<...>`s *do* share the same binder level.
|
||||||
TraitRefHackInner {
|
TraitRefHackInner {
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
named_late_bound_vars: u32,
|
|
||||||
s: ScopeRef<'a>,
|
s: ScopeRef<'a>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -331,7 +340,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
next_early_index,
|
next_early_index,
|
||||||
track_lifetime_uses,
|
track_lifetime_uses,
|
||||||
opaque_type_parent,
|
opaque_type_parent,
|
||||||
named_late_bound_vars,
|
|
||||||
from_poly_trait_ref,
|
from_poly_trait_ref,
|
||||||
hir_id,
|
hir_id,
|
||||||
s: _,
|
s: _,
|
||||||
|
@ -341,7 +349,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
.field("next_early_index", next_early_index)
|
.field("next_early_index", next_early_index)
|
||||||
.field("track_lifetime_uses", track_lifetime_uses)
|
.field("track_lifetime_uses", track_lifetime_uses)
|
||||||
.field("opaque_type_parent", opaque_type_parent)
|
.field("opaque_type_parent", opaque_type_parent)
|
||||||
.field("named_late_bound_vars", named_late_bound_vars)
|
|
||||||
.field("from_poly_trait_ref", from_poly_trait_ref)
|
.field("from_poly_trait_ref", from_poly_trait_ref)
|
||||||
.field("hir_id", hir_id)
|
.field("hir_id", hir_id)
|
||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
|
@ -357,10 +364,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
.field("lifetime", lifetime)
|
.field("lifetime", lifetime)
|
||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
.finish(),
|
.finish(),
|
||||||
Scope::TraitRefHackInner { hir_id, named_late_bound_vars, s: _ } => f
|
Scope::TraitRefHackInner { hir_id, s: _ } => f
|
||||||
.debug_struct("TraitRefHackInner")
|
.debug_struct("TraitRefHackInner")
|
||||||
.field("hir_id", hir_id)
|
.field("hir_id", hir_id)
|
||||||
.field("named_late_bound_vars", named_late_bound_vars)
|
|
||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
.finish(),
|
.finish(),
|
||||||
Scope::Supertrait { lifetimes, s: _ } => f
|
Scope::Supertrait { lifetimes, s: _ } => f
|
||||||
|
@ -664,7 +670,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, move |_old_scope, this| {
|
self.with(scope, move |_old_scope, this| {
|
||||||
|
@ -790,7 +795,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index: index + non_lifetime_count,
|
next_early_index: index + non_lifetime_count,
|
||||||
opaque_type_parent: true,
|
opaque_type_parent: true,
|
||||||
track_lifetime_uses,
|
track_lifetime_uses,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
s: ROOT_SCOPE,
|
s: ROOT_SCOPE,
|
||||||
};
|
};
|
||||||
|
@ -838,21 +842,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
self.missing_named_lifetime_spots
|
self.missing_named_lifetime_spots
|
||||||
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
||||||
let mut named_late_bound_vars = 0;
|
|
||||||
let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = c
|
let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = c
|
||||||
.generic_params
|
.generic_params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => Some(param),
|
||||||
let late_bound_idx = named_late_bound_vars;
|
|
||||||
named_late_bound_vars += 1;
|
|
||||||
let pair = Region::late(late_bound_idx, &self.tcx.hir(), param);
|
|
||||||
let r = pair.1.clone();
|
|
||||||
let r = late_region_as_bound_region(self.tcx, &r);
|
|
||||||
Some((pair, r))
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
.enumerate()
|
||||||
|
.map(|(late_bound_idx, param)| {
|
||||||
|
let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
|
||||||
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
|
(pair, r)
|
||||||
|
})
|
||||||
.unzip();
|
.unzip();
|
||||||
self.map.late_bound_vars.insert(ty.hir_id, binders);
|
self.map.late_bound_vars.insert(ty.hir_id, binders);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
|
@ -862,7 +864,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index,
|
next_early_index,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, |old_scope, this| {
|
self.with(scope, |old_scope, this| {
|
||||||
|
@ -1053,7 +1054,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
s: this.scope,
|
s: this.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
this.with(scope, |_old_scope, this| {
|
this.with(scope, |_old_scope, this| {
|
||||||
|
@ -1071,7 +1071,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, |_old_scope, this| {
|
self.with(scope, |_old_scope, this| {
|
||||||
|
@ -1128,7 +1127,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: true,
|
opaque_type_parent: true,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, |old_scope, this| {
|
self.with(scope, |old_scope, this| {
|
||||||
|
@ -1195,7 +1193,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: true,
|
opaque_type_parent: true,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, |old_scope, this| {
|
self.with(scope, |old_scope, this| {
|
||||||
|
@ -1279,21 +1276,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
ref bound_generic_params,
|
ref bound_generic_params,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let mut named_late_bound_vars = 0;
|
let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) =
|
||||||
let (lifetimes, binders): (FxHashMap<_, _>, Vec<_>) = bound_generic_params
|
bound_generic_params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => Some(param),
|
||||||
let late_bound_idx = named_late_bound_vars;
|
_ => None,
|
||||||
named_late_bound_vars += 1;
|
})
|
||||||
let pair = Region::late(late_bound_idx, &self.tcx.hir(), param);
|
.enumerate()
|
||||||
let r = pair.1.clone();
|
.map(|(late_bound_idx, param)| {
|
||||||
let r = late_region_as_bound_region(self.tcx, &r);
|
let pair =
|
||||||
Some((pair, r))
|
Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
|
||||||
}
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
_ => None,
|
(pair, r)
|
||||||
})
|
})
|
||||||
.unzip();
|
.unzip();
|
||||||
self.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
|
self.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
|
||||||
if !lifetimes.is_empty() {
|
if !lifetimes.is_empty() {
|
||||||
let next_early_index = self.next_early_index();
|
let next_early_index = self.next_early_index();
|
||||||
|
@ -1304,13 +1301,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index,
|
next_early_index,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars,
|
|
||||||
from_poly_trait_ref: true,
|
from_poly_trait_ref: true,
|
||||||
};
|
};
|
||||||
let result = self.with(scope, |old_scope, this| {
|
let result = self.with(scope, |old_scope, this| {
|
||||||
this.check_lifetime_params(old_scope, &bound_generic_params);
|
this.check_lifetime_params(old_scope, &bound_generic_params);
|
||||||
this.visit_ty(&bounded_ty);
|
this.visit_ty(&bounded_ty);
|
||||||
this.trait_ref_hack = Some((binders, named_late_bound_vars));
|
this.trait_ref_hack = Some(bounded_ty.hir_id);
|
||||||
walk_list!(this, visit_param_bound, bounds);
|
walk_list!(this, visit_param_bound, bounds);
|
||||||
this.trait_ref_hack = None;
|
this.trait_ref_hack = None;
|
||||||
});
|
});
|
||||||
|
@ -1351,7 +1347,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index: self.next_early_index(),
|
next_early_index: self.next_early_index(),
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars: 0,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, |_, this| {
|
self.with(scope, |_, this| {
|
||||||
|
@ -1389,112 +1384,97 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
let (binders, named_late_bound_vars, lifetimes) =
|
let (binders, lifetimes) = if let Some(hir_id) = trait_ref_hack {
|
||||||
if let Some((mut binders, mut named_late_bound_vars)) = trait_ref_hack.clone() {
|
let mut binders = self.map.late_bound_vars.entry(hir_id).or_default().clone();
|
||||||
let initial_binders = named_late_bound_vars;
|
let initial_bound_vars = binders.len() as u32;
|
||||||
binders.extend(trait_ref.bound_generic_params.iter().filter_map(|param| {
|
let mut lifetimes: FxHashMap<hir::ParamName, Region> = FxHashMap::default();
|
||||||
match param.kind {
|
let binders_iter = trait_ref
|
||||||
GenericParamKind::Lifetime { .. } => {
|
.bound_generic_params
|
||||||
let late_bound_idx = named_late_bound_vars;
|
.iter()
|
||||||
named_late_bound_vars += 1;
|
.filter_map(|param| match param.kind {
|
||||||
let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
|
GenericParamKind::Lifetime { .. } => Some(param),
|
||||||
Some(late_region_as_bound_region(self.tcx, ®ion))
|
_ => None,
|
||||||
}
|
})
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
.enumerate()
|
||||||
|
.map(|(late_bound_idx, param)| {
|
||||||
|
let pair = Region::late(
|
||||||
|
initial_bound_vars + late_bound_idx as u32,
|
||||||
|
&self.tcx.hir(),
|
||||||
|
param,
|
||||||
|
);
|
||||||
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
|
lifetimes.insert(pair.0, pair.1);
|
||||||
|
r
|
||||||
|
});
|
||||||
|
binders.extend(binders_iter);
|
||||||
|
|
||||||
|
(binders, lifetimes)
|
||||||
|
} else {
|
||||||
|
let mut supertrait_lifetimes = vec![];
|
||||||
|
let mut scope = self.scope;
|
||||||
|
let mut outer_binders = loop {
|
||||||
|
match scope {
|
||||||
|
Scope::Body { .. } | Scope::Root => {
|
||||||
|
break vec![];
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
|
|
||||||
let mut named_late_bound_vars = initial_binders;
|
Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
|
||||||
let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref
|
scope = s;
|
||||||
.bound_generic_params
|
}
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
|
||||||
let late_bound_idx = named_late_bound_vars;
|
|
||||||
named_late_bound_vars += 1;
|
|
||||||
Some(Region::late(late_bound_idx, &self.tcx.hir(), param))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(binders, named_late_bound_vars, lifetimes)
|
Scope::TraitRefHackInner { hir_id, .. } => {
|
||||||
} else {
|
// Nested poly trait refs have the binders concatenated
|
||||||
let mut supertrait_lifetimes = vec![];
|
// If we reach `TraitRefHackInner`, then there is only one more `Binder` above us,
|
||||||
let mut scope = self.scope;
|
// over all the bounds. We don't want this, since all the lifetimes we care about
|
||||||
let mut binders = loop {
|
// are here anyways.
|
||||||
match scope {
|
let mut full_binders =
|
||||||
Scope::Body { .. } | Scope::Root => {
|
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
|
||||||
|
full_binders.extend(supertrait_lifetimes.into_iter());
|
||||||
|
break full_binders;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::Supertrait { s, lifetimes } => {
|
||||||
|
supertrait_lifetimes = lifetimes.clone();
|
||||||
|
scope = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::Binder { hir_id, from_poly_trait_ref, .. } => {
|
||||||
|
if !from_poly_trait_ref {
|
||||||
|
// We should only see super trait lifetimes if there is a `Binder` above
|
||||||
|
assert!(supertrait_lifetimes.is_empty());
|
||||||
break vec![];
|
break vec![];
|
||||||
}
|
}
|
||||||
|
// Nested poly trait refs have the binders concatenated
|
||||||
Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
|
let mut full_binders =
|
||||||
scope = s;
|
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
|
||||||
}
|
full_binders.extend(supertrait_lifetimes.into_iter());
|
||||||
|
break full_binders;
|
||||||
Scope::TraitRefHackInner { hir_id, .. } => {
|
|
||||||
// Nested poly trait refs have the binders concatenated
|
|
||||||
// If we reach `TraitRefHackInner`, then there is only one more `Binder` above us,
|
|
||||||
// over all the bounds. We don't want this, since all the lifetimes we care about
|
|
||||||
// are here anyways.
|
|
||||||
let mut full_binders =
|
|
||||||
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
|
|
||||||
full_binders.extend(supertrait_lifetimes.into_iter());
|
|
||||||
break full_binders;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope::Supertrait { s, lifetimes } => {
|
|
||||||
supertrait_lifetimes = lifetimes.clone();
|
|
||||||
scope = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope::Binder { hir_id, from_poly_trait_ref, .. } => {
|
|
||||||
if !from_poly_trait_ref {
|
|
||||||
// We should only see super trait lifetimes if there is a `Binder` above
|
|
||||||
assert!(supertrait_lifetimes.is_empty());
|
|
||||||
break vec![];
|
|
||||||
}
|
|
||||||
// Nested poly trait refs have the binders concatenated
|
|
||||||
let mut full_binders =
|
|
||||||
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
|
|
||||||
full_binders.extend(supertrait_lifetimes.into_iter());
|
|
||||||
break full_binders;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
let mut named_late_bound_vars = binders.len() as u32;
|
|
||||||
let local_binders: Vec<_> = trait_ref
|
|
||||||
.bound_generic_params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
|
||||||
let late_bound_idx = named_late_bound_vars;
|
|
||||||
named_late_bound_vars += 1;
|
|
||||||
let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
|
|
||||||
Some(late_region_as_bound_region(self.tcx, ®ion))
|
|
||||||
}
|
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut named_late_bound_vars = binders.len() as u32;
|
|
||||||
let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref
|
|
||||||
.bound_generic_params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
|
||||||
let late_bound_idx = named_late_bound_vars;
|
|
||||||
named_late_bound_vars += 1;
|
|
||||||
Some(Region::late(late_bound_idx, &self.tcx.hir(), param))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
binders.extend(local_binders.into_iter());
|
|
||||||
|
|
||||||
(binders, named_late_bound_vars, lifetimes)
|
|
||||||
};
|
};
|
||||||
|
let (lifetimes, local_binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = trait_ref
|
||||||
|
.bound_generic_params
|
||||||
|
.iter()
|
||||||
|
.filter_map(|param| match param.kind {
|
||||||
|
GenericParamKind::Lifetime { .. } => Some(param),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
.map(|(late_bound_idx, param)| {
|
||||||
|
let pair = Region::late(
|
||||||
|
outer_binders.len() as u32 + late_bound_idx as u32,
|
||||||
|
&self.tcx.hir(),
|
||||||
|
param,
|
||||||
|
);
|
||||||
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
|
(pair, r)
|
||||||
|
})
|
||||||
|
.unzip();
|
||||||
|
|
||||||
|
outer_binders.extend(local_binders.into_iter());
|
||||||
|
|
||||||
|
(outer_binders, lifetimes)
|
||||||
|
};
|
||||||
|
|
||||||
debug!(?binders);
|
debug!(?binders);
|
||||||
self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
|
self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
|
||||||
|
@ -1507,7 +1487,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index,
|
next_early_index,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
named_late_bound_vars: named_late_bound_vars as u32,
|
|
||||||
from_poly_trait_ref: true,
|
from_poly_trait_ref: true,
|
||||||
};
|
};
|
||||||
self.with(scope, |old_scope, this| {
|
self.with(scope, |old_scope, this| {
|
||||||
|
@ -1516,11 +1495,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
this.visit_trait_ref(&trait_ref.trait_ref);
|
this.visit_trait_ref(&trait_ref.trait_ref);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let scope = Scope::TraitRefHackInner {
|
let scope =
|
||||||
hir_id: trait_ref.trait_ref.hir_ref_id,
|
Scope::TraitRefHackInner { hir_id: trait_ref.trait_ref.hir_ref_id, s: self.scope };
|
||||||
named_late_bound_vars: named_late_bound_vars as u32,
|
|
||||||
s: self.scope,
|
|
||||||
};
|
|
||||||
self.with(scope, |_old_scope, this| {
|
self.with(scope, |_old_scope, this| {
|
||||||
this.visit_trait_ref(&trait_ref.trait_ref);
|
this.visit_trait_ref(&trait_ref.trait_ref);
|
||||||
});
|
});
|
||||||
|
@ -2234,23 +2210,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
.collect();
|
.collect();
|
||||||
let next_early_index = next_early_index + non_lifetime_count;
|
let next_early_index = next_early_index + non_lifetime_count;
|
||||||
|
|
||||||
let mut named_late_bound_vars = 0;
|
|
||||||
let binders: Vec<_> = generics
|
let binders: Vec<_> = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. }
|
||||||
if self.map.late_bound.contains(¶m.hir_id) {
|
if self.map.late_bound.contains(¶m.hir_id) =>
|
||||||
let late_bound_idx = named_late_bound_vars;
|
{
|
||||||
named_late_bound_vars += 1;
|
Some(param)
|
||||||
let r = Region::late(late_bound_idx, &self.tcx.hir(), param).1;
|
|
||||||
let r = late_region_as_bound_region(self.tcx, &r);
|
|
||||||
Some(r)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
_ => None,
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
.map(|(late_bound_idx, param)| {
|
||||||
|
let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
|
||||||
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
|
r
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.map.late_bound_vars.insert(hir_id, binders);
|
self.map.late_bound_vars.insert(hir_id, binders);
|
||||||
|
@ -2261,7 +2236,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
opaque_type_parent: true,
|
opaque_type_parent: true,
|
||||||
track_lifetime_uses: false,
|
track_lifetime_uses: false,
|
||||||
named_late_bound_vars: named_late_bound_vars as u32,
|
|
||||||
from_poly_trait_ref: false,
|
from_poly_trait_ref: false,
|
||||||
};
|
};
|
||||||
self.with(scope, move |old_scope, this| {
|
self.with(scope, move |old_scope, this| {
|
||||||
|
@ -2629,49 +2603,85 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
let has_lifetime_parameter =
|
let has_lifetime_parameter =
|
||||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||||
|
|
||||||
// Resolve lifetimes found in the type `XX` from `Item = XX` bindings.
|
// Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or
|
||||||
|
// in the trait ref `YY<...>` in `Item: YY<...>`.
|
||||||
for binding in generic_args.bindings {
|
for binding in generic_args.bindings {
|
||||||
let scope = Scope::ObjectLifetimeDefault {
|
let scope = Scope::ObjectLifetimeDefault {
|
||||||
lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
|
lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
};
|
};
|
||||||
if let Some(type_def_id) = type_def_id {
|
if let Some(type_def_id) = type_def_id {
|
||||||
let lifetimes =
|
let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
|
||||||
LifetimeContext::supertrait_bounds(self.tcx, type_def_id, binding.ident);
|
self.tcx,
|
||||||
if let Some(lifetimes) = lifetimes {
|
type_def_id,
|
||||||
self.with(scope, |_, this| {
|
binding.ident,
|
||||||
let scope = Scope::Supertrait { lifetimes, s: this.scope };
|
);
|
||||||
this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
|
self.with(scope, |_, this| {
|
||||||
});
|
let scope =
|
||||||
} else {
|
Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope };
|
||||||
self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
|
this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
|
||||||
}
|
});
|
||||||
} else {
|
} else {
|
||||||
self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
|
self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_defines_associated_type_named(
|
/// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the
|
||||||
tcx: TyCtxt<'tcx>,
|
/// associated type name and starting trait.
|
||||||
trait_def_id: DefId,
|
/// For example, imagine we have
|
||||||
assoc_name: Ident,
|
/// ```rust
|
||||||
) -> bool {
|
/// trait Foo<'a, 'b> {
|
||||||
tcx.associated_items(trait_def_id)
|
/// type As;
|
||||||
.find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
|
/// }
|
||||||
.is_some()
|
/// trait Bar<'b>: for<'a> Foo<'a, 'b> {}
|
||||||
}
|
/// trait Bar: for<'b> Bar<'b> {}
|
||||||
|
/// ```
|
||||||
fn supertrait_bounds(
|
/// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
|
||||||
|
/// the starting trait `Bar`, we would return `Some(['b, 'a])`.
|
||||||
|
fn supertrait_hrtb_lifetimes(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
) -> Option<Vec<ty::BoundVariableKind>> {
|
) -> Option<Vec<ty::BoundVariableKind>> {
|
||||||
let all_candidates = super::supertraits::supertraits(tcx, def_id);
|
let trait_defines_associated_type_named = |trait_def_id: DefId| {
|
||||||
let mut matching_candidates = all_candidates
|
tcx.associated_items(trait_def_id)
|
||||||
.filter(|r| LifetimeContext::trait_defines_associated_type_named(tcx, r.0, assoc_name));
|
.find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
|
||||||
|
.is_some()
|
||||||
|
};
|
||||||
|
|
||||||
matching_candidates.next().map(|c| c.1.into_iter().collect())
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> =
|
||||||
|
smallvec![(def_id, smallvec![])];
|
||||||
|
let mut visited: FxHashSet<DefId> = FxHashSet::default();
|
||||||
|
loop {
|
||||||
|
let (def_id, bound_vars) = match stack.pop() {
|
||||||
|
Some(next) => next,
|
||||||
|
None => break None,
|
||||||
|
};
|
||||||
|
if trait_defines_associated_type_named(def_id) {
|
||||||
|
break Some(bound_vars.into_iter().collect());
|
||||||
|
}
|
||||||
|
let predicates =
|
||||||
|
tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
|
||||||
|
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
||||||
|
let bound_predicate = pred.kind();
|
||||||
|
match bound_predicate.skip_binder() {
|
||||||
|
ty::PredicateKind::Trait(data, _) => {
|
||||||
|
// The order here needs to match what we would get from `subst_supertrait`
|
||||||
|
let pred_bound_vars = bound_predicate.bound_vars();
|
||||||
|
let mut all_bound_vars = bound_vars.clone();
|
||||||
|
all_bound_vars.extend(pred_bound_vars.iter());
|
||||||
|
let super_def_id = data.trait_ref.def_id;
|
||||||
|
Some((super_def_id, all_bound_vars))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let obligations = obligations.filter(|o| visited.insert(o.0));
|
||||||
|
stack.extend(obligations);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
@ -2682,13 +2692,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
debug!("visit_fn_like_elision: enter");
|
debug!("visit_fn_like_elision: enter");
|
||||||
let mut scope = &*self.scope;
|
let mut scope = &*self.scope;
|
||||||
let (hir_id, named_late_bound_vars) = loop {
|
let hir_id = loop {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::Binder { hir_id, named_late_bound_vars, .. }
|
Scope::Binder { hir_id, .. } | Scope::TraitRefHackInner { hir_id, .. } => {
|
||||||
| Scope::TraitRefHackInner { hir_id, named_late_bound_vars, .. } => {
|
break *hir_id;
|
||||||
break (*hir_id, *named_late_bound_vars);
|
|
||||||
}
|
}
|
||||||
Scope::Body { id, .. } => break (id.hir_id, 0),
|
Scope::Body { id, .. } => break id.hir_id,
|
||||||
Scope::ObjectLifetimeDefault { ref s, .. }
|
Scope::ObjectLifetimeDefault { ref s, .. }
|
||||||
| Scope::Elision { ref s, .. }
|
| Scope::Elision { ref s, .. }
|
||||||
| Scope::Supertrait { ref s, .. } => {
|
| Scope::Supertrait { ref s, .. } => {
|
||||||
|
@ -2697,11 +2706,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
Scope::Root => bug!("In fn_like_elision without appropriate scope above"),
|
Scope::Root => bug!("In fn_like_elision without appropriate scope above"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// While not strictly necessary, we gather anon lifetimes *before* actually
|
||||||
|
// visiting the argument types.
|
||||||
let mut gather = GatherAnonLifetimes { anon_count: 0 };
|
let mut gather = GatherAnonLifetimes { anon_count: 0 };
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
gather.visit_ty(input);
|
gather.visit_ty(input);
|
||||||
}
|
}
|
||||||
self.map.late_bound_vars.entry(hir_id).or_default().extend(
|
let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default();
|
||||||
|
let named_late_bound_vars = late_bound_vars.len() as u32;
|
||||||
|
late_bound_vars.extend(
|
||||||
(0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))),
|
(0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))),
|
||||||
);
|
);
|
||||||
let arg_scope = Scope::Elision {
|
let arg_scope = Scope::Elision {
|
||||||
|
@ -2987,6 +3000,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||||
|
// If we enter a `BareFn`, then we enter a *new* binding scope
|
||||||
if let hir::TyKind::BareFn(_) = ty.kind {
|
if let hir::TyKind::BareFn(_) = ty.kind {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2998,6 +3012,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
path_span: Span,
|
path_span: Span,
|
||||||
generic_args: &'v hir::GenericArgs<'v>,
|
generic_args: &'v hir::GenericArgs<'v>,
|
||||||
) {
|
) {
|
||||||
|
// parenthesized args enter a new elison scope
|
||||||
if generic_args.parenthesized {
|
if generic_args.parenthesized {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
use smallvec::{smallvec, SmallVec};
|
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
|
||||||
use rustc_hir::def_id::DefId;
|
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
|
||||||
|
|
||||||
pub struct Elaborator<'tcx> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]>,
|
|
||||||
visited: FxHashSet<DefId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn supertraits<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Elaborator<'tcx> {
|
|
||||||
Elaborator { tcx, stack: smallvec![(def_id, smallvec![])], visited: Default::default() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Elaborator<'tcx> {
|
|
||||||
fn elaborate(&mut self, def_id: DefId, bound_vars: &SmallVec<[ty::BoundVariableKind; 8]>) {
|
|
||||||
let tcx = self.tcx;
|
|
||||||
|
|
||||||
let predicates = tcx.super_predicates_of(def_id);
|
|
||||||
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
|
|
||||||
let bound_predicate = pred.kind();
|
|
||||||
match bound_predicate.skip_binder() {
|
|
||||||
ty::PredicateKind::Trait(data, _) => {
|
|
||||||
// The order here needs to match what we would get from `subst_supertrait`
|
|
||||||
let pred_bound_vars = bound_predicate.bound_vars();
|
|
||||||
let mut all_bound_vars = bound_vars.clone();
|
|
||||||
all_bound_vars.extend(pred_bound_vars.iter());
|
|
||||||
let super_def_id = data.trait_ref.def_id;
|
|
||||||
Some((super_def_id, all_bound_vars))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let visited = &mut self.visited;
|
|
||||||
let obligations = obligations.filter(|o| visited.insert(o.0));
|
|
||||||
self.stack.extend(obligations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Iterator for Elaborator<'tcx> {
|
|
||||||
type Item = (DefId, SmallVec<[ty::BoundVariableKind; 8]>);
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
(self.stack.len(), None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
match self.stack.pop() {
|
|
||||||
Some((def_id, bound_vars)) => {
|
|
||||||
self.elaborate(def_id, &bound_vars);
|
|
||||||
Some((def_id, bound_vars))
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -82,7 +82,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
) -> AutoTraitResult<A> {
|
) -> AutoTraitResult<A> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
debug_assert!(!ty.has_escaping_bound_vars());
|
|
||||||
let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
|
let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
|
||||||
|
|
||||||
let trait_pred = ty::Binder::dummy(trait_ref);
|
let trait_pred = ty::Binder::dummy(trait_ref);
|
||||||
|
|
|
@ -2186,13 +2186,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses the programmer's textual representation of a type into our
|
||||||
|
/// internal notion of a type.
|
||||||
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
||||||
self.ast_ty_to_ty_inner(ast_ty, false)
|
self.ast_ty_to_ty_inner(ast_ty, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the programmer's textual representation of a type into our
|
|
||||||
/// internal notion of a type.
|
|
||||||
///
|
|
||||||
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
|
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
|
||||||
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
|
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue