diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index c20e5146546a2..31104411ab55b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_signature}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, @@ -332,6 +333,17 @@ fn report_mismatched_rpitit_signature<'tcx>( hir::FnRetTy::Return(ty) => ty.span, }); + // Use ForSignature mode to ensure RPITITs are printed as `impl Trait` rather than + // `impl Trait { T::method(..) }` when RTN is enabled. + // + // We use `with_no_trimmed_paths!` to avoid triggering the `trimmed_def_paths` query, + // which requires diagnostic context (via `must_produce_diag`). Since we're formatting + // the type before creating the diagnostic, we need to avoid this query. This is the + // standard approach used elsewhere in the compiler for formatting types in suggestions + // (e.g., see `rustc_hir_typeck/src/demand.rs`). + let return_ty_suggestion = + with_no_trimmed_paths!(with_types_for_signature!(format!("{return_ty}"))); + let span = unmatched_bound.unwrap_or(span); tcx.emit_node_span_lint( if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, @@ -342,7 +354,7 @@ fn report_mismatched_rpitit_signature<'tcx>( trait_return_span, pre, post, - return_ty, + return_ty: return_ty_suggestion, unmatched_bound, }, ); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a23b42ae0981..990c762135b1c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1122,7 +1122,7 @@ pub(crate) struct UnusedAssociatedTypeBounds { #[note( "we are soliciting feedback, see issue #121718 for more information" )] -pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { +pub(crate) struct ReturnPositionImplTraitInTraitRefined { #[suggestion( "replace the return type so that it matches the trait", applicability = "maybe-incorrect", @@ -1136,7 +1136,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub pre: &'static str, pub post: &'static str, - pub return_ty: Ty<'tcx>, + pub return_ty: String, } #[derive(LintDiagnostic)] diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index d3765a7e6e6fd..327ac40503ac0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> Pin + '_>> { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 3328dea37fe4d..983c946d2a70d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> MyFuture { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 8bc3c8b647c08..29975bdfcce8c 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -29,7 +29,7 @@ LL | fn iter(&self) -> impl 'a + Iterator> { help: replace the return type so that it matches the trait | LL - fn iter(&self) -> impl 'a + Iterator> { -LL + fn iter(&self) -> impl Iterator::Item<'_>> + '_ { +LL + fn iter(&self) -> impl std::iter::Iterator::Item<'_>> + '_ { | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr index 0a73a36378601..f44b34e38cfd6 100644 --- a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr +++ b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr @@ -12,8 +12,9 @@ LL | fn bar(&self) -> impl Iterator + '_ { = note: `#[warn(refining_impl_trait_internal)]` (part of `#[warn(refining_impl_trait)]`) on by default help: replace the return type so that it matches the trait | -LL | fn bar(&self) -> impl Iterator + '_ { - | +++++++++++++++++++ +LL - fn bar(&self) -> impl Iterator + '_ { +LL + fn bar(&self) -> impl std::iter::Iterator + '_ { + | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr index 8801ccc68b3be..f1c76f743c6e2 100644 --- a/tests/ui/impl-trait/in-trait/foreign.stderr +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -15,7 +15,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: impl trait in impl method signature does not match trait method signature @@ -34,7 +34,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: 2 warnings emitted diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs new file mode 100644 index 0000000000000..281f4c73ac21a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +#![deny(refining_impl_trait)] + +trait Trait { + fn f() -> impl Sized; +} + +impl Trait for () { + fn f() {} + //~^ ERROR impl trait in impl method signature does not match trait method signature +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr new file mode 100644 index 0000000000000..1f9a5b9e87492 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr @@ -0,0 +1,24 @@ +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine-return-type-notation.rs:9:5 + | +LL | fn f() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn f() {} + | ^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/refine-return-type-notation.rs:2:9 + | +LL | #![deny(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn f()-> impl Sized {} + | +++++++++++++ + +error: aborting due to 1 previous error +