diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index c2e62328cb1..45d91c2047d 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -480,6 +480,7 @@ E0781: include_str!("./error_codes/E0781.md"), E0782: include_str!("./error_codes/E0782.md"), E0783: include_str!("./error_codes/E0783.md"), E0784: include_str!("./error_codes/E0784.md"), +E0785: include_str!("./error_codes/E0785.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/compiler/rustc_error_codes/src/error_codes/E0785.md b/compiler/rustc_error_codes/src/error_codes/E0785.md new file mode 100644 index 00000000000..373320539ef --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0785.md @@ -0,0 +1,30 @@ +An inherent `impl` was written on a dyn auto trait. + +Erroneous code example: + +```compile_fail,E0785 +#![feature(auto_traits)] + +auto trait AutoTrait {} + +impl dyn AutoTrait {} +``` + +Dyn objects allow any number of auto traits, plus at most one non-auto trait. +The non-auto trait becomes the "principal trait". + +When checking if an impl on a dyn trait is coherent, the principal trait is +normally the only one considered. Since the erroneous code has no principal +trait, it cannot be implemented at all. + +Working example: + +``` +#![feature(auto_traits)] + +trait PrincipalTrait {} + +auto trait AutoTrait {} + +impl dyn PrincipalTrait + AutoTrait + Send {} +``` diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 51698437a30..c7be9e21235 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -60,6 +60,17 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } + ty::Dynamic(..) => { + struct_span_err!( + self.tcx.sess, + ty.span, + E0785, + "cannot define inherent `impl` for a dyn auto trait" + ) + .span_label(ty.span, "impl requires at least one non-auto trait") + .note("define and implement a new trait or type instead") + .emit(); + } ty::Bool => { self.check_primitive_impl( item.def_id, diff --git a/src/test/ui/coherence/issue-85026.rs b/src/test/ui/coherence/issue-85026.rs new file mode 100644 index 00000000000..8b116545aa6 --- /dev/null +++ b/src/test/ui/coherence/issue-85026.rs @@ -0,0 +1,10 @@ +#![feature(auto_traits)] +auto trait AutoTrait {} + +// You cannot impl your own `dyn AutoTrait`. +impl dyn AutoTrait {} //~ERROR E0785 + +// You cannot impl someone else's `dyn AutoTrait` +impl dyn Unpin {} //~ERROR E0785 + +fn main() {} diff --git a/src/test/ui/coherence/issue-85026.stderr b/src/test/ui/coherence/issue-85026.stderr new file mode 100644 index 00000000000..a5da19bbfaa --- /dev/null +++ b/src/test/ui/coherence/issue-85026.stderr @@ -0,0 +1,19 @@ +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:5:6 + | +LL | impl dyn AutoTrait {} + | ^^^^^^^^^^^^^ impl requires at least one non-auto trait + | + = note: define and implement a new trait or type instead + +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:8:6 + | +LL | impl dyn Unpin {} + | ^^^^^^^^^ impl requires at least one non-auto trait + | + = note: define and implement a new trait or type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0785`.