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 b013f292e52..a8149b634ef 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 @@ -23,8 +23,22 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) { return; } + // crate-private traits don't have any library guarantees, there's no need to do this check. + if !tcx.visibility(trait_m.container_id(tcx)).is_public() { + return; + } + // If a type in the trait ref is private, then there's also no reason to to do this check. let impl_def_id = impl_m.container_id(tcx); + for arg in impl_trait_ref.args { + if let Some(ty) = arg.as_type() + && let Some(self_visibility) = type_visibility(tcx, ty) + && !self_visibility.is_public() + { + return; + } + } + let impl_m_args = ty::GenericArgs::identity_for_item(tcx, impl_m.def_id); let trait_m_to_impl_m_args = impl_m_args.rebase_onto(tcx, impl_def_id, impl_trait_ref.args); let bound_trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_to_impl_m_args); @@ -281,3 +295,17 @@ fn report_mismatched_rpitit_signature<'tcx>( }, ); } + +fn type_visibility<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option> { + match *ty.kind() { + ty::Ref(_, ty, _) => type_visibility(tcx, ty), + ty::Adt(def, args) => { + if def.is_fundamental() { + type_visibility(tcx, args.type_at(0)) + } else { + Some(tcx.visibility(def.did())) + } + } + _ => None, + } +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index df0151dc499..2567e273e11 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4496,7 +4496,7 @@ declare_lint! { /// /// use std::fmt::Display; /// - /// trait AsDisplay { + /// pub trait AsDisplay { /// fn as_display(&self) -> impl Display; /// } /// diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index 1bbf4836a2a..3505690f1ec 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -2,14 +2,14 @@ // edition: 2021 #![feature(async_fn_in_trait)] -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] use std::future::Future; use std::pin::Pin; use std::task::Poll; -trait MyTrait { +pub trait MyTrait { async fn foo(&self) -> i32; } @@ -27,7 +27,7 @@ impl Future for MyFuture { } impl MyTrait for i32 { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn foo(&self) -> impl Future + Clone { MyFuture(*self) } diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs index 5bd5c48ca69..6e99402113a 100644 --- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs +++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -1,4 +1,4 @@ -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] use std::ops::Deref; @@ -8,7 +8,7 @@ pub trait Foo { pub struct Foreign; impl Foo for Foreign { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(self) -> &'static () { &() } diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs index 063adb7c378..fbbbb8585d1 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.rs @@ -2,7 +2,7 @@ #![feature(return_position_impl_trait_in_trait)] -trait Iterable { +pub trait Iterable { type Item<'a> where Self: 'a; diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs index ffd10d9b1ff..fc290f11f9d 100644 --- a/tests/ui/impl-trait/in-trait/deep-match-works.rs +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -1,16 +1,16 @@ // check-pass -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] -struct Wrapper(T); +pub struct Wrapper(T); -trait Foo { +pub trait Foo { fn bar() -> Wrapper; } impl Foo for () { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar() -> Wrapper { Wrapper(0) } diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs index 035d91c1876..6285d7786d5 100644 --- a/tests/ui/impl-trait/in-trait/foreign.rs +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -1,15 +1,25 @@ // check-pass // aux-build: rpitit.rs +#![feature(lint_reasons)] + extern crate rpitit; use rpitit::{Foo, Foreign}; use std::sync::Arc; // Implement an RPITIT from another crate. -struct Local; +pub struct Local; impl Foo for Local { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] + fn bar(self) -> Arc { + Arc::new(String::new()) + } +} + +struct LocalIgnoreRefining; +impl Foo for LocalIgnoreRefining { + #[deny(refining_impl_trait)] fn bar(self) -> Arc { Arc::new(String::new()) } @@ -24,4 +34,5 @@ fn main() { let &() = Foreign.bar(); let x: Arc = Local.bar(); + let x: Arc = LocalIgnoreRefining.bar(); } diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs index cb943eb5af9..58ba1acaf14 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -1,28 +1,28 @@ // check-pass -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] use std::fmt::Display; use std::ops::Deref; -trait Foo { +pub trait Foo { fn bar(self) -> impl Deref; } -struct A; +pub struct A; impl Foo for A { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(self) -> &'static str { "Hello, world" } } -struct B; +pub struct B; impl Foo for B { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(self) -> Box { Box::new(42) } diff --git a/tests/ui/impl-trait/in-trait/refine.rs b/tests/ui/impl-trait/in-trait/refine.rs index e9b5e669fde..a91f9b3e722 100644 --- a/tests/ui/impl-trait/in-trait/refine.rs +++ b/tests/ui/impl-trait/in-trait/refine.rs @@ -1,33 +1,45 @@ #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] #![deny(refining_impl_trait)] -trait Foo { +pub trait Foo { fn bar() -> impl Sized; } -struct A; +pub struct A; impl Foo for A { fn bar() -> impl Copy {} //~^ ERROR impl method signature does not match trait method signature } -struct B; +pub struct B; impl Foo for B { fn bar() {} //~^ ERROR impl method signature does not match trait method signature } -struct C; +pub struct C; impl Foo for C { fn bar() -> () {} //~^ ERROR impl method signature does not match trait method signature } -trait Late { +struct Private; +impl Foo for Private { + fn bar() -> () {} +} + +pub trait Arg { + fn bar() -> impl Sized; +} +impl Arg for A { + fn bar() -> () {} +} + +pub trait Late { fn bar<'a>(&'a self) -> impl Sized + 'a; } -struct D; +pub struct D; impl Late for D { fn bar(&self) -> impl Copy + '_ {} //~^ ERROR impl method signature does not match trait method signature diff --git a/tests/ui/impl-trait/in-trait/refine.stderr b/tests/ui/impl-trait/in-trait/refine.stderr index 28d53270da3..65dfdf869e4 100644 --- a/tests/ui/impl-trait/in-trait/refine.stderr +++ b/tests/ui/impl-trait/in-trait/refine.stderr @@ -46,7 +46,7 @@ LL | fn bar() -> impl Sized {} | ~~~~~~~~~~ error: impl trait in impl method signature does not match trait method signature - --> $DIR/refine.rs:32:27 + --> $DIR/refine.rs:44:27 | LL | fn bar<'a>(&'a self) -> impl Sized + 'a; | --------------- return type from trait method defined here diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs index 65425ba1a84..b1b46d75b8f 100644 --- a/tests/ui/impl-trait/in-trait/reveal.rs +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -1,14 +1,14 @@ // check-pass -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] -trait Foo { +pub trait Foo { fn f() -> Box; } impl Foo for () { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn f() -> Box { Box::new(String::new()) } diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs index 747f7ed9e72..44a2b430344 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs @@ -1,6 +1,6 @@ // issue: 113903 -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] use std::ops::Deref; @@ -10,7 +10,7 @@ pub trait Tr { } impl Tr for () { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn w() -> &'static () { &() } diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 135467d57ee..685c0f06e88 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -2,17 +2,17 @@ // revisions: success failure //[success] check-pass -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] use std::future::Future; -trait Captures<'a> {} +pub trait Captures<'a> {} impl Captures<'_> for T {} -trait Captures2<'a, 'b> {} +pub trait Captures2<'a, 'b> {} impl Captures2<'_, '_> for T {} -trait AsyncTrait { +pub trait AsyncTrait { #[cfg(success)] fn async_fn(&self, buff: &[u8]) -> impl Future>; @@ -44,7 +44,7 @@ impl AsyncTrait for Struct { // Does not capture more lifetimes that trait def'n, since trait def'n // implicitly captures all in-scope lifetimes. #[cfg(success)] - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { async move { buff.to_vec() } } @@ -52,7 +52,7 @@ impl AsyncTrait for Struct { // Does not capture more lifetimes that trait def'n, since trait def'n // implicitly captures all in-scope lifetimes. #[cfg(success)] - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { async move { buff.to_vec() } } @@ -60,7 +60,7 @@ impl AsyncTrait for Struct { // Does not capture more lifetimes that trait def'n, since trait def'n // implicitly captures all in-scope lifetimes. #[cfg(success)] - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn async_fn_multiple<'a, 'b>( &'a self, buff: &'b [u8], diff --git a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs index 83812d6cd8a..41fc285883a 100644 --- a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs +++ b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -1,10 +1,10 @@ // check-pass #![feature(specialization)] -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] -trait Foo { +pub trait Foo { fn bar(&self) -> impl Sized; } @@ -12,7 +12,7 @@ impl Foo for U where U: Copy, { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(&self) -> U { *self } diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs index f583604a021..7d415ea17a4 100644 --- a/tests/ui/impl-trait/in-trait/success.rs +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -1,32 +1,32 @@ // check-pass -#![feature(return_position_impl_trait_in_trait)] +#![feature(return_position_impl_trait_in_trait, lint_reasons)] #![allow(incomplete_features)] use std::fmt::Display; -trait Foo { +pub trait Foo { fn bar(&self) -> impl Display; } impl Foo for i32 { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(&self) -> i32 { *self } } impl Foo for &'static str { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(&self) -> &'static str { *self } } -struct Yay; +pub struct Yay; impl Foo for Yay { - #[allow(refining_impl_trait)] + #[expect(refining_impl_trait)] fn bar(&self) -> String { String::from(":^)") }