1
Fork 0

Auto merge of #103530 - cjgillot:hir-lifetimes-direct, r=estebank

Resolve lifetimes independently for each item-like.

Now that the heavy-lifting is done on the AST and during lowering, we do not need to perform HIR lifetime resolution on a full item at once.  Instead, we can treat each item-like independently, and look at `generics_of` the parent exceptionally for associated items.
This commit is contained in:
bors 2022-11-12 05:22:17 +00:00
commit 825f8edc2f
20 changed files with 224 additions and 384 deletions

View file

@ -117,7 +117,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
} }
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
let node = tcx.hir().expect_owner(def_id); let node = tcx.hir().owner(def_id);
match node { match node {
hir::OwnerNode::Crate(_) => {} hir::OwnerNode::Crate(_) => {}
hir::OwnerNode::Item(item) => check_item(tcx, item), hir::OwnerNode::Item(item) => check_item(tcx, item),

View file

@ -644,12 +644,6 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
} }
} }
// Desugared from `impl Trait`, so visited by the function's return type.
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
..
}) => {}
// Don't call `type_of` on opaque types, since that depends on type // Don't call `type_of` on opaque types, since that depends on type
// checking function bodies. `check_item_type` ensures that it's called // checking function bodies. `check_item_type` ensures that it's called
// instead. // instead.
@ -657,27 +651,32 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
tcx.ensure().generics_of(def_id); tcx.ensure().generics_of(def_id);
tcx.ensure().predicates_of(def_id); tcx.ensure().predicates_of(def_id);
tcx.ensure().explicit_item_bounds(def_id); tcx.ensure().explicit_item_bounds(def_id);
tcx.ensure().item_bounds(def_id);
} }
hir::ItemKind::TyAlias(..)
| hir::ItemKind::Static(..) hir::ItemKind::TyAlias(..) => {
| hir::ItemKind::Const(..)
| hir::ItemKind::Fn(..) => {
tcx.ensure().generics_of(def_id); tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id); tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id); tcx.ensure().predicates_of(def_id);
match it.kind { }
hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => {
hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => { tcx.ensure().generics_of(def_id);
if !is_suggestable_infer_ty(ty) { tcx.ensure().type_of(def_id);
let mut visitor = HirPlaceholderCollector::default(); tcx.ensure().predicates_of(def_id);
visitor.visit_item(it); if !is_suggestable_infer_ty(ty) {
placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr()); let mut visitor = HirPlaceholderCollector::default();
} visitor.visit_item(it);
} placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
_ => (),
} }
} }
hir::ItemKind::Fn(..) => {
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
tcx.ensure().fn_sig(def_id);
}
} }
} }

View file

@ -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| {
@ -548,7 +452,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_item(this, item) intravisit::walk_item(this, item)
}); });
} }
hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => { hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias, ..
}) => {
// Opaque types are visited when we visit the // Opaque types are visited when we visit the
// `TyKind::OpaqueDef`, so that they have the lifetimes from // `TyKind::OpaqueDef`, so that they have the lifetimes from
// their parent opaque_ty in scope. // their parent opaque_ty in scope.
@ -557,34 +463,53 @@ 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 }, hir::ItemKind::OpaqueTy(hir::OpaqueTy {
late_bound_vars.clone(), origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
); generics,
}); ..
} }) => {
break; // We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s.
let mut lifetimes = FxIndexMap::default();
debug!(?generics.params);
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {
let (def_id, reg) = Region::early(self.tcx.hir(), &param);
lifetimes.insert(def_id, reg);
} }
hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"), GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
_ => {}
} }
} }
let scope = Scope::Binder {
hir_id: item.hir_id(),
lifetimes,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| intravisit::walk_item(this, item))
});
} }
hir::ItemKind::TyAlias(_, ref generics) hir::ItemKind::TyAlias(_, ref generics)
| hir::ItemKind::Enum(_, ref generics) | hir::ItemKind::Enum(_, ref generics)
@ -609,7 +534,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| {
@ -712,7 +637,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// ^ ^ this gets resolved in the scope of // ^ ^ this gets resolved in the scope of
// the opaque_ty generics // the opaque_ty generics
let opaque_ty = self.tcx.hir().item(item_id); let opaque_ty = self.tcx.hir().item(item_id);
let (generics, bounds) = match opaque_ty.kind { match opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias, origin: hir::OpaqueTyOrigin::TyAlias,
.. ..
@ -733,10 +658,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} }
hir::ItemKind::OpaqueTy(hir::OpaqueTy { hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
ref generics,
bounds,
.. ..
}) => (generics, bounds), }) => {}
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
}; };
@ -766,65 +689,28 @@ 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 bound at the fn or impl level"
"`impl Trait` can only capture lifetimes \ )
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());
} }
} }
// We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s.
let mut lifetimes = FxIndexMap::default();
debug!(?generics.params);
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {
let (def_id, reg) = Region::early(self.tcx.hir(), &param);
lifetimes.insert(def_id, reg);
}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
}
}
self.record_late_bound_vars(ty.hir_id, vec![]);
let scope = Scope::Binder {
hir_id: ty.hir_id,
lifetimes,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| {
this.visit_generics(generics);
for bound in bounds {
this.visit_param_bound(bound);
}
})
});
} }
_ => intravisit::walk_ty(self, ty), _ => intravisit::walk_ty(self, ty),
} }
@ -1193,12 +1079,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 +1184,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(&region_def_id.to_def_id())
{
break Some(Region::EarlyBound(region_def_id.to_def_id()));
}
break None; break None;
} }
@ -1417,7 +1304,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 +1382,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 +1619,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,

View file

@ -163,7 +163,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe
// Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do // Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do
// a standard visit. // a standard visit.
// FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's. // FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's.
_ => match tcx.hir().expect_owner(owner) { _ => match tcx.hir().owner(owner) {
hir::OwnerNode::Item(item) => levels.visit_item(item), hir::OwnerNode::Item(item) => levels.visit_item(item),
hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item), hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item),
hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item), hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item),

View file

@ -353,6 +353,10 @@ impl<'hir> Map<'hir> {
node.node.generics() node.node.generics()
} }
pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> {
self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node
}
pub fn item(self, id: ItemId) -> &'hir Item<'hir> { pub fn item(self, id: ItemId) -> &'hir Item<'hir> {
self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item() self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item()
} }
@ -822,8 +826,11 @@ impl<'hir> Map<'hir> {
) )
} }
pub fn expect_owner(self, id: OwnerId) -> OwnerNode<'hir> { pub fn expect_owner(self, def_id: LocalDefId) -> OwnerNode<'hir> {
self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node self.tcx
.hir_owner(OwnerId { def_id })
.unwrap_or_else(|| bug!("expected owner for {:?}", def_id))
.node
} }
pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {

View file

@ -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" }
} }

View file

@ -132,12 +132,15 @@ where
} }
fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
iter::empty() iter::empty()
} }
fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
iter::empty() iter::empty()
} }
fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
iter::empty() iter::empty()
} }
fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}

View file

@ -191,7 +191,31 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:143:40 --> $DIR/duplicate.rs:134:42
|
LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:138:42
|
LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
| ---------- ^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:142:45
|
LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
| ------------- ^^^^^^^^^^^^^ re-bound here
| |
| `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:146:40
| |
LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -199,7 +223,7 @@ LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:145:40 --> $DIR/duplicate.rs:148:40
| |
LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -207,7 +231,7 @@ LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:147:43 --> $DIR/duplicate.rs:150:43
| |
LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -215,7 +239,7 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:150:35 --> $DIR/duplicate.rs:153:35
| |
LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -223,7 +247,7 @@ LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:152:35 --> $DIR/duplicate.rs:155:35
| |
LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -231,7 +255,7 @@ LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:154:38 --> $DIR/duplicate.rs:157:38
| |
LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -239,7 +263,7 @@ LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:158:29 --> $DIR/duplicate.rs:161:29
| |
LL | T: Iterator<Item: Copy, Item: Send>, LL | T: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -247,7 +271,7 @@ LL | T: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:163:29 --> $DIR/duplicate.rs:166:29
| |
LL | T: Iterator<Item: Copy, Item: Copy>, LL | T: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -255,7 +279,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:168:32 --> $DIR/duplicate.rs:171:32
| |
LL | T: Iterator<Item: 'static, Item: 'static>, LL | T: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -263,7 +287,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:172:36 --> $DIR/duplicate.rs:175:36
| |
LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -271,7 +295,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:174:36 --> $DIR/duplicate.rs:177:36
| |
LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -279,7 +303,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:176:39 --> $DIR/duplicate.rs:179:39
| |
LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -287,7 +311,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:178:40 --> $DIR/duplicate.rs:181:40
| |
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -295,7 +319,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:180:40 --> $DIR/duplicate.rs:183:40
| |
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -303,7 +327,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:182:43 --> $DIR/duplicate.rs:185:43
| |
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -311,7 +335,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:185:36 --> $DIR/duplicate.rs:188:36
| |
LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -319,7 +343,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:187:36 --> $DIR/duplicate.rs:190:36
| |
LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -327,7 +351,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:189:39 --> $DIR/duplicate.rs:192:39
| |
LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -335,7 +359,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:191:34 --> $DIR/duplicate.rs:194:34
| |
LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -343,7 +367,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:193:34 --> $DIR/duplicate.rs:196:34
| |
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -351,7 +375,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:195:37 --> $DIR/duplicate.rs:198:37
| |
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -359,7 +383,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:199:29 --> $DIR/duplicate.rs:202:29
| |
LL | T: Iterator<Item: Copy, Item: Send>, LL | T: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -367,7 +391,7 @@ LL | T: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:205:29 --> $DIR/duplicate.rs:208:29
| |
LL | T: Iterator<Item: Copy, Item: Copy>, LL | T: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -375,7 +399,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:211:32 --> $DIR/duplicate.rs:214:32
| |
LL | T: Iterator<Item: 'static, Item: 'static>, LL | T: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -383,7 +407,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:217:32 --> $DIR/duplicate.rs:220:32
| |
LL | Self: Iterator<Item: Copy, Item: Send>, LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -391,7 +415,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:217:32 --> $DIR/duplicate.rs:220:32
| |
LL | Self: Iterator<Item: Copy, Item: Send>, LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -399,7 +423,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:224:32 --> $DIR/duplicate.rs:227:32
| |
LL | Self: Iterator<Item: Copy, Item: Copy>, LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -407,7 +431,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:224:32 --> $DIR/duplicate.rs:227:32
| |
LL | Self: Iterator<Item: Copy, Item: Copy>, LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -415,7 +439,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:231:35 --> $DIR/duplicate.rs:234:35
| |
LL | Self: Iterator<Item: 'static, Item: 'static>, LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -423,7 +447,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:231:35 --> $DIR/duplicate.rs:234:35
| |
LL | Self: Iterator<Item: 'static, Item: 'static>, LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -431,7 +455,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:249:40 --> $DIR/duplicate.rs:252:40
| |
LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -439,7 +463,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:251:44 --> $DIR/duplicate.rs:254:44
| |
LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -447,7 +471,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:253:43 --> $DIR/duplicate.rs:256:43
| |
LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -455,7 +479,7 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:237:34 --> $DIR/duplicate.rs:240:34
| |
LL | type A: Iterator<Item: Copy, Item: Send>; LL | type A: Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -463,7 +487,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:241:34 --> $DIR/duplicate.rs:244:34
| |
LL | type A: Iterator<Item: Copy, Item: Copy>; LL | type A: Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -471,13 +495,13 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified
--> $DIR/duplicate.rs:245:37 --> $DIR/duplicate.rs:248:37
| |
LL | type A: Iterator<Item: 'static, Item: 'static>; LL | type A: Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
| | | |
| `Item` bound here first | `Item` bound here first
error: aborting due to 60 previous errors error: aborting due to 63 previous errors
For more information about this error, try `rustc --explain E0719`. For more information about this error, try `rustc --explain E0719`.

View file

@ -6,7 +6,6 @@ async fn copy() -> Result<()>
//~^ ERROR this enum takes 2 generic arguments //~^ ERROR this enum takes 2 generic arguments
{ {
Ok(()) Ok(())
//~^ ERROR type annotations needed
} }
fn main() { } fn main() { }

View file

@ -16,18 +16,6 @@ help: add missing generic argument
LL | async fn copy() -> Result<(), E> LL | async fn copy() -> Result<(), E>
| +++ | +++
error[E0282]: type annotations needed error: aborting due to previous error
--> $DIR/issue-65159.rs:8:5
|
LL | Ok(())
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
|
help: consider specifying the generic arguments
|
LL | Ok::<(), E>(())
| +++++++++
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0107`.
Some errors have detailed explanations: E0107, E0282.
For more information about an error, try `rustc --explain E0107`.

View file

@ -17,7 +17,6 @@ async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
//~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
//~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied //~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
LockedMarket(generator.lock().unwrap().buy()) LockedMarket(generator.lock().unwrap().buy())
//~^ ERROR cannot return value referencing temporary
} }
struct LockedMarket<T>(T); struct LockedMarket<T>(T);

View file

@ -7,7 +7,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
| expected 0 lifetime arguments | expected 0 lifetime arguments
| |
note: struct defined here, with 0 lifetime parameters note: struct defined here, with 0 lifetime parameters
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
| |
LL | struct LockedMarket<T>(T); LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
@ -19,7 +19,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
| ^^^^^^^^^^^^ expected 1 generic argument | ^^^^^^^^^^^^ expected 1 generic argument
| |
note: struct defined here, with 1 generic parameter: `T` note: struct defined here, with 1 generic parameter: `T`
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
| |
LL | struct LockedMarket<T>(T); LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^ - | ^^^^^^^^^^^^ -
@ -28,16 +28,6 @@ help: add missing generic argument
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> { LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
| +++ | +++
error[E0515]: cannot return value referencing temporary value error: aborting due to 2 previous errors
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
|
LL | LockedMarket(generator.lock().unwrap().buy())
| ^^^^^^^^^^^^^-------------------------^^^^^^^
| | |
| | temporary value created here
| returns a value referencing data owned by the current function
error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0107`.
Some errors have detailed explanations: E0107, E0515.
For more information about an error, try `rustc --explain E0107`.

View file

@ -14,7 +14,6 @@ impl<const N: usize> Marker<N> for Example<N> {}
fn make_marker() -> impl Marker<gimme_a_const!(marker)> { fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
//~^ ERROR: type provided when a constant was expected //~^ ERROR: type provided when a constant was expected
Example::<gimme_a_const!(marker)> Example::<gimme_a_const!(marker)>
//~^ ERROR: type provided when a constant was expected
} }
fn from_marker(_: impl Marker<{ fn from_marker(_: impl Marker<{
@ -34,9 +33,7 @@ fn main() {
}>; }>;
let _fail = Example::<external_macro!()>; let _fail = Example::<external_macro!()>;
//~^ ERROR: type provided when a constant was expected
let _fail = Example::<gimme_a_const!()>; let _fail = Example::<gimme_a_const!()>;
//~^ ERROR: type provided when a constant was expected //~^ ERROR unexpected end of macro invocation
//~| ERROR unexpected end of macro invocation
} }

View file

@ -1,5 +1,5 @@
error: expected type, found `{` error: expected type, found `{`
--> $DIR/macro-fail.rs:29:27 --> $DIR/macro-fail.rs:28:27
| |
LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
| ---------------------- | ----------------------
@ -13,7 +13,7 @@ LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
= note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected type, found `{` error: expected type, found `{`
--> $DIR/macro-fail.rs:29:27 --> $DIR/macro-fail.rs:28:27
| |
LL | Example::<gimme_a_const!(marker)> LL | Example::<gimme_a_const!(marker)>
| ---------------------- | ----------------------
@ -46,7 +46,7 @@ LL | let _fail = Example::<external_macro!()>;
= note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unexpected end of macro invocation error: unexpected end of macro invocation
--> $DIR/macro-fail.rs:39:25 --> $DIR/macro-fail.rs:37:25
| |
LL | macro_rules! gimme_a_const { LL | macro_rules! gimme_a_const {
| -------------------------- when calling this macro | -------------------------- when calling this macro
@ -60,24 +60,6 @@ error[E0747]: type provided when a constant was expected
LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> { LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0747]: type provided when a constant was expected error: aborting due to 5 previous errors
--> $DIR/macro-fail.rs:16:13
|
LL | Example::<gimme_a_const!(marker)>
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0747]: type provided when a constant was expected
--> $DIR/macro-fail.rs:36:25
|
LL | let _fail = Example::<external_macro!()>;
| ^^^^^^^^^^^^^^^^^
error[E0747]: type provided when a constant was expected
--> $DIR/macro-fail.rs:39:25
|
LL | let _fail = Example::<gimme_a_const!()>;
| ^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0747`. For more information about this error, try `rustc --explain E0747`.

View file

@ -9,13 +9,6 @@ help: add `dyn` keyword before this trait
LL | fn ice() -> impl AsRef<dyn Fn(&())> { LL | fn ice() -> impl AsRef<dyn Fn(&())> {
| +++ | +++
error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied error: aborting due to previous error
--> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13
|
LL | fn ice() -> impl AsRef<Fn(&())> {
| ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()`
error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0782`.
Some errors have detailed explanations: E0277, E0782.
For more information about an error, try `rustc --explain E0277`.

View file

@ -4,8 +4,8 @@
#![allow(warnings)] #![allow(warnings)]
fn ice() -> impl AsRef<Fn(&())> { fn ice() -> impl AsRef<Fn(&())> {
//~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277]
//[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782] //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782]
todo!() todo!()
} }

View file

@ -3,7 +3,7 @@ use std::fmt::Debug;
fn a() -> impl Fn(&u8) -> impl Debug + '_ { fn a() -> impl Fn(&u8) -> impl Debug + '_ {
//~^ ERROR ambiguous `+` in a type //~^ ERROR ambiguous `+` in a type
//~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
|x| x |x| x
} }

View file

@ -4,11 +4,10 @@ use std::iter;
fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> { fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
//~^ ERROR: missing generics for struct `Vec` [E0107] //~^ ERROR: missing generics for struct `Vec` [E0107]
iter::empty() //~ ERROR: type annotations needed [E0282] iter::empty()
} }
fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> { fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> {
//~^ ERROR: type annotations needed [E0282]
f(data).filter(|x| x == target) f(data).filter(|x| x == target)
} }

View file

@ -14,24 +14,6 @@ help: add missing generic argument
LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> { LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
| ~~~~~~ | ~~~~~~
error[E0282]: type annotations needed error: aborting due to previous error
--> $DIR/issue-92305.rs:7:5
|
LL | iter::empty()
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
|
help: consider specifying the generic argument
|
LL | iter::empty::<T>()
| +++++
error[E0282]: type annotations needed For more information about this error, try `rustc --explain E0107`.
--> $DIR/issue-92305.rs:10:35
|
LL | fn g<T>(data: &[T], target: T) -> impl Iterator<Item = Vec<T>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0107, E0282.
For more information about an error, try `rustc --explain E0107`.

View file

@ -35,26 +35,26 @@ fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
// This should pass. // This should resolve.
fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {} fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {}
// This should pass. // This should resolve.
fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {} fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {}
// This should pass. // This should resolve.
fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
// This should pass. // This should resolve.
fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {} fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
// This should pass. // This should resolve.
fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {} fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}
// `'b` is not in scope for the outlives bound. // `'b` is not in scope for the outlives bound.
fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
//~^ ERROR use of undeclared lifetime name `'b` [E0261] //~^ ERROR use of undeclared lifetime name `'b` [E0261]
// This should pass. // This should resolve.
fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {} fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
// `'b` is not in scope for the outlives bound. // `'b` is not in scope for the outlives bound.