@@ -27,6 +27,8 @@ pub enum NonStructuralMatchTyKind<'tcx> {
27
27
Generator ,
28
28
Projection ,
29
29
Float ,
30
+ FnPtr ,
31
+ RawPtr ,
30
32
}
31
33
32
34
/// This method traverses the structure of `ty`, trying to find an
@@ -55,14 +57,15 @@ pub enum NonStructuralMatchTyKind<'tcx> {
55
57
/// that arose when the requirement was not enforced completely, see
56
58
/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
57
59
///
58
- /// The floats_allowed flag is used to deny constants in floating point
60
+ /// When the `valtree_semantics` flag is set, then we also deny additional
61
+ /// types that are not evaluatable to valtrees, such as floats and fn ptrs.
59
62
pub fn search_for_structural_match_violation < ' tcx > (
60
63
span : Span ,
61
64
tcx : TyCtxt < ' tcx > ,
62
65
ty : Ty < ' tcx > ,
63
- floats_allowed : bool ,
66
+ valtree_semantics : bool ,
64
67
) -> Option < NonStructuralMatchTy < ' tcx > > {
65
- ty. visit_with ( & mut Search { tcx, span, seen : FxHashSet :: default ( ) , floats_allowed } )
68
+ ty. visit_with ( & mut Search { tcx, span, seen : FxHashSet :: default ( ) , valtree_semantics } )
66
69
. break_value ( )
67
70
}
68
71
@@ -125,7 +128,9 @@ struct Search<'tcx> {
125
128
/// we will not recur on them again.
126
129
seen : FxHashSet < hir:: def_id:: DefId > ,
127
130
128
- floats_allowed : bool ,
131
+ // Additionally deny things that have been allowed in patterns,
132
+ // but are not evaluatable to a valtree, such as floats and fn ptrs.
133
+ valtree_semantics : bool ,
129
134
}
130
135
131
136
impl < ' tcx > Search < ' tcx > {
@@ -170,24 +175,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
170
175
let kind = NonStructuralMatchTyKind :: Generator ;
171
176
return ControlFlow :: Break ( NonStructuralMatchTy { ty, kind } ) ;
172
177
}
173
- ty:: RawPtr ( ..) => {
174
- // structural-match ignores substructure of
175
- // `*const _`/`*mut _`, so skip `super_visit_with`.
176
- //
177
- // For example, if you have:
178
- // ```
179
- // struct NonStructural;
180
- // #[derive(PartialEq, Eq)]
181
- // struct T(*const NonStructural);
182
- // const C: T = T(std::ptr::null());
183
- // ```
184
- //
185
- // Even though `NonStructural` does not implement `PartialEq`,
186
- // structural equality on `T` does not recur into the raw
187
- // pointer. Therefore, one can still use `C` in a pattern.
188
- return ControlFlow :: CONTINUE ;
189
- }
190
- ty:: FnDef ( ..) | ty:: FnPtr ( ..) => {
178
+ ty:: FnDef ( ..) => {
191
179
// Types of formals and return in `fn(_) -> _` are also irrelevant;
192
180
// so we do not recur into them via `super_visit_with`
193
181
return ControlFlow :: CONTINUE ;
@@ -206,8 +194,44 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
206
194
return ControlFlow :: CONTINUE ;
207
195
}
208
196
197
+ ty:: FnPtr ( ..) => {
198
+ if !self . valtree_semantics {
199
+ return ControlFlow :: CONTINUE ;
200
+ } else {
201
+ return ControlFlow :: Break ( NonStructuralMatchTy {
202
+ ty,
203
+ kind : NonStructuralMatchTyKind :: FnPtr ,
204
+ } ) ;
205
+ }
206
+ }
207
+
208
+ ty:: RawPtr ( ..) => {
209
+ if !self . valtree_semantics {
210
+ // structural-match ignores substructure of
211
+ // `*const _`/`*mut _`, so skip `super_visit_with`.
212
+ //
213
+ // For example, if you have:
214
+ // ```
215
+ // struct NonStructural;
216
+ // #[derive(PartialEq, Eq)]
217
+ // struct T(*const NonStructural);
218
+ // const C: T = T(std::ptr::null());
219
+ // ```
220
+ //
221
+ // Even though `NonStructural` does not implement `PartialEq`,
222
+ // structural equality on `T` does not recur into the raw
223
+ // pointer. Therefore, one can still use `C` in a pattern.
224
+ return ControlFlow :: CONTINUE ;
225
+ } else {
226
+ return ControlFlow :: Break ( NonStructuralMatchTy {
227
+ ty,
228
+ kind : NonStructuralMatchTyKind :: FnPtr ,
229
+ } ) ;
230
+ }
231
+ }
232
+
209
233
ty:: Float ( _) => {
210
- if self . floats_allowed {
234
+ if ! self . valtree_semantics {
211
235
return ControlFlow :: CONTINUE ;
212
236
} else {
213
237
return ControlFlow :: Break ( NonStructuralMatchTy {
0 commit comments