Skip to content

Commit f34909d

Browse files
committed
simplify the logic and document
1 parent 110a9b3 commit f34909d

File tree

1 file changed

+32
-36
lines changed

1 file changed

+32
-36
lines changed

compiler/rustc_typeck/src/expr_use_visitor.rs

+32-36
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! normal visitor, which just walks the entire body in one shot, the
33
//! `ExprUseVisitor` determines how expressions are being used.
44
5+
use hir::def::DefKind;
56
// Export these here so that Clippy can use them.
67
pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
78

@@ -14,7 +15,7 @@ use rustc_index::vec::Idx;
1415
use rustc_infer::infer::InferCtxt;
1516
use rustc_middle::hir::place::ProjectionKind;
1617
use rustc_middle::mir::FakeReadCause;
17-
use rustc_middle::ty::{self, adjustment, TyCtxt};
18+
use rustc_middle::ty::{self, adjustment, Ty, TyCtxt};
1819
use rustc_target::abi::VariantIdx;
1920
use std::iter;
2021

@@ -251,43 +252,34 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
251252
needs_to_be_read = true;
252253
}
253254
}
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.
269265
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-
}
288266
}
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) {
291283
needs_to_be_read = true;
292284
}
293285
}
@@ -854,3 +846,7 @@ fn delegate_consume<'a, 'tcx>(
854846
}
855847
}
856848
}
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

Comments
 (0)