Resolve lifetimes independently for each item-like.
This commit is contained in:
parent
0ff1d1e122
commit
44c10e4cb0
2 changed files with 67 additions and 187 deletions
|
@ -94,11 +94,6 @@ struct LifetimeContext<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
map: &'a mut NamedRegionMap,
|
map: &'a mut NamedRegionMap,
|
||||||
scope: ScopeRef<'a>,
|
scope: ScopeRef<'a>,
|
||||||
|
|
||||||
/// Indicates that we only care about the definition of a trait. This should
|
|
||||||
/// be false if the `Item` we are resolving lifetimes for is not a trait or
|
|
||||||
/// we eventually need lifetimes resolve for trait items.
|
|
||||||
trait_definition_only: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -166,7 +161,9 @@ enum Scope<'a> {
|
||||||
s: ScopeRef<'a>,
|
s: ScopeRef<'a>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Root,
|
Root {
|
||||||
|
opt_parent_item: Option<LocalDefId>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -214,95 +211,58 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
.finish(),
|
.finish(),
|
||||||
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
||||||
Scope::Root => f.debug_struct("Root").finish(),
|
Scope::Root { opt_parent_item } => {
|
||||||
|
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScopeRef<'a> = &'a Scope<'a>;
|
type ScopeRef<'a> = &'a Scope<'a>;
|
||||||
|
|
||||||
const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
|
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||||
*providers = ty::query::Providers {
|
*providers = ty::query::Providers {
|
||||||
resolve_lifetimes_trait_definition,
|
|
||||||
resolve_lifetimes,
|
resolve_lifetimes,
|
||||||
|
|
||||||
named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
|
named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id),
|
||||||
is_late_bound_map,
|
is_late_bound_map,
|
||||||
object_lifetime_default,
|
object_lifetime_default,
|
||||||
late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
|
late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id),
|
||||||
|
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `resolve_lifetimes`, but does not resolve lifetimes for trait items.
|
|
||||||
/// Also does not generate any diagnostics.
|
|
||||||
///
|
|
||||||
/// This is ultimately a subset of the `resolve_lifetimes` work. It effectively
|
|
||||||
/// resolves lifetimes only within the trait "header" -- that is, the trait
|
|
||||||
/// and supertrait list. In contrast, `resolve_lifetimes` resolves all the
|
|
||||||
/// lifetimes within the trait and its items. There is room to refactor this,
|
|
||||||
/// for example to resolve lifetimes for each trait item in separate queries,
|
|
||||||
/// but it's convenient to do the entire trait at once because the lifetimes
|
|
||||||
/// from the trait definition are in scope within the trait items as well.
|
|
||||||
///
|
|
||||||
/// The reason for this separate call is to resolve what would otherwise
|
|
||||||
/// be a cycle. Consider this example:
|
|
||||||
///
|
|
||||||
/// ```ignore UNSOLVED (maybe @jackh726 knows what lifetime parameter to give Sub)
|
|
||||||
/// trait Base<'a> {
|
|
||||||
/// type BaseItem;
|
|
||||||
/// }
|
|
||||||
/// trait Sub<'b>: for<'a> Base<'a> {
|
|
||||||
/// type SubItem: Sub<BaseItem = &'b u32>;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// When we resolve `Sub` and all its items, we also have to resolve `Sub<BaseItem = &'b u32>`.
|
|
||||||
/// To figure out the index of `'b`, we have to know about the supertraits
|
|
||||||
/// of `Sub` so that we can determine that the `for<'a>` will be in scope.
|
|
||||||
/// (This is because we -- currently at least -- flatten all the late-bound
|
|
||||||
/// lifetimes into a single binder.) This requires us to resolve the
|
|
||||||
/// *trait definition* of `Sub`; basically just enough lifetime information
|
|
||||||
/// to look at the supertraits.
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
fn resolve_lifetimes_trait_definition(
|
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
local_def_id: LocalDefId,
|
|
||||||
) -> ResolveLifetimes {
|
|
||||||
convert_named_region_map(do_resolve(tcx, local_def_id, true))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
|
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
|
||||||
/// You should not read the result of this query directly, but rather use
|
/// You should not read the result of this query directly, but rather use
|
||||||
/// `named_region_map`, `is_late_bound_map`, etc.
|
/// `named_region_map`, `is_late_bound_map`, etc.
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
#[instrument(level = "debug", skip(tcx))]
|
||||||
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
|
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes {
|
||||||
convert_named_region_map(do_resolve(tcx, local_def_id, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_resolve(
|
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
local_def_id: LocalDefId,
|
|
||||||
trait_definition_only: bool,
|
|
||||||
) -> NamedRegionMap {
|
|
||||||
let item = tcx.hir().expect_item(local_def_id);
|
|
||||||
let mut named_region_map =
|
let mut named_region_map =
|
||||||
NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
|
NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
|
||||||
let mut visitor = LifetimeContext {
|
let mut visitor = LifetimeContext {
|
||||||
tcx,
|
tcx,
|
||||||
map: &mut named_region_map,
|
map: &mut named_region_map,
|
||||||
scope: ROOT_SCOPE,
|
scope: &Scope::Root { opt_parent_item: None },
|
||||||
trait_definition_only,
|
|
||||||
};
|
};
|
||||||
visitor.visit_item(item);
|
match tcx.hir().owner(local_def_id) {
|
||||||
|
hir::OwnerNode::Item(item) => visitor.visit_item(item),
|
||||||
|
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
|
||||||
|
hir::OwnerNode::TraitItem(item) => {
|
||||||
|
let scope =
|
||||||
|
Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
|
||||||
|
visitor.scope = &scope;
|
||||||
|
visitor.visit_trait_item(item)
|
||||||
|
}
|
||||||
|
hir::OwnerNode::ImplItem(item) => {
|
||||||
|
let scope =
|
||||||
|
Scope::Root { opt_parent_item: Some(tcx.local_parent(item.owner_id.def_id)) };
|
||||||
|
visitor.scope = &scope;
|
||||||
|
visitor.visit_impl_item(item)
|
||||||
|
}
|
||||||
|
hir::OwnerNode::Crate(_) => {}
|
||||||
|
}
|
||||||
|
|
||||||
named_region_map
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
|
|
||||||
let mut rl = ResolveLifetimes::default();
|
let mut rl = ResolveLifetimes::default();
|
||||||
|
|
||||||
for (hir_id, v) in named_region_map.defs {
|
for (hir_id, v) in named_region_map.defs {
|
||||||
|
@ -319,53 +279,6 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
|
||||||
rl
|
rl
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given `any` owner (structs, traits, trait methods, etc.), does lifetime resolution.
|
|
||||||
/// There are two important things this does.
|
|
||||||
/// First, we have to resolve lifetimes for
|
|
||||||
/// the entire *`Item`* that contains this owner, because that's the largest "scope"
|
|
||||||
/// where we can have relevant lifetimes.
|
|
||||||
/// Second, if we are asking for lifetimes in a trait *definition*, we use `resolve_lifetimes_trait_definition`
|
|
||||||
/// instead of `resolve_lifetimes`, which does not descend into the trait items and does not emit diagnostics.
|
|
||||||
/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
|
|
||||||
/// other than the trait itself (like the trait methods or associated types), then we just use the regular
|
|
||||||
/// `resolve_lifetimes`.
|
|
||||||
fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes {
|
|
||||||
let item_id = item_for(tcx, def_id.def_id);
|
|
||||||
let local_def_id = item_id.owner_id.def_id;
|
|
||||||
if item_id.owner_id == def_id {
|
|
||||||
let item = tcx.hir().item(item_id);
|
|
||||||
match item.kind {
|
|
||||||
hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id),
|
|
||||||
_ => tcx.resolve_lifetimes(local_def_id),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tcx.resolve_lifetimes(local_def_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds the `Item` that contains the given `LocalDefId`
|
|
||||||
fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> hir::ItemId {
|
|
||||||
match tcx.hir().find_by_def_id(local_def_id) {
|
|
||||||
Some(Node::Item(item)) => {
|
|
||||||
return item.item_id();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
let item = {
|
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
|
|
||||||
let mut parent_iter = tcx.hir().parent_iter(hir_id);
|
|
||||||
loop {
|
|
||||||
let node = parent_iter.next().map(|n| n.1);
|
|
||||||
match node {
|
|
||||||
Some(hir::Node::Item(item)) => break item.item_id(),
|
|
||||||
Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
item
|
|
||||||
}
|
|
||||||
|
|
||||||
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) => {
|
||||||
|
@ -383,7 +296,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
let mut supertrait_lifetimes = vec![];
|
let mut supertrait_lifetimes = vec![];
|
||||||
loop {
|
loop {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::Body { .. } | Scope::Root => {
|
Scope::Body { .. } | Scope::Root { .. } => {
|
||||||
break (vec![], BinderScopeType::Normal);
|
break (vec![], BinderScopeType::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,21 +327,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
type NestedFilter = nested_filter::All;
|
type NestedFilter = nested_filter::OnlyBodies;
|
||||||
|
|
||||||
fn nested_visit_map(&mut self) -> Self::Map {
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
self.tcx.hir()
|
self.tcx.hir()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to nest trait/impl items in their parent, but nothing else.
|
|
||||||
fn visit_nested_item(&mut self, _: hir::ItemId) {}
|
|
||||||
|
|
||||||
fn visit_trait_item_ref(&mut self, ii: &'tcx hir::TraitItemRef) {
|
|
||||||
if !self.trait_definition_only {
|
|
||||||
intravisit::walk_trait_item_ref(self, ii)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let body = self.tcx.hir().body(body);
|
let body = self.tcx.hir().body(body);
|
||||||
self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
|
self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
|
||||||
|
@ -557,33 +461,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
// their owner, we can keep going until we find the Item that owns that. We then
|
// their owner, we can keep going until we find the Item that owns that. We then
|
||||||
// conservatively add all resolved lifetimes. Otherwise we run into problems in
|
// conservatively add all resolved lifetimes. Otherwise we run into problems in
|
||||||
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
|
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
|
||||||
for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) {
|
let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
|
||||||
match node {
|
let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item);
|
||||||
hir::Node::Item(parent_item) => {
|
// We need to add *all* deps, since opaque tys may want them from *us*
|
||||||
let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(
|
for (&owner, defs) in resolved_lifetimes.defs.iter() {
|
||||||
item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id,
|
defs.iter().for_each(|(&local_id, region)| {
|
||||||
);
|
self.map.defs.insert(hir::HirId { owner, local_id }, *region);
|
||||||
// We need to add *all* deps, since opaque tys may want them from *us*
|
});
|
||||||
for (&owner, defs) in resolved_lifetimes.defs.iter() {
|
}
|
||||||
defs.iter().for_each(|(&local_id, region)| {
|
for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() {
|
||||||
self.map.defs.insert(hir::HirId { owner, local_id }, *region);
|
late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
|
||||||
});
|
self.record_late_bound_vars(
|
||||||
}
|
hir::HirId { owner, local_id },
|
||||||
for (&owner, late_bound_vars) in
|
late_bound_vars.clone(),
|
||||||
resolved_lifetimes.late_bound_vars.iter()
|
);
|
||||||
{
|
});
|
||||||
late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
|
|
||||||
self.record_late_bound_vars(
|
|
||||||
hir::HirId { owner, local_id },
|
|
||||||
late_bound_vars.clone(),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::TyAlias(_, ref generics)
|
hir::ItemKind::TyAlias(_, ref generics)
|
||||||
|
@ -609,7 +501,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir_id: item.hir_id(),
|
hir_id: item.hir_id(),
|
||||||
lifetimes,
|
lifetimes,
|
||||||
scope_type: BinderScopeType::Normal,
|
scope_type: BinderScopeType::Normal,
|
||||||
s: ROOT_SCOPE,
|
s: self.scope,
|
||||||
where_bound_origin: None,
|
where_bound_origin: None,
|
||||||
};
|
};
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
|
@ -766,30 +658,26 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
// Ensure that the parent of the def is an item, not HRTB
|
// Ensure that the parent of the def is an item, not HRTB
|
||||||
let parent_id = self.tcx.hir().get_parent_node(hir_id);
|
let parent_id = self.tcx.hir().get_parent_node(hir_id);
|
||||||
if !parent_id.is_owner() {
|
if !parent_id.is_owner() {
|
||||||
if !self.trait_definition_only {
|
struct_span_err!(
|
||||||
struct_span_err!(
|
self.tcx.sess,
|
||||||
self.tcx.sess,
|
lifetime.span,
|
||||||
lifetime.span,
|
E0657,
|
||||||
E0657,
|
"`impl Trait` can only capture lifetimes \
|
||||||
"`impl Trait` can only capture lifetimes \
|
|
||||||
bound at the fn or impl level"
|
bound at the fn or impl level"
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
|
||||||
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
||||||
}
|
}
|
||||||
if let hir::Node::Item(hir::Item {
|
if let hir::Node::Item(hir::Item {
|
||||||
kind: hir::ItemKind::OpaqueTy { .. }, ..
|
kind: hir::ItemKind::OpaqueTy { .. }, ..
|
||||||
}) = self.tcx.hir().get(parent_id)
|
}) = self.tcx.hir().get(parent_id)
|
||||||
{
|
{
|
||||||
if !self.trait_definition_only {
|
let mut err = self.tcx.sess.struct_span_err(
|
||||||
let mut err = self.tcx.sess.struct_span_err(
|
|
||||||
lifetime.span,
|
lifetime.span,
|
||||||
"higher kinded lifetime bounds on nested opaque types are not supported yet",
|
"higher kinded lifetime bounds on nested opaque types are not supported yet",
|
||||||
);
|
);
|
||||||
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
|
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
|
||||||
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,12 +1081,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
|
F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
|
||||||
{
|
{
|
||||||
let LifetimeContext { tcx, map, .. } = self;
|
let LifetimeContext { tcx, map, .. } = self;
|
||||||
let mut this = LifetimeContext {
|
let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope };
|
||||||
tcx: *tcx,
|
|
||||||
map,
|
|
||||||
scope: &wrap_scope,
|
|
||||||
trait_definition_only: self.trait_definition_only,
|
|
||||||
};
|
|
||||||
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
|
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
|
||||||
{
|
{
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
|
@ -1303,7 +1186,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Root => {
|
Scope::Root { opt_parent_item } => {
|
||||||
|
if let Some(parent_item) = opt_parent_item
|
||||||
|
&& let parent_generics = self.tcx.generics_of(parent_item)
|
||||||
|
&& parent_generics.param_def_id_to_index.contains_key(®ion_def_id.to_def_id())
|
||||||
|
{
|
||||||
|
break Some(Region::EarlyBound(region_def_id.to_def_id()));
|
||||||
|
}
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,7 +1306,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
err.emit();
|
err.emit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Scope::Root => break,
|
Scope::Root { .. } => break,
|
||||||
Scope::Binder { s, .. }
|
Scope::Binder { s, .. }
|
||||||
| Scope::Body { s, .. }
|
| Scope::Body { s, .. }
|
||||||
| Scope::Elision { s, .. }
|
| Scope::Elision { s, .. }
|
||||||
|
@ -1495,7 +1384,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
loop {
|
loop {
|
||||||
match *scope {
|
match *scope {
|
||||||
Scope::Root => break false,
|
Scope::Root { .. } => break false,
|
||||||
|
|
||||||
Scope::Body { .. } => break true,
|
Scope::Body { .. } => break true,
|
||||||
|
|
||||||
|
@ -1732,7 +1621,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Root | Scope::Elision { .. } => break Region::Static,
|
Scope::Root { .. } | Scope::Elision { .. } => break Region::Static,
|
||||||
|
|
||||||
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
|
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
|
||||||
|
|
||||||
|
|
|
@ -1614,19 +1614,10 @@ rustc_queries! {
|
||||||
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
|
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does lifetime resolution, but does not descend into trait items. This
|
|
||||||
/// should only be used for resolving lifetimes of on trait definitions,
|
|
||||||
/// and is used to avoid cycles. Importantly, `resolve_lifetimes` still visits
|
|
||||||
/// the same lifetimes and is responsible for diagnostics.
|
|
||||||
/// See `rustc_resolve::late::lifetimes for details.
|
|
||||||
query resolve_lifetimes_trait_definition(_: LocalDefId) -> ResolveLifetimes {
|
|
||||||
arena_cache
|
|
||||||
desc { "resolving lifetimes for a trait definition" }
|
|
||||||
}
|
|
||||||
/// Does lifetime resolution on items. Importantly, we can't resolve
|
/// Does lifetime resolution on items. Importantly, we can't resolve
|
||||||
/// lifetimes directly on things like trait methods, because of trait params.
|
/// lifetimes directly on things like trait methods, because of trait params.
|
||||||
/// See `rustc_resolve::late::lifetimes for details.
|
/// See `rustc_resolve::late::lifetimes for details.
|
||||||
query resolve_lifetimes(_: LocalDefId) -> ResolveLifetimes {
|
query resolve_lifetimes(_: hir::OwnerId) -> ResolveLifetimes {
|
||||||
arena_cache
|
arena_cache
|
||||||
desc { "resolving lifetimes" }
|
desc { "resolving lifetimes" }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue