Remove index from Region::EarlyBound.
This commit is contained in:
parent
63c3aabeb8
commit
421bb6ac62
6 changed files with 50 additions and 214 deletions
|
@ -103,7 +103,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
|
||||||
// Find the index of the named region that was part of the
|
// Find the index of the named region that was part of the
|
||||||
// error. We will then search the function parameters for a bound
|
// error. We will then search the function parameters for a bound
|
||||||
// region at the right depth with the same index
|
// region at the right depth with the same index
|
||||||
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
|
(Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
|
||||||
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
|
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
|
||||||
if id == def_id {
|
if id == def_id {
|
||||||
self.found_type = Some(arg);
|
self.found_type = Some(arg);
|
||||||
|
@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
|
||||||
Some(
|
Some(
|
||||||
rl::Region::Static
|
rl::Region::Static
|
||||||
| rl::Region::Free(_, _)
|
| rl::Region::Free(_, _)
|
||||||
| rl::Region::EarlyBound(_, _)
|
| rl::Region::EarlyBound(_)
|
||||||
| rl::Region::LateBound(_, _, _),
|
| rl::Region::LateBound(_, _, _),
|
||||||
)
|
)
|
||||||
| None,
|
| None,
|
||||||
|
@ -188,7 +188,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
|
||||||
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
|
||||||
match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
|
match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
|
||||||
// the lifetime of the TyPath!
|
// the lifetime of the TyPath!
|
||||||
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
|
(Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
|
||||||
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
|
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
|
||||||
if id == def_id {
|
if id == def_id {
|
||||||
self.found_it = true;
|
self.found_it = true;
|
||||||
|
@ -209,7 +209,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
|
||||||
(
|
(
|
||||||
Some(
|
Some(
|
||||||
rl::Region::Static
|
rl::Region::Static
|
||||||
| rl::Region::EarlyBound(_, _)
|
| rl::Region::EarlyBound(_)
|
||||||
| rl::Region::LateBound(_, _, _)
|
| rl::Region::LateBound(_, _, _)
|
||||||
| rl::Region::Free(_, _),
|
| rl::Region::Free(_, _),
|
||||||
)
|
)
|
||||||
|
|
|
@ -2039,13 +2039,13 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN
|
||||||
impl ExplicitOutlivesRequirements {
|
impl ExplicitOutlivesRequirements {
|
||||||
fn lifetimes_outliving_lifetime<'tcx>(
|
fn lifetimes_outliving_lifetime<'tcx>(
|
||||||
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
|
inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
|
||||||
index: u32,
|
def_id: DefId,
|
||||||
) -> Vec<ty::Region<'tcx>> {
|
) -> Vec<ty::Region<'tcx>> {
|
||||||
inferred_outlives
|
inferred_outlives
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
|
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
|
||||||
ty::ReEarlyBound(ebr) if ebr.index == index => Some(b),
|
ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -2082,8 +2082,12 @@ impl ExplicitOutlivesRequirements {
|
||||||
.filter_map(|(i, bound)| {
|
.filter_map(|(i, bound)| {
|
||||||
if let hir::GenericBound::Outlives(lifetime) = bound {
|
if let hir::GenericBound::Outlives(lifetime) = bound {
|
||||||
let is_inferred = match tcx.named_region(lifetime.hir_id) {
|
let is_inferred = match tcx.named_region(lifetime.hir_id) {
|
||||||
Some(Region::EarlyBound(index, ..)) => inferred_outlives.iter().any(|r| {
|
Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| {
|
||||||
if let ty::ReEarlyBound(ebr) = **r { ebr.index == index } else { false }
|
if let ty::ReEarlyBound(ebr) = **r {
|
||||||
|
ebr.def_id == def_id
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -2177,11 +2181,14 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
||||||
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
|
for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
|
||||||
let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
|
let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
|
||||||
hir::WherePredicate::RegionPredicate(predicate) => {
|
hir::WherePredicate::RegionPredicate(predicate) => {
|
||||||
if let Some(Region::EarlyBound(index, ..)) =
|
if let Some(Region::EarlyBound(region_def_id)) =
|
||||||
cx.tcx.named_region(predicate.lifetime.hir_id)
|
cx.tcx.named_region(predicate.lifetime.hir_id)
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
Self::lifetimes_outliving_lifetime(inferred_outlives, index),
|
Self::lifetimes_outliving_lifetime(
|
||||||
|
inferred_outlives,
|
||||||
|
region_def_id,
|
||||||
|
),
|
||||||
&predicate.bounds,
|
&predicate.bounds,
|
||||||
predicate.span,
|
predicate.span,
|
||||||
predicate.in_where_clause,
|
predicate.in_where_clause,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_macros::HashStable;
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
|
||||||
pub enum Region {
|
pub enum Region {
|
||||||
Static,
|
Static,
|
||||||
EarlyBound(/* index */ u32, /* lifetime decl */ DefId),
|
EarlyBound(/* lifetime decl */ DefId),
|
||||||
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
|
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
|
||||||
Free(DefId, /* lifetime decl */ DefId),
|
Free(DefId, /* lifetime decl */ DefId),
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ use rustc_span::Span;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
trait RegionExt {
|
trait RegionExt {
|
||||||
fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
||||||
|
|
||||||
fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
||||||
|
|
||||||
|
@ -34,19 +34,13 @@ trait RegionExt {
|
||||||
fn shifted(self, amount: u32) -> Region;
|
fn shifted(self, amount: u32) -> Region;
|
||||||
|
|
||||||
fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
|
fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
|
||||||
|
|
||||||
fn subst<'a, L>(self, params: L, map: &NamedRegionMap) -> Option<Region>
|
|
||||||
where
|
|
||||||
L: Iterator<Item = &'a hir::Lifetime>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegionExt for Region {
|
impl RegionExt for Region {
|
||||||
fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
|
fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
|
||||||
let i = *index;
|
|
||||||
*index += 1;
|
|
||||||
let def_id = hir_map.local_def_id(param.hir_id);
|
let def_id = hir_map.local_def_id(param.hir_id);
|
||||||
debug!("Region::early: index={} def_id={:?}", i, def_id);
|
debug!("Region::early: def_id={:?}", def_id);
|
||||||
(def_id, Region::EarlyBound(i, def_id.to_def_id()))
|
(def_id, Region::EarlyBound(def_id.to_def_id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
|
fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
|
||||||
|
@ -63,9 +57,7 @@ impl RegionExt for Region {
|
||||||
match *self {
|
match *self {
|
||||||
Region::Static => None,
|
Region::Static => None,
|
||||||
|
|
||||||
Region::EarlyBound(_, id) | Region::LateBound(_, _, id) | Region::Free(_, id) => {
|
Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
|
||||||
Some(id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,17 +78,6 @@ impl RegionExt for Region {
|
||||||
_ => self,
|
_ => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option<Region>
|
|
||||||
where
|
|
||||||
L: Iterator<Item = &'a hir::Lifetime>,
|
|
||||||
{
|
|
||||||
if let Region::EarlyBound(index, _) = self {
|
|
||||||
params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.hir_id).cloned())
|
|
||||||
} else {
|
|
||||||
Some(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the id of each lifetime reference to the lifetime decl
|
/// Maps the id of each lifetime reference to the lifetime decl
|
||||||
|
@ -142,25 +123,6 @@ enum Scope<'a> {
|
||||||
/// for diagnostics.
|
/// for diagnostics.
|
||||||
lifetimes: FxIndexMap<LocalDefId, Region>,
|
lifetimes: FxIndexMap<LocalDefId, Region>,
|
||||||
|
|
||||||
/// if we extend this scope with another scope, what is the next index
|
|
||||||
/// we should use for an early-bound region?
|
|
||||||
next_early_index: u32,
|
|
||||||
|
|
||||||
/// Whether or not this binder would serve as the parent
|
|
||||||
/// binder for opaque types introduced within. For example:
|
|
||||||
///
|
|
||||||
/// ```text
|
|
||||||
/// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Here, the opaque types we create for the `impl Trait`
|
|
||||||
/// and `impl Trait2` references will both have the `foo` item
|
|
||||||
/// as their parent. When we get to `impl Trait2`, we find
|
|
||||||
/// that it is nested within the `for<>` binder -- this flag
|
|
||||||
/// allows us to skip that when looking for the parent binder
|
|
||||||
/// of the resulting opaque type.
|
|
||||||
opaque_type_parent: bool,
|
|
||||||
|
|
||||||
scope_type: BinderScopeType,
|
scope_type: BinderScopeType,
|
||||||
|
|
||||||
/// The late bound vars for a given item are stored by `HirId` to be
|
/// The late bound vars for a given item are stored by `HirId` to be
|
||||||
|
@ -240,19 +202,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
|
||||||
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
Scope::Binder {
|
Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
|
||||||
lifetimes,
|
|
||||||
next_early_index,
|
|
||||||
opaque_type_parent,
|
|
||||||
scope_type,
|
|
||||||
hir_id,
|
|
||||||
where_bound_origin,
|
|
||||||
s: _,
|
|
||||||
} => f
|
|
||||||
.debug_struct("Binder")
|
.debug_struct("Binder")
|
||||||
.field("lifetimes", lifetimes)
|
.field("lifetimes", lifetimes)
|
||||||
.field("next_early_index", next_early_index)
|
|
||||||
.field("opaque_type_parent", opaque_type_parent)
|
|
||||||
.field("scope_type", scope_type)
|
.field("scope_type", scope_type)
|
||||||
.field("hir_id", hir_id)
|
.field("hir_id", hir_id)
|
||||||
.field("where_bound_origin", where_bound_origin)
|
.field("where_bound_origin", where_bound_origin)
|
||||||
|
@ -423,13 +375,6 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In traits, there is an implicit `Self` type parameter which comes before the generics.
|
|
||||||
/// We have to account for this when computing the index of the other generic parameters.
|
|
||||||
/// This function returns whether there is such an implicit parameter defined on the given item.
|
|
||||||
fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
|
|
||||||
matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
|
fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
|
||||||
match region {
|
match region {
|
||||||
Region::LateBound(_, _, def_id) => {
|
Region::LateBound(_, _, def_id) => {
|
||||||
|
@ -549,7 +494,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_early_index = self.next_early_index();
|
|
||||||
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
|
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
|
||||||
bound_generic_params
|
bound_generic_params
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -567,8 +511,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: e.hir_id,
|
hir_id: e.hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
next_early_index,
|
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -594,7 +536,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
match item.kind {
|
match item.kind {
|
||||||
hir::ItemKind::Fn(_, ref generics, _) => {
|
hir::ItemKind::Fn(_, ref generics, _) => {
|
||||||
self.visit_early_late(None, item.hir_id(), generics, |this| {
|
self.visit_early_late(item.hir_id(), generics, |this| {
|
||||||
intravisit::walk_item(this, item);
|
intravisit::walk_item(this, item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -661,31 +603,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
| hir::ItemKind::TraitAlias(ref generics, ..)
|
| hir::ItemKind::TraitAlias(ref generics, ..)
|
||||||
| hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
|
| hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
|
||||||
// These kinds of items have only early-bound lifetime parameters.
|
// These kinds of items have only early-bound lifetime parameters.
|
||||||
let mut index = if sub_items_have_self_param(&item.kind) {
|
|
||||||
1 // Self comes before lifetimes
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
let mut non_lifetime_count = 0;
|
|
||||||
let lifetimes = generics
|
let lifetimes = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(self.tcx.hir(), &mut index, param))
|
Some(Region::early(self.tcx.hir(), param))
|
||||||
}
|
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
|
||||||
non_lifetime_count += 1;
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.map.late_bound_vars.insert(item.hir_id(), vec![]);
|
self.map.late_bound_vars.insert(item.hir_id(), vec![]);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: item.hir_id(),
|
hir_id: item.hir_id(),
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index: index + non_lifetime_count,
|
|
||||||
opaque_type_parent: true,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
s: ROOT_SCOPE,
|
s: ROOT_SCOPE,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
|
@ -703,7 +634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
hir::ForeignItemKind::Fn(_, _, ref generics) => {
|
hir::ForeignItemKind::Fn(_, _, ref generics) => {
|
||||||
self.visit_early_late(None, item.hir_id(), generics, |this| {
|
self.visit_early_late(item.hir_id(), generics, |this| {
|
||||||
intravisit::walk_foreign_item(this, item);
|
intravisit::walk_foreign_item(this, item);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -720,7 +651,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
hir::TyKind::BareFn(ref c) => {
|
hir::TyKind::BareFn(ref c) => {
|
||||||
let next_early_index = self.next_early_index();
|
|
||||||
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
|
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
|
||||||
.generic_params
|
.generic_params
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -737,8 +667,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: ty.hir_id,
|
hir_id: ty.hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
next_early_index,
|
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -877,32 +805,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
|
|
||||||
// We want to start our early-bound indices at the end of the parent scope,
|
// We want to start our early-bound indices at the end of the parent scope,
|
||||||
// not including any parent `impl Trait`s.
|
// not including any parent `impl Trait`s.
|
||||||
let mut index = self.next_early_index_for_opaque_type();
|
|
||||||
debug!(?index);
|
|
||||||
|
|
||||||
let mut lifetimes = FxIndexMap::default();
|
let mut lifetimes = FxIndexMap::default();
|
||||||
let mut non_lifetime_count = 0;
|
|
||||||
debug!(?generics.params);
|
debug!(?generics.params);
|
||||||
for param in generics.params {
|
for param in generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, ¶m);
|
let (def_id, reg) = Region::early(self.tcx.hir(), ¶m);
|
||||||
lifetimes.insert(def_id, reg);
|
lifetimes.insert(def_id, reg);
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
|
||||||
non_lifetime_count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let next_early_index = index + non_lifetime_count;
|
|
||||||
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
|
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
|
||||||
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: ty.hir_id,
|
hir_id: ty.hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index,
|
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -924,39 +843,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
use self::hir::TraitItemKind::*;
|
use self::hir::TraitItemKind::*;
|
||||||
match trait_item.kind {
|
match trait_item.kind {
|
||||||
Fn(_, _) => {
|
Fn(_, _) => {
|
||||||
let tcx = self.tcx;
|
self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
|
||||||
self.visit_early_late(
|
intravisit::walk_trait_item(this, trait_item)
|
||||||
Some(tcx.hir().get_parent_item(trait_item.hir_id())),
|
});
|
||||||
trait_item.hir_id(),
|
|
||||||
&trait_item.generics,
|
|
||||||
|this| intravisit::walk_trait_item(this, trait_item),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Type(bounds, ref ty) => {
|
Type(bounds, ref ty) => {
|
||||||
let generics = &trait_item.generics;
|
let generics = &trait_item.generics;
|
||||||
let mut index = self.next_early_index();
|
|
||||||
debug!("visit_ty: index = {}", index);
|
|
||||||
let mut non_lifetime_count = 0;
|
|
||||||
let lifetimes = generics
|
let lifetimes = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(self.tcx.hir(), &mut index, param))
|
Some(Region::early(self.tcx.hir(), param))
|
||||||
}
|
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
|
||||||
non_lifetime_count += 1;
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
|
self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: trait_item.hir_id(),
|
hir_id: trait_item.hir_id(),
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index: index + non_lifetime_count,
|
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
opaque_type_parent: true,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -984,40 +891,26 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||||
use self::hir::ImplItemKind::*;
|
use self::hir::ImplItemKind::*;
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
Fn(..) => {
|
Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
|
||||||
let tcx = self.tcx;
|
intravisit::walk_impl_item(this, impl_item)
|
||||||
self.visit_early_late(
|
}),
|
||||||
Some(tcx.hir().get_parent_item(impl_item.hir_id())),
|
|
||||||
impl_item.hir_id(),
|
|
||||||
&impl_item.generics,
|
|
||||||
|this| intravisit::walk_impl_item(this, impl_item),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
TyAlias(ref ty) => {
|
TyAlias(ref ty) => {
|
||||||
let generics = &impl_item.generics;
|
let generics = &impl_item.generics;
|
||||||
let mut index = self.next_early_index();
|
|
||||||
let mut non_lifetime_count = 0;
|
|
||||||
debug!("visit_ty: index = {}", index);
|
|
||||||
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
|
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(self.tcx.hir(), &mut index, param))
|
Some(Region::early(self.tcx.hir(), param))
|
||||||
}
|
|
||||||
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => {
|
|
||||||
non_lifetime_count += 1;
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
|
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: ty.hir_id,
|
hir_id: ty.hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index: index + non_lifetime_count,
|
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
opaque_type_parent: true,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -1120,7 +1013,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
.unzip();
|
.unzip();
|
||||||
this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
|
this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
|
||||||
let next_early_index = this.next_early_index();
|
|
||||||
// Even if there are no lifetimes defined here, we still wrap it in a binder
|
// Even if there are no lifetimes defined here, we still wrap it in a binder
|
||||||
// scope. If there happens to be a nested poly trait ref (an error), that
|
// scope. If there happens to be a nested poly trait ref (an error), that
|
||||||
// will be `Concatenating` anyways, so we don't have to worry about the depth
|
// will be `Concatenating` anyways, so we don't have to worry about the depth
|
||||||
|
@ -1129,8 +1021,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: bounded_ty.hir_id,
|
hir_id: bounded_ty.hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
s: this.scope,
|
s: this.scope,
|
||||||
next_early_index,
|
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: Some(origin),
|
where_bound_origin: Some(origin),
|
||||||
};
|
};
|
||||||
|
@ -1201,8 +1091,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: *hir_id,
|
hir_id: *hir_id,
|
||||||
lifetimes: FxIndexMap::default(),
|
lifetimes: FxIndexMap::default(),
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
next_early_index: self.next_early_index(),
|
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type,
|
scope_type,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -1221,7 +1109,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
|
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
|
||||||
|
|
||||||
let next_early_index = self.next_early_index();
|
|
||||||
let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
|
let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
|
||||||
|
|
||||||
let initial_bound_vars = binders.len() as u32;
|
let initial_bound_vars = binders.len() as u32;
|
||||||
|
@ -1251,8 +1138,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: trait_ref.trait_ref.hir_ref_id,
|
hir_id: trait_ref.trait_ref.hir_ref_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
next_early_index,
|
|
||||||
opaque_type_parent: false,
|
|
||||||
scope_type,
|
scope_type,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
|
@ -1354,30 +1239,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
/// ordering is not important there.
|
/// ordering is not important there.
|
||||||
fn visit_early_late<F>(
|
fn visit_early_late<F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
parent_id: Option<LocalDefId>,
|
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
generics: &'tcx hir::Generics<'tcx>,
|
generics: &'tcx hir::Generics<'tcx>,
|
||||||
walk: F,
|
walk: F,
|
||||||
) where
|
) where
|
||||||
F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
|
F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
|
||||||
{
|
{
|
||||||
// Find the start of nested early scopes, e.g., in methods.
|
|
||||||
let mut next_early_index = 0;
|
|
||||||
if let Some(parent_id) = parent_id {
|
|
||||||
let parent = self.tcx.hir().expect_item(parent_id);
|
|
||||||
if sub_items_have_self_param(&parent.kind) {
|
|
||||||
next_early_index += 1; // Self comes before lifetimes
|
|
||||||
}
|
|
||||||
match parent.kind {
|
|
||||||
hir::ItemKind::Trait(_, _, ref generics, ..)
|
|
||||||
| hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
|
|
||||||
next_early_index += generics.params.len() as u32;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut non_lifetime_count = 0;
|
|
||||||
let mut named_late_bound_vars = 0;
|
let mut named_late_bound_vars = 0;
|
||||||
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
|
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
|
||||||
.params
|
.params
|
||||||
|
@ -1389,16 +1256,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
named_late_bound_vars += 1;
|
named_late_bound_vars += 1;
|
||||||
Some(Region::late(late_bound_idx, self.tcx.hir(), param))
|
Some(Region::late(late_bound_idx, self.tcx.hir(), param))
|
||||||
} else {
|
} else {
|
||||||
Some(Region::early(self.tcx.hir(), &mut next_early_index, param))
|
Some(Region::early(self.tcx.hir(), param))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
|
||||||
non_lifetime_count += 1;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let next_early_index = next_early_index + non_lifetime_count;
|
|
||||||
|
|
||||||
let binders: Vec<_> = generics
|
let binders: Vec<_> = generics
|
||||||
.params
|
.params
|
||||||
|
@ -1417,51 +1280,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id,
|
hir_id,
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index,
|
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
opaque_type_parent: true,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
self.with(scope, walk);
|
self.with(scope, walk);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_early_index_helper(&self, only_opaque_type_parent: bool) -> u32 {
|
|
||||||
let mut scope = self.scope;
|
|
||||||
loop {
|
|
||||||
match *scope {
|
|
||||||
Scope::Root => return 0,
|
|
||||||
|
|
||||||
Scope::Binder { next_early_index, opaque_type_parent, .. }
|
|
||||||
if (!only_opaque_type_parent || opaque_type_parent) =>
|
|
||||||
{
|
|
||||||
return next_early_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope::Binder { s, .. }
|
|
||||||
| Scope::Body { s, .. }
|
|
||||||
| Scope::Elision { s, .. }
|
|
||||||
| Scope::ObjectLifetimeDefault { s, .. }
|
|
||||||
| Scope::Supertrait { s, .. }
|
|
||||||
| Scope::TraitRefBoundary { s, .. } => scope = s,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the next index one would use for an early-bound-region
|
|
||||||
/// if extending the current scope.
|
|
||||||
fn next_early_index(&self) -> u32 {
|
|
||||||
self.next_early_index_helper(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the next index one would use for an `impl Trait` that
|
|
||||||
/// is being converted into an opaque type alias `impl Trait`. This will be the
|
|
||||||
/// next early index from the enclosing item, for the most
|
|
||||||
/// part. See the `opaque_type_parent` field for more info.
|
|
||||||
fn next_early_index_for_opaque_type(&self) -> u32 {
|
|
||||||
self.next_early_index_helper(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn resolve_lifetime_ref(
|
fn resolve_lifetime_ref(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -221,7 +221,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
tcx.mk_region(ty::ReLateBound(debruijn, br))
|
tcx.mk_region(ty::ReLateBound(debruijn, br))
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(rl::Region::EarlyBound(_, def_id)) => {
|
Some(rl::Region::EarlyBound(def_id)) => {
|
||||||
let name = tcx.hir().ty_param_name(def_id.expect_local());
|
let name = tcx.hir().ty_param_name(def_id.expect_local());
|
||||||
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
|
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
|
||||||
let generics = tcx.generics_of(item_def_id);
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
@ -2840,10 +2840,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
);
|
);
|
||||||
|
|
||||||
if !infer_replacements.is_empty() {
|
if !infer_replacements.is_empty() {
|
||||||
diag.multipart_suggestion(&format!(
|
diag.multipart_suggestion(
|
||||||
|
&format!(
|
||||||
"try replacing `_` with the type{} in the corresponding trait method signature",
|
"try replacing `_` with the type{} in the corresponding trait method signature",
|
||||||
rustc_errors::pluralize!(infer_replacements.len()),
|
rustc_errors::pluralize!(infer_replacements.len()),
|
||||||
), infer_replacements, Applicability::MachineApplicable);
|
),
|
||||||
|
infer_replacements,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
diag.emit();
|
diag.emit();
|
||||||
|
|
|
@ -216,7 +216,7 @@ impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> {
|
||||||
fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
|
||||||
let def = cx.tcx.named_region(lifetime.hir_id);
|
let def = cx.tcx.named_region(lifetime.hir_id);
|
||||||
if let Some(
|
if let Some(
|
||||||
rl::Region::EarlyBound(_, node_id)
|
rl::Region::EarlyBound(node_id)
|
||||||
| rl::Region::LateBound(_, _, node_id)
|
| rl::Region::LateBound(_, _, node_id)
|
||||||
| rl::Region::Free(_, node_id),
|
| rl::Region::Free(_, node_id),
|
||||||
) = def
|
) = def
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue