@@ -27,6 +27,8 @@ pub enum NonStructuralMatchTyKind<'tcx> {
2727 Generator ,
2828 Projection ,
2929 Float ,
30+ FnPtr ,
31+ RawPtr ,
3032}
3133
3234/// This method traverses the structure of `ty`, trying to find an
@@ -55,14 +57,15 @@ pub enum NonStructuralMatchTyKind<'tcx> {
5557/// that arose when the requirement was not enforced completely, see
5658/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
5759///
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.
5962pub fn search_for_structural_match_violation < ' tcx > (
6063 span : Span ,
6164 tcx : TyCtxt < ' tcx > ,
6265 ty : Ty < ' tcx > ,
63- floats_allowed : bool ,
66+ valtree_semantics : bool ,
6467) -> 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 } )
6669 . break_value ( )
6770}
6871
@@ -125,7 +128,9 @@ struct Search<'tcx> {
125128 /// we will not recur on them again.
126129 seen : FxHashSet < hir:: def_id:: DefId > ,
127130
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 ,
129134}
130135
131136impl < ' tcx > Search < ' tcx > {
@@ -170,24 +175,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
170175 let kind = NonStructuralMatchTyKind :: Generator ;
171176 return ControlFlow :: Break ( NonStructuralMatchTy { ty, kind } ) ;
172177 }
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 ( ..) => {
191179 // Types of formals and return in `fn(_) -> _` are also irrelevant;
192180 // so we do not recur into them via `super_visit_with`
193181 return ControlFlow :: CONTINUE ;
@@ -206,8 +194,44 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
206194 return ControlFlow :: CONTINUE ;
207195 }
208196
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+
209233 ty:: Float ( _) => {
210- if self . floats_allowed {
234+ if ! self . valtree_semantics {
211235 return ControlFlow :: CONTINUE ;
212236 } else {
213237 return ControlFlow :: Break ( NonStructuralMatchTy {
0 commit comments