Don't emit refining_impl_trait for private items

This commit is contained in:
Michael Goulet 2023-09-07 00:45:12 +00:00
parent 4745d34bc3
commit 4d05da46e7
15 changed files with 98 additions and 47 deletions

View File

@ -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) { if !tcx.impl_method_has_trait_impl_trait_tys(impl_m.def_id) {
return; 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); 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 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 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); 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<ty::Visibility<DefId>> {
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,
}
}

View File

@ -4496,7 +4496,7 @@ declare_lint! {
/// ///
/// use std::fmt::Display; /// use std::fmt::Display;
/// ///
/// trait AsDisplay { /// pub trait AsDisplay {
/// fn as_display(&self) -> impl Display; /// fn as_display(&self) -> impl Display;
/// } /// }
/// ///

View File

@ -2,14 +2,14 @@
// edition: 2021 // edition: 2021
#![feature(async_fn_in_trait)] #![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
use std::future::Future; use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::Poll; use std::task::Poll;
trait MyTrait { pub trait MyTrait {
async fn foo(&self) -> i32; async fn foo(&self) -> i32;
} }
@ -27,7 +27,7 @@ impl Future for MyFuture {
} }
impl MyTrait for i32 { impl MyTrait for i32 {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn foo(&self) -> impl Future<Output = i32> + Clone { fn foo(&self) -> impl Future<Output = i32> + Clone {
MyFuture(*self) MyFuture(*self)
} }

View File

@ -1,4 +1,4 @@
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
use std::ops::Deref; use std::ops::Deref;
@ -8,7 +8,7 @@ pub trait Foo {
pub struct Foreign; pub struct Foreign;
impl Foo for Foreign { impl Foo for Foreign {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(self) -> &'static () { fn bar(self) -> &'static () {
&() &()
} }

View File

@ -2,7 +2,7 @@
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait)]
trait Iterable { pub trait Iterable {
type Item<'a> type Item<'a>
where where
Self: 'a; Self: 'a;

View File

@ -1,16 +1,16 @@
// check-pass // check-pass
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
struct Wrapper<T>(T); pub struct Wrapper<T>(T);
trait Foo { pub trait Foo {
fn bar() -> Wrapper<impl Sized>; fn bar() -> Wrapper<impl Sized>;
} }
impl Foo for () { impl Foo for () {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar() -> Wrapper<i32> { fn bar() -> Wrapper<i32> {
Wrapper(0) Wrapper(0)
} }

View File

@ -1,15 +1,25 @@
// check-pass // check-pass
// aux-build: rpitit.rs // aux-build: rpitit.rs
#![feature(lint_reasons)]
extern crate rpitit; extern crate rpitit;
use rpitit::{Foo, Foreign}; use rpitit::{Foo, Foreign};
use std::sync::Arc; use std::sync::Arc;
// Implement an RPITIT from another crate. // Implement an RPITIT from another crate.
struct Local; pub struct Local;
impl Foo for Local { impl Foo for Local {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(self) -> Arc<String> {
Arc::new(String::new())
}
}
struct LocalIgnoreRefining;
impl Foo for LocalIgnoreRefining {
#[deny(refining_impl_trait)]
fn bar(self) -> Arc<String> { fn bar(self) -> Arc<String> {
Arc::new(String::new()) Arc::new(String::new())
} }
@ -24,4 +34,5 @@ fn main() {
let &() = Foreign.bar(); let &() = Foreign.bar();
let x: Arc<String> = Local.bar(); let x: Arc<String> = Local.bar();
let x: Arc<String> = LocalIgnoreRefining.bar();
} }

View File

@ -1,28 +1,28 @@
// check-pass // check-pass
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
use std::fmt::Display; use std::fmt::Display;
use std::ops::Deref; use std::ops::Deref;
trait Foo { pub trait Foo {
fn bar(self) -> impl Deref<Target = impl Display + ?Sized>; fn bar(self) -> impl Deref<Target = impl Display + ?Sized>;
} }
struct A; pub struct A;
impl Foo for A { impl Foo for A {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(self) -> &'static str { fn bar(self) -> &'static str {
"Hello, world" "Hello, world"
} }
} }
struct B; pub struct B;
impl Foo for B { impl Foo for B {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(self) -> Box<i32> { fn bar(self) -> Box<i32> {
Box::new(42) Box::new(42)
} }

View File

@ -1,33 +1,45 @@
#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
#![deny(refining_impl_trait)] #![deny(refining_impl_trait)]
trait Foo { pub trait Foo {
fn bar() -> impl Sized; fn bar() -> impl Sized;
} }
struct A; pub struct A;
impl Foo for A { impl Foo for A {
fn bar() -> impl Copy {} fn bar() -> impl Copy {}
//~^ ERROR impl method signature does not match trait method signature //~^ ERROR impl method signature does not match trait method signature
} }
struct B; pub struct B;
impl Foo for B { impl Foo for B {
fn bar() {} fn bar() {}
//~^ ERROR impl method signature does not match trait method signature //~^ ERROR impl method signature does not match trait method signature
} }
struct C; pub struct C;
impl Foo for C { impl Foo for C {
fn bar() -> () {} fn bar() -> () {}
//~^ ERROR impl method signature does not match trait method signature //~^ ERROR impl method signature does not match trait method signature
} }
trait Late { struct Private;
impl Foo for Private {
fn bar() -> () {}
}
pub trait Arg<A> {
fn bar() -> impl Sized;
}
impl Arg<Private> for A {
fn bar() -> () {}
}
pub trait Late {
fn bar<'a>(&'a self) -> impl Sized + 'a; fn bar<'a>(&'a self) -> impl Sized + 'a;
} }
struct D; pub struct D;
impl Late for D { impl Late for D {
fn bar(&self) -> impl Copy + '_ {} fn bar(&self) -> impl Copy + '_ {}
//~^ ERROR impl method signature does not match trait method signature //~^ ERROR impl method signature does not match trait method signature

View File

@ -46,7 +46,7 @@ LL | fn bar() -> impl Sized {}
| ~~~~~~~~~~ | ~~~~~~~~~~
error: impl trait in impl method signature does not match trait method signature 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; LL | fn bar<'a>(&'a self) -> impl Sized + 'a;
| --------------- return type from trait method defined here | --------------- return type from trait method defined here

View File

@ -1,14 +1,14 @@
// check-pass // check-pass
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
trait Foo { pub trait Foo {
fn f() -> Box<impl Sized>; fn f() -> Box<impl Sized>;
} }
impl Foo for () { impl Foo for () {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn f() -> Box<String> { fn f() -> Box<String> {
Box::new(String::new()) Box::new(String::new())
} }

View File

@ -1,6 +1,6 @@
// issue: 113903 // issue: 113903
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
use std::ops::Deref; use std::ops::Deref;
@ -10,7 +10,7 @@ pub trait Tr {
} }
impl Tr for () { impl Tr for () {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn w() -> &'static () { fn w() -> &'static () {
&() &()
} }

View File

@ -2,17 +2,17 @@
// revisions: success failure // revisions: success failure
//[success] check-pass //[success] check-pass
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
use std::future::Future; use std::future::Future;
trait Captures<'a> {} pub trait Captures<'a> {}
impl<T> Captures<'_> for T {} impl<T> Captures<'_> for T {}
trait Captures2<'a, 'b> {} pub trait Captures2<'a, 'b> {}
impl<T> Captures2<'_, '_> for T {} impl<T> Captures2<'_, '_> for T {}
trait AsyncTrait { pub trait AsyncTrait {
#[cfg(success)] #[cfg(success)]
fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>; fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
@ -44,7 +44,7 @@ impl AsyncTrait for Struct {
// Does not capture more lifetimes that trait def'n, since trait def'n // Does not capture more lifetimes that trait def'n, since trait def'n
// implicitly captures all in-scope lifetimes. // implicitly captures all in-scope lifetimes.
#[cfg(success)] #[cfg(success)]
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a { fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
async move { buff.to_vec() } 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 // Does not capture more lifetimes that trait def'n, since trait def'n
// implicitly captures all in-scope lifetimes. // implicitly captures all in-scope lifetimes.
#[cfg(success)] #[cfg(success)]
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a { fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
async move { buff.to_vec() } 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 // Does not capture more lifetimes that trait def'n, since trait def'n
// implicitly captures all in-scope lifetimes. // implicitly captures all in-scope lifetimes.
#[cfg(success)] #[cfg(success)]
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn async_fn_multiple<'a, 'b>( fn async_fn_multiple<'a, 'b>(
&'a self, &'a self,
buff: &'b [u8], buff: &'b [u8],

View File

@ -1,10 +1,10 @@
// check-pass // check-pass
#![feature(specialization)] #![feature(specialization)]
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
trait Foo { pub trait Foo {
fn bar(&self) -> impl Sized; fn bar(&self) -> impl Sized;
} }
@ -12,7 +12,7 @@ impl<U> Foo for U
where where
U: Copy, U: Copy,
{ {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(&self) -> U { fn bar(&self) -> U {
*self *self
} }

View File

@ -1,32 +1,32 @@
// check-pass // check-pass
#![feature(return_position_impl_trait_in_trait)] #![feature(return_position_impl_trait_in_trait, lint_reasons)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
use std::fmt::Display; use std::fmt::Display;
trait Foo { pub trait Foo {
fn bar(&self) -> impl Display; fn bar(&self) -> impl Display;
} }
impl Foo for i32 { impl Foo for i32 {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(&self) -> i32 { fn bar(&self) -> i32 {
*self *self
} }
} }
impl Foo for &'static str { impl Foo for &'static str {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(&self) -> &'static str { fn bar(&self) -> &'static str {
*self *self
} }
} }
struct Yay; pub struct Yay;
impl Foo for Yay { impl Foo for Yay {
#[allow(refining_impl_trait)] #[expect(refining_impl_trait)]
fn bar(&self) -> String { fn bar(&self) -> String {
String::from(":^)") String::from(":^)")
} }