From 9f34b82de203a01b7bb1afd57714886a65dbea8f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 11 Apr 2020 21:02:49 +0200 Subject: [PATCH 1/2] forbid `dyn Trait` in const generics --- .../hair/pattern/const_to_pat.rs | 3 +++ .../traits/structural_match.rs | 5 +++++ .../issues/issue-63322-forbid-dyn.rs | 15 +++++++++++++++ .../issues/issue-63322-forbid-dyn.stderr | 17 +++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs create mode 100644 src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index ad87afc3e0301..5a3eea3877570 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -116,6 +116,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { traits::NonStructuralMatchTy::Param => { bug!("use of constant whose type is a parameter inside a pattern") } + traits::NonStructuralMatchTy::Dynamic => { + bug!("use of a trait object inside a pattern") + } }; let path = self.tcx().def_path_str(adt_def.did); diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs index fbe1fcb08f2ef..8007290f35d85 100644 --- a/src/librustc_trait_selection/traits/structural_match.rs +++ b/src/librustc_trait_selection/traits/structural_match.rs @@ -11,6 +11,7 @@ use rustc_span::Span; pub enum NonStructuralMatchTy<'tcx> { Adt(&'tcx AdtDef), Param, + Dynamic, } /// This method traverses the structure of `ty`, trying to find an @@ -137,6 +138,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { self.found = Some(NonStructuralMatchTy::Param); return true; // Stop visiting. } + ty::Dynamic(..) => { + self.found = Some(NonStructuralMatchTy::Dynamic); + return true; // Stop visiting. + } ty::RawPtr(..) => { // structural-match ignores substructure of // `*const _`/`*mut _`, so skip `super_visit_with`. diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs new file mode 100644 index 0000000000000..2bacd6c9a9c5a --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs @@ -0,0 +1,15 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait A {} +struct B; +impl A for B {} + +fn test() { + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used + unimplemented!() +} + +fn main() { + test::<{ &B }>(); +} diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr new file mode 100644 index 0000000000000..73315af4483e2 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-63322-forbid-dyn.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-63322-forbid-dyn.rs:8:18 + | +LL | fn test() { + | ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. From 2f5c0f59a96612667ca6aeb40b6e40259f861e7e Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 12 Apr 2020 15:34:42 +0200 Subject: [PATCH 2/2] emit err when using trait objects in pat --- .../hair/pattern/const_to_pat.rs | 30 +++++++++---------- .../issues/issue-63322-forbid-dyn.stderr | 2 +- src/test/ui/match/issue-70972-dyn-trait.rs | 10 +++++++ .../ui/match/issue-70972-dyn-trait.stderr | 8 +++++ 4 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/match/issue-70972-dyn-trait.rs create mode 100644 src/test/ui/match/issue-70972-dyn-trait.stderr diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 5a3eea3877570..4cc6a27a6da93 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -111,23 +111,21 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { } if let Some(non_sm_ty) = structural { - let adt_def = match non_sm_ty { - traits::NonStructuralMatchTy::Adt(adt_def) => adt_def, - traits::NonStructuralMatchTy::Param => { - bug!("use of constant whose type is a parameter inside a pattern") + let msg = match non_sm_ty { + traits::NonStructuralMatchTy::Adt(adt_def) => { + let path = self.tcx().def_path_str(adt_def.did); + format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, path, + ) } traits::NonStructuralMatchTy::Dynamic => { - bug!("use of a trait object inside a pattern") + format!("trait objects cannot be used in patterns") + } + traits::NonStructuralMatchTy::Param => { + bug!("use of constant whose type is a parameter inside a pattern") } - }; - let path = self.tcx().def_path_str(adt_def.did); - - let make_msg = || -> String { - format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, path, - ) }; // double-check there even *is* a semantic `PartialEq` to dispatch to. @@ -158,13 +156,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { if !ty_is_partial_eq { // span_fatal avoids ICE from resolution of non-existent method (rare case). - self.tcx().sess.span_fatal(self.span, &make_msg()); + self.tcx().sess.span_fatal(self.span, &msg); } else if mir_structural_match_violation { self.tcx().struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, self.id, self.span, - |lint| lint.build(&make_msg()).emit(), + |lint| lint.build(&msg).emit(), ); } else { debug!( diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr index 73315af4483e2..c3db6c65a8f4c 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr @@ -12,6 +12,6 @@ error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(Part LL | fn test() { | ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq` -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/match/issue-70972-dyn-trait.rs b/src/test/ui/match/issue-70972-dyn-trait.rs new file mode 100644 index 0000000000000..a9b2699cafdc4 --- /dev/null +++ b/src/test/ui/match/issue-70972-dyn-trait.rs @@ -0,0 +1,10 @@ +const F: &'static dyn Send = &7u32; + +fn main() { + let a: &dyn Send = &7u32; + match a { + F => panic!(), + //~^ ERROR trait objects cannot be used in patterns + _ => {} + } +} diff --git a/src/test/ui/match/issue-70972-dyn-trait.stderr b/src/test/ui/match/issue-70972-dyn-trait.stderr new file mode 100644 index 0000000000000..a4e827357de6b --- /dev/null +++ b/src/test/ui/match/issue-70972-dyn-trait.stderr @@ -0,0 +1,8 @@ +error: trait objects cannot be used in patterns + --> $DIR/issue-70972-dyn-trait.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error +