From 12243ec41586bd5b68c032ef456a369fb0350469 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 15 Jun 2023 14:34:32 +0000 Subject: [PATCH] Point to argument/return type instead of the whole function header --- .../infer/error_reporting/note_and_explain.rs | 3 +- compiler/rustc_ty_utils/src/opaque_types.rs | 36 +++++++++++++++---- .../issue-88595.stderr | 8 ++--- .../in-assoc-type-unconstrained.stderr | 4 +-- tests/ui/impl-trait/in-assoc-type.stderr | 4 +-- ...s-impl-trait-declaration-too-subtle.stderr | 8 ++--- .../higher_kinded_params3.rs | 35 ++++++++++++++++++ .../higher_kinded_params3.stderr | 15 ++++++++ .../invalid_impl_trait_in_assoc_ty.stderr | 4 +-- ...t-matching-trait-refs-isnt-defining.stderr | 4 +-- .../unnameable_type.stderr | 4 +-- 11 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/higher_kinded_params3.rs create mode 100644 tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index a723dc3f079..2a32f0b5047 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -260,7 +260,8 @@ impl Trait for 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"); } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 7af5f847e8b..d97b74017ed 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -19,15 +19,26 @@ struct OpaqueTypeCollector<'tcx> { /// Avoid infinite recursion due to recursive declarations. seen: FxHashSet, + + span: Option, } impl<'tcx> OpaqueTypeCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { - Self { tcx, opaques: Vec::new(), item, seen: Default::default() } + 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>) { + let old = self.span; + self.span = Some(span); + value.visit_with(self); + self.span = old; } fn parent_trait_ref(&self) -> Option> { @@ -72,13 +83,13 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { 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 + for (pred, span) in self .tcx .explicit_item_bounds(alias_ty.def_id) .subst_iter_copied(self.tcx, alias_ty.substs) { trace!(?pred); - pred.visit_with(self)?; + self.visit_spanned(span, pred); } ControlFlow::Continue(()) @@ -163,10 +174,23 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ let mut collector = OpaqueTypeCollector::new(tcx, item); match kind { DefKind::AssocFn | DefKind::Fn => { - tcx.fn_sig(item).subst_identity().visit_with(&mut collector); + let ty_sig = tcx.fn_sig(item).subst_identity(); + let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap(); + 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::AssocTy | DefKind::AssocConst => { - tcx.type_of(item).subst_identity().visit_with(&mut collector); + let span = match tcx.hir().get_by_def_id(item) { + rustc_hir::Node::ImplItem(it) => match it.kind { + rustc_hir::ImplItemKind::Const(ty, _) => ty.span, + rustc_hir::ImplItemKind::Type(ty) => ty.span, + other => span_bug!(tcx.def_span(item), "{other:#?}"), + }, + other => span_bug!(tcx.def_span(item), "{other:#?}"), + }; + collector.visit_spanned(span, tcx.type_of(item).subst_identity()); } _ => unreachable!(), } diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr index d6caed85459..b0f6864f6ec 100644 --- a/tests/ui/generic-associated-types/issue-88595.stderr +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -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 @@ -24,10 +24,10 @@ LL | fn a(&'a self) -> Self::B<'a> {} = note: expected opaque type `>::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 + --> $DIR/issue-88595.rs:21:8 | LL | fn a(&'a self) -> Self::B<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr index 1097cd0f452..8e61a65abe4 100644 --- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr +++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr @@ -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 diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr index f0a272dc2d5..ab3f3a14410 100644 --- a/tests/ui/impl-trait/in-assoc-type.stderr +++ b/tests/ui/impl-trait/in-assoc-type.stderr @@ -12,10 +12,10 @@ LL | fn foo(&self) -> >::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) -> >::Bar {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ error: aborting due to previous error diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index bbd60d4398b..3e1981f096c 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -21,10 +21,10 @@ 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 + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:12 | 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 +49,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 diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs new file mode 100644 index 00000000000..839a611cb71 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr new file mode 100644 index 00000000000..aaba9ad5ca7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr index 2beed73cb85..6ec5d13f812 100644 --- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr +++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr @@ -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 diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr index d2d00749091..a621bb519cd 100644 --- a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr +++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr @@ -12,10 +12,10 @@ LL | let _: >::Assoc = ""; = note: expected opaque type `<() as Foo>::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>::Assoc { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr index 24f5cc8c733..c609ace919e 100644 --- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -26,10 +26,10 @@ 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 + --> $DIR/unnameable_type.rs:20:8 | LL | fn dont_define_this(_private: MyPrivate) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors