From 026322c34b2ae68af15b59df69a121209c8364f1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 30 Aug 2021 22:11:25 -0700 Subject: [PATCH] fix(rustc_typeck): produce better errors for dyn auto trait Fixes #85026 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0785.md | 30 +++++++++++++++++++ .../src/coherence/inherent_impls.rs | 11 +++++++ src/test/ui/coherence/issue-85026.rs | 10 +++++++ src/test/ui/coherence/issue-85026.stderr | 19 ++++++++++++ 5 files changed, 71 insertions(+) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0785.md create mode 100644 src/test/ui/coherence/issue-85026.rs create mode 100644 src/test/ui/coherence/issue-85026.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index c2e62328cb151..45d91c2047d41 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 0000000000000..b8a03cd109d87 --- /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 51698437a305b..05d7dfb9c8ffa 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 a principal 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 0000000000000..8b116545aa696 --- /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 0000000000000..cf9cd52d2bfdd --- /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 a principal 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 a principal 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`.