Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 19ee378

Browse files
authoredApr 28, 2020
Rollup merge of rust-lang#71038 - lcnr:dyn_trait_structural_match, r=pnkfelix
forbid `dyn Trait` in patterns Do not allow `&dyn Trait` as a generic const parameters. This also changes dyn trait in pattern from ICE to error. closes rust-lang#63322 closes rust-lang#70972 r? @eddyb
2 parents 75f59ba + 4549ef5 commit 19ee378

File tree

6 files changed

+69
-13
lines changed

6 files changed

+69
-13
lines changed
 

‎src/librustc_mir_build/hair/pattern/const_to_pat.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,22 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
101101
cv.ty, structural
102102
);
103103
if let Some(non_sm_ty) = structural {
104-
let adt_def = match non_sm_ty {
105-
traits::NonStructuralMatchTy::Adt(adt_def) => adt_def,
104+
let msg = match non_sm_ty {
105+
traits::NonStructuralMatchTy::Adt(adt_def) => {
106+
let path = self.tcx().def_path_str(adt_def.did);
107+
format!(
108+
"to use a constant of type `{}` in a pattern, \
109+
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
110+
path, path,
111+
)
112+
}
113+
traits::NonStructuralMatchTy::Dynamic => {
114+
format!("trait objects cannot be used in patterns")
115+
}
106116
traits::NonStructuralMatchTy::Param => {
107117
bug!("use of constant whose type is a parameter inside a pattern")
108118
}
109119
};
110-
let path = self.tcx().def_path_str(adt_def.did);
111-
112-
let make_msg = || -> String {
113-
format!(
114-
"to use a constant of type `{}` in a pattern, \
115-
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
116-
path, path,
117-
)
118-
};
119120

120121
// double-check there even *is* a semantic `PartialEq` to dispatch to.
121122
//
@@ -145,13 +146,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
145146

146147
if !ty_is_partial_eq {
147148
// span_fatal avoids ICE from resolution of non-existent method (rare case).
148-
self.tcx().sess.span_fatal(self.span, &make_msg());
149+
self.tcx().sess.span_fatal(self.span, &msg);
149150
} else {
150151
self.tcx().struct_span_lint_hir(
151152
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
152153
self.id,
153154
self.span,
154-
|lint| lint.build(&make_msg()).emit(),
155+
|lint| lint.build(&msg).emit(),
155156
);
156157
}
157158
}

‎src/librustc_trait_selection/traits/structural_match.rs

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_span::Span;
1111
pub enum NonStructuralMatchTy<'tcx> {
1212
Adt(&'tcx AdtDef),
1313
Param,
14+
Dynamic,
1415
}
1516

1617
/// This method traverses the structure of `ty`, trying to find an
@@ -137,6 +138,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
137138
self.found = Some(NonStructuralMatchTy::Param);
138139
return true; // Stop visiting.
139140
}
141+
ty::Dynamic(..) => {
142+
self.found = Some(NonStructuralMatchTy::Dynamic);
143+
return true; // Stop visiting.
144+
}
140145
ty::RawPtr(..) => {
141146
// structural-match ignores substructure of
142147
// `*const _`/`*mut _`, so skip `super_visit_with`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
trait A {}
5+
struct B;
6+
impl A for B {}
7+
8+
fn test<const T: &'static dyn A>() {
9+
//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq`
10+
unimplemented!()
11+
}
12+
13+
fn main() {
14+
test::<{ &B }>();
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/issue-63322-forbid-dyn.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
9+
error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq`
10+
--> $DIR/issue-63322-forbid-dyn.rs:8:18
11+
|
12+
LL | fn test<const T: &'static dyn A>() {
13+
| ^^^^^^^^^^^^^^ `&'static (dyn A + 'static)` doesn't derive both `PartialEq` and `Eq`
14+
15+
error: aborting due to previous error; 1 warning emitted
16+
17+
For more information about this error, try `rustc --explain E0741`.
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const F: &'static dyn Send = &7u32;
2+
3+
fn main() {
4+
let a: &dyn Send = &7u32;
5+
match a {
6+
F => panic!(),
7+
//~^ ERROR trait objects cannot be used in patterns
8+
_ => {}
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: trait objects cannot be used in patterns
2+
--> $DIR/issue-70972-dyn-trait.rs:6:9
3+
|
4+
LL | F => panic!(),
5+
| ^
6+
7+
error: aborting due to previous error
8+

0 commit comments

Comments
 (0)
Please sign in to comment.