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`
This commit is contained in:
commit
41433795e7
@ -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;
|
||||
}
|
||||
|
35
src/test/ui/closures/2229_closure_analysis/issue-87097.rs
Normal file
35
src/test/ui/closures/2229_closure_analysis/issue-87097.rs
Normal file
@ -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();
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user