1
Fork 0

Add var to BoundRegion. Add query to get bound vars for applicable items.

This commit is contained in:
Jack Huey 2020-10-26 14:18:31 -04:00
parent 666859a6f8
commit 6d5efa9f04
53 changed files with 1274 additions and 385 deletions

View file

@ -402,7 +402,7 @@ pub enum TraitBoundModifier {
/// `typeck::collect::compute_bounds` matches these against /// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and /// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`. /// detects `Copy`, `Send` and `Sync`.
#[derive(Debug, HashStable_Generic)] #[derive(Clone, Debug, HashStable_Generic)]
pub enum GenericBound<'hir> { pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier), Trait(PolyTraitRef<'hir>, TraitBoundModifier),
// FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
@ -2556,7 +2556,7 @@ pub enum UseKind {
/// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
/// trait being referred to but just a unique `HirId` that serves as a key /// trait being referred to but just a unique `HirId` that serves as a key
/// within the resolution map. /// within the resolution map.
#[derive(Debug, HashStable_Generic)] #[derive(Clone, Debug, HashStable_Generic)]
pub struct TraitRef<'hir> { pub struct TraitRef<'hir> {
pub path: &'hir Path<'hir>, pub path: &'hir Path<'hir>,
// Don't hash the `ref_id`. It is tracked via the thing it is used to access. // Don't hash the `ref_id`. It is tracked via the thing it is used to access.
@ -2575,7 +2575,7 @@ impl TraitRef<'_> {
} }
} }
#[derive(Debug, HashStable_Generic)] #[derive(Clone, Debug, HashStable_Generic)]
pub struct PolyTraitRef<'hir> { pub struct PolyTraitRef<'hir> {
/// The `'a` in `for<'a> Foo<&'a T>`. /// The `'a` in `for<'a> Foo<&'a T>`.
pub bound_generic_params: &'hir [GenericParam<'hir>], pub bound_generic_params: &'hir [GenericParam<'hir>],

View file

@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
r: ty::Region<'tcx>, r: ty::Region<'tcx>,
) -> ty::Region<'tcx> { ) -> ty::Region<'tcx> {
let var = self.canonical_var(info, r.into()); let var = self.canonical_var(info, r.into());
let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) }; let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) };
let region = ty::ReLateBound(self.binder_index, br); let region = ty::ReLateBound(self.binder_index, br);
self.tcx().mk_region(region) self.tcx().mk_region(region)
} }

View file

@ -439,7 +439,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
// We only allow a `ty::INNERMOST` index in substitutions. // We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(debruijn, ty::INNERMOST); assert_eq!(debruijn, ty::INNERMOST);
opt_values[br.assert_bound_var()] = Some(*original_value); opt_values[br.var] = Some(*original_value);
} }
} }
GenericArgKind::Const(result_value) => { GenericArgKind::Const(result_value) => {

View file

@ -71,11 +71,10 @@ where
if var_values.var_values.is_empty() { if var_values.var_values.is_empty() {
value value
} else { } else {
let fld_r = let fld_r = |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
|br: ty::BoundRegion| match var_values.var_values[br.assert_bound_var()].unpack() { GenericArgKind::Lifetime(l) => l,
GenericArgKind::Lifetime(l) => l, r => bug!("{:?} is a region but value is {:?}", br, r),
r => bug!("{:?} is a region but value is {:?}", br, r), };
};
let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
GenericArgKind::Type(ty) => ty, GenericArgKind::Type(ty) => ty,

View file

@ -70,16 +70,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
ty::ReEmpty(universe) => { ty::ReEmpty(universe) => {
universe.hash_stable(hcx, hasher); universe.hash_stable(hcx, hasher);
} }
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => { ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
db.hash_stable(hcx, hasher); db.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher);
} }
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => { ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => {
db.hash_stable(hcx, hasher); db.hash_stable(hcx, hasher);
def_id.hash_stable(hcx, hasher); def_id.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher);
} }
ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => { ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => {
db.hash_stable(hcx, hasher); db.hash_stable(hcx, hasher);
} }
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {

View file

@ -314,7 +314,8 @@ impl<'tcx> CanonicalVarValues<'tcx> {
tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
} }
GenericArgKind::Lifetime(..) => { GenericArgKind::Lifetime(..) => {
let br = ty::BoundRegion { kind: ty::BrAnon(i) }; let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) };
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
} }
GenericArgKind::Const(ct) => tcx GenericArgKind::Const(ct) => tcx

View file

@ -83,4 +83,6 @@ pub struct ResolveLifetimes {
/// be late-bound if (a) it does NOT appear in a where-clause and /// be late-bound if (a) it does NOT appear in a where-clause and
/// (b) it DOES appear in the arguments. /// (b) it DOES appear in the arguments.
pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>, pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
} }

View file

@ -1290,6 +1290,10 @@ rustc_queries! {
-> Option<Vec<ObjectLifetimeDefault>> { -> Option<Vec<ObjectLifetimeDefault>> {
desc { "looking up lifetime defaults for a region on an item" } desc { "looking up lifetime defaults for a region on an item" }
} }
query late_bound_vars_map(_: LocalDefId)
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {
desc { "looking up late bound vars" }
}
query visibility(def_id: DefId) -> ty::Visibility { query visibility(def_id: DefId) -> ty::Visibility {
eval_always eval_always

View file

@ -810,7 +810,7 @@ impl CanonicalUserType<'tcx> {
ty::ReLateBound(debruijn, br) => { ty::ReLateBound(debruijn, br) => {
// We only allow a `ty::INNERMOST` index in substitutions. // We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(*debruijn, ty::INNERMOST); assert_eq!(*debruijn, ty::INNERMOST);
cvar == br.assert_bound_var() cvar == br.var
} }
_ => false, _ => false,
}, },
@ -2672,6 +2672,17 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> { pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> {
self.object_lifetime_defaults_map(id.owner) self.object_lifetime_defaults_map(id.owner)
} }
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
self.mk_bound_variable_kinds(
self.late_bound_vars_map(id.owner)
.and_then(|map| map.get(&id.local_id).cloned())
.unwrap_or_else(|| {
bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
})
.iter(),
)
}
} }
impl TyCtxtAt<'tcx> { impl TyCtxtAt<'tcx> {

View file

@ -634,6 +634,42 @@ impl<'tcx> TyCtxt<'tcx> {
.0 .0
} }
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
self.replace_escaping_bound_vars(
value,
|r| {
self.mk_region(ty::ReLateBound(
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars),
kind: r.kind,
},
))
},
|t| {
self.mk_ty(ty::Bound(
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars),
kind: t.kind,
},
))
},
|c, ty| {
self.mk_const(ty::Const {
val: ty::ConstKind::Bound(
ty::INNERMOST,
ty::BoundVar::from_usize(c.as_usize() + bound_vars),
),
ty,
})
},
)
}
/// Returns a set of all late-bound regions that are constrained /// Returns a set of all late-bound regions that are constrained
/// by `value`, meaning that if we instantiate those LBR with /// by `value`, meaning that if we instantiate those LBR with
/// variables and equate `value` with something else, those /// variables and equate `value` with something else, those
@ -695,16 +731,21 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
let mut counter = 0; let mut counter = 0;
Binder::bind( let inner = self
self.replace_late_bound_regions(sig, |_| { .replace_late_bound_regions(sig, |_| {
let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),
kind: ty::BrAnon(counter),
};
let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
counter += 1; counter += 1;
r r
}) })
.0, .0;
self, let bound_vars = self.mk_bound_variable_kinds(
) (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
);
Binder::bind_with_vars(inner, bound_vars)
} }
} }
@ -777,27 +818,105 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
use std::collections::btree_map::Entry;
match r { match r {
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::ReLateBound(index, _br) if *index == self.binder_index => {
ty::BrNamed(_def_id, _name) => { bug!("{:?} {:?}", index, _br)
// FIXME }
}
ty::BrAnon(var) => match self.vars.entry(var) { _ => (),
Entry::Vacant(entry) => { };
entry.insert(ty::BoundVariableKind::Region(br.kind));
r.super_visit_with(self)
}
}
pub struct ValidateBoundVars<'tcx> {
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
binder_index: ty::DebruijnIndex,
// We may encounter the same variable at different levels of binding, so
// this can't just be `Ty`
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
}
impl<'tcx> ValidateBoundVars<'tcx> {
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
ValidateBoundVars {
bound_vars,
binder_index: ty::INNERMOST,
visited: SsoHashSet::default(),
}
}
}
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = ();
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.binder_index.shift_in(1);
let result = t.super_visit_with(self);
self.binder_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.outer_exclusive_binder < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
return ControlFlow::BREAK;
}
match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
if self.bound_vars.len() <= bound_ty.var.as_usize() {
panic!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
}
let list_var = self.bound_vars[bound_ty.var.as_usize()];
match list_var {
ty::BoundVariableKind::Ty(kind) => {
if kind != bound_ty.kind {
panic!(
"Mismatched type kinds: {:?} doesn't var in list {:?}",
bound_ty.kind, list_var
);
}
} }
Entry::Occupied(entry) => match entry.get() { _ => panic!(
ty::BoundVariableKind::Region(_) => {} "Mismatched bound variable kinds! Expected type, found {:?}",
_ => bug!("Conflicting bound vars"), list_var
}, ),
},
ty::BrEnv => {
// FIXME
} }
}, }
_ => (),
};
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match r {
ty::ReLateBound(index, br) if *index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() {
panic!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars);
}
let list_var = self.bound_vars[br.var.as_usize()];
match list_var {
ty::BoundVariableKind::Region(kind) => {
if kind != br.kind {
panic!(
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
br.kind, list_var, self.bound_vars
);
}
}
_ => panic!(
"Mismatched bound variable kinds! Expected region, found {:?}",
list_var
),
}
}
_ => (), _ => (),
}; };

View file

@ -1,3 +1,4 @@
// ignore-tidy-filelength
use crate::ich::StableHashingContext; use crate::ich::StableHashingContext;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
@ -2481,21 +2482,42 @@ impl<'tcx> ty::Instance<'tcx> {
ty::Closure(def_id, substs) => { ty::Closure(def_id, substs) => {
let sig = substs.as_closure().sig(); let sig = substs.as_closure().sig();
let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); let bound_vars = tcx.mk_bound_variable_kinds(
sig.map_bound(|sig| { sig.bound_vars()
.iter()
.chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
let env_region = ty::ReLateBound(ty::INNERMOST, br);
let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
let sig = sig.skip_binder();
ty::Binder::bind_with_vars(
tcx.mk_fn_sig( tcx.mk_fn_sig(
iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), iter::once(env_ty).chain(sig.inputs().iter().cloned()),
sig.output(), sig.output(),
sig.c_variadic, sig.c_variadic,
sig.unsafety, sig.unsafety,
sig.abi, sig.abi,
) ),
}) bound_vars,
)
} }
ty::Generator(_, substs, _) => { ty::Generator(_, substs, _) => {
let sig = substs.as_generator().poly_sig(); let sig = substs.as_generator().poly_sig();
let br = ty::BoundRegion { kind: ty::BrEnv }; let bound_vars = tcx.mk_bound_variable_kinds(
sig.bound_vars()
.iter()
.chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
let env_region = ty::ReLateBound(ty::INNERMOST, br); let env_region = ty::ReLateBound(ty::INNERMOST, br);
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
@ -2504,21 +2526,21 @@ impl<'tcx> ty::Instance<'tcx> {
let pin_substs = tcx.intern_substs(&[env_ty.into()]); let pin_substs = tcx.intern_substs(&[env_ty.into()]);
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
sig.map_bound(|sig| { let sig = sig.skip_binder();
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
let state_adt_ref = tcx.adt_def(state_did); let state_adt_ref = tcx.adt_def(state_did);
let state_substs = let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); ty::Binder::bind_with_vars(
tcx.mk_fn_sig( tcx.mk_fn_sig(
[env_ty, sig.resume_ty].iter(), [env_ty, sig.resume_ty].iter(),
&ret_ty, &ret_ty,
false, false,
hir::Unsafety::Normal, hir::Unsafety::Normal,
rustc_target::spec::abi::Abi::Rust, rustc_target::spec::abi::Abi::Rust,
) ),
}) bound_vars,
)
} }
_ => bug!("unexpected type {:?} in Instance::fn_sig", ty), _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
} }

View file

@ -543,10 +543,33 @@ impl<'tcx> Predicate<'tcx> {
// substitution code expects equal binding levels in the values // substitution code expects equal binding levels in the values
// from the substitution and the value being substituted into, and // from the substitution and the value being substituted into, and
// this trick achieves that). // this trick achieves that).
let substs = trait_ref.skip_binder().substs;
let pred = self.kind().skip_binder(); // Working through the second example:
let new = pred.subst(tcx, substs); // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0]
tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new, tcx)) // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0]
// We want to end up with:
// for<'x, 'b> T: Bar1<'^0.0, '^0.1>
// To do this:
// 1) We must shift all bound vars in predicate by the length
// of trait ref's bound vars. So, we would end up with predicate like
// Self: Bar1<'a, '^0.1>
// 2) We can then apply the trait substs to this, ending up with
// T: Bar1<'^0.0, '^0.1>
// 3) Finally, to create the final bound vars, we concatenate the bound
// vars of the trait ref with those of the predicate:
// ['x, 'b]
let bound_pred = self.kind();
let pred_bound_vars = bound_pred.bound_vars();
let trait_bound_vars = trait_ref.bound_vars();
// 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
let shifted_pred =
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b]
let bound_vars =
tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars));
tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
} }
} }

View file

@ -1636,7 +1636,7 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
data.name != kw::Empty && data.name != kw::UnderscoreLifetime data.name != kw::Empty && data.name != kw::UnderscoreLifetime
} }
ty::ReLateBound(_, ty::BoundRegion { kind: br }) ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
if let ty::BrNamed(_, name) = br { if let ty::BrNamed(_, name) = br {
@ -1715,7 +1715,7 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
return Ok(self); return Ok(self);
} }
} }
ty::ReLateBound(_, ty::BoundRegion { kind: br }) ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
if let ty::BrNamed(_, name) = br { if let ty::BrNamed(_, name) = br {
@ -1821,7 +1821,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
} }
}; };
self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind })) self.tcx
.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
}); });
start_or_continue(&mut self, "", "> ")?; start_or_continue(&mut self, "", "> ")?;
@ -1865,7 +1866,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>); struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r { if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
self.0.insert(name); self.0.insert(name);
} }
r.super_visit_with(self) r.super_visit_with(self)

View file

@ -6,6 +6,7 @@ use self::TyKind::*;
use crate::infer::canonical::Canonical; use crate::infer::canonical::Canonical;
use crate::ty::fold::BoundVarsCollector; use crate::ty::fold::BoundVarsCollector;
use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::InferTy::{self, *}; use crate::ty::InferTy::{self, *};
use crate::ty::{ use crate::ty::{
@ -63,22 +64,10 @@ pub enum BoundRegionKind {
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
#[derive(HashStable)] #[derive(HashStable)]
pub struct BoundRegion { pub struct BoundRegion {
pub var: BoundVar,
pub kind: BoundRegionKind, pub kind: BoundRegionKind,
} }
impl BoundRegion {
/// When canonicalizing, we replace unbound inference variables and free
/// regions with anonymous late bound regions. This method asserts that
/// we have an anonymous late bound region, which hence may refer to
/// a canonical variable.
pub fn assert_bound_var(&self) -> BoundVar {
match self.kind {
BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var),
_ => bug!("bound region is not anonymous"),
}
}
}
impl BoundRegionKind { impl BoundRegionKind {
pub fn is_named(&self) -> bool { pub fn is_named(&self) -> bool {
match *self { match *self {
@ -987,13 +976,17 @@ where
value.visit_with(&mut collector); value.visit_with(&mut collector);
Binder(value, collector.into_vars(tcx)) Binder(value, collector.into_vars(tcx))
} }
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(vars);
value.visit_with(&mut validator);
}
Binder(value, vars)
}
} }
impl<'tcx, T> Binder<'tcx, T> { impl<'tcx, T> Binder<'tcx, T> {
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
Binder(value, vars)
}
/// Skips the binder and returns the "bound" value. This is a /// Skips the binder and returns the "bound" value. This is a
/// risky thing to do because it's easy to get confused about /// risky thing to do because it's easy to get confused about
/// De Bruijn indices and the like. It is usually better to /// De Bruijn indices and the like. It is usually better to
@ -1022,18 +1015,31 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(&self.0, self.1) Binder(&self.0, self.1)
} }
pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<'tcx, U> pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
let value = f(&self.0);
Binder(value, self.1)
}
pub fn map_bound_ref<F, U: TypeFoldable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
where where
F: FnOnce(&T) -> U, F: FnOnce(&T) -> U,
{ {
self.as_ref().map_bound(f) self.as_ref().map_bound(f)
} }
pub fn map_bound<F, U>(self, f: F) -> Binder<'tcx, U> pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
where where
F: FnOnce(T) -> U, F: FnOnce(T) -> U,
{ {
Binder(f(self.0), self.1) let value = f(self.0);
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.1);
value.visit_with(&mut validator);
}
Binder(value, self.1)
} }
/// Wraps a `value` in a binder, using the same bound variables as the /// Wraps a `value` in a binder, using the same bound variables as the
@ -1045,7 +1051,14 @@ impl<'tcx, T> Binder<'tcx, T> {
/// don't actually track bound vars. However, semantically, it is different /// don't actually track bound vars. However, semantically, it is different
/// because bound vars aren't allowed to change here, whereas they are /// because bound vars aren't allowed to change here, whereas they are
/// in `bind`. This may be (debug) asserted in the future. /// in `bind`. This may be (debug) asserted in the future.
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U> { pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
where
U: TypeFoldable<'tcx>,
{
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.bound_vars());
value.visit_with(&mut validator);
}
Binder(value, self.1) Binder(value, self.1)
} }
@ -1066,20 +1079,6 @@ impl<'tcx, T> Binder<'tcx, T> {
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
} }
/// Given two things that have the same binder level,
/// and an operation that wraps on their contents, executes the operation
/// and then wraps its result.
///
/// `f` should consider bound regions at depth 1 to be free, and
/// anything it produces with bound regions at depth 1 will be
/// bound in the resulting return value.
pub fn fuse<U, F, R>(self, u: Binder<'tcx, U>, f: F) -> Binder<'tcx, R>
where
F: FnOnce(T, U) -> R,
{
Binder(f(self.0, u.0), self.1)
}
/// Splits the contents into two things that share the same binder /// Splits the contents into two things that share the same binder
/// level as the original, returning two distinct binders. /// level as the original, returning two distinct binders.
/// ///
@ -1204,7 +1203,7 @@ pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
impl<'tcx> PolyFnSig<'tcx> { impl<'tcx> PolyFnSig<'tcx> {
#[inline] #[inline]
pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> {
self.map_bound_ref(|fn_sig| fn_sig.inputs()) self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs())
} }
#[inline] #[inline]
pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {

View file

@ -499,18 +499,18 @@ impl<'tcx> TyCtxt<'tcx> {
self, self,
closure_def_id: DefId, closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>, closure_substs: SubstsRef<'tcx>,
) -> Option<ty::Binder<'tcx, Ty<'tcx>>> { env_region: ty::RegionKind,
) -> Option<Ty<'tcx>> {
let closure_ty = self.mk_closure(closure_def_id, closure_substs); let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let br = ty::BoundRegion { kind: ty::BrEnv };
let env_region = ty::ReLateBound(ty::INNERMOST, br);
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),
ty::ClosureKind::FnOnce => closure_ty, ty::ClosureKind::FnOnce => closure_ty,
}; };
Some(ty::Binder::bind(env_ty, self)) Some(env_ty)
} }
/// Returns `true` if the node pointed to by `def_id` is a `static` item. /// Returns `true` if the node pointed to by `def_id` is a `static` item.

View file

@ -502,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// lifetimes without names with the value `'0`. // lifetimes without names with the value `'0`.
match ty.kind() { match ty.kind() {
ty::Ref( ty::Ref(
ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
_, _,
_, _,
@ -523,7 +523,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let region = match ty.kind() { let region = match ty.kind() {
ty::Ref(region, _, _) => { ty::Ref(region, _, _) => {
match region { match region {
ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
printer.region_highlight_mode.highlighting_bound_region(*br, counter) printer.region_highlight_mode.highlighting_bound_region(*br, counter)
} }

View file

@ -596,24 +596,38 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
assert_eq!(self.mir_def.did.to_def_id(), def_id); assert_eq!(self.mir_def.did.to_def_id(), def_id);
let closure_sig = substs.as_closure().sig(); let closure_sig = substs.as_closure().sig();
let inputs_and_output = closure_sig.inputs_and_output(); let inputs_and_output = closure_sig.inputs_and_output();
let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); let bound_vars = tcx.mk_bound_variable_kinds(
ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| { inputs_and_output
// The "inputs" of the closure in the .bound_vars()
// signature appear as a tuple. The MIR side .iter()
// flattens this tuple. .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); );
assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); let br = ty::BoundRegion {
let inputs = match tuplized_inputs[0].kind() { var: ty::BoundVar::from_usize(bound_vars.len() - 1),
ty::Tuple(inputs) => inputs, kind: ty::BrEnv,
_ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), };
}; let env_region = ty::ReLateBound(ty::INNERMOST, br);
let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
// The "inputs" of the closure in the
// signature appear as a tuple. The MIR side
// flattens this tuple.
let (&output, tuplized_inputs) =
inputs_and_output.skip_binder().split_last().unwrap();
assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
let inputs = match tuplized_inputs[0].kind() {
ty::Tuple(inputs) => inputs,
_ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
};
ty::Binder::bind_with_vars(
tcx.mk_type_list( tcx.mk_type_list(
iter::once(closure_ty) iter::once(closure_ty)
.chain(inputs.iter().map(|k| k.expect_ty())) .chain(inputs.iter().map(|k| k.expect_ty()))
.chain(iter::once(output)), .chain(iter::once(output)),
) ),
}) bound_vars,
)
} }
DefiningTy::Generator(def_id, substs, movability) => { DefiningTy::Generator(def_id, substs, movability) => {

View file

@ -252,8 +252,13 @@ fn liberated_closure_env_ty(
_ => bug!("closure expr does not have closure type: {:?}", closure_ty), _ => bug!("closure expr does not have closure type: {:?}", closure_ty),
}; };
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); let bound_vars =
tcx.erase_late_bound_regions(closure_env_ty) tcx.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrEnv)));
let br =
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv };
let env_region = ty::ReLateBound(ty::INNERMOST, br);
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
tcx.erase_late_bound_regions(ty::Binder::bind_with_vars(closure_env_ty, bound_vars))
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]

View file

@ -34,6 +34,7 @@ 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>;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
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,
}
}
}

View file

@ -318,7 +318,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
// Late-bound lifetimes use indices starting at 1, // Late-bound lifetimes use indices starting at 1,
// see `BinderLevel` for more details. // see `BinderLevel` for more details.
ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i) }) => { ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => {
let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
let depth = binder.lifetime_depths.start + i; let depth = binder.lifetime_depths.start + i;

View file

@ -735,7 +735,10 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
.into(), .into(),
ty::GenericParamDefKind::Lifetime => { ty::GenericParamDefKind::Lifetime => {
let br = ty::BoundRegion { kind: ty::BrAnon(substs.len() as u32) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(substs.len()),
kind: ty::BrAnon(substs.len() as u32),
};
tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into() tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into()
} }

View file

@ -434,17 +434,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
ReEarlyBound(_) => { ReEarlyBound(_) => {
panic!("Should have already been substituted."); panic!("Should have already been substituted.");
} }
ReLateBound(db, br) => match br.kind { ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
ty::BoundRegionKind::BrAnon(var) => { chalk_ir::DebruijnIndex::new(db.as_u32()),
chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( br.var.as_usize(),
chalk_ir::DebruijnIndex::new(db.as_u32()), ))
var as usize, .intern(interner),
))
.intern(interner)
}
ty::BoundRegionKind::BrNamed(_def_id, _name) => unimplemented!(),
ty::BrEnv => unimplemented!(),
},
ReFree(_) => unimplemented!(), ReFree(_) => unimplemented!(),
ReStatic => chalk_ir::LifetimeData::Static.intern(interner), ReStatic => chalk_ir::LifetimeData::Static.intern(interner),
ReVar(_) => unimplemented!(), ReVar(_) => unimplemented!(),
@ -467,7 +461,10 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
let kind = match self.data(interner) { let kind = match self.data(interner) {
chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound( chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound(
ty::DebruijnIndex::from_u32(var.debruijn.depth()), ty::DebruijnIndex::from_u32(var.debruijn.depth()),
ty::BoundRegion { kind: ty::BrAnon(var.index as u32) }, ty::BoundRegion {
var: ty::BoundVar::from_usize(var.index),
kind: ty::BrAnon(var.index as u32),
},
), ),
chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
chalk_ir::LifetimeData::Placeholder(p) => { chalk_ir::LifetimeData::Placeholder(p) => {
@ -900,7 +897,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
}, },
}, },
ty::BrEnv => unimplemented!(), ty::BoundRegionKind::BrEnv => unimplemented!(),
}, },
ty::ReEarlyBound(_re) => { ty::ReEarlyBound(_re) => {
@ -948,7 +945,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
Some(idx) => { Some(idx) => {
let new_br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)); return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br));
} }
None => panic!("Missing `BrNamed`."), None => panic!("Missing `BrNamed`."),
@ -1031,12 +1028,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
// This covers any region variables in a goal, right? // This covers any region variables in a goal, right?
ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) { ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) {
Some(idx) => { Some(idx) => {
let br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(*idx),
kind: ty::BrAnon(*idx),
};
self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
} }
None => { None => {
let idx = self.named_regions.len() as u32; let idx = self.named_regions.len() as u32;
let br = ty::BoundRegion { kind: ty::BrAnon(idx) }; let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
self.named_regions.insert(_re.def_id, idx); self.named_regions.insert(_re.def_id, idx);
self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
} }

View file

@ -166,7 +166,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
parent_substs: &[subst::GenericArg<'tcx>], parent_substs: &[subst::GenericArg<'tcx>],
has_self: bool, has_self: bool,
self_ty: Option<Ty<'tcx>>, self_ty: Option<Ty<'tcx>>,
arg_count: GenericArgCountResult, arg_count: &GenericArgCountResult,
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
) -> SubstsRef<'tcx> { ) -> SubstsRef<'tcx> {
// Collect the segments of the path; we need to substitute arguments // Collect the segments of the path; we need to substitute arguments

View file

@ -210,14 +210,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let r = match tcx.named_region(lifetime.hir_id) { let r = match tcx.named_region(lifetime.hir_id) {
Some(rl::Region::Static) => tcx.lifetimes.re_static, Some(rl::Region::Static) => tcx.lifetimes.re_static,
Some(rl::Region::LateBound(debruijn, _, id, _)) => { Some(rl::Region::LateBound(debruijn, index, def_id, _)) => {
let name = lifetime_name(id.expect_local()); let name = lifetime_name(def_id.expect_local());
let br = ty::BoundRegion { kind: ty::BrNamed(id, name) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
kind: ty::BrNamed(def_id, name),
};
tcx.mk_region(ty::ReLateBound(debruijn, br)) tcx.mk_region(ty::ReLateBound(debruijn, br))
} }
Some(rl::Region::LateBoundAnon(debruijn, _index, anon_index)) => { Some(rl::Region::LateBoundAnon(debruijn, index, anon_index)) => {
let br = ty::BoundRegion { kind: ty::BrAnon(anon_index) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
kind: ty::BrAnon(anon_index),
};
tcx.mk_region(ty::ReLateBound(debruijn, br)) tcx.mk_region(ty::ReLateBound(debruijn, br))
} }
@ -266,7 +272,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
def_id: DefId, def_id: DefId,
item_segment: &hir::PathSegment<'_>, item_segment: &hir::PathSegment<'_>,
) -> SubstsRef<'tcx> { ) -> SubstsRef<'tcx> {
let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( let (substs, _) = self.create_substs_for_ast_path(
span, span,
def_id, def_id,
&[], &[],
@ -275,6 +281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment.infer_args, item_segment.infer_args,
None, None,
); );
let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
if let Some(b) = assoc_bindings.first() { if let Some(b) = assoc_bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@ -314,6 +321,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated /// `[Vec<u8>, u8]` and `generic_args` are the arguments for the associated
/// type itself: `['a]`. The returned `SubstsRef` concatenates these two /// type itself: `['a]`. The returned `SubstsRef` concatenates these two
/// lists: `[Vec<u8>, u8, 'a]`. /// lists: `[Vec<u8>, u8, 'a]`.
#[tracing::instrument(level = "debug", skip(self, span))]
fn create_substs_for_ast_path<'a>( fn create_substs_for_ast_path<'a>(
&self, &self,
span: Span, span: Span,
@ -323,15 +331,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generic_args: &'a hir::GenericArgs<'_>, generic_args: &'a hir::GenericArgs<'_>,
infer_args: bool, infer_args: bool,
self_ty: Option<Ty<'tcx>>, self_ty: Option<Ty<'tcx>>,
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) { ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
// If the type is parameterized by this region, then replace this // If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words, // region with the current anon region binding (in other words,
// whatever & would get replaced with). // whatever & would get replaced with).
debug!(
"create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
generic_args={:?})",
def_id, self_ty, generic_args
);
let tcx = self.tcx(); let tcx = self.tcx();
let generics = tcx.generics_of(def_id); let generics = tcx.generics_of(def_id);
@ -367,7 +370,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// here and so associated type bindings will be handled regardless of whether there are any // here and so associated type bindings will be handled regardless of whether there are any
// non-`Self` generic parameters. // non-`Self` generic parameters.
if generics.params.len() == 0 { if generics.params.len() == 0 {
return (tcx.intern_substs(&[]), vec![], arg_count); return (tcx.intern_substs(&[]), arg_count);
} }
let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self); let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self);
@ -540,7 +543,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
parent_substs, parent_substs,
self_ty.is_some(), self_ty.is_some(),
self_ty, self_ty,
arg_count.clone(), &arg_count,
&mut substs_ctx, &mut substs_ctx,
); );
@ -551,6 +554,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generic_args.args.is_empty(), generic_args.args.is_empty(),
); );
debug!(
"create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
generics, self_ty, substs
);
(substs, arg_count)
}
fn create_assoc_bindings_for_generic_args<'a>(
&self,
generic_args: &'a hir::GenericArgs<'_>,
) -> Vec<ConvertedBinding<'a, 'tcx>> {
// Convert associated-type bindings or constraints into a separate vector. // Convert associated-type bindings or constraints into a separate vector.
// Example: Given this: // Example: Given this:
// //
@ -581,12 +596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}) })
.collect(); .collect();
debug!( assoc_bindings
"create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
generics, self_ty, substs
);
(substs, assoc_bindings, arg_count)
} }
crate fn create_substs_for_associated_item( crate fn create_substs_for_associated_item(
@ -636,55 +646,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) )
} }
/// The given trait-ref must actually be a trait.
pub(super) fn instantiate_poly_trait_ref_inner(
&self,
trait_ref: &hir::TraitRef<'_>,
span: Span,
constness: Constness,
self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>,
speculative: bool,
) -> GenericArgCountResult {
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
trait_ref.path.span,
trait_def_id,
self_ty,
trait_ref.path.segments.last().unwrap(),
);
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs), self.tcx());
bounds.trait_bounds.push((poly_trait_ref, span, constness));
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {
// Specify type to assert that error was already reported in `Err` case.
let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
trait_ref.hir_ref_id,
poly_trait_ref,
binding,
bounds,
speculative,
&mut dup_bindings,
binding.span,
);
// Okay to ignore `Err` because of `ErrorReported` (see above).
}
debug!(
"instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
trait_ref, bounds, poly_trait_ref
);
arg_count
}
/// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
/// a full trait reference. The resulting trait reference is returned. This may also generate /// a full trait reference. The resulting trait reference is returned. This may also generate
/// auxiliary bounds, which are added to `bounds`. /// auxiliary bounds, which are added to `bounds`.
@ -704,21 +665,55 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be
/// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
/// however. /// however.
#[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
pub fn instantiate_poly_trait_ref( pub fn instantiate_poly_trait_ref(
&self, &self,
poly_trait_ref: &hir::PolyTraitRef<'_>, trait_ref: &hir::TraitRef<'_>,
span: Span,
constness: Constness, constness: Constness,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
speculative: bool,
) -> GenericArgCountResult { ) -> GenericArgCountResult {
self.instantiate_poly_trait_ref_inner( let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
&poly_trait_ref.trait_ref,
poly_trait_ref.span, self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
constness,
let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
debug!(?bound_vars);
let (substs, arg_count) = self.create_substs_for_ast_trait_ref(
trait_ref.path.span,
trait_def_id,
self_ty, self_ty,
bounds, trait_ref.path.segments.last().unwrap(),
false, );
) let assoc_bindings = self
.create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args());
let poly_trait_ref =
ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
debug!(?poly_trait_ref, ?assoc_bindings);
bounds.trait_bounds.push((poly_trait_ref, span, constness));
let mut dup_bindings = FxHashMap::default();
for binding in &assoc_bindings {
// Specify type to assert that error was already reported in `Err` case.
let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
trait_ref.hir_ref_id,
poly_trait_ref,
binding,
bounds,
speculative,
&mut dup_bindings,
binding.span,
);
// Okay to ignore `Err` because of `ErrorReported` (see above).
}
arg_count
} }
pub fn instantiate_lang_item_trait_ref( pub fn instantiate_lang_item_trait_ref(
@ -732,7 +727,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) { ) {
let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( let (substs, _) = self.create_substs_for_ast_path(
span, span,
trait_def_id, trait_def_id,
&[], &[],
@ -741,7 +736,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
false, false,
Some(self_ty), Some(self_ty),
); );
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs), self.tcx()); let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(hir_id);
let poly_trait_ref =
ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst)); bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
let mut dup_bindings = FxHashMap::default(); let mut dup_bindings = FxHashMap::default();
@ -765,23 +764,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>, trait_segment: &hir::PathSegment<'_>,
) -> ty::TraitRef<'tcx> { ) -> ty::TraitRef<'tcx> {
let (substs, assoc_bindings, _) = let (substs, _) =
self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment);
let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args());
if let Some(b) = assoc_bindings.first() { if let Some(b) = assoc_bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span); Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
} }
ty::TraitRef::new(trait_def_id, substs) ty::TraitRef::new(trait_def_id, substs)
} }
#[tracing::instrument(level = "debug", skip(self, span))]
fn create_substs_for_ast_trait_ref<'a>( fn create_substs_for_ast_trait_ref<'a>(
&self, &self,
span: Span, span: Span,
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
trait_segment: &'a hir::PathSegment<'a>, trait_segment: &'a hir::PathSegment<'a>,
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) { ) -> (SubstsRef<'tcx>, GenericArgCountResult) {
debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
self.create_substs_for_ast_path( self.create_substs_for_ast_path(
@ -803,7 +802,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
// Returns `true` if a bounds list includes `?Sized`. // Returns `true` if a bounds list includes `?Sized`.
pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool { pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
let tcx = self.tcx(); let tcx = self.tcx();
// Try to find an unbound in bounds. // Try to find an unbound in bounds.
@ -858,28 +857,44 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// **A note on binders:** there is an implied binder around /// **A note on binders:** there is an implied binder around
/// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
/// for more details. /// for more details.
#[tracing::instrument(level = "debug", skip(self, bounds))]
fn add_bounds( fn add_bounds(
&self, &self,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
ast_bounds: &[&hir::GenericBound<'_>], ast_bounds: &[hir::GenericBound<'_>],
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
) { ) {
let constness = self.default_constness_for_trait_bounds(); let constness = self.default_constness_for_trait_bounds();
for ast_bound in ast_bounds { for ast_bound in ast_bounds {
match *ast_bound { match *ast_bound {
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
self.instantiate_poly_trait_ref(b, constness, param_ty, bounds); self.instantiate_poly_trait_ref(
&b.trait_ref,
b.span,
constness,
param_ty,
bounds,
false,
);
} }
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
self.instantiate_poly_trait_ref(b, Constness::NotConst, param_ty, bounds); self.instantiate_poly_trait_ref(
&b.trait_ref,
b.span,
Constness::NotConst,
param_ty,
bounds,
false,
);
} }
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
.instantiate_lang_item_trait_ref( .instantiate_lang_item_trait_ref(
*lang_item, *span, *hir_id, args, param_ty, bounds, lang_item, span, hir_id, args, param_ty, bounds,
), ),
hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push((
ty::Binder::bind(self.ast_region_to_region(l, None), self.tcx()), ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars),
l.span, l.span,
)), )),
} }
@ -909,7 +924,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
sized_by_default: SizedByDefault, sized_by_default: SizedByDefault,
span: Span, span: Span,
) -> Bounds<'tcx> { ) -> Bounds<'tcx> {
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
} }
@ -929,7 +943,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(trait_ref) = ast_bound.trait_ref() { if let Some(trait_ref) = ast_bound.trait_ref() {
if let Some(trait_did) = trait_ref.trait_def_id() { if let Some(trait_did) = trait_ref.trait_def_id() {
if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
result.push(ast_bound); result.push(ast_bound.clone());
} }
} }
} }
@ -941,13 +955,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
fn compute_bounds_inner( fn compute_bounds_inner(
&self, &self,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
ast_bounds: &[&hir::GenericBound<'_>], ast_bounds: &[hir::GenericBound<'_>],
sized_by_default: SizedByDefault, sized_by_default: SizedByDefault,
span: Span, span: Span,
) -> Bounds<'tcx> { ) -> Bounds<'tcx> {
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
self.add_bounds(param_ty, ast_bounds, &mut bounds); self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
@ -964,6 +978,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the
/// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside*
/// the binder (e.g., `&'a u32`) and hence may reference bound regions. /// the binder (e.g., `&'a u32`) and hence may reference bound regions.
#[tracing::instrument(
level = "debug",
skip(self, bounds, speculative, dup_bindings, path_span)
)]
fn add_predicates_for_ast_type_binding( fn add_predicates_for_ast_type_binding(
&self, &self,
hir_ref_id: hir::HirId, hir_ref_id: hir::HirId,
@ -990,7 +1008,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// //
// We want to produce `<B as SuperTrait<i32>>::T == foo`. // We want to produce `<B as SuperTrait<i32>>::T == foo`.
debug!(?hir_ref_id, ?trait_ref, ?binding, ?bounds, "add_predicates_for_ast_type_binding",);
let tcx = self.tcx(); let tcx = self.tcx();
let candidate = let candidate =
@ -1140,10 +1157,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// //
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder. // parameter to have a skipped binder.
let param_ty = let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs); self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars());
let ast_bounds: Vec<_> = ast_bounds.iter().collect();
self.add_bounds(param_ty, &ast_bounds, bounds);
} }
} }
Ok(()) Ok(())
@ -1177,10 +1192,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
.. ..
} = self.instantiate_poly_trait_ref( } = self.instantiate_poly_trait_ref(
trait_bound, &trait_bound.trait_ref,
trait_bound.span,
Constness::NotConst, Constness::NotConst,
dummy_self, dummy_self,
&mut bounds, &mut bounds,
false,
) { ) {
potential_assoc_types.extend(cur_potential_assoc_types); potential_assoc_types.extend(cur_potential_assoc_types);
} }
@ -2169,12 +2186,13 @@ 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))]
@ -2200,6 +2218,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
tcx.mk_fn_ptr(self.ty_of_fn( tcx.mk_fn_ptr(self.ty_of_fn(
ast_ty.hir_id,
bf.unsafety, bf.unsafety,
bf.abi, bf.abi,
&bf.decl, &bf.decl,
@ -2242,7 +2261,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} }
hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => {
let def_id = tcx.require_lang_item(lang_item, Some(span)); let def_id = tcx.require_lang_item(lang_item, Some(span));
let (substs, _, _) = self.create_substs_for_ast_path( let (substs, _) = self.create_substs_for_ast_path(
span, span,
def_id, def_id,
&[], &[],
@ -2279,7 +2298,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
result_ty result_ty
} }
pub fn impl_trait_ty_to_ty( fn impl_trait_ty_to_ty(
&self, &self,
def_id: DefId, def_id: DefId,
lifetimes: &[hir::GenericArg<'_>], lifetimes: &[hir::GenericArg<'_>],
@ -2340,6 +2359,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
pub fn ty_of_fn( pub fn ty_of_fn(
&self, &self,
hir_id: hir::HirId,
unsafety: hir::Unsafety, unsafety: hir::Unsafety,
abi: abi::Abi, abi: abi::Abi,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
@ -2350,6 +2370,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("ty_of_fn"); debug!("ty_of_fn");
let tcx = self.tcx(); let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(hir_id);
debug!(?bound_vars);
// We proactively collect all the inferred type params to emit a single error per fn def. // We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = PlaceholderHirTyCollector::default(); let mut visitor = PlaceholderHirTyCollector::default();
@ -2369,10 +2391,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("ty_of_fn: output_ty={:?}", output_ty); debug!("ty_of_fn: output_ty={:?}", output_ty);
let bare_fn_ty = ty::Binder::bind( let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi);
tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi), let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
tcx,
);
if !self.allow_ty_infer() { if !self.allow_ty_infer() {
// We always collect the spans for placeholder types when evaluating `fn`s, but we // We always collect the spans for placeholder types when evaluating `fn`s, but we

View file

@ -69,7 +69,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id);
let ClosureSignatures { bound_sig, liberated_sig } = let ClosureSignatures { bound_sig, liberated_sig } =
self.sig_of_closure(expr_def_id.to_def_id(), decl, body, expected_sig); self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig);
debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); debug!("check_closure: ty_of_closure returns {:?}", liberated_sig);
@ -288,15 +288,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn sig_of_closure( fn sig_of_closure(
&self, &self,
hir_id: hir::HirId,
expr_def_id: DefId, expr_def_id: DefId,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
body: &hir::Body<'_>, body: &hir::Body<'_>,
expected_sig: Option<ExpectedSig<'tcx>>, expected_sig: Option<ExpectedSig<'tcx>>,
) -> ClosureSignatures<'tcx> { ) -> ClosureSignatures<'tcx> {
if let Some(e) = expected_sig { if let Some(e) = expected_sig {
self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e)
} else { } else {
self.sig_of_closure_no_expectation(expr_def_id, decl, body) self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body)
} }
} }
@ -304,13 +305,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// types that the user gave into a signature. /// types that the user gave into a signature.
fn sig_of_closure_no_expectation( fn sig_of_closure_no_expectation(
&self, &self,
hir_id: hir::HirId,
expr_def_id: DefId, expr_def_id: DefId,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
body: &hir::Body<'_>, body: &hir::Body<'_>,
) -> ClosureSignatures<'tcx> { ) -> ClosureSignatures<'tcx> {
debug!("sig_of_closure_no_expectation()"); debug!("sig_of_closure_no_expectation()");
let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body);
self.closure_sigs(expr_def_id, body, bound_sig) self.closure_sigs(expr_def_id, body, bound_sig)
} }
@ -364,6 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// regions with depth 1, which are bound then by the closure. /// regions with depth 1, which are bound then by the closure.
fn sig_of_closure_with_expectation( fn sig_of_closure_with_expectation(
&self, &self,
hir_id: hir::HirId,
expr_def_id: DefId, expr_def_id: DefId,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
body: &hir::Body<'_>, body: &hir::Body<'_>,
@ -375,7 +378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// expectation if things don't see to match up with what we // expectation if things don't see to match up with what we
// expect. // expect.
if expected_sig.sig.c_variadic() != decl.c_variadic { if expected_sig.sig.c_variadic() != decl.c_variadic {
return self.sig_of_closure_no_expectation(expr_def_id, decl, body); return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body);
} else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 {
return self.sig_of_closure_with_mismatched_number_of_arguments( return self.sig_of_closure_with_mismatched_number_of_arguments(
expr_def_id, expr_def_id,
@ -411,9 +414,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Along the way, it also writes out entries for types that the user // Along the way, it also writes out entries for types that the user
// wrote into our typeck results, which are then later used by the privacy // wrote into our typeck results, which are then later used by the privacy
// check. // check.
match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { match self.check_supplied_sig_against_expectation(
hir_id,
expr_def_id,
decl,
body,
&closure_sigs,
) {
Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), Err(_) => return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body),
} }
closure_sigs closure_sigs
@ -460,6 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// strategy. /// strategy.
fn check_supplied_sig_against_expectation( fn check_supplied_sig_against_expectation(
&self, &self,
hir_id: hir::HirId,
expr_def_id: DefId, expr_def_id: DefId,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
body: &hir::Body<'_>, body: &hir::Body<'_>,
@ -469,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// //
// (See comment on `sig_of_closure_with_expectation` for the // (See comment on `sig_of_closure_with_expectation` for the
// meaning of these letters.) // meaning of these letters.)
let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body);
debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig);
@ -534,6 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Also, record this closure signature for later. /// Also, record this closure signature for later.
fn supplied_sig_of_closure( fn supplied_sig_of_closure(
&self, &self,
hir_id: hir::HirId,
expr_def_id: DefId, expr_def_id: DefId,
decl: &hir::FnDecl<'_>, decl: &hir::FnDecl<'_>,
body: &hir::Body<'_>, body: &hir::Body<'_>,
@ -545,6 +556,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
decl, body.generator_kind, decl, body.generator_kind,
); );
let bound_vars = self.tcx.late_bound_vars(hir_id);
// First, convert the types that the user supplied (if any). // First, convert the types that the user supplied (if any).
let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
let supplied_return = match decl.output { let supplied_return = match decl.output {
@ -571,7 +584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}, },
}; };
let result = ty::Binder::bind( let result = ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig( self.tcx.mk_fn_sig(
supplied_arguments, supplied_arguments,
supplied_return, supplied_return,
@ -579,7 +592,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Unsafety::Normal, hir::Unsafety::Normal,
Abi::RustCall, Abi::RustCall,
), ),
self.tcx, bound_vars,
); );
debug!("supplied_sig_of_closure: result={:?}", result); debug!("supplied_sig_of_closure: result={:?}", result);

View file

@ -1462,7 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&[][..], &[][..],
has_self, has_self,
self_ty, self_ty,
arg_count, &arg_count,
&mut CreateCtorSubstsContext { &mut CreateCtorSubstsContext {
fcx: self, fcx: self,
span, span,

View file

@ -186,7 +186,10 @@ pub fn resolve_interior<'a, 'tcx>(
// which means that none of the regions inside relate to any other, even if // which means that none of the regions inside relate to any other, even if
// typeck had previously found constraints that would cause them to be related. // typeck had previously found constraints that would cause them to be related.
let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| { let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| {
let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),
kind: ty::BrAnon(counter),
};
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
counter += 1; counter += 1;
r r
@ -202,11 +205,15 @@ pub fn resolve_interior<'a, 'tcx>(
// Extract type components to build the witness type. // Extract type components to build the witness type.
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list, fcx.tcx)); let bound_vars = fcx.tcx.mk_bound_variable_kinds(
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))),
);
let witness =
fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
// Store the generator types and spans into the typeck results for this generator. // Store the generator types and spans into the typeck results for this generator.
visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types = visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types =
ty::Binder::bind(type_causes, fcx.tcx); ty::Binder::bind_with_vars(type_causes, bound_vars);
debug!( debug!(
"types in generator after region replacement {:?}, span = {:?}", "types in generator after region replacement {:?}, span = {:?}",

View file

@ -101,12 +101,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let intrinsic_name = tcx.item_name(it.def_id.to_def_id()); let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
let name_str = intrinsic_name.as_str(); let name_str = intrinsic_name.as_str();
let bound_vars = tcx.mk_bound_variable_kinds(
[ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
.iter()
.copied(),
);
let mk_va_list_ty = |mutbl| { let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| { tcx.lang_items().va_list().map(|did| {
let region = tcx let region = tcx.mk_region(ty::ReLateBound(
.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) })); ty::INNERMOST,
let env_region = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) },
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv })); ));
let env_region = tcx.mk_region(ty::ReLateBound(
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
));
let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
(tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
}) })
@ -305,7 +314,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
let br = ty::BoundRegion { kind: ty::BrAnon(0) }; let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
( (
1, 1,
vec![ vec![
@ -366,7 +375,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
(n_tps, inputs, output, unsafety) (n_tps, inputs, output, unsafety)
}; };
let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
let sig = ty::Binder::bind(sig, tcx); let sig = ty::Binder::bind_with_vars(sig, bound_vars);
equate_intrinsic_type(tcx, it, n_tps, sig) equate_intrinsic_type(tcx, it, n_tps, sig)
} }

View file

@ -381,7 +381,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
parent_substs, parent_substs,
false, false,
None, None,
arg_count_correct, &arg_count_correct,
&mut MethodSubstsCtxt { cfcx: self, pick, seg }, &mut MethodSubstsCtxt { cfcx: self, pick, seg },
) )
} }

View file

@ -497,6 +497,7 @@ fn typeck_with_fallback<'tcx>(
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
<dyn AstConv<'_>>::ty_of_fn( <dyn AstConv<'_>>::ty_of_fn(
&fcx, &fcx,
id,
header.unsafety, header.unsafety,
header.abi, header.abi,
decl, decl,

View file

@ -1712,6 +1712,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
} }
None => <dyn AstConv<'_>>::ty_of_fn( None => <dyn AstConv<'_>>::ty_of_fn(
&icx, &icx,
hir_id,
sig.header.unsafety, sig.header.unsafety,
sig.header.abi, sig.header.abi,
&sig.decl, &sig.decl,
@ -1729,6 +1730,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
.. ..
}) => <dyn AstConv<'_>>::ty_of_fn( }) => <dyn AstConv<'_>>::ty_of_fn(
&icx, &icx,
hir_id,
header.unsafety, header.unsafety,
header.abi, header.abi,
decl, decl,
@ -2082,6 +2084,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
match predicate { match predicate {
hir::WherePredicate::BoundPredicate(bound_pred) => { hir::WherePredicate::BoundPredicate(bound_pred) => {
let ty = icx.to_ty(&bound_pred.bounded_ty); let ty = icx.to_ty(&bound_pred.bounded_ty);
let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id);
// Keep the type around in a dummy predicate, in case of no bounds. // Keep the type around in a dummy predicate, in case of no bounds.
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty` // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
@ -2097,12 +2100,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
} else { } else {
let span = bound_pred.bounded_ty.span; let span = bound_pred.bounded_ty.span;
let re_root_empty = tcx.lifetimes.re_root_empty; let re_root_empty = tcx.lifetimes.re_root_empty;
let predicate = ty::Binder::bind( let predicate = ty::Binder::bind_with_vars(
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
ty, ty,
re_root_empty, re_root_empty,
)), )),
tcx, bound_vars,
); );
predicates.insert((predicate.to_predicate(tcx), span)); predicates.insert((predicate.to_predicate(tcx), span));
} }
@ -2120,10 +2123,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref( let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
&icx, &icx,
&poly_trait_ref, &poly_trait_ref.trait_ref,
poly_trait_ref.span,
constness, constness,
ty, ty,
&mut bounds, &mut bounds,
false,
); );
predicates.extend(bounds.predicates(tcx, ty)); predicates.extend(bounds.predicates(tcx, ty));
} }
@ -2146,11 +2151,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
let region = let region =
<dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None); <dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
predicates.insert(( predicates.insert((
ty::Binder::bind( ty::Binder::bind_with_vars(
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
ty, region, ty, region,
)), )),
tcx, bound_vars,
) )
.to_predicate(tcx), .to_predicate(tcx),
lifetime.span, lifetime.span,
@ -2373,7 +2378,14 @@ fn predicates_from_bound<'tcx>(
}; };
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds); let _ = astconv.instantiate_poly_trait_ref(
&tr.trait_ref,
tr.span,
constness,
param_ty,
&mut bounds,
false,
);
bounds.predicates(astconv.tcx(), param_ty) bounds.predicates(astconv.tcx(), param_ty)
} }
hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
@ -2409,8 +2421,10 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
} else { } else {
hir::Unsafety::Unsafe hir::Unsafety::Unsafe
}; };
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let fty = <dyn AstConv<'_>>::ty_of_fn( let fty = <dyn AstConv<'_>>::ty_of_fn(
&ItemCtxt::new(tcx, def_id), &ItemCtxt::new(tcx, def_id),
hir_id,
unsafety, unsafety,
abi, abi,
decl, decl,

View file

@ -430,7 +430,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id); let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id);
let env_def_id = tcx.hir().local_def_id(env_node_id); let env_def_id = tcx.hir().local_def_id(env_node_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
item_cx.to_ty(hir_ty) AstConv::ast_ty_to_ty(&item_cx, hir_ty)
} }
pub fn hir_trait_to_predicates<'tcx>( pub fn hir_trait_to_predicates<'tcx>(
@ -445,7 +445,7 @@ pub fn hir_trait_to_predicates<'tcx>(
let env_def_id = tcx.hir().local_def_id(env_hir_id); let env_def_id = tcx.hir().local_def_id(env_hir_id);
let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id());
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref_inner( let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
&item_cx, &item_cx,
hir_trait, hir_trait,
DUMMY_SP, DUMMY_SP,

View file

@ -411,7 +411,7 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> { fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
match *self { match *self {
ty::ReStatic => Some(Lifetime::statik()), ty::ReStatic => Some(Lifetime::statik()),
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => { ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
Some(Lifetime(name)) Some(Lifetime(name))
} }
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),

View file

@ -97,7 +97,7 @@ fn external_generic_args(
.iter() .iter()
.filter_map(|kind| match kind.unpack() { .filter_map(|kind| match kind.unpack() {
GenericArgKind::Lifetime(lt) => match lt { GenericArgKind::Lifetime(lt) => match lt {
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_) }) => { ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => {
Some(GenericArg::Lifetime(Lifetime::elided())) Some(GenericArg::Lifetime(Lifetime::elided()))
} }
_ => lt.clean(cx).map(GenericArg::Lifetime), _ => lt.clean(cx).map(GenericArg::Lifetime),

View file

@ -118,7 +118,7 @@ pub fn type_parameter<T>() {}
pub fn lifetime_parameter() {} pub fn lifetime_parameter() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of")] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
pub fn lifetime_parameter<'a>() {} pub fn lifetime_parameter<'a>() {}
@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean( #[rustc_clean(
cfg = "cfail2", cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
)] )]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
pub fn lifetime_bound<'a, T: 'a>() {} pub fn lifetime_bound<'a, T: 'a>() {}
@ -183,7 +183,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean( #[rustc_clean(
cfg = "cfail2", cfg = "cfail2",
except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
)] )]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}

View file

@ -312,7 +312,7 @@ impl Foo {
// if we lower generics before the body, then the `HirId` for // if we lower generics before the body, then the `HirId` for
// things in the body will be affected. So if you start to see // things in the body will be affected. So if you start to see
// `typeck` appear dirty, that might be the cause. -nmatsakis // `typeck` appear dirty, that might be the cause. -nmatsakis
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
pub fn add_lifetime_parameter_to_method<'a>(&self) { } pub fn add_lifetime_parameter_to_method<'a>(&self) { }
} }
@ -360,7 +360,7 @@ impl Foo {
impl Foo { impl Foo {
#[rustc_clean( #[rustc_clean(
cfg="cfail2", cfg="cfail2",
except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of" except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
)] )]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
@ -388,7 +388,7 @@ impl Foo {
// body will be affected. So if you start to see `typeck` // body will be affected. So if you start to see `typeck`
// appear dirty, that might be the cause. -nmatsakis // appear dirty, that might be the cause. -nmatsakis
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\
type_of")] type_of,fn_sig")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
} }

View file

@ -0,0 +1,65 @@
// check-pass
#![feature(associated_type_bounds)]
trait A<'a> {}
trait B<'b> {}
fn foo<T>()
where
for<'a> T: A<'a> + 'a,
{
}
trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
type As;
}
struct D<T>
where
T: for<'c> C<'c, As: A<'c>>,
{
t: std::marker::PhantomData<T>,
}
trait E<'e> {
type As;
}
trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {}
struct G<T>
where
for<'f> T: F<'f, As: E<'f>> + 'f,
{
t: std::marker::PhantomData<T>,
}
trait I<'a, 'b, 'c> {
type As;
}
trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {}
fn foo2<T>()
where
T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>,
{
}
fn foo3<T>()
where
T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>,
{
}
fn foo4<T>()
where
T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>,
{
}
struct X<'x, 'y> {
x: std::marker::PhantomData<&'x ()>,
y: std::marker::PhantomData<&'y ()>,
}
fn foo5<T>()
where
T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i>
{
}
fn main() {}

View file

@ -9,12 +9,20 @@ trait C<'c>: for<'a> A<'a> + for<'b> B<'b> {
struct D<T> where T: for<'c> C<'c, As=&'c ()> { struct D<T> where T: for<'c> C<'c, As=&'c ()> {
t: std::marker::PhantomData<T>, t: std::marker::PhantomData<T>,
} }
trait E<'e> { trait E<'e, 'g> {
type As; type As;
} }
trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {} trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {}
struct G<T> where T: for<'f> F<'f, As=&'f ()> { struct G<T> where T: for<'f> F<'f, As=&'f ()> {
t: std::marker::PhantomData<T>, t: std::marker::PhantomData<T>,
} }
trait H<'a, 'b> {
type As;
}
trait I<'a>: for<'b> H<'a, 'b> {}
struct J<T> where T: for<'i> I<'i, As=&'i ()> {
t: std::marker::PhantomData<T>,
}
fn main() {} fn main() {}

View file

@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
| |
= note: defining type: test::{closure#0} with closure substs [ = note: defining type: test::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) i32)), for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)),
(), (),
] ]

View file

@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
| |
= note: defining type: test::{closure#0} with closure substs [ = note: defining type: test::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)), for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)),
(), (),
] ]

View file

@ -10,7 +10,7 @@ LL | | },
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#4r = note: late-bound region is '_#4r

View file

@ -11,7 +11,7 @@ LL | | });
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#3r = note: late-bound region is '_#3r

View file

@ -10,7 +10,7 @@ LL | | })
| |
= note: defining type: case1::{closure#0} with closure substs [ = note: defining type: case1::{closure#0} with closure substs [
i32, i32,
for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
(), (),
] ]
@ -49,7 +49,7 @@ LL | | })
| |
= note: defining type: case2::{closure#0} with closure substs [ = note: defining type: case2::{closure#0} with closure substs [
i32, i32,
for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
(), (),
] ]
= note: number of external vids: 2 = note: number of external vids: 2

View file

@ -12,7 +12,7 @@ LL | | });
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) u32>)), for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#2r = note: late-bound region is '_#2r

View file

@ -12,7 +12,7 @@ LL | | });
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#3r = note: late-bound region is '_#3r

View file

@ -11,7 +11,7 @@ LL | | });
| |
= note: defining type: test::{closure#0} with closure substs [ = note: defining type: test::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#3r = note: late-bound region is '_#3r

View file

@ -10,7 +10,7 @@ LL | | },
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#3r = note: late-bound region is '_#3r

View file

@ -11,7 +11,7 @@ LL | | });
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#2r = note: late-bound region is '_#2r

View file

@ -11,7 +11,7 @@ LL | | });
| |
= note: defining type: supply::{closure#0} with closure substs [ = note: defining type: supply::{closure#0} with closure substs [
i16, i16,
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
(), (),
] ]
= note: late-bound region is '_#3r = note: late-bound region is '_#3r

View file

@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a`
| |
= note: defining type: test::{closure#0} with closure substs [ = note: defining type: test::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32,
(), (),
] ]

View file

@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b));
| |
= note: defining type: generic::<T>::{closure#0} with closure substs [ = note: defining type: generic::<T>::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
(), (),
] ]
= note: number of external vids: 2 = note: number of external vids: 2
@ -31,7 +31,7 @@ LL | twice(cell, value, |a, b| invoke(a, b));
| |
= note: defining type: generic_fail::<T>::{closure#0} with closure substs [ = note: defining type: generic_fail::<T>::{closure#0} with closure substs [
i16, i16,
for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
(), (),
] ]
= note: late-bound region is '_#2r = note: late-bound region is '_#2r