diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2021-07-16 10:08:08 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-16 10:08:08 +0200 |
| commit | 41433795e75fa96e4ad880802879da7892d12fad (patch) | |
| tree | d31facc98fa12aef40e6121e63978329a0a2f38b | |
| parent | c1b9bbf1e78b932b857849330241f742e01238de (diff) | |
| parent | 9fe470b620430775d084130ccd9333c15deb54d0 (diff) | |
| download | rust-41433795e75fa96e4ad880802879da7892d12fad.tar.gz rust-41433795e75fa96e4ad880802879da7892d12fad.zip | |
Rollup merge of #87161 - sexxi-goose:fix-issue-87097, r=nikomatsakis
RFC2229: Use the correct place type Closes https://github.com/rust-lang/rust/issues/87097 The ICE occurred because instead of looking at the type of the place after all the projections are applied, we instead looked at the `base_ty` of the Place to decide whether a discriminant should be read of not. This lead to two issues: 1. the kind of the type is not necessarily `Adt` since we only look at the `base_ty`, it could be instead `Ref` for example 2. if the kind of the type is `Adt` you could still be looking at the wrong variant to make a decision on whether the discriminant should be read or not r? `@nikomatsakis`
3 files changed, 74 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index a2bb420a901..806f1a2711c 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -252,12 +252,16 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | PatKind::Path(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { - // If the PatKind is a TupleStruct, Struct or Tuple then we want to check + // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check // whether the Variant is a MultiVariant or a SingleVariant. We only want // to borrow discr if it is a MultiVariant. // If it is a SingleVariant and creates a binding we will handle that when // this callback gets called again. - if let ty::Adt(def, _) = place.place.base_ty.kind() { + + // Get the type of the Place after all projections have been applied + let place_ty = place.place.ty(); + + if let ty::Adt(def, _) = place_ty.kind() { if def.variants.len() > 1 { needs_to_be_read = true; } diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs new file mode 100644 index 00000000000..241ddcb83e1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs @@ -0,0 +1,35 @@ +// run-pass +// edition:2021 + +enum Variant { + A, + B, //~ WARNING: variant is never constructed: `B` +} + +struct A { + field: Variant, +} + +fn discriminant_is_a_ref() { + let here = A { field: Variant::A }; + let out_ref = &here.field; + + || match out_ref { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn discriminant_is_a_field() { + let here = A { field: Variant::A }; + + || match here.field { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn main() { + discriminant_is_a_ref(); + discriminant_is_a_field(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr new file mode 100644 index 00000000000..38f2929a05f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr @@ -0,0 +1,33 @@ +warning: variant is never constructed: `B` + --> $DIR/issue-87097.rs:6:5 + | +LL | B, + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:17:5 + | +LL | / || match out_ref { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |______^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: closures are lazy and do nothing unless called + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:26:5 + | +LL | / || match here.field { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |______^ + | + = note: closures are lazy and do nothing unless called + +warning: 3 warnings emitted + |
