Auto merge of #128440 - oli-obk:defines, r=lcnr
Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed. A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table. Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable. Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature. One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now. fixes #131298
This commit is contained in:
commit
6650252439
666 changed files with 3025 additions and 2582 deletions
|
@ -397,32 +397,37 @@ pub(crate) enum AliasPossibility {
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum PathSource<'a> {
|
||||
// Type paths `Path`.
|
||||
/// Type paths `Path`.
|
||||
Type,
|
||||
// Trait paths in bounds or impls.
|
||||
/// Trait paths in bounds or impls.
|
||||
Trait(AliasPossibility),
|
||||
// Expression paths `path`, with optional parent context.
|
||||
/// Expression paths `path`, with optional parent context.
|
||||
Expr(Option<&'a Expr>),
|
||||
// Paths in path patterns `Path`.
|
||||
/// Paths in path patterns `Path`.
|
||||
Pat,
|
||||
// Paths in struct expressions and patterns `Path { .. }`.
|
||||
/// Paths in struct expressions and patterns `Path { .. }`.
|
||||
Struct,
|
||||
// Paths in tuple struct patterns `Path(..)`.
|
||||
/// Paths in tuple struct patterns `Path(..)`.
|
||||
TupleStruct(Span, &'a [Span]),
|
||||
// `m::A::B` in `<T as m::A>::B::C`.
|
||||
/// `m::A::B` in `<T as m::A>::B::C`.
|
||||
TraitItem(Namespace),
|
||||
// Paths in delegation item
|
||||
/// Paths in delegation item
|
||||
Delegation,
|
||||
/// An arg in a `use<'a, N>` precise-capturing bound.
|
||||
PreciseCapturingArg(Namespace),
|
||||
// Paths that end with `(..)`, for return type notation.
|
||||
/// Paths that end with `(..)`, for return type notation.
|
||||
ReturnTypeNotation,
|
||||
/// Paths from `#[define_opaque]` attributes
|
||||
DefineOpaques,
|
||||
}
|
||||
|
||||
impl<'a> PathSource<'a> {
|
||||
fn namespace(self) -> Namespace {
|
||||
match self {
|
||||
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
|
||||
PathSource::Type
|
||||
| PathSource::Trait(_)
|
||||
| PathSource::Struct
|
||||
| PathSource::DefineOpaques => TypeNS,
|
||||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
| PathSource::TupleStruct(..)
|
||||
|
@ -443,6 +448,7 @@ impl<'a> PathSource<'a> {
|
|||
| PathSource::ReturnTypeNotation => true,
|
||||
PathSource::Trait(_)
|
||||
| PathSource::TraitItem(..)
|
||||
| PathSource::DefineOpaques
|
||||
| PathSource::Delegation
|
||||
| PathSource::PreciseCapturingArg(..) => false,
|
||||
}
|
||||
|
@ -450,6 +456,7 @@ impl<'a> PathSource<'a> {
|
|||
|
||||
fn descr_expected(self) -> &'static str {
|
||||
match &self {
|
||||
PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
|
||||
PathSource::Type => "type",
|
||||
PathSource::Trait(_) => "trait",
|
||||
PathSource::Pat => "unit struct, unit variant or constant",
|
||||
|
@ -493,6 +500,19 @@ impl<'a> PathSource<'a> {
|
|||
|
||||
pub(crate) fn is_expected(self, res: Res) -> bool {
|
||||
match self {
|
||||
PathSource::DefineOpaques => {
|
||||
matches!(
|
||||
res,
|
||||
Res::Def(
|
||||
DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::TyAlias
|
||||
| DefKind::AssocTy,
|
||||
_
|
||||
) | Res::SelfTyAlias { .. }
|
||||
)
|
||||
}
|
||||
PathSource::Type => matches!(
|
||||
res,
|
||||
Res::Def(
|
||||
|
@ -572,16 +592,16 @@ impl<'a> PathSource<'a> {
|
|||
match (self, has_unexpected_resolution) {
|
||||
(PathSource::Trait(_), true) => E0404,
|
||||
(PathSource::Trait(_), false) => E0405,
|
||||
(PathSource::Type, true) => E0573,
|
||||
(PathSource::Type, false) => E0412,
|
||||
(PathSource::Type | PathSource::DefineOpaques, true) => E0573,
|
||||
(PathSource::Type | PathSource::DefineOpaques, false) => E0412,
|
||||
(PathSource::Struct, true) => E0574,
|
||||
(PathSource::Struct, false) => E0422,
|
||||
(PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
|
||||
(PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
|
||||
(PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
|
||||
(PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
|
||||
(PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
|
||||
(PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575,
|
||||
(PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, false) => E0576,
|
||||
(PathSource::PreciseCapturingArg(..), true) => E0799,
|
||||
(PathSource::PreciseCapturingArg(..), false) => E0800,
|
||||
}
|
||||
|
@ -2006,6 +2026,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
| PathSource::Pat
|
||||
| PathSource::Struct
|
||||
| PathSource::TupleStruct(..)
|
||||
| PathSource::DefineOpaques
|
||||
| PathSource::Delegation => true,
|
||||
};
|
||||
if inferred {
|
||||
|
@ -2619,7 +2640,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
ItemKind::Fn(box Fn { ref generics, .. }) => {
|
||||
ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
|
||||
|
@ -2630,6 +2651,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
},
|
||||
|this| visit::walk_item(this, item),
|
||||
);
|
||||
|
||||
for (id, path) in define_opaque.iter().flatten() {
|
||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
||||
}
|
||||
}
|
||||
|
||||
ItemKind::Enum(_, ref generics)
|
||||
|
@ -3100,8 +3125,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
},
|
||||
);
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
||||
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
||||
|
||||
for (id, path) in define_opaque.iter().flatten() {
|
||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
||||
}
|
||||
}
|
||||
AssocItemKind::Delegation(delegation) => {
|
||||
self.with_generic_param_rib(
|
||||
|
@ -3311,7 +3340,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
},
|
||||
);
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||
AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
|
||||
debug!("resolve_implementation AssocItemKind::Fn");
|
||||
// We also need a new scope for the impl item type parameters.
|
||||
self.with_generic_param_rib(
|
||||
|
@ -3338,6 +3367,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
visit::walk_assoc_item(this, item, AssocCtxt::Impl)
|
||||
},
|
||||
);
|
||||
|
||||
for (id, path) in define_opaque.iter().flatten() {
|
||||
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
|
||||
}
|
||||
}
|
||||
AssocItemKind::Type(box TyAlias { generics, .. }) => {
|
||||
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue