about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-07-16 10:08:08 +0200
committerGitHub <noreply@github.com>2021-07-16 10:08:08 +0200
commit41433795e75fa96e4ad880802879da7892d12fad (patch)
treed31facc98fa12aef40e6121e63978329a0a2f38b
parentc1b9bbf1e78b932b857849330241f742e01238de (diff)
parent9fe470b620430775d084130ccd9333c15deb54d0 (diff)
downloadrust-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`
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs8
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-87097.rs35
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-87097.stderr33
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
+