Remap impl-trait lifetimes on HIR instead of AST lowering.
This commit is contained in:
parent
298c7462c3
commit
b6e1214ac0
35 changed files with 508 additions and 597 deletions
|
@ -45,16 +45,14 @@ use rustc_ast::ptr::P;
|
||||||
use rustc_ast::{self as ast, *};
|
use rustc_ast::{self as ast, *};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
|
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
|
||||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
|
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, MissingLifetimeKind,
|
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
|
||||||
ParamName, TraitCandidate,
|
|
||||||
};
|
};
|
||||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
|
@ -83,7 +81,6 @@ mod expr;
|
||||||
mod format;
|
mod format;
|
||||||
mod index;
|
mod index;
|
||||||
mod item;
|
mod item;
|
||||||
mod lifetime_collector;
|
|
||||||
mod pat;
|
mod pat;
|
||||||
mod path;
|
mod path;
|
||||||
|
|
||||||
|
@ -149,12 +146,6 @@ struct LoweringContext<'a, 'hir> {
|
||||||
allow_async_iterator: Lrc<[Symbol]>,
|
allow_async_iterator: Lrc<[Symbol]>,
|
||||||
allow_for_await: Lrc<[Symbol]>,
|
allow_for_await: Lrc<[Symbol]>,
|
||||||
allow_async_fn_traits: Lrc<[Symbol]>,
|
allow_async_fn_traits: Lrc<[Symbol]>,
|
||||||
|
|
||||||
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
|
|
||||||
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
|
|
||||||
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
|
|
||||||
/// field from the original parameter 'a to the new parameter 'a1.
|
|
||||||
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
@ -199,7 +190,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
// FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`
|
||||||
// interact with `gen`/`async gen` blocks
|
// interact with `gen`/`async gen` blocks
|
||||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||||
generics_def_id_map: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,54 +518,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
|
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
|
||||||
/// resolver (if any).
|
/// resolver (if any).
|
||||||
fn orig_opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
|
|
||||||
self.resolver.node_id_to_def_id.get(&node).copied()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
|
|
||||||
/// resolver (if any), after applying any remapping from `get_remapped_def_id`.
|
|
||||||
///
|
|
||||||
/// For example, in a function like `fn foo<'a>(x: &'a u32)`,
|
|
||||||
/// invoking with the id from the `ast::Lifetime` node found inside
|
|
||||||
/// the `&'a u32` type would return the `LocalDefId` of the
|
|
||||||
/// `'a` parameter declared on `foo`.
|
|
||||||
///
|
|
||||||
/// This function also applies remapping from `get_remapped_def_id`.
|
|
||||||
/// These are used when synthesizing opaque types from `-> impl Trait` return types and so forth.
|
|
||||||
/// For example, in a function like `fn foo<'a>() -> impl Debug + 'a`,
|
|
||||||
/// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`.
|
|
||||||
/// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`.
|
|
||||||
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
|
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
|
||||||
self.orig_opt_local_def_id(node).map(|local_def_id| self.get_remapped_def_id(local_def_id))
|
self.resolver.node_id_to_def_id.get(&node).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn local_def_id(&self, node: NodeId) -> LocalDefId {
|
fn local_def_id(&self, node: NodeId) -> LocalDefId {
|
||||||
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
|
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the previously recorded `to` local def id given the `from` local def id, obtained using
|
|
||||||
/// `generics_def_id_map` field.
|
|
||||||
fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId {
|
|
||||||
// `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
|
|
||||||
// push new mappings, so we first need to get the latest (innermost) mappings, hence `iter().rev()`.
|
|
||||||
//
|
|
||||||
// Consider:
|
|
||||||
//
|
|
||||||
// `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
|
|
||||||
//
|
|
||||||
// We would end with a generics_def_id_map like:
|
|
||||||
//
|
|
||||||
// `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
|
|
||||||
//
|
|
||||||
// for the opaque type generated on `impl Sized + 'b`, we want the result to be: impl_sized#'b.
|
|
||||||
// So, if we were trying to find first from the start (outermost) would give the wrong result, impl_trait#'b.
|
|
||||||
self.generics_def_id_map
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.find_map(|map| map.get(&local_def_id).copied())
|
|
||||||
.unwrap_or(local_def_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Freshen the `LoweringContext` and ready it to lower a nested item.
|
/// Freshen the `LoweringContext` and ready it to lower a nested item.
|
||||||
/// The lowered item is registered into `self.children`.
|
/// The lowered item is registered into `self.children`.
|
||||||
///
|
///
|
||||||
|
@ -647,27 +597,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Installs the remapping `remap` in scope while `f` is being executed.
|
|
||||||
/// This causes references to the `LocalDefId` keys to be changed to
|
|
||||||
/// refer to the values instead.
|
|
||||||
///
|
|
||||||
/// The remapping is used when one piece of AST expands to multiple
|
|
||||||
/// pieces of HIR. For example, the function `fn foo<'a>(...) -> impl Debug + 'a`,
|
|
||||||
/// expands to both a function definition (`foo`) and a TAIT for the return value,
|
|
||||||
/// both of which have a lifetime parameter `'a`. The remapping allows us to
|
|
||||||
/// rewrite the `'a` in the return value to refer to the
|
|
||||||
/// `'a` declared on the TAIT, instead of the function.
|
|
||||||
fn with_remapping<R>(
|
|
||||||
&mut self,
|
|
||||||
remap: LocalDefIdMap<LocalDefId>,
|
|
||||||
f: impl FnOnce(&mut Self) -> R,
|
|
||||||
) -> R {
|
|
||||||
self.generics_def_id_map.push(remap);
|
|
||||||
let res = f(self);
|
|
||||||
self.generics_def_id_map.pop();
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
|
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
|
||||||
let attrs = std::mem::take(&mut self.attrs);
|
let attrs = std::mem::take(&mut self.attrs);
|
||||||
let mut bodies = std::mem::take(&mut self.bodies);
|
let mut bodies = std::mem::take(&mut self.bodies);
|
||||||
|
@ -1499,27 +1428,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
// frequently opened issues show.
|
// frequently opened issues show.
|
||||||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
||||||
|
|
||||||
// Whether this opaque always captures lifetimes in scope.
|
|
||||||
// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
|
|
||||||
// is enabled. We don't check the span of the edition, since this is done
|
|
||||||
// on a per-opaque basis to account for nested opaques.
|
|
||||||
let always_capture_in_scope = match origin {
|
|
||||||
_ if self.tcx.features().lifetime_capture_rules_2024() => true,
|
|
||||||
hir::OpaqueTyOrigin::TyAlias { .. } => true,
|
|
||||||
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
|
|
||||||
hir::OpaqueTyOrigin::AsyncFn { .. } => {
|
|
||||||
unreachable!("should be using `lower_coroutine_fn_ret_ty`")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let captured_lifetimes_to_duplicate = lifetime_collector::lifetimes_for_opaque(
|
|
||||||
self.resolver,
|
|
||||||
always_capture_in_scope,
|
|
||||||
opaque_ty_node_id,
|
|
||||||
bounds,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
debug!(?captured_lifetimes_to_duplicate);
|
|
||||||
|
|
||||||
// Feature gate for RPITIT + use<..>
|
// Feature gate for RPITIT + use<..>
|
||||||
match origin {
|
match origin {
|
||||||
rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
|
rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
|
||||||
|
@ -1542,22 +1450,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lower_opaque_inner(
|
self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
|
||||||
opaque_ty_node_id,
|
this.lower_param_bounds(bounds, itctx)
|
||||||
origin,
|
})
|
||||||
captured_lifetimes_to_duplicate,
|
|
||||||
span,
|
|
||||||
opaque_ty_span,
|
|
||||||
|this| this.lower_param_bounds(bounds, itctx),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_opaque_inner(
|
fn lower_opaque_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
opaque_ty_node_id: NodeId,
|
opaque_ty_node_id: NodeId,
|
||||||
origin: hir::OpaqueTyOrigin,
|
origin: hir::OpaqueTyOrigin,
|
||||||
captured_lifetimes_to_duplicate: FxIndexSet<Lifetime>,
|
|
||||||
span: Span,
|
|
||||||
opaque_ty_span: Span,
|
opaque_ty_span: Span,
|
||||||
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
||||||
) -> hir::TyKind<'hir> {
|
) -> hir::TyKind<'hir> {
|
||||||
|
@ -1565,145 +1466,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);
|
let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);
|
||||||
debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);
|
debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);
|
||||||
|
|
||||||
// Map from captured (old) lifetime to synthetic (new) lifetime.
|
|
||||||
// Used to resolve lifetimes in the bounds of the opaque.
|
|
||||||
let mut captured_to_synthesized_mapping = LocalDefIdMap::default();
|
|
||||||
// List of (early-bound) synthetic lifetimes that are owned by the opaque.
|
|
||||||
// This is used to create the `hir::Generics` owned by the opaque.
|
|
||||||
let mut synthesized_lifetime_definitions = vec![];
|
|
||||||
// Pairs of lifetime arg (that resolves to the captured lifetime)
|
|
||||||
// and the def-id of the (early-bound) synthetic lifetime definition.
|
|
||||||
// This is used both to create generics for the `TyKind::OpaqueDef` that
|
|
||||||
// we return, and also as a captured lifetime mapping for RPITITs.
|
|
||||||
let mut synthesized_lifetime_args = vec![];
|
|
||||||
|
|
||||||
for lifetime in captured_lifetimes_to_duplicate {
|
|
||||||
let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
|
|
||||||
let (old_def_id, missing_kind) = match res {
|
|
||||||
LifetimeRes::Param { param: old_def_id, binder: _ } => (old_def_id, None),
|
|
||||||
|
|
||||||
LifetimeRes::Fresh { param, kind, .. } => {
|
|
||||||
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
|
|
||||||
if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
|
|
||||||
(old_def_id, Some(kind))
|
|
||||||
} else {
|
|
||||||
self.dcx()
|
|
||||||
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opaques do not capture `'static`
|
|
||||||
LifetimeRes::Static { .. } | LifetimeRes::Error => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
res => {
|
|
||||||
let bug_msg = format!(
|
|
||||||
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
|
||||||
res, lifetime.ident, lifetime.ident.span
|
|
||||||
);
|
|
||||||
span_bug!(lifetime.ident.span, "{}", bug_msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if captured_to_synthesized_mapping.get(&old_def_id).is_none() {
|
|
||||||
// Create a new lifetime parameter local to the opaque.
|
|
||||||
let duplicated_lifetime_node_id = self.next_node_id();
|
|
||||||
let duplicated_lifetime_def_id = self.create_def(
|
|
||||||
opaque_ty_def_id,
|
|
||||||
duplicated_lifetime_node_id,
|
|
||||||
lifetime.ident.name,
|
|
||||||
DefKind::LifetimeParam,
|
|
||||||
self.lower_span(lifetime.ident.span),
|
|
||||||
);
|
|
||||||
captured_to_synthesized_mapping.insert(old_def_id, duplicated_lifetime_def_id);
|
|
||||||
// FIXME: Instead of doing this, we could move this whole loop
|
|
||||||
// into the `with_hir_id_owner`, then just directly construct
|
|
||||||
// the `hir::GenericParam` here.
|
|
||||||
synthesized_lifetime_definitions.push((
|
|
||||||
duplicated_lifetime_node_id,
|
|
||||||
duplicated_lifetime_def_id,
|
|
||||||
self.lower_ident(lifetime.ident),
|
|
||||||
missing_kind,
|
|
||||||
));
|
|
||||||
|
|
||||||
// Now make an arg that we can use for the generic params of the opaque tykind.
|
|
||||||
let id = self.next_node_id();
|
|
||||||
let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res);
|
|
||||||
let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id);
|
|
||||||
synthesized_lifetime_args.push((lifetime_arg, duplicated_lifetime_def_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| {
|
let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| {
|
||||||
// Install the remapping from old to new (if any). This makes sure that
|
let bounds = lower_item_bounds(this);
|
||||||
// any lifetimes that would have resolved to the def-id of captured
|
|
||||||
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
|
|
||||||
let bounds = this
|
|
||||||
.with_remapping(captured_to_synthesized_mapping, |this| lower_item_bounds(this));
|
|
||||||
|
|
||||||
let generic_params =
|
|
||||||
this.arena.alloc_from_iter(synthesized_lifetime_definitions.iter().map(
|
|
||||||
|&(new_node_id, new_def_id, ident, missing_kind)| {
|
|
||||||
let hir_id = this.lower_node_id(new_node_id);
|
|
||||||
let (name, kind) = if ident.name == kw::UnderscoreLifetime {
|
|
||||||
(
|
|
||||||
hir::ParamName::Fresh,
|
|
||||||
hir::LifetimeParamKind::Elided(
|
|
||||||
missing_kind.unwrap_or(MissingLifetimeKind::Underscore),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
|
||||||
};
|
|
||||||
|
|
||||||
hir::GenericParam {
|
|
||||||
hir_id,
|
|
||||||
def_id: new_def_id,
|
|
||||||
name,
|
|
||||||
span: ident.span,
|
|
||||||
pure_wrt_drop: false,
|
|
||||||
kind: hir::GenericParamKind::Lifetime { kind },
|
|
||||||
colon_span: None,
|
|
||||||
source: hir::GenericParamSource::Generics,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
));
|
|
||||||
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
|
|
||||||
|
|
||||||
let lifetime_mapping = self.arena.alloc_slice(&synthesized_lifetime_args);
|
|
||||||
|
|
||||||
trace!("registering opaque type with id {:#?}", opaque_ty_def_id);
|
|
||||||
let opaque_ty_def = hir::OpaqueTy {
|
let opaque_ty_def = hir::OpaqueTy {
|
||||||
hir_id: opaque_ty_hir_id,
|
hir_id: opaque_ty_hir_id,
|
||||||
def_id: opaque_ty_def_id,
|
def_id: opaque_ty_def_id,
|
||||||
generics: this.arena.alloc(hir::Generics {
|
|
||||||
params: generic_params,
|
|
||||||
predicates: &[],
|
|
||||||
has_where_clause_predicates: false,
|
|
||||||
where_clause_span: this.lower_span(span),
|
|
||||||
span: this.lower_span(span),
|
|
||||||
}),
|
|
||||||
bounds,
|
bounds,
|
||||||
origin,
|
origin,
|
||||||
lifetime_mapping,
|
|
||||||
span: this.lower_span(opaque_ty_span),
|
span: this.lower_span(opaque_ty_span),
|
||||||
};
|
};
|
||||||
this.arena.alloc(opaque_ty_def)
|
this.arena.alloc(opaque_ty_def)
|
||||||
});
|
});
|
||||||
|
|
||||||
let generic_args = self.arena.alloc_from_iter(
|
hir::TyKind::OpaqueDef(opaque_ty_def)
|
||||||
synthesized_lifetime_args
|
|
||||||
.iter()
|
|
||||||
.map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create the `Foo<...>` reference itself. Note that the `type
|
|
||||||
// Foo = impl Trait` is, internally, created as a child of the
|
|
||||||
// async fn, so the *type parameters* are inherited. It's
|
|
||||||
// only the lifetime parameters that we must supply.
|
|
||||||
hir::TyKind::OpaqueDef(opaque_ty_def, generic_args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_precise_capturing_args(
|
fn lower_precise_capturing_args(
|
||||||
|
@ -1885,13 +1660,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let opaque_ty_span =
|
let opaque_ty_span =
|
||||||
self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
|
self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features);
|
||||||
|
|
||||||
let captured_lifetimes = self
|
|
||||||
.resolver
|
|
||||||
.extra_lifetime_params(opaque_ty_node_id)
|
|
||||||
.into_iter()
|
|
||||||
.map(|(ident, id, _)| Lifetime { id, ident })
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let in_trait_or_impl = match fn_kind {
|
let in_trait_or_impl = match fn_kind {
|
||||||
FnDeclKind::Trait => Some(hir::RpitContext::Trait),
|
FnDeclKind::Trait => Some(hir::RpitContext::Trait),
|
||||||
FnDeclKind::Impl => Some(hir::RpitContext::TraitImpl),
|
FnDeclKind::Impl => Some(hir::RpitContext::TraitImpl),
|
||||||
|
@ -1902,8 +1670,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
let opaque_ty_ref = self.lower_opaque_inner(
|
let opaque_ty_ref = self.lower_opaque_inner(
|
||||||
opaque_ty_node_id,
|
opaque_ty_node_id,
|
||||||
hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
|
hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
|
||||||
captured_lifetimes,
|
|
||||||
span,
|
|
||||||
opaque_ty_span,
|
opaque_ty_span,
|
||||||
|this| {
|
|this| {
|
||||||
let bound = this.lower_coroutine_fn_output_type_to_bound(
|
let bound = this.lower_coroutine_fn_output_type_to_bound(
|
||||||
|
@ -2000,10 +1766,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
res: LifetimeRes,
|
res: LifetimeRes,
|
||||||
) -> &'hir hir::Lifetime {
|
) -> &'hir hir::Lifetime {
|
||||||
let res = match res {
|
let res = match res {
|
||||||
LifetimeRes::Param { param, .. } => {
|
LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
|
||||||
let param = self.get_remapped_def_id(param);
|
|
||||||
hir::LifetimeName::Param(param)
|
|
||||||
}
|
|
||||||
LifetimeRes::Fresh { param, .. } => {
|
LifetimeRes::Fresh { param, .. } => {
|
||||||
let param = self.local_def_id(param);
|
let param = self.local_def_id(param);
|
||||||
hir::LifetimeName::Param(param)
|
hir::LifetimeName::Param(param)
|
||||||
|
|
|
@ -830,7 +830,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
||||||
///
|
///
|
||||||
/// [`OpaqueDef`]: hir::TyKind::OpaqueDef
|
/// [`OpaqueDef`]: hir::TyKind::OpaqueDef
|
||||||
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
|
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
|
||||||
let hir::TyKind::OpaqueDef(opaque_ty, _) = hir_ty.kind else {
|
let hir::TyKind::OpaqueDef(opaque_ty) = hir_ty.kind else {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
"lowered return type of async fn is not OpaqueDef: {:?}",
|
"lowered return type of async fn is not OpaqueDef: {:?}",
|
||||||
|
|
|
@ -2627,7 +2627,6 @@ impl<'hir> Ty<'hir> {
|
||||||
}
|
}
|
||||||
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
|
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
|
||||||
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
|
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
|
||||||
TyKind::OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
|
|
||||||
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
|
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
|
||||||
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
|
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
|
||||||
}
|
}
|
||||||
|
@ -2746,19 +2745,8 @@ pub struct BareFnTy<'hir> {
|
||||||
pub struct OpaqueTy<'hir> {
|
pub struct OpaqueTy<'hir> {
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
pub def_id: LocalDefId,
|
pub def_id: LocalDefId,
|
||||||
pub generics: &'hir Generics<'hir>,
|
|
||||||
pub bounds: GenericBounds<'hir>,
|
pub bounds: GenericBounds<'hir>,
|
||||||
pub origin: OpaqueTyOrigin,
|
pub origin: OpaqueTyOrigin,
|
||||||
/// Return-position impl traits (and async futures) must "reify" any late-bound
|
|
||||||
/// lifetimes that are captured from the function signature they originate from.
|
|
||||||
///
|
|
||||||
/// This is done by generating a new early-bound lifetime parameter local to the
|
|
||||||
/// opaque which is instantiated in the function signature with the late-bound
|
|
||||||
/// lifetime.
|
|
||||||
///
|
|
||||||
/// This mapping associated a captured lifetime (first parameter) with the new
|
|
||||||
/// early-bound lifetime that was generated for the opaque.
|
|
||||||
pub lifetime_mapping: &'hir [(&'hir Lifetime, LocalDefId)],
|
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2866,7 +2854,7 @@ pub enum TyKind<'hir> {
|
||||||
/// possibly parameters) that are actually bound on the `impl Trait`.
|
/// possibly parameters) that are actually bound on the `impl Trait`.
|
||||||
///
|
///
|
||||||
/// The last parameter specifies whether this opaque appears in a trait definition.
|
/// The last parameter specifies whether this opaque appears in a trait definition.
|
||||||
OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]),
|
OpaqueDef(&'hir OpaqueTy<'hir>),
|
||||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||||
/// where `Bound` is a trait or a lifetime.
|
/// where `Bound` is a trait or a lifetime.
|
||||||
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
|
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
|
||||||
|
@ -3991,7 +3979,6 @@ impl<'hir> Node<'hir> {
|
||||||
| Node::TraitItem(TraitItem { generics, .. })
|
| Node::TraitItem(TraitItem { generics, .. })
|
||||||
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
||||||
Node::Item(item) => item.kind.generics(),
|
Node::Item(item) => item.kind.generics(),
|
||||||
Node::OpaqueTy(opaque) => Some(opaque.generics),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -896,9 +896,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
||||||
TyKind::Path(ref qpath) => {
|
TyKind::Path(ref qpath) => {
|
||||||
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
|
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
|
||||||
}
|
}
|
||||||
TyKind::OpaqueDef(opaque, lifetimes) => {
|
TyKind::OpaqueDef(opaque) => {
|
||||||
try_visit!(visitor.visit_opaque_ty(opaque));
|
try_visit!(visitor.visit_opaque_ty(opaque));
|
||||||
walk_list!(visitor, visit_generic_arg, lifetimes);
|
|
||||||
}
|
}
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
|
@ -1188,10 +1187,8 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
|
pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
|
||||||
let &OpaqueTy { hir_id, def_id: _, generics, bounds, origin: _, lifetime_mapping: _, span: _ } =
|
let &OpaqueTy { hir_id, def_id: _, bounds, origin: _, span: _ } = opaque;
|
||||||
opaque;
|
|
||||||
try_visit!(visitor.visit_id(hir_id));
|
try_visit!(visitor.visit_id(hir_id));
|
||||||
try_visit!(walk_generics(visitor, generics));
|
|
||||||
walk_list!(visitor, visit_param_bound, bounds);
|
walk_list!(visitor, visit_param_bound, bounds);
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1302,7 +1302,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
#[instrument(level = "debug", skip(tcx), ret)]
|
||||||
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
|
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
|
||||||
use rustc_hir::Node::*;
|
use rustc_hir::Node::*;
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
|
|
@ -426,6 +426,21 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Node::OpaqueTy(&hir::OpaqueTy { .. }) = node {
|
||||||
|
assert!(own_params.is_empty());
|
||||||
|
|
||||||
|
let lifetimes = tcx.opaque_captured_lifetimes(def_id);
|
||||||
|
debug!(?lifetimes);
|
||||||
|
|
||||||
|
own_params.extend(lifetimes.iter().map(|&(_, param)| ty::GenericParamDef {
|
||||||
|
name: tcx.item_name(param.to_def_id()),
|
||||||
|
index: next_index(),
|
||||||
|
def_id: param.to_def_id(),
|
||||||
|
pure_wrt_drop: false,
|
||||||
|
kind: ty::GenericParamDefKind::Lifetime,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
let param_def_id_to_index =
|
let param_def_id_to_index =
|
||||||
own_params.iter().map(|param| (param.def_id, param.index)).collect();
|
own_params.iter().map(|param| (param.def_id, param.index)).collect();
|
||||||
|
|
||||||
|
|
|
@ -329,13 +329,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
// We create bi-directional Outlives predicates between the original
|
// We create bi-directional Outlives predicates between the original
|
||||||
// and the duplicated parameter, to ensure that they do not get out of sync.
|
// and the duplicated parameter, to ensure that they do not get out of sync.
|
||||||
if let Node::OpaqueTy(..) = node {
|
if let Node::OpaqueTy(..) = node {
|
||||||
let opaque_ty_node = tcx.parent_hir_node(hir_id);
|
|
||||||
let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes), .. }) = opaque_ty_node
|
|
||||||
else {
|
|
||||||
bug!("unexpected {opaque_ty_node:?}")
|
|
||||||
};
|
|
||||||
debug!(?lifetimes);
|
|
||||||
|
|
||||||
compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
|
compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
|
||||||
debug!(?predicates);
|
debug!(?predicates);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
|
//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
|
||||||
//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
|
//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
|
||||||
|
|
||||||
use core::ops::ControlFlow;
|
use std::cell::RefCell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_ast::visit::walk_list;
|
use rustc_ast::visit::walk_list;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
|
@ -25,7 +27,7 @@ use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::def_id::{DefId, LocalDefId};
|
use rustc_span::def_id::{DefId, LocalDefId, LocalDefIdMap};
|
||||||
use rustc_span::symbol::{Ident, sym};
|
use rustc_span::symbol::{Ident, sym};
|
||||||
use tracing::{debug, debug_span, instrument};
|
use tracing::{debug, debug_span, instrument};
|
||||||
|
|
||||||
|
@ -80,6 +82,9 @@ struct NamedVarMap {
|
||||||
// - trait refs
|
// - trait refs
|
||||||
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
|
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
|
||||||
late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
|
late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
|
||||||
|
|
||||||
|
// List captured variables for each opaque type.
|
||||||
|
opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BoundVarContext<'a, 'tcx> {
|
struct BoundVarContext<'a, 'tcx> {
|
||||||
|
@ -147,6 +152,20 @@ enum Scope<'a> {
|
||||||
s: ScopeRef<'a>,
|
s: ScopeRef<'a>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Resolve the lifetimes in the bounds to the lifetime defs in the generics.
|
||||||
|
/// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
|
||||||
|
/// `type MyAnonTy<'b> = impl MyTrait<'b>;`
|
||||||
|
/// ^ ^ this gets resolved in the scope of
|
||||||
|
/// the opaque_ty generics
|
||||||
|
Opaque {
|
||||||
|
/// The opaque type we are traversing.
|
||||||
|
def_id: LocalDefId,
|
||||||
|
/// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`.
|
||||||
|
captures: &'a RefCell<FxIndexMap<ResolvedArg, LocalDefId>>,
|
||||||
|
|
||||||
|
s: ScopeRef<'a>,
|
||||||
|
},
|
||||||
|
|
||||||
/// Disallows capturing late-bound vars from parent scopes.
|
/// Disallows capturing late-bound vars from parent scopes.
|
||||||
///
|
///
|
||||||
/// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
|
/// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
|
||||||
|
@ -192,6 +211,12 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||||
.field("where_bound_origin", where_bound_origin)
|
.field("where_bound_origin", where_bound_origin)
|
||||||
.field("s", &"..")
|
.field("s", &"..")
|
||||||
.finish(),
|
.finish(),
|
||||||
|
Scope::Opaque { captures, def_id, s: _ } => f
|
||||||
|
.debug_struct("Opaque")
|
||||||
|
.field("def_id", def_id)
|
||||||
|
.field("captures", &captures.borrow())
|
||||||
|
.field("s", &"..")
|
||||||
|
.finish(),
|
||||||
Scope::Body { id, s: _ } => {
|
Scope::Body { id, s: _ } => {
|
||||||
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
|
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
|
||||||
}
|
}
|
||||||
|
@ -226,6 +251,12 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
is_late_bound_map,
|
is_late_bound_map,
|
||||||
object_lifetime_default,
|
object_lifetime_default,
|
||||||
late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
|
late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
|
||||||
|
opaque_captured_lifetimes: |tcx, id| {
|
||||||
|
&tcx.resolve_bound_vars(tcx.local_def_id_to_hir_id(id).owner)
|
||||||
|
.opaque_captured_lifetimes
|
||||||
|
.get(&id)
|
||||||
|
.map_or(&[][..], |x| &x[..])
|
||||||
|
},
|
||||||
|
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
|
@ -236,8 +267,11 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
/// `named_variable_map`, `is_late_bound_map`, etc.
|
/// `named_variable_map`, `is_late_bound_map`, etc.
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
#[instrument(level = "debug", skip(tcx))]
|
||||||
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
|
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
|
||||||
let mut named_variable_map =
|
let mut named_variable_map = NamedVarMap {
|
||||||
NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
|
defs: Default::default(),
|
||||||
|
late_bound_vars: Default::default(),
|
||||||
|
opaque_captured_lifetimes: Default::default(),
|
||||||
|
};
|
||||||
let mut visitor = BoundVarContext {
|
let mut visitor = BoundVarContext {
|
||||||
tcx,
|
tcx,
|
||||||
map: &mut named_variable_map,
|
map: &mut named_variable_map,
|
||||||
|
@ -264,13 +298,16 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
|
||||||
|
|
||||||
let defs = named_variable_map.defs.into_sorted_stable_ord();
|
let defs = named_variable_map.defs.into_sorted_stable_ord();
|
||||||
let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
|
let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
|
||||||
|
let opaque_captured_lifetimes = named_variable_map.opaque_captured_lifetimes;
|
||||||
let rl = ResolveBoundVars {
|
let rl = ResolveBoundVars {
|
||||||
defs: SortedMap::from_presorted_elements(defs),
|
defs: SortedMap::from_presorted_elements(defs),
|
||||||
late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
|
late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
|
||||||
|
opaque_captured_lifetimes,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(?rl.defs);
|
debug!(?rl.defs);
|
||||||
debug!(?rl.late_bound_vars);
|
debug!(?rl.late_bound_vars);
|
||||||
|
debug!(?rl.opaque_captured_lifetimes);
|
||||||
rl
|
rl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +343,26 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this opaque always captures lifetimes in scope.
|
||||||
|
/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
|
||||||
|
/// is enabled. We don't check the span of the edition, since this is done
|
||||||
|
/// on a per-opaque basis to account for nested opaques.
|
||||||
|
fn opaque_captures_all_in_scope_lifetimes<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
opaque: &'tcx hir::OpaqueTy<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
match opaque.origin {
|
||||||
|
// if the opaque has the `use<...>` syntax, the user is telling us that they only want
|
||||||
|
// to account for those lifetimes, so do not try to be clever.
|
||||||
|
_ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
|
||||||
|
hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
|
||||||
|
_ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
|
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
|
||||||
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
|
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
|
||||||
|
@ -317,7 +374,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
break (vec![], BinderScopeType::Normal);
|
break (vec![], BinderScopeType::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::ObjectLifetimeDefault { s, .. } | Scope::LateBoundary { s, .. } => {
|
Scope::Opaque { s, .. }
|
||||||
|
| Scope::ObjectLifetimeDefault { s, .. }
|
||||||
|
| Scope::LateBoundary { s, .. } => {
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,29 +547,100 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve the lifetimes that are applied to the opaque type.
|
||||||
|
/// These are resolved in the current scope.
|
||||||
|
/// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
|
||||||
|
/// `fn foo<'a>() -> MyAnonTy<'a> { ... }`
|
||||||
|
/// ^ ^this gets resolved in the current scope
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
|
||||||
// We want to start our early-bound indices at the end of the parent scope,
|
let mut captures = FxIndexMap::default();
|
||||||
// not including any parent `impl Trait`s.
|
|
||||||
let mut bound_vars = FxIndexMap::default();
|
let capture_all_in_scope_lifetimes =
|
||||||
debug!(?opaque.generics.params);
|
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
|
||||||
for param in opaque.generics.params {
|
if capture_all_in_scope_lifetimes {
|
||||||
let arg = ResolvedArg::early(param);
|
let mut create_def_for_duplicated_param = |original_lifetime: LocalDefId, def| {
|
||||||
bound_vars.insert(param.def_id, arg);
|
captures.entry(def).or_insert_with(|| {
|
||||||
|
let name = self.tcx.item_name(original_lifetime.to_def_id());
|
||||||
|
let span = self.tcx.def_span(original_lifetime);
|
||||||
|
let feed = self.tcx.create_def(opaque.def_id, name, DefKind::LifetimeParam);
|
||||||
|
feed.def_span(span);
|
||||||
|
feed.def_ident_span(Some(span));
|
||||||
|
feed.def_id()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// We list scopes outwards, this causes us to see lifetime parameters in reverse
|
||||||
|
// declaration order. In order to make it consistent with what `generics_of` might
|
||||||
|
// give, we will reverse the IndexMap after early captures.
|
||||||
|
let mut scope = self.scope;
|
||||||
|
loop {
|
||||||
|
match *scope {
|
||||||
|
Scope::Binder { ref bound_vars, s, .. } => {
|
||||||
|
for (&original_lifetime, &(mut def)) in bound_vars.iter().rev() {
|
||||||
|
if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) {
|
||||||
|
if let Err(guar) =
|
||||||
|
self.check_lifetime_is_capturable(opaque.def_id, def, None)
|
||||||
|
{
|
||||||
|
def = ResolvedArg::Error(guar);
|
||||||
|
}
|
||||||
|
create_def_for_duplicated_param(original_lifetime, def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
let hir_id = self.tcx.local_def_id_to_hir_id(opaque.def_id);
|
Scope::Root { mut opt_parent_item } => {
|
||||||
let scope = Scope::Binder {
|
while let Some(parent_item) = opt_parent_item {
|
||||||
hir_id,
|
let parent_generics = self.tcx.generics_of(parent_item);
|
||||||
bound_vars,
|
for param in parent_generics.own_params.iter().rev() {
|
||||||
s: self.scope,
|
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||||
scope_type: BinderScopeType::Normal,
|
create_def_for_duplicated_param(
|
||||||
where_bound_origin: None,
|
param.def_id.expect_local(),
|
||||||
};
|
ResolvedArg::EarlyBound(param.def_id.expect_local()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt_parent_item = parent_generics.parent.and_then(DefId::as_local);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::Opaque { captures: outer_captures, .. } => {
|
||||||
|
for (_, &duplicated_param) in outer_captures.borrow().iter().rev() {
|
||||||
|
create_def_for_duplicated_param(
|
||||||
|
duplicated_param,
|
||||||
|
ResolvedArg::EarlyBound(duplicated_param),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::Body { .. } => {
|
||||||
|
bug!("{:?}", scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::ObjectLifetimeDefault { s, .. }
|
||||||
|
| Scope::Supertrait { s, .. }
|
||||||
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
|
| Scope::LateBoundary { s, .. } => {
|
||||||
|
scope = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
captures.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
let captures = RefCell::new(captures);
|
||||||
|
|
||||||
|
let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope };
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
let scope = Scope::TraitRefBoundary { s: this.scope };
|
let scope = Scope::TraitRefBoundary { s: this.scope };
|
||||||
this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
|
this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
|
||||||
})
|
});
|
||||||
|
|
||||||
|
let captures = captures.into_inner().into_iter().collect();
|
||||||
|
self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
@ -685,66 +815,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
self.with(scope, |this| this.visit_ty(mt.ty));
|
self.with(scope, |this| this.visit_ty(mt.ty));
|
||||||
}
|
}
|
||||||
hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
|
hir::TyKind::OpaqueDef(opaque_ty) => {
|
||||||
self.visit_opaque_ty(opaque_ty);
|
self.visit_opaque_ty(opaque_ty);
|
||||||
|
|
||||||
// Resolve the lifetimes in the bounds to the lifetime defs in the generics.
|
|
||||||
// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
|
|
||||||
// `type MyAnonTy<'b> = impl MyTrait<'b>;`
|
|
||||||
// ^ ^ this gets resolved in the scope of
|
|
||||||
// the opaque_ty generics
|
|
||||||
|
|
||||||
// Resolve the lifetimes that are applied to the opaque type.
|
|
||||||
// These are resolved in the current scope.
|
|
||||||
// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
|
|
||||||
// `fn foo<'a>() -> MyAnonTy<'a> { ... }`
|
|
||||||
// ^ ^this gets resolved in the current scope
|
|
||||||
for lifetime in lifetimes {
|
|
||||||
let hir::GenericArg::Lifetime(lifetime) = lifetime else { continue };
|
|
||||||
self.visit_lifetime(lifetime);
|
|
||||||
|
|
||||||
// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
|
|
||||||
// and ban them. Type variables instantiated inside binders aren't
|
|
||||||
// well-supported at the moment, so this doesn't work.
|
|
||||||
// In the future, this should be fixed and this error should be removed.
|
|
||||||
let def = self.map.defs.get(&lifetime.hir_id.local_id).copied();
|
|
||||||
let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
|
|
||||||
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
|
|
||||||
|
|
||||||
let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id))
|
|
||||||
{
|
|
||||||
// Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
|
|
||||||
// it must be a reified late-bound lifetime from a trait goal.
|
|
||||||
hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
|
|
||||||
// Other items are fine.
|
|
||||||
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
|
|
||||||
"higher-ranked lifetime from function pointer"
|
|
||||||
}
|
|
||||||
hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
|
|
||||||
"higher-ranked lifetime from `dyn` type"
|
|
||||||
}
|
|
||||||
_ => "higher-ranked lifetime",
|
|
||||||
};
|
|
||||||
|
|
||||||
let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id)
|
|
||||||
{
|
|
||||||
(opaque_ty.span, Some(opaque_ty.span))
|
|
||||||
} else {
|
|
||||||
(lifetime.ident.span, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure that the parent of the def is an item, not HRTB
|
|
||||||
self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
|
|
||||||
span,
|
|
||||||
label,
|
|
||||||
decl_span: self.tcx.def_span(lifetime_def_id),
|
|
||||||
bad_place,
|
|
||||||
});
|
|
||||||
self.uninsert_lifetime_on_error(lifetime, def.unwrap());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => intravisit::walk_ty(self, ty),
|
_ => intravisit::walk_ty(self, ty),
|
||||||
}
|
}
|
||||||
|
@ -1129,6 +1201,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
let mut outermost_body = None;
|
let mut outermost_body = None;
|
||||||
let mut crossed_late_boundary = None;
|
let mut crossed_late_boundary = None;
|
||||||
|
let mut opaque_capture_scopes = vec![];
|
||||||
let result = loop {
|
let result = loop {
|
||||||
match *scope {
|
match *scope {
|
||||||
Scope::Body { id, s } => {
|
Scope::Body { id, s } => {
|
||||||
|
@ -1204,6 +1277,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
scope = s;
|
scope = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope::Opaque { captures, def_id, s } => {
|
||||||
|
opaque_capture_scopes.push((def_id, captures));
|
||||||
|
late_depth = 0;
|
||||||
|
scope = s;
|
||||||
|
}
|
||||||
|
|
||||||
Scope::ObjectLifetimeDefault { s, .. }
|
Scope::ObjectLifetimeDefault { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. } => {
|
| Scope::TraitRefBoundary { s, .. } => {
|
||||||
|
@ -1218,6 +1297,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(mut def) = result {
|
if let Some(mut def) = result {
|
||||||
|
def = self.remap_opaque_captures(opaque_capture_scopes, def, lifetime_ref.ident);
|
||||||
|
|
||||||
if let ResolvedArg::EarlyBound(..) = def {
|
if let ResolvedArg::EarlyBound(..) = def {
|
||||||
// Do not free early-bound regions, only late-bound ones.
|
// Do not free early-bound regions, only late-bound ones.
|
||||||
} else if let ResolvedArg::LateBound(_, _, param_def_id) = def
|
} else if let ResolvedArg::LateBound(_, _, param_def_id) = def
|
||||||
|
@ -1291,6 +1372,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
Scope::Root { .. } => break,
|
Scope::Root { .. } => break,
|
||||||
Scope::Binder { s, .. }
|
Scope::Binder { s, .. }
|
||||||
| Scope::Body { s, .. }
|
| Scope::Body { s, .. }
|
||||||
|
| Scope::Opaque { s, .. }
|
||||||
| Scope::ObjectLifetimeDefault { s, .. }
|
| Scope::ObjectLifetimeDefault { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. }
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
|
@ -1306,6 +1388,78 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
|
||||||
|
/// and ban them. Type variables instantiated inside binders aren't
|
||||||
|
/// well-supported at the moment, so this doesn't work.
|
||||||
|
/// In the future, this should be fixed and this error should be removed.
|
||||||
|
fn check_lifetime_is_capturable(
|
||||||
|
&self,
|
||||||
|
opaque_def_id: LocalDefId,
|
||||||
|
lifetime: ResolvedArg,
|
||||||
|
span: Option<Span>,
|
||||||
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
|
let ResolvedArg::LateBound(_, _, lifetime_def_id) = lifetime else { return Ok(()) };
|
||||||
|
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
|
||||||
|
let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) {
|
||||||
|
// Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
|
||||||
|
// it must be a reified late-bound lifetime from a trait goal.
|
||||||
|
hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
|
||||||
|
// Other items are fine.
|
||||||
|
hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => return Ok(()),
|
||||||
|
hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
|
||||||
|
"higher-ranked lifetime from function pointer"
|
||||||
|
}
|
||||||
|
hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
|
||||||
|
"higher-ranked lifetime from `dyn` type"
|
||||||
|
}
|
||||||
|
_ => "higher-ranked lifetime",
|
||||||
|
};
|
||||||
|
|
||||||
|
let decl_span = self.tcx.def_span(lifetime_def_id);
|
||||||
|
let (span, label) = if let Some(span) = span
|
||||||
|
&& span != decl_span
|
||||||
|
{
|
||||||
|
(span, None)
|
||||||
|
} else {
|
||||||
|
let opaque_span = self.tcx.def_span(opaque_def_id);
|
||||||
|
(opaque_span, Some(opaque_span))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure that the parent of the def is an item, not HRTB
|
||||||
|
let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
|
||||||
|
span,
|
||||||
|
label,
|
||||||
|
decl_span,
|
||||||
|
bad_place,
|
||||||
|
});
|
||||||
|
Err(guar)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap_opaque_captures(
|
||||||
|
&self,
|
||||||
|
opaque_capture_scopes: Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
|
||||||
|
mut lifetime: ResolvedArg,
|
||||||
|
ident: Ident,
|
||||||
|
) -> ResolvedArg {
|
||||||
|
for (opaque_def_id, captures) in opaque_capture_scopes.into_iter().rev() {
|
||||||
|
if let Err(guar) =
|
||||||
|
self.check_lifetime_is_capturable(opaque_def_id, lifetime, Some(ident.span))
|
||||||
|
{
|
||||||
|
return ResolvedArg::Error(guar);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut captures = captures.borrow_mut();
|
||||||
|
let remapped = *captures.entry(lifetime).or_insert_with(|| {
|
||||||
|
let feed = self.tcx.create_def(opaque_def_id, ident.name, DefKind::LifetimeParam);
|
||||||
|
feed.def_span(ident.span);
|
||||||
|
feed.def_ident_span(Some(ident.span));
|
||||||
|
feed.def_id()
|
||||||
|
});
|
||||||
|
lifetime = ResolvedArg::EarlyBound(remapped);
|
||||||
|
}
|
||||||
|
lifetime
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
|
fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
|
||||||
// Walk up the scope chain, tracking the number of fn scopes
|
// Walk up the scope chain, tracking the number of fn scopes
|
||||||
// that we pass through, until we find a lifetime with the
|
// that we pass through, until we find a lifetime with the
|
||||||
|
@ -1345,6 +1499,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::ObjectLifetimeDefault { s, .. }
|
Scope::ObjectLifetimeDefault { s, .. }
|
||||||
|
| Scope::Opaque { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. } => {
|
| Scope::TraitRefBoundary { s, .. } => {
|
||||||
scope = s;
|
scope = s;
|
||||||
|
@ -1425,6 +1580,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
Scope::Root { .. } => break,
|
Scope::Root { .. } => break,
|
||||||
Scope::Binder { s, .. }
|
Scope::Binder { s, .. }
|
||||||
| Scope::Body { s, .. }
|
| Scope::Body { s, .. }
|
||||||
|
| Scope::Opaque { s, .. }
|
||||||
| Scope::ObjectLifetimeDefault { s, .. }
|
| Scope::ObjectLifetimeDefault { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. }
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
|
@ -1501,6 +1657,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
|
|
||||||
Scope::Binder { s, .. }
|
Scope::Binder { s, .. }
|
||||||
| Scope::ObjectLifetimeDefault { s, .. }
|
| Scope::ObjectLifetimeDefault { s, .. }
|
||||||
|
| Scope::Opaque { s, .. }
|
||||||
| Scope::Supertrait { s, .. }
|
| Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. }
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
| Scope::LateBoundary { s, .. } => {
|
| Scope::LateBoundary { s, .. } => {
|
||||||
|
@ -1786,7 +1943,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
||||||
let mut late_depth = 0;
|
let mut late_depth = 0;
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
let lifetime = loop {
|
let mut opaque_capture_scopes = vec![];
|
||||||
|
let mut lifetime = loop {
|
||||||
match *scope {
|
match *scope {
|
||||||
Scope::Binder { s, scope_type, .. } => {
|
Scope::Binder { s, scope_type, .. } => {
|
||||||
match scope_type {
|
match scope_type {
|
||||||
|
@ -1800,7 +1958,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
|
|
||||||
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
|
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
|
||||||
|
|
||||||
Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
|
Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => {
|
||||||
|
break l.shifted(late_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::Opaque { captures, def_id, s } => {
|
||||||
|
opaque_capture_scopes.push((def_id, captures));
|
||||||
|
late_depth = 0;
|
||||||
|
scope = s;
|
||||||
|
}
|
||||||
|
|
||||||
Scope::Supertrait { s, .. }
|
Scope::Supertrait { s, .. }
|
||||||
| Scope::TraitRefBoundary { s, .. }
|
| Scope::TraitRefBoundary { s, .. }
|
||||||
|
@ -1809,7 +1975,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
|
|
||||||
|
lifetime = self.remap_opaque_captures(opaque_capture_scopes, lifetime, lifetime_ref.ident);
|
||||||
|
|
||||||
|
self.insert_lifetime(lifetime_ref, lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
@ -1818,18 +1987,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
||||||
self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
|
self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sometimes we resolve a lifetime, but later find that it is an
|
|
||||||
/// error (esp. around impl trait). In that case, we remove the
|
|
||||||
/// entry into `map.defs` so as not to confuse later code.
|
|
||||||
fn uninsert_lifetime_on_error(
|
|
||||||
&mut self,
|
|
||||||
lifetime_ref: &'tcx hir::Lifetime,
|
|
||||||
bad_def: ResolvedArg,
|
|
||||||
) {
|
|
||||||
let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id);
|
|
||||||
assert_eq!(old_value, Some(bad_def));
|
|
||||||
}
|
|
||||||
|
|
||||||
// When we have a return type notation type in a where clause, like
|
// When we have a return type notation type in a where clause, like
|
||||||
// `where <T as Trait>::method(..): Send`, we need to introduce new bound
|
// `where <T as Trait>::method(..): Send`, we need to introduce new bound
|
||||||
// vars to the existing where clause's binder, to represent the lifetimes
|
// vars to the existing where clause's binder, to represent the lifetimes
|
||||||
|
@ -2013,18 +2170,22 @@ fn is_late_bound_map(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
owner_id: hir::OwnerId,
|
owner_id: hir::OwnerId,
|
||||||
) -> Option<&FxIndexSet<hir::ItemLocalId>> {
|
) -> Option<&FxIndexSet<hir::ItemLocalId>> {
|
||||||
let decl = tcx.hir().fn_decl_by_hir_id(owner_id.into())?;
|
let sig = tcx.hir().fn_sig_by_hir_id(owner_id.into())?;
|
||||||
let generics = tcx.hir().get_generics(owner_id.def_id)?;
|
let generics = tcx.hir().get_generics(owner_id.def_id)?;
|
||||||
|
|
||||||
let mut late_bound = FxIndexSet::default();
|
let mut late_bound = FxIndexSet::default();
|
||||||
|
|
||||||
let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
|
let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
|
||||||
for arg_ty in decl.inputs {
|
for arg_ty in sig.decl.inputs {
|
||||||
constrained_by_input.visit_ty(arg_ty);
|
constrained_by_input.visit_ty(arg_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut appears_in_output = AllCollector::default();
|
let mut appears_in_output =
|
||||||
intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
|
AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
|
||||||
|
intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
|
||||||
|
if appears_in_output.has_fully_capturing_opaque {
|
||||||
|
appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
|
||||||
|
}
|
||||||
|
|
||||||
debug!(?constrained_by_input.regions);
|
debug!(?constrained_by_input.regions);
|
||||||
|
|
||||||
|
@ -2032,7 +2193,8 @@ fn is_late_bound_map(
|
||||||
//
|
//
|
||||||
// Subtle point: because we disallow nested bindings, we can just
|
// Subtle point: because we disallow nested bindings, we can just
|
||||||
// ignore binders here and scrape up all names we see.
|
// ignore binders here and scrape up all names we see.
|
||||||
let mut appears_in_where_clause = AllCollector::default();
|
let mut appears_in_where_clause =
|
||||||
|
AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
|
||||||
appears_in_where_clause.visit_generics(generics);
|
appears_in_where_clause.visit_generics(generics);
|
||||||
debug!(?appears_in_where_clause.regions);
|
debug!(?appears_in_where_clause.regions);
|
||||||
|
|
||||||
|
@ -2198,17 +2360,26 @@ fn is_late_bound_map(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
struct AllCollector<'tcx> {
|
||||||
struct AllCollector {
|
tcx: TyCtxt<'tcx>,
|
||||||
|
has_fully_capturing_opaque: bool,
|
||||||
regions: FxHashSet<LocalDefId>,
|
regions: FxHashSet<LocalDefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for AllCollector {
|
impl<'v> Visitor<'v> for AllCollector<'v> {
|
||||||
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
|
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
|
||||||
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
|
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
|
||||||
self.regions.insert(def_id);
|
self.regions.insert(def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
|
||||||
|
if !self.has_fully_capturing_opaque {
|
||||||
|
self.has_fully_capturing_opaque =
|
||||||
|
opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
|
||||||
|
}
|
||||||
|
intravisit::walk_opaque_ty(self, opaque);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,13 +294,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
lifetime: &hir::Lifetime,
|
lifetime: &hir::Lifetime,
|
||||||
reason: RegionInferReason<'_>,
|
reason: RegionInferReason<'_>,
|
||||||
) -> ty::Region<'tcx> {
|
) -> ty::Region<'tcx> {
|
||||||
|
if let Some(resolved) = self.tcx().named_bound_var(lifetime.hir_id) {
|
||||||
|
self.lower_resolved_lifetime(resolved)
|
||||||
|
} else {
|
||||||
|
self.re_infer(lifetime.ident.span, reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lower a lifetime from the HIR to our internal notion of a lifetime called a *region*.
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
|
pub fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
|
let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
|
||||||
|
|
||||||
match tcx.named_bound_var(lifetime.hir_id) {
|
match resolved {
|
||||||
Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
|
rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,
|
||||||
|
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
|
rbv::ResolvedArg::LateBound(debruijn, index, def_id) => {
|
||||||
let name = lifetime_name(def_id);
|
let name = lifetime_name(def_id);
|
||||||
let br = ty::BoundRegion {
|
let br = ty::BoundRegion {
|
||||||
var: ty::BoundVar::from_u32(index),
|
var: ty::BoundVar::from_u32(index),
|
||||||
|
@ -309,7 +319,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
ty::Region::new_bound(tcx, debruijn, br)
|
ty::Region::new_bound(tcx, debruijn, br)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
rbv::ResolvedArg::EarlyBound(def_id) => {
|
||||||
let name = tcx.hir().ty_param_name(def_id);
|
let name = tcx.hir().ty_param_name(def_id);
|
||||||
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
||||||
let generics = tcx.generics_of(item_def_id);
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
@ -317,7 +327,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
|
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(rbv::ResolvedArg::Free(scope, id)) => {
|
rbv::ResolvedArg::Free(scope, id) => {
|
||||||
let name = lifetime_name(id);
|
let name = lifetime_name(id);
|
||||||
ty::Region::new_late_param(
|
ty::Region::new_late_param(
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -328,9 +338,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// (*) -- not late-bound, won't change
|
// (*) -- not late-bound, won't change
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar),
|
rbv::ResolvedArg::Error(guar) => ty::Region::new_error(tcx, guar),
|
||||||
|
|
||||||
None => self.re_infer(lifetime.ident.span, reason),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2094,13 +2102,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
|
||||||
self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
|
self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
|
||||||
}
|
}
|
||||||
&hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
|
&hir::TyKind::OpaqueDef(opaque_ty) => {
|
||||||
let local_def_id = opaque_ty.def_id;
|
|
||||||
|
|
||||||
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
|
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
|
||||||
// generate the def_id of an associated type for the trait and return as
|
// generate the def_id of an associated type for the trait and return as
|
||||||
// type a projection.
|
// type a projection.
|
||||||
match opaque_ty.origin {
|
let in_trait = match opaque_ty.origin {
|
||||||
hir::OpaqueTyOrigin::FnReturn {
|
hir::OpaqueTyOrigin::FnReturn {
|
||||||
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
||||||
..
|
..
|
||||||
|
@ -2108,11 +2114,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
| hir::OpaqueTyOrigin::AsyncFn {
|
| hir::OpaqueTyOrigin::AsyncFn {
|
||||||
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
||||||
..
|
..
|
||||||
} => self.lower_opaque_ty(
|
} => true,
|
||||||
tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id(),
|
|
||||||
lifetimes,
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
hir::OpaqueTyOrigin::FnReturn {
|
hir::OpaqueTyOrigin::FnReturn {
|
||||||
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
||||||
..
|
..
|
||||||
|
@ -2121,10 +2123,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| hir::OpaqueTyOrigin::TyAlias { .. } => {
|
| hir::OpaqueTyOrigin::TyAlias { .. } => false,
|
||||||
self.lower_opaque_ty(local_def_id.to_def_id(), lifetimes, false)
|
};
|
||||||
}
|
|
||||||
}
|
self.lower_opaque_ty(opaque_ty.def_id, in_trait)
|
||||||
}
|
}
|
||||||
// If we encounter a type relative path with RTN generics, then it must have
|
// If we encounter a type relative path with RTN generics, then it must have
|
||||||
// *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
|
// *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
|
||||||
|
@ -2264,40 +2266,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
|
/// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
|
||||||
#[instrument(level = "debug", skip_all, ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn lower_opaque_ty(
|
fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {
|
||||||
&self,
|
|
||||||
def_id: DefId,
|
|
||||||
lifetimes: &[hir::GenericArg<'_>],
|
|
||||||
in_trait: bool,
|
|
||||||
) -> Ty<'tcx> {
|
|
||||||
debug!(?def_id, ?lifetimes);
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
let lifetimes = tcx.opaque_captured_lifetimes(def_id);
|
||||||
|
debug!(?lifetimes);
|
||||||
|
|
||||||
|
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
|
||||||
|
// generate the def_id of an associated type for the trait and return as
|
||||||
|
// type a projection.
|
||||||
|
let def_id = if in_trait {
|
||||||
|
tcx.associated_type_for_impl_trait_in_trait(def_id).to_def_id()
|
||||||
|
} else {
|
||||||
|
def_id.to_def_id()
|
||||||
|
};
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
debug!(?generics);
|
debug!(?generics);
|
||||||
|
|
||||||
let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
|
||||||
// We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
|
// We use `generics.count() - lifetimes.len()` here instead of `generics.parent_count`
|
||||||
// since return-position impl trait in trait squashes all of the generics from its source fn
|
// since return-position impl trait in trait squashes all of the generics from its source fn
|
||||||
// into its own generics, so the opaque's "own" params isn't always just lifetimes.
|
// into its own generics, so the opaque's "own" params isn't always just lifetimes.
|
||||||
if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len())
|
let offset = generics.count() - lifetimes.len();
|
||||||
{
|
|
||||||
// Resolve our own lifetime parameters.
|
let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
|
||||||
let GenericParamDefKind::Lifetime { .. } = param.kind else {
|
if let Some(i) = (param.index as usize).checked_sub(offset) {
|
||||||
span_bug!(
|
let (lifetime, _) = lifetimes[i];
|
||||||
tcx.def_span(param.def_id),
|
self.lower_resolved_lifetime(lifetime).into()
|
||||||
"only expected lifetime for opaque's own generics, got {:?}",
|
|
||||||
param
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
|
|
||||||
bug!(
|
|
||||||
"expected lifetime argument for param {param:?}, found {:?}",
|
|
||||||
&lifetimes[i]
|
|
||||||
)
|
|
||||||
};
|
|
||||||
self.lower_lifetime(lifetime, RegionInferReason::Param(¶m)).into()
|
|
||||||
} else {
|
} else {
|
||||||
tcx.mk_param_from_def(param)
|
tcx.mk_param_from_def(param)
|
||||||
}
|
}
|
||||||
|
|
|
@ -659,8 +659,6 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
|
fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
|
||||||
self.head("opaque");
|
self.head("opaque");
|
||||||
self.print_generic_params(o.generics.params);
|
|
||||||
self.print_where_clause(o.generics);
|
|
||||||
self.word("{");
|
self.word("{");
|
||||||
self.print_bounds("impl", o.bounds);
|
self.print_bounds("impl", o.bounds);
|
||||||
self.word("}");
|
self.word("}");
|
||||||
|
|
|
@ -69,7 +69,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
||||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx>) {
|
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
let hir::TyKind::OpaqueDef(opaque, _) = &ty.kind else {
|
let hir::TyKind::OpaqueDef(opaque) = &ty.kind else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use rustc_data_structures::sorted_map::SortedMap;
|
use rustc_data_structures::sorted_map::SortedMap;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::ItemLocalId;
|
use rustc_hir::ItemLocalId;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
|
||||||
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
|
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
|
||||||
|
|
||||||
use crate::ty;
|
use crate::ty;
|
||||||
|
@ -54,4 +54,6 @@ pub struct ResolveBoundVars {
|
||||||
pub defs: SortedMap<ItemLocalId, ResolvedArg>,
|
pub defs: SortedMap<ItemLocalId, ResolvedArg>,
|
||||||
|
|
||||||
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
|
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
|
||||||
|
|
||||||
|
pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1781,6 +1781,23 @@ rustc_queries! {
|
||||||
-> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>> {
|
-> &'tcx SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>> {
|
||||||
desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) }
|
desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) }
|
||||||
}
|
}
|
||||||
|
/// For an opaque type, return the list of (captured lifetime, inner generic param).
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into<Self> + 'b { ... }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound.
|
||||||
|
///
|
||||||
|
/// After hir_ty_lowering, we get:
|
||||||
|
/// ```ignore (pseudo-code)
|
||||||
|
/// opaque foo::<'a>::opaque<'_a, '_b>: Into<Foo<'_a>> + '_b;
|
||||||
|
/// ^^^^^^^^ inner generic params
|
||||||
|
/// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b>
|
||||||
|
/// ^^^^^^ captured lifetimes
|
||||||
|
/// ```
|
||||||
|
query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] {
|
||||||
|
desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the visibility of the provided `def_id`.
|
/// Computes the visibility of the provided `def_id`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -3060,7 +3060,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let parent = self.local_parent(opaque_lifetime_param_def_id);
|
let parent = self.local_parent(opaque_lifetime_param_def_id);
|
||||||
let hir::OpaqueTy { lifetime_mapping, .. } = self.hir().expect_opaque_ty(parent);
|
let lifetime_mapping = self.opaque_captured_lifetimes(parent);
|
||||||
|
|
||||||
let Some((lifetime, _)) = lifetime_mapping
|
let Some((lifetime, _)) = lifetime_mapping
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -3069,8 +3069,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
bug!("duplicated lifetime param should be present");
|
bug!("duplicated lifetime param should be present");
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.named_bound_var(lifetime.hir_id) {
|
match *lifetime {
|
||||||
Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => {
|
resolve_bound_vars::ResolvedArg::EarlyBound(ebv) => {
|
||||||
let new_parent = self.local_parent(ebv);
|
let new_parent = self.local_parent(ebv);
|
||||||
|
|
||||||
// If we map to another opaque, then it should be a parent
|
// If we map to another opaque, then it should be a parent
|
||||||
|
@ -3089,7 +3089,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
name: self.item_name(ebv.to_def_id()),
|
name: self.item_name(ebv.to_def_id()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
|
resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv) => {
|
||||||
let new_parent = self.local_parent(lbv);
|
let new_parent = self.local_parent(lbv);
|
||||||
return ty::Region::new_late_param(
|
return ty::Region::new_late_param(
|
||||||
self,
|
self,
|
||||||
|
@ -3100,13 +3100,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(resolve_bound_vars::ResolvedArg::Error(guar)) => {
|
resolve_bound_vars::ResolvedArg::Error(guar) => {
|
||||||
return ty::Region::new_error(self, guar);
|
return ty::Region::new_error(self, guar);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return ty::Region::new_error_with_message(
|
return ty::Region::new_error_with_message(
|
||||||
self,
|
self,
|
||||||
lifetime.ident.span,
|
self.def_span(opaque_lifetime_param_def_id),
|
||||||
"cannot resolve lifetime",
|
"cannot resolve lifetime",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1354,6 +1354,7 @@ impl<'tcx> Ty<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "trace", skip(tcx))]
|
||||||
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
|
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
|
FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
|
||||||
|
|
|
@ -841,10 +841,9 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
self.r.record_partial_res(ty.id, PartialRes::new(res));
|
self.r.record_partial_res(ty.id, PartialRes::new(res));
|
||||||
visit::walk_ty(self, ty)
|
visit::walk_ty(self, ty)
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(node_id, _) => {
|
TyKind::ImplTrait(_, _) => {
|
||||||
let candidates = self.lifetime_elision_candidates.take();
|
let candidates = self.lifetime_elision_candidates.take();
|
||||||
visit::walk_ty(self, ty);
|
visit::walk_ty(self, ty);
|
||||||
self.record_lifetime_params_for_impl_trait(*node_id);
|
|
||||||
self.lifetime_elision_candidates = candidates;
|
self.lifetime_elision_candidates = candidates;
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(bounds, ..) => {
|
TyKind::TraitObject(bounds, ..) => {
|
||||||
|
@ -977,14 +976,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
|
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
|
||||||
&sig.decl.output,
|
&sig.decl.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((coro_node_id, _)) = sig
|
|
||||||
.header
|
|
||||||
.coroutine_kind
|
|
||||||
.map(|coroutine_kind| coroutine_kind.return_id())
|
|
||||||
{
|
|
||||||
this.record_lifetime_params_for_impl_trait(coro_node_id);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -1026,10 +1017,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
.map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
|
.map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
|
||||||
&declaration.output,
|
&declaration.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((async_node_id, _)) = coro_node_id {
|
|
||||||
this.record_lifetime_params_for_impl_trait(async_node_id);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1220,7 +1207,6 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AssocItemConstraintKind::Bound { ref bounds } => {
|
AssocItemConstraintKind::Bound { ref bounds } => {
|
||||||
self.record_lifetime_params_for_impl_trait(constraint.id);
|
|
||||||
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
|
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4795,30 +4781,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct the list of in-scope lifetime parameters for impl trait lowering.
|
|
||||||
/// We include all lifetime parameters, either named or "Fresh".
|
|
||||||
/// The order of those parameters does not matter, as long as it is
|
|
||||||
/// deterministic.
|
|
||||||
fn record_lifetime_params_for_impl_trait(&mut self, impl_trait_node_id: NodeId) {
|
|
||||||
let mut extra_lifetime_params = vec![];
|
|
||||||
|
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
|
||||||
extra_lifetime_params
|
|
||||||
.extend(rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)));
|
|
||||||
match rib.kind {
|
|
||||||
LifetimeRibKind::Item => break,
|
|
||||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
|
||||||
if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
|
|
||||||
extra_lifetime_params.extend(earlier_fresh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.r.extra_lifetime_params_map.insert(impl_trait_node_id, extra_lifetime_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
|
fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
|
||||||
// FIXME: This caching may be incorrect in case of multiple `macro_rules`
|
// FIXME: This caching may be incorrect in case of multiple `macro_rules`
|
||||||
// items with the same name in the same module.
|
// items with the same name in the same module.
|
||||||
|
|
|
@ -284,7 +284,7 @@ pub fn suggest_new_region_bound(
|
||||||
}
|
}
|
||||||
match fn_return.kind {
|
match fn_return.kind {
|
||||||
// FIXME(precise_captures): Suggest adding to `use<...>` list instead.
|
// FIXME(precise_captures): Suggest adding to `use<...>` list instead.
|
||||||
TyKind::OpaqueDef(opaque, _) => {
|
TyKind::OpaqueDef(opaque) => {
|
||||||
// Get the identity type for this RPIT
|
// Get the identity type for this RPIT
|
||||||
let did = opaque.def_id.to_def_id();
|
let did = opaque.def_id.to_def_id();
|
||||||
let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did));
|
let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did));
|
||||||
|
|
|
@ -862,22 +862,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
self.add_lt_suggs.push(lt.suggestion(self.new_lt));
|
self.add_lt_suggs.push(lt.suggestion(self.new_lt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) {
|
|
||||||
let hir::TyKind::OpaqueDef(opaque_ty, _) = ty.kind else {
|
|
||||||
return hir::intravisit::walk_ty(self, ty);
|
|
||||||
};
|
|
||||||
if let Some(&(_, b)) =
|
|
||||||
opaque_ty.lifetime_mapping.iter().find(|&(a, _)| a.res == self.needle)
|
|
||||||
{
|
|
||||||
let prev_needle =
|
|
||||||
std::mem::replace(&mut self.needle, hir::LifetimeName::Param(b));
|
|
||||||
for bound in opaque_ty.bounds {
|
|
||||||
self.visit_param_bound(bound);
|
|
||||||
}
|
|
||||||
self.needle = prev_needle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (lifetime_def_id, lifetime_scope) =
|
let (lifetime_def_id, lifetime_scope) =
|
||||||
|
|
|
@ -361,7 +361,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
| hir::Node::TraitItem(hir::TraitItem { generics, .. })
|
| hir::Node::TraitItem(hir::TraitItem { generics, .. })
|
||||||
| hir::Node::ImplItem(hir::ImplItem { generics, .. })
|
| hir::Node::ImplItem(hir::ImplItem { generics, .. })
|
||||||
| hir::Node::OpaqueTy(hir::OpaqueTy { generics, .. })
|
|
||||||
if param_ty =>
|
if param_ty =>
|
||||||
{
|
{
|
||||||
// We skip the 0'th arg (self) because we do not want
|
// We skip the 0'th arg (self) because we do not want
|
||||||
|
@ -424,10 +423,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
| hir::ItemKind::Const(_, generics, _)
|
| hir::ItemKind::Const(_, generics, _)
|
||||||
| hir::ItemKind::TraitAlias(generics, _),
|
| hir::ItemKind::TraitAlias(generics, _),
|
||||||
..
|
..
|
||||||
})
|
}) if !param_ty => {
|
||||||
| hir::Node::OpaqueTy(hir::OpaqueTy { generics, .. })
|
|
||||||
if !param_ty =>
|
|
||||||
{
|
|
||||||
// Missing generic type parameter bound.
|
// Missing generic type parameter bound.
|
||||||
if suggest_arbitrary_trait_bound(
|
if suggest_arbitrary_trait_bound(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
|
|
|
@ -190,7 +190,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for RPITVisitor {
|
impl<'tcx> Visitor<'tcx> for RPITVisitor {
|
||||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||||
if let hir::TyKind::OpaqueDef(opaq, _) = ty.kind
|
if let hir::TyKind::OpaqueDef(opaq) = ty.kind
|
||||||
&& self.rpits.insert(opaq.def_id)
|
&& self.rpits.insert(opaq.def_id)
|
||||||
{
|
{
|
||||||
for bound in opaq.bounds {
|
for bound in opaq.bounds {
|
||||||
|
|
|
@ -1829,7 +1829,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
||||||
Array(Box::new(clean_ty(ty, cx)), length.into())
|
Array(Box::new(clean_ty(ty, cx)), length.into())
|
||||||
}
|
}
|
||||||
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
|
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
|
||||||
TyKind::OpaqueDef(ty, _) => {
|
TyKind::OpaqueDef(ty) => {
|
||||||
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
|
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
|
||||||
}
|
}
|
||||||
TyKind::Path(_) => clean_qpath(ty, cx),
|
TyKind::Path(_) => clean_qpath(ty, cx),
|
||||||
|
|
|
@ -420,15 +420,6 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
TyKind::OpaqueDef(opaque, bounds) => {
|
|
||||||
let len = self.lts.len();
|
|
||||||
self.visit_opaque_ty(opaque);
|
|
||||||
self.lts.truncate(len);
|
|
||||||
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
|
||||||
GenericArg::Lifetime(&l) => Some(l),
|
|
||||||
_ => None,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
TyKind::BareFn(&BareFnTy { decl, .. }) => {
|
TyKind::BareFn(&BareFnTy { decl, .. }) => {
|
||||||
let mut sub_visitor = RefVisitor::new(self.cx);
|
let mut sub_visitor = RefVisitor::new(self.cx);
|
||||||
sub_visitor.visit_fn_decl(decl);
|
sub_visitor.visit_fn_decl(decl);
|
||||||
|
|
|
@ -4,9 +4,11 @@ use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
|
Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
|
||||||
FnRetTy, GenericArg, GenericBound, ImplItem, Item, LifetimeName, Node, TraitRef, Ty, TyKind,
|
FnRetTy, GenericBound, ImplItem, Item, Node, OpaqueTy, TraitRef, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||||
|
use rustc_middle::ty;
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::{Span, sym};
|
use rustc_span::{Span, sym};
|
||||||
|
@ -44,21 +46,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
|
||||||
decl: &'tcx FnDecl<'_>,
|
decl: &'tcx FnDecl<'_>,
|
||||||
body: &'tcx Body<'_>,
|
body: &'tcx Body<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
def_id: LocalDefId,
|
fn_def_id: LocalDefId,
|
||||||
) {
|
) {
|
||||||
if let Some(header) = kind.header()
|
if let Some(header) = kind.header()
|
||||||
&& !header.asyncness.is_async()
|
&& !header.asyncness.is_async()
|
||||||
// Check that this function returns `impl Future`
|
// Check that this function returns `impl Future`
|
||||||
&& let FnRetTy::Return(ret_ty) = decl.output
|
&& let FnRetTy::Return(ret_ty) = decl.output
|
||||||
&& let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
|
&& let TyKind::OpaqueDef(opaque) = ret_ty.kind
|
||||||
|
&& let Some(trait_ref) = future_trait_ref(cx, opaque)
|
||||||
&& let Some(output) = future_output_ty(trait_ref)
|
&& let Some(output) = future_output_ty(trait_ref)
|
||||||
&& captures_all_lifetimes(decl.inputs, &output_lifetimes)
|
&& captures_all_lifetimes(cx, fn_def_id, opaque.def_id)
|
||||||
// Check that the body of the function consists of one async block
|
// Check that the body of the function consists of one async block
|
||||||
&& let ExprKind::Block(block, _) = body.value.kind
|
&& let ExprKind::Block(block, _) = body.value.kind
|
||||||
&& block.stmts.is_empty()
|
&& block.stmts.is_empty()
|
||||||
&& let Some(closure_body) = desugared_async_block(cx, block)
|
&& let Some(closure_body) = desugared_async_block(cx, block)
|
||||||
&& let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
|
&& let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
|
||||||
cx.tcx.hir_node_by_def_id(def_id)
|
cx.tcx.hir_node_by_def_id(fn_def_id)
|
||||||
{
|
{
|
||||||
let header_span = span.with_hi(ret_ty.span.hi());
|
let header_span = span.with_hi(ret_ty.span.hi());
|
||||||
|
|
||||||
|
@ -101,12 +104,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn future_trait_ref<'tcx>(
|
fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, opaque: &'tcx OpaqueTy<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
|
||||||
cx: &LateContext<'tcx>,
|
if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
|
||||||
ty: &'tcx Ty<'tcx>,
|
|
||||||
) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
|
|
||||||
if let TyKind::OpaqueDef(opaque, bounds) = ty.kind
|
|
||||||
&& let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
|
|
||||||
if let GenericBound::Trait(poly) = bound {
|
if let GenericBound::Trait(poly) = bound {
|
||||||
Some(&poly.trait_ref)
|
Some(&poly.trait_ref)
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,18 +114,7 @@ fn future_trait_ref<'tcx>(
|
||||||
})
|
})
|
||||||
&& trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
|
&& trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
|
||||||
{
|
{
|
||||||
let output_lifetimes = bounds
|
return Some(trait_ref);
|
||||||
.iter()
|
|
||||||
.filter_map(|bound| {
|
|
||||||
if let GenericArg::Lifetime(lt) = bound {
|
|
||||||
Some(lt.res)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
return Some((trait_ref, output_lifetimes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -145,27 +133,35 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) -> bool {
|
fn captures_all_lifetimes(cx: &LateContext<'_>, fn_def_id: LocalDefId, opaque_def_id: LocalDefId) -> bool {
|
||||||
let input_lifetimes: Vec<LifetimeName> = inputs
|
let early_input_params = ty::GenericArgs::identity_for_item(cx.tcx, fn_def_id);
|
||||||
.iter()
|
let late_input_params = cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(fn_def_id));
|
||||||
.filter_map(|ty| {
|
|
||||||
if let TyKind::Ref(lt, _) = ty.kind {
|
|
||||||
Some(lt.res)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// The lint should trigger in one of these cases:
|
let num_early_lifetimes = early_input_params
|
||||||
// - There are no input lifetimes
|
|
||||||
// - There's only one output lifetime bound using `+ '_`
|
|
||||||
// - All input lifetimes are explicitly bound to the output
|
|
||||||
input_lifetimes.is_empty()
|
|
||||||
|| (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
|
|
||||||
|| input_lifetimes
|
|
||||||
.iter()
|
.iter()
|
||||||
.all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))
|
.filter(|param| param.as_region().is_some())
|
||||||
|
.count();
|
||||||
|
let num_late_lifetimes = late_input_params
|
||||||
|
.iter()
|
||||||
|
.filter(|param_kind| matches!(param_kind, ty::BoundVariableKind::Region(_)))
|
||||||
|
.count();
|
||||||
|
|
||||||
|
// There is no lifetime, so they are all captured.
|
||||||
|
if num_early_lifetimes == 0 && num_late_lifetimes == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// By construction, each captured lifetime only appears once in `opaque_captured_lifetimes`.
|
||||||
|
let num_captured_lifetimes = cx
|
||||||
|
.tcx
|
||||||
|
.opaque_captured_lifetimes(opaque_def_id)
|
||||||
|
.iter()
|
||||||
|
.filter(|&(lifetime, _)| match *lifetime {
|
||||||
|
ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
num_captured_lifetimes == num_early_lifetimes + num_late_lifetimes
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
|
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
|
||||||
|
|
|
@ -1231,16 +1231,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TyKind::Path(ref qpath) => self.hash_qpath(qpath),
|
TyKind::Path(ref qpath) => self.hash_qpath(qpath),
|
||||||
TyKind::OpaqueDef(_, arg_list) => {
|
|
||||||
self.hash_generic_args(arg_list);
|
|
||||||
},
|
|
||||||
TyKind::TraitObject(_, lifetime, _) => {
|
TyKind::TraitObject(_, lifetime, _) => {
|
||||||
self.hash_lifetime(lifetime);
|
self.hash_lifetime(lifetime);
|
||||||
},
|
},
|
||||||
TyKind::Typeof(anon_const) => {
|
TyKind::Typeof(anon_const) => {
|
||||||
self.hash_body(anon_const.body);
|
self.hash_body(anon_const.body);
|
||||||
},
|
},
|
||||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
|
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) | TyKind::AnonAdt(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ error: the following explicit lifetimes could be elided: 'a
|
||||||
--> tests/ui/issue_4266.rs:10:21
|
--> tests/ui/issue_4266.rs:10:21
|
||||||
|
|
|
|
||||||
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
|
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
|
||||||
| ^^ ^^
|
| ^^ ^^ ^^
|
||||||
|
|
||||||
error: methods called `new` usually take no `self`
|
error: methods called `new` usually take no `self`
|
||||||
--> tests/ui/issue_4266.rs:31:22
|
--> tests/ui/issue_4266.rs:31:22
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
trait Foo<'i> {
|
trait Foo<'i> {
|
||||||
fn implicit_capture_early<'a: 'a>() -> impl Sized {}
|
fn implicit_capture_early<'a: 'a>() -> impl Sized {}
|
||||||
//~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
|
//~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
|
||||||
|
|
||||||
fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
|
fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {}
|
||||||
//~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
|
//~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
|
||||||
|
@ -13,12 +13,12 @@ trait Foo<'i> {
|
||||||
//~^ [Self: o, 'i: o, 'a: *, 'i: o]
|
//~^ [Self: o, 'i: o, 'a: *, 'i: o]
|
||||||
|
|
||||||
fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
|
fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
|
||||||
//~^ [Self: o, 'i: o, 'a: o, 'i: o]
|
//~^ [Self: o, 'i: o, 'i: o, 'a: o]
|
||||||
|
|
||||||
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
|
fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {}
|
||||||
//~^ [Self: o, 'i: o, 'i: o, 'a: o]
|
//~^ [Self: o, 'i: o, 'i: o, 'a: o]
|
||||||
|
|
||||||
fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
|
fn not_captured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
|
||||||
//~^ [Self: o, 'i: o, 'i: o]
|
//~^ [Self: o, 'i: o, 'i: o]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o]
|
error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:6:44
|
--> $DIR/variance.rs:6:44
|
||||||
|
|
|
|
||||||
LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {}
|
LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {}
|
||||||
|
@ -16,7 +16,7 @@ error: [Self: o, 'i: o, 'a: *, 'i: o]
|
||||||
LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
|
LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: [Self: o, 'i: o, 'a: o, 'i: o]
|
error: [Self: o, 'i: o, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:15:48
|
--> $DIR/variance.rs:15:48
|
||||||
|
|
|
|
||||||
LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
|
LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {}
|
||||||
|
@ -31,7 +31,7 @@ LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Sel
|
||||||
error: [Self: o, 'i: o, 'i: o]
|
error: [Self: o, 'i: o, 'i: o]
|
||||||
--> $DIR/variance.rs:21:44
|
--> $DIR/variance.rs:21:44
|
||||||
|
|
|
|
||||||
LL | fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
|
LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
#![rustc_variance_of_opaques]
|
#![rustc_variance_of_opaques]
|
||||||
|
|
||||||
fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
//~^ ERROR ['_: o]
|
//~^ ERROR []
|
||||||
//~| ERROR ['_: o]
|
//~| ERROR []
|
||||||
//~| ERROR `impl Trait` captures lifetime parameter
|
|
||||||
[*x]
|
[*x]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
|
error: []
|
||||||
--> $DIR/capturing-implicit.rs:8:11
|
|
||||||
|
|
|
||||||
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
|
||||||
| ^ -------------------------------------------- lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
|
||||||
| |
|
|
||||||
| this lifetime parameter is captured
|
|
||||||
|
|
||||||
error: ['_: o]
|
|
||||||
--> $DIR/capturing-implicit.rs:8:19
|
--> $DIR/capturing-implicit.rs:8:19
|
||||||
|
|
|
|
||||||
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: ['_: o]
|
error: []
|
||||||
--> $DIR/capturing-implicit.rs:8:44
|
--> $DIR/capturing-implicit.rs:8:44
|
||||||
|
|
|
|
||||||
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
LL | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ impl<T> Captures<'_> for T {}
|
||||||
|
|
||||||
fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
||||||
|
//~| ERROR return type cannot have an unboxed trait object
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +13,9 @@ pub fn main() {
|
||||||
//~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
//~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
||||||
type Opaque = impl Sized;
|
type Opaque = impl Sized;
|
||||||
fn define() -> Opaque {
|
fn define() -> Opaque {
|
||||||
|
//~^ ERROR the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
||||||
let x: Opaque = dyn_hoops::<()>();
|
let x: Opaque = dyn_hoops::<()>();
|
||||||
|
//~^ ERROR the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,57 @@ note: lifetime declared here
|
||||||
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
|
error[E0746]: return type cannot have an unboxed trait object
|
||||||
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:6:29
|
||||||
|
|
|
||||||
|
LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
help: consider returning an `impl Trait` instead of a `dyn Trait`
|
||||||
|
|
|
||||||
|
LL | fn dyn_hoops<T: Sized>() -> impl for<'a> Iterator<Item = impl Captures<'a>> {
|
||||||
|
| ~~~~
|
||||||
|
help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
|
||||||
|
|
|
||||||
|
LL ~ fn dyn_hoops<T: Sized>() -> Box<dyn for<'a> Iterator<Item = impl Captures<'a>>> {
|
||||||
|
LL |
|
||||||
|
LL |
|
||||||
|
LL ~ Box::new(loop {})
|
||||||
|
|
|
||||||
|
|
||||||
error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:11:8
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:12:8
|
||||||
|
|
|
|
||||||
LL | pub fn main() {
|
LL | pub fn main() {
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= note: consider moving the opaque type's declaration and defining uses into a separate module
|
= note: consider moving the opaque type's declaration and defining uses into a separate module
|
||||||
note: this opaque type is in the signature
|
note: this opaque type is in the signature
|
||||||
--> $DIR/bound-lifetime-through-dyn-trait.rs:13:19
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:14:19
|
||||||
|
|
|
|
||||||
LL | type Opaque = impl Sized;
|
LL | type Opaque = impl Sized;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)` cannot be known at compilation time
|
||||||
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:15:20
|
||||||
|
|
|
||||||
|
LL | fn define() -> Opaque {
|
||||||
|
| ^^^^^^ doesn't have a size known at compile-time
|
||||||
|
...
|
||||||
|
LL | x
|
||||||
|
| - return type was inferred to be `(dyn Iterator<Item = impl Captures<'_>> + 'static)` here
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0657`.
|
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Captures<'_>> + 'static)` cannot be known at compilation time
|
||||||
|
--> $DIR/bound-lifetime-through-dyn-trait.rs:17:25
|
||||||
|
|
|
||||||
|
LL | let x: Opaque = dyn_hoops::<()>();
|
||||||
|
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Captures<'_>> + 'static)`
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0657, E0746.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -8,6 +8,7 @@ trait Test<'a> {}
|
||||||
|
|
||||||
pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
||||||
|
//~| ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
||||||
|
|
||||||
impl Trait<'_> for () {
|
impl Trait<'_> for () {
|
||||||
type Assoc = ();
|
type Assoc = ();
|
||||||
|
|
|
@ -10,6 +10,18 @@ note: lifetime declared here
|
||||||
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
||||||
|
--> $DIR/escaping-bound-var.rs:9:57
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
note: lifetime declared here
|
||||||
|
--> $DIR/escaping-bound-var.rs:9:25
|
||||||
|
|
|
||||||
|
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0657`.
|
For more information about this error, try `rustc --explain E0657`.
|
||||||
|
|
|
@ -11,11 +11,11 @@ type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o]
|
||||||
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o]
|
type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ ['a: *, 'b: o, 'a: o]
|
type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ ['a: *, 'a: o, 'b: o]
|
||||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
||||||
//~| ERROR: unconstrained opaque type
|
//~| ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ ['a: *, 'b: o, 'a: o]
|
type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ ['a: *, 'a: o, 'b: o]
|
||||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
|
||||||
//~| ERROR: unconstrained opaque type
|
//~| ERROR: unconstrained opaque type
|
||||||
|
|
||||||
|
@ -31,24 +31,24 @@ trait Foo<'i> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'i> Foo<'i> for &'i () {
|
impl<'i> Foo<'i> for &'i () {
|
||||||
type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'i> Foo<'i> for () {
|
impl<'i> Foo<'i> for () {
|
||||||
type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
|
|
||||||
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'a: o, 'i: o]
|
type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
//~^ ERROR: unconstrained opaque type
|
//~^ ERROR: unconstrained opaque type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,13 +122,13 @@ error: ['a: *, 'a: o]
|
||||||
LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
|
LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: ['a: *, 'b: o, 'a: o]
|
error: ['a: *, 'a: o, 'b: o]
|
||||||
--> $DIR/variance.rs:14:56
|
--> $DIR/variance.rs:14:56
|
||||||
|
|
|
|
||||||
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
|
LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: ['a: *, 'b: o, 'a: o]
|
error: ['a: *, 'a: o, 'b: o]
|
||||||
--> $DIR/variance.rs:18:49
|
--> $DIR/variance.rs:18:49
|
||||||
|
|
|
|
||||||
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
|
LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
|
||||||
|
@ -140,37 +140,37 @@ error: ['a: *, 'b: *, T: o, 'a: o, 'b: o]
|
||||||
LL | type Bar<'a, 'b: 'b, T> = impl Sized;
|
LL | type Bar<'a, 'b: 'b, T> = impl Sized;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:34:32
|
--> $DIR/variance.rs:34:32
|
||||||
|
|
|
|
||||||
LL | type ImplicitCapture<'a> = impl Sized;
|
LL | type ImplicitCapture<'a> = impl Sized;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:37:42
|
--> $DIR/variance.rs:37:42
|
||||||
|
|
|
|
||||||
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:40:39
|
--> $DIR/variance.rs:40:39
|
||||||
|
|
|
|
||||||
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:45:32
|
--> $DIR/variance.rs:45:32
|
||||||
|
|
|
|
||||||
LL | type ImplicitCapture<'a> = impl Sized;
|
LL | type ImplicitCapture<'a> = impl Sized;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:48:42
|
--> $DIR/variance.rs:48:42
|
||||||
|
|
|
|
||||||
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: ['i: *, 'a: *, 'a: o, 'i: o]
|
error: ['i: *, 'a: *, 'i: o, 'a: o]
|
||||||
--> $DIR/variance.rs:51:39
|
--> $DIR/variance.rs:51:39
|
||||||
|
|
|
|
||||||
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue