2
2
//! normal visitor, which just walks the entire body in one shot, the
3
3
//! `ExprUseVisitor` determines how expressions are being used.
4
4
5
+ use hir:: def:: DefKind ;
5
6
// Export these here so that Clippy can use them.
6
7
pub use rustc_middle:: hir:: place:: { Place , PlaceBase , PlaceWithHirId , Projection } ;
7
8
@@ -14,7 +15,7 @@ use rustc_index::vec::Idx;
14
15
use rustc_infer:: infer:: InferCtxt ;
15
16
use rustc_middle:: hir:: place:: ProjectionKind ;
16
17
use rustc_middle:: mir:: FakeReadCause ;
17
- use rustc_middle:: ty:: { self , adjustment, TyCtxt } ;
18
+ use rustc_middle:: ty:: { self , adjustment, Ty , TyCtxt } ;
18
19
use rustc_target:: abi:: VariantIdx ;
19
20
use std:: iter;
20
21
@@ -251,43 +252,34 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
251
252
needs_to_be_read = true ;
252
253
}
253
254
}
254
- PatKind :: TupleStruct ( ..)
255
- | PatKind :: Path ( ..)
256
- | PatKind :: Struct ( ..)
257
- | PatKind :: Tuple ( ..) => {
258
- // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check
259
- // whether the Variant is a MultiVariant or a SingleVariant. We only want
260
- // to borrow discr if it is a MultiVariant.
261
- // If it is a SingleVariant and creates a binding we will handle that when
262
- // this callback gets called again.
263
-
264
- // Get the type of the Place after all projections have been applied
265
- let place_ty = place. place. ty( ) ;
266
-
267
- if let ty:: Adt ( def, _) = place_ty. kind( ) {
268
- if def. variants. len( ) > 1 {
255
+ PatKind :: Path ( qpath) => {
256
+ // A `Path` pattern is just a name like `Foo`. This is either a
257
+ // named constant or else it refers to an ADT variant
258
+
259
+ let res = self . mc. typeck_results. qpath_res( qpath, pat. hir_id) ;
260
+ match res {
261
+ Res :: Def ( DefKind :: Const , _)
262
+ | Res :: Def ( DefKind :: AssocConst , _) => {
263
+ // Named constants have to be equated with the value
264
+ // being matched, so that's a read of the value being matched.
269
265
needs_to_be_read = true ;
270
- } else if let Some ( variant) = def. variants. iter( ) . next( ) {
271
- // We need to handle `const` in match arms slightly differently
272
- // as they are not processed the same way as other match arms.
273
- // Consider this const `const OP1: Opcode = Opcode(0x1)`, this
274
- // will generate a pattern with kind Path while if use Opcode(0x1)
275
- // this will generate pattern TupleStruct and Lit.
276
- // When dealing with pat kind Path we need to make additional checks
277
- // to ensure we have all the info needed to make a decision on whether
278
- // to borrow discr.
279
- //
280
- // If the pat kind is a Path we want to check whether the
281
- // variant contains at least one field. If that's the case,
282
- // we want to borrow discr.
283
- if matches!( pat. kind, PatKind :: Path ( ..) )
284
- && variant. fields. len( ) > 0
285
- {
286
- needs_to_be_read = true ;
287
- }
288
266
}
289
- } else {
290
- // If it is not ty::Adt, then it should be read
267
+ _ => {
268
+ // Otherwise, this is a struct/enum variant, and so it's
269
+ // only a read if we need to read the discriminant.
270
+ needs_to_be_read = is_multivariant_adt( place. place. ty( ) ) ;
271
+ }
272
+ }
273
+ }
274
+ PatKind :: TupleStruct ( ..) | PatKind :: Struct ( ..) | PatKind :: Tuple ( ..) => {
275
+ // For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching
276
+ // against a multivariant enum or struct. In that case, we have to read
277
+ // the discriminant. Otherwise this kind of pattern doesn't actually
278
+ // read anything (we'll get invoked for the `...`, which may indeed
279
+ // perform some reads).
280
+
281
+ let place_ty = place. place. ty( ) ;
282
+ if is_multivariant_adt( place_ty) {
291
283
needs_to_be_read = true ;
292
284
}
293
285
}
@@ -854,3 +846,7 @@ fn delegate_consume<'a, 'tcx>(
854
846
}
855
847
}
856
848
}
849
+
850
+ fn is_multivariant_adt ( ty : Ty < ' tcx > ) -> bool {
851
+ if let ty:: Adt ( def, _) = ty. kind ( ) { def. variants . len ( ) > 1 } else { false }
852
+ }
0 commit comments