Auto merge of #112891 - oli-obk:impl_trait_in_assoc_tys_cleanup, r=compiler-errors
Various impl trait in assoc tys cleanups r? `@compiler-errors` All commits except for the last are pure refactorings. 274dab5bd658c97886a8987340bf50ae57900c39 allows struct fields to participate in deciding whether a function has an opaque in its signature. best reviewed commit by commit
This commit is contained in:
commit
1d67eba687
@ -3743,6 +3743,29 @@ pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the type for constants, assoc types, type aliases and statics.
|
||||
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
|
||||
match self {
|
||||
Node::Item(it) => match it.kind {
|
||||
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
|
||||
Some(ty)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
Node::TraitItem(it) => match it.kind {
|
||||
TraitItemKind::Const(ty, _) => Some(ty),
|
||||
TraitItemKind::Type(_, ty) => ty,
|
||||
_ => None,
|
||||
},
|
||||
Node::ImplItem(it) => match it.kind {
|
||||
ImplItemKind::Const(ty, _) => Some(ty),
|
||||
ImplItemKind::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
|
||||
match self {
|
||||
Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
|
||||
|
@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
||||
check_union(tcx, id.owner_id.def_id);
|
||||
}
|
||||
DefKind::OpaqueTy => {
|
||||
let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
|
||||
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
|
||||
let origin = tcx.opaque_type_origin(id.owner_id.def_id);
|
||||
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
|
||||
&& let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
|
||||
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
|
||||
{
|
||||
|
@ -1543,8 +1543,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
|
||||
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
|
||||
&& self.seen.insert(unshifted_opaque_ty.def_id)
|
||||
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
|
||||
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
|
||||
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
|
||||
&& let origin = tcx.opaque_type_origin(opaque_def_id)
|
||||
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
|
||||
&& source == self.fn_def_id
|
||||
{
|
||||
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
|
||||
|
@ -260,7 +260,8 @@ fn foo(&self, x: T) -> T { x }
|
||||
(ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
|
||||
if tcx.is_type_alias_impl_trait(alias.def_id) {
|
||||
if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
|
||||
diag.span_note(tcx.def_span(body_owner_def_id), "\
|
||||
let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id));
|
||||
diag.span_note(sp, "\
|
||||
this item must have the opaque type in its signature \
|
||||
in order to be able to register hidden types");
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
|
||||
DefiningAnchor::Bind(bind) => bind,
|
||||
};
|
||||
|
||||
let origin = self.opaque_type_origin_unchecked(def_id);
|
||||
let origin = self.tcx.opaque_type_origin(def_id);
|
||||
let in_definition_scope = match origin {
|
||||
// Async `impl Trait`
|
||||
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
|
||||
@ -395,13 +395,6 @@ pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
|
||||
};
|
||||
in_definition_scope.then_some(origin)
|
||||
}
|
||||
|
||||
/// Returns the origin of the opaque type `def_id` even if we are not in its
|
||||
/// defining scope.
|
||||
#[instrument(skip(self), level = "trace", ret)]
|
||||
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
|
||||
self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor that requires that (almost) all regions in the type visited outlive
|
||||
|
@ -1138,8 +1138,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
||||
| DefKind::InlineConst => true,
|
||||
|
||||
DefKind::OpaqueTy => {
|
||||
let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty();
|
||||
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
|
||||
let origin = tcx.opaque_type_origin(def_id);
|
||||
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
|
||||
&& let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
|
||||
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
|
||||
{
|
||||
|
@ -1192,6 +1192,12 @@ pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
|
||||
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
|
||||
self.visibility(def_id).expect_local()
|
||||
}
|
||||
|
||||
/// Returns the origin of the opaque type `def_id`.
|
||||
#[instrument(skip(self), level = "trace", ret)]
|
||||
pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
|
||||
self.hir().expect_item(def_id).expect_opaque_ty().origin
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait implemented for all `X<'a>` types that can be safely and
|
||||
|
@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
opaque_ty_def_id: LocalDefId,
|
||||
) -> LocalDefId {
|
||||
let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
|
||||
tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
|
||||
tcx.opaque_type_origin(opaque_ty_def_id)
|
||||
else {
|
||||
bug!("expected opaque for {opaque_ty_def_id:?}");
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_impl_trait_not_param)]
|
||||
#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
|
||||
pub struct NotParam<'tcx> {
|
||||
pub arg: GenericArg<'tcx>,
|
||||
#[primary_span]
|
||||
|
@ -1,5 +1,4 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::{def::DefKind, def_id::LocalDefId};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
|
||||
@ -19,21 +18,26 @@ struct OpaqueTypeCollector<'tcx> {
|
||||
|
||||
/// Avoid infinite recursion due to recursive declarations.
|
||||
seen: FxHashSet<LocalDefId>,
|
||||
|
||||
span: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeCollector<'tcx> {
|
||||
fn collect(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: LocalDefId,
|
||||
val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
|
||||
) -> Vec<LocalDefId> {
|
||||
let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
|
||||
val.skip_binder().visit_with(&mut collector);
|
||||
collector.opaques
|
||||
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
|
||||
Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
|
||||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
self.tcx.def_span(self.item)
|
||||
self.span.unwrap_or_else(|| {
|
||||
self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item))
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
|
||||
let old = self.span;
|
||||
self.span = Some(span);
|
||||
value.visit_with(self);
|
||||
self.span = old;
|
||||
}
|
||||
|
||||
fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
|
||||
@ -60,53 +64,57 @@ fn parent(&self) -> Option<LocalDefId> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||
type BreakTy = ErrorGuaranteed;
|
||||
|
||||
#[instrument(skip(self), ret, level = "trace")]
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
|
||||
t.super_visit_with(self)?;
|
||||
match t.kind() {
|
||||
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
|
||||
if !self.seen.insert(alias_ty.def_id.expect_local()) {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
self.opaques.push(alias_ty.def_id.expect_local());
|
||||
|
||||
match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
|
||||
Ok(()) => {
|
||||
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
|
||||
// supported at all, so this is sound to do, but once we want to support them, you'll
|
||||
// start seeing the error below.
|
||||
|
||||
self.opaques.push(alias_ty.def_id.expect_local());
|
||||
|
||||
// Collect opaque types nested within the associated type bounds of this opaque type.
|
||||
for (pred, _span) in self
|
||||
// We use identity substs here, because we already know that the opaque type uses
|
||||
// only generic parameters, and thus substituting would not give us more information.
|
||||
for (pred, span) in self
|
||||
.tcx
|
||||
.explicit_item_bounds(alias_ty.def_id)
|
||||
.subst_iter_copied(self.tcx, alias_ty.substs)
|
||||
.subst_identity_iter_copied()
|
||||
{
|
||||
trace!(?pred);
|
||||
pred.visit_with(self)?;
|
||||
self.visit_spanned(span, pred);
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
Err(NotUniqueParam::NotParam(arg)) => {
|
||||
let err = self.tcx.sess.emit_err(NotParam {
|
||||
self.tcx.sess.emit_err(NotParam {
|
||||
arg,
|
||||
span: self.span(),
|
||||
opaque_span: self.tcx.def_span(alias_ty.def_id),
|
||||
});
|
||||
ControlFlow::Break(err)
|
||||
}
|
||||
Err(NotUniqueParam::DuplicateParam(arg)) => {
|
||||
let err = self.tcx.sess.emit_err(DuplicateArg {
|
||||
self.tcx.sess.emit_err(DuplicateArg {
|
||||
arg,
|
||||
span: self.span(),
|
||||
opaque_span: self.tcx.def_span(alias_ty.def_id),
|
||||
});
|
||||
ControlFlow::Break(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
|
||||
self.tcx
|
||||
.type_of(alias_ty.def_id)
|
||||
.subst(self.tcx, alias_ty.substs)
|
||||
.visit_with(self)?;
|
||||
}
|
||||
ty::Alias(ty::Projection, alias_ty) => {
|
||||
// This avoids having to do normalization of `Self::AssocTy` by only
|
||||
// supporting the case of a method defining opaque types from assoc types
|
||||
@ -136,26 +144,44 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
|
||||
ty::InternalSubsts::identity_for_item(self.tcx, parent),
|
||||
);
|
||||
|
||||
if !check_substs_compatible(self.tcx, assoc, impl_substs) {
|
||||
if check_substs_compatible(self.tcx, assoc, impl_substs) {
|
||||
return self
|
||||
.tcx
|
||||
.type_of(assoc.def_id)
|
||||
.subst(self.tcx, impl_substs)
|
||||
.visit_with(self);
|
||||
} else {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
self.tcx.def_span(assoc.def_id),
|
||||
"item had incorrect substs",
|
||||
);
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
return self
|
||||
.tcx
|
||||
.type_of(assoc.def_id)
|
||||
.subst(self.tcx, impl_substs)
|
||||
.visit_with(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
_ => t.super_visit_with(self),
|
||||
ty::Adt(def, _) if def.did().is_local() => {
|
||||
if !self.seen.insert(def.did().expect_local()) {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
for variant in def.variants().iter() {
|
||||
for field in variant.fields.iter() {
|
||||
// Don't use the `ty::Adt` substs, we either
|
||||
// * found the opaque in the substs
|
||||
// * will find the opaque in the unsubstituted fields
|
||||
// The only other situation that can occur is that after substituting,
|
||||
// some projection resolves to an opaque that we would have otherwise
|
||||
// not found. While we could substitute and walk those, that would mean we
|
||||
// would have to walk all substitutions of an Adt, which can quickly
|
||||
// degenerate into looking at an exponential number of types.
|
||||
let ty = self.tcx.type_of(field.did).subst_identity();
|
||||
self.visit_spanned(self.tcx.def_span(field.did), ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => trace!(kind=?t.kind()),
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
|
||||
match kind {
|
||||
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
|
||||
DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||
let defined_opaques = match kind {
|
||||
DefKind::Fn => {
|
||||
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
|
||||
let mut collector = OpaqueTypeCollector::new(tcx, item);
|
||||
match kind {
|
||||
// Walk over the signature of the function-like to find the opaques.
|
||||
DefKind::AssocFn | DefKind::Fn => {
|
||||
let ty_sig = tcx.fn_sig(item).subst_identity();
|
||||
let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
|
||||
// Walk over the inputs and outputs manually in order to get good spans for them.
|
||||
collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
|
||||
for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
|
||||
collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
|
||||
}
|
||||
}
|
||||
DefKind::AssocFn => {
|
||||
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
|
||||
// Walk over the type of the item to find opaques.
|
||||
DefKind::AssocTy | DefKind::AssocConst => {
|
||||
let span = match tcx.hir().get_by_def_id(item).ty() {
|
||||
Some(ty) => ty.span,
|
||||
_ => tcx.def_span(item),
|
||||
};
|
||||
collector.visit_spanned(span, tcx.type_of(item).subst_identity());
|
||||
}
|
||||
DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
|
||||
tcx,
|
||||
item,
|
||||
ty::Binder::dummy(tcx.type_of(item).subst_identity()),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
tcx.arena.alloc_from_iter(defined_opaques)
|
||||
}
|
||||
tcx.arena.alloc_from_iter(collector.opaques)
|
||||
}
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
@ -209,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator => &[],
|
||||
| DefKind::Generator => {
|
||||
span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,19 @@ fn foo(&self) { }
|
||||
pub type Type10 = impl Send;
|
||||
pub type Type11 = impl Send;
|
||||
|
||||
pub fn fn1<'a>() {
|
||||
pub fn fn1<'a>() where
|
||||
Type1: 'static,
|
||||
Type2: 'static,
|
||||
Type3: 'static,
|
||||
Type4: 'static,
|
||||
Type5: 'static,
|
||||
Type6: 'static,
|
||||
Type7: 'static,
|
||||
Type8: 'static,
|
||||
Type9: 'static,
|
||||
Type10: 'static,
|
||||
Type11: 'static,
|
||||
{
|
||||
// Closure
|
||||
let closure1 = || { };
|
||||
let _: Type1 = closure1;
|
||||
|
@ -19,5 +19,4 @@ impl<'a> A<'a> for C {
|
||||
type B<'b> = impl Clone;
|
||||
|
||||
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/issue-88595.rs:21:5
|
||||
--> $DIR/issue-88595.rs:21:23
|
||||
|
|
||||
LL | fn a(&'a self) -> Self::B<'a> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
|
||||
| ^^^^^^^^^^^ generic argument `'a` used twice
|
||||
|
|
||||
note: for this opaque type
|
||||
--> $DIR/issue-88595.rs:19:18
|
||||
@ -10,25 +10,5 @@ note: for this opaque type
|
||||
LL | type B<'b> = impl Clone;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-88595.rs:21:23
|
||||
|
|
||||
LL | type B<'b> = impl Clone;
|
||||
| ---------- the expected opaque type
|
||||
LL |
|
||||
LL | fn a(&'a self) -> Self::B<'a> {}
|
||||
| - ^^^^^^^^^^^ expected opaque type, found `()`
|
||||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
|
||||
= note: expected opaque type `<C as A<'a>>::B<'a>`
|
||||
found unit type `()`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/issue-88595.rs:21:5
|
||||
|
|
||||
LL | fn a(&'a self) -> Self::B<'a> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -40,10 +40,10 @@ LL | fn method() -> Self::Ty;
|
||||
= note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
|
||||
found signature `fn()`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/in-assoc-type-unconstrained.rs:22:9
|
||||
--> $DIR/in-assoc-type-unconstrained.rs:22:12
|
||||
|
|
||||
LL | fn method() -> () {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/in-assoc-type-unconstrained.rs:20:19
|
||||
|
@ -12,10 +12,10 @@ LL | fn foo(&self) -> <Self as Foo<()>>::Bar {}
|
||||
= note: expected opaque type `<() as Foo<()>>::Bar`
|
||||
found unit type `()`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/in-assoc-type.rs:17:5
|
||||
--> $DIR/in-assoc-type.rs:17:8
|
||||
|
|
||||
LL | fn foo(&self) -> <Self as Foo<()>>::Bar {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -20,11 +20,6 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
|
|
||||
= note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
|
||||
found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9
|
||||
|
|
||||
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unconstrained opaque type
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
|
||||
@ -49,10 +44,10 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
= note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
|
||||
found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:9
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
|
||||
|
|
||||
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
//! This test shows that a field type that is a projection that resolves to an opaque,
|
||||
//! is not a defining use. While we could substitute the struct generics, that would
|
||||
//! mean we would have to walk all substitutions of an `Foo`, which can quickly
|
||||
//! degenerate into looking at an exponential number of types depending on the complexity
|
||||
//! of a program.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
struct Bar;
|
||||
|
||||
trait Trait: Sized {
|
||||
type Assoc;
|
||||
fn foo() -> Foo<Self>;
|
||||
}
|
||||
|
||||
impl Trait for Bar {
|
||||
type Assoc = impl std::fmt::Debug;
|
||||
fn foo() -> Foo<Bar> {
|
||||
Foo { field: () }
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo<T: Trait> {
|
||||
field: <T as Trait>::Assoc,
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,20 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/hidden_behind_projection_behind_struct_field.rs:19:22
|
||||
|
|
||||
LL | type Assoc = impl std::fmt::Debug;
|
||||
| -------------------- the expected opaque type
|
||||
LL | fn foo() -> Foo<Bar> {
|
||||
LL | Foo { field: () }
|
||||
| ^^ expected opaque type, found `()`
|
||||
|
|
||||
= note: expected opaque type `<Bar as Trait>::Assoc`
|
||||
found unit type `()`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/hidden_behind_projection_behind_struct_field.rs:18:8
|
||||
|
|
||||
LL | fn foo() -> Foo<Bar> {
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
30
tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
Normal file
30
tests/ui/type-alias-impl-trait/hidden_behind_struct_field.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! This test shows that the appearance of an opaque type
|
||||
//! in the substs of a struct are enough to make it count
|
||||
//! for making the function a defining use. It doesn't matter
|
||||
//! if the opaque type is actually used in the field.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
// check-pass
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Bar;
|
||||
|
||||
trait Trait: Sized {
|
||||
type Assoc;
|
||||
fn foo() -> Foo<Self::Assoc>;
|
||||
}
|
||||
|
||||
impl Trait for Bar {
|
||||
type Assoc = impl std::fmt::Debug;
|
||||
fn foo() -> Foo<Self::Assoc> {
|
||||
let foo: Foo<()> = Foo { field: PhantomData };
|
||||
foo
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo<T> {
|
||||
field: PhantomData<T>,
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,26 @@
|
||||
//! This test shows that we can even follow projections
|
||||
//! into associated types of the same impl if they are
|
||||
//! indirectly mentioned in a struct field.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
// check-pass
|
||||
|
||||
struct Bar;
|
||||
|
||||
trait Trait: Sized {
|
||||
type Assoc;
|
||||
fn foo() -> Foo;
|
||||
}
|
||||
|
||||
impl Trait for Bar {
|
||||
type Assoc = impl std::fmt::Debug;
|
||||
fn foo() -> Foo {
|
||||
Foo { field: () }
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
field: <Bar as Trait>::Assoc,
|
||||
}
|
||||
|
||||
fn main() {}
|
35
tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
Normal file
35
tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//! This test checks that we can't actually have an opaque type behind
|
||||
//! a binder that references variables from that binder.
|
||||
|
||||
// edition: 2021
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait B {
|
||||
type C;
|
||||
}
|
||||
|
||||
struct A;
|
||||
|
||||
impl<'a> B for &'a A {
|
||||
type C = Tait<'a>;
|
||||
}
|
||||
|
||||
type Tait<'a> = impl std::fmt::Debug + 'a;
|
||||
|
||||
struct Terminator;
|
||||
|
||||
type Successors<'a> = impl std::fmt::Debug + 'a;
|
||||
|
||||
impl Terminator {
|
||||
fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
|
||||
f = g;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
fn g(x: &()) -> &() {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
Normal file
15
tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/higher_kinded_params3.rs:26:9
|
||||
|
|
||||
LL | type Tait<'a> = impl std::fmt::Debug + 'a;
|
||||
| ------------------------- the expected opaque type
|
||||
...
|
||||
LL | f = g;
|
||||
| ^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
|
||||
found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -12,10 +12,10 @@ LL | let x: Self::Foo = ();
|
||||
= note: expected opaque type `<() as Foo>::Foo`
|
||||
found unit type `()`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:5
|
||||
--> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:8
|
||||
|
|
||||
LL | fn bar() {
|
||||
| ^^^^^^^^
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
23
tests/ui/type-alias-impl-trait/multi-error.rs
Normal file
23
tests/ui/type-alias-impl-trait/multi-error.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//! This test checks that we don't follow up
|
||||
//! with type mismatch errors of opaque types
|
||||
//! with their hidden types if we failed the
|
||||
//! defining scope check at the signature level.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
trait Foo {
|
||||
type Bar<T>;
|
||||
type Baz;
|
||||
fn foo() -> (Self::Bar<u32>, Self::Baz);
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
type Bar<T> = impl Sized;
|
||||
type Baz = impl Sized;
|
||||
fn foo() -> (Self::Bar<u32>, Self::Baz) {
|
||||
//~^ ERROR non-defining opaque type use
|
||||
((), ())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/type-alias-impl-trait/multi-error.stderr
Normal file
15
tests/ui/type-alias-impl-trait/multi-error.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0792]: non-defining opaque type use in defining scope
|
||||
--> $DIR/multi-error.rs:17:17
|
||||
|
|
||||
LL | fn foo() -> (Self::Bar<u32>, Self::Baz) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
|
||||
|
|
||||
note: for this opaque type
|
||||
--> $DIR/multi-error.rs:15:19
|
||||
|
|
||||
LL | type Bar<T> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
21
tests/ui/type-alias-impl-trait/non-defining-method.rs
Normal file
21
tests/ui/type-alias-impl-trait/non-defining-method.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//! This test checks that we don't follow up
|
||||
//! with type mismatch errors of opaque types
|
||||
//! with their hidden types if we failed the
|
||||
//! defining scope check at the signature level.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
trait Foo {
|
||||
type Bar<T>;
|
||||
fn foo() -> Self::Bar<u32>;
|
||||
fn bar<T>() -> Self::Bar<T>;
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
type Bar<T> = impl Sized;
|
||||
fn foo() -> Self::Bar<u32> {}
|
||||
//~^ ERROR non-defining opaque type use
|
||||
fn bar<T>() -> Self::Bar<T> {}
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/type-alias-impl-trait/non-defining-method.stderr
Normal file
15
tests/ui/type-alias-impl-trait/non-defining-method.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0792]: non-defining opaque type use in defining scope
|
||||
--> $DIR/non-defining-method.rs:16:17
|
||||
|
|
||||
LL | fn foo() -> Self::Bar<u32> {}
|
||||
| ^^^^^^^^^^^^^^ argument `u32` is not a generic parameter
|
||||
|
|
||||
note: for this opaque type
|
||||
--> $DIR/non-defining-method.rs:15:19
|
||||
|
|
||||
LL | type Bar<T> = impl Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
@ -12,10 +12,10 @@ LL | let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
|
||||
= note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc`
|
||||
found reference `&'static str`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/not-matching-trait-refs-isnt-defining.rs:16:5
|
||||
--> $DIR/not-matching-trait-refs-isnt-defining.rs:16:8
|
||||
|
|
||||
LL | fn test() -> <() as Foo<NoOpaques>>::Assoc {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -25,11 +25,6 @@ LL | fn dont_define_this(_private: Private) {}
|
||||
| ^^^^^^^
|
||||
= note: expected signature `fn(Private)`
|
||||
found signature `fn(MyPrivate)`
|
||||
note: this item must have the opaque type in its signature in order to be able to register hidden types
|
||||
--> $DIR/unnameable_type.rs:20:5
|
||||
|
|
||||
LL | fn dont_define_this(_private: MyPrivate) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user