Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make closure capturing have consistent and correct behaviour around patterns #138961

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
413 changes: 162 additions & 251 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -1447,6 +1447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.resolve_vars_with_obligations(ty);

debug!("next_solver = {:?}", self.next_trait_solver());
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
10 changes: 5 additions & 5 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
@@ -18,12 +18,12 @@
//! from there).
//!
//! The fact that we are inferring borrow kinds as we go results in a
//! semi-hacky interaction with mem-categorization. In particular,
//! mem-categorization will query the current borrow kind as it
//! categorizes, and we'll return the *current* value, but this may get
//! semi-hacky interaction with the way `ExprUseVisitor` is computing
//! `Place`s. In particular, it will query the current borrow kind as it
//! goes, and we'll return the *current* value, but this may get
//! adjusted later. Therefore, in this module, we generally ignore the
//! borrow kind (and derived mutabilities) that are returned from
//! mem-categorization, since they may be inaccurate. (Another option
//! borrow kind (and derived mutabilities) that `ExprUseVisitor` returns
//! within `Place`s, since they may be inaccurate. (Another option
//! would be to use a unification scheme, where instead of returning a
//! concrete borrow kind like `ty::ImmBorrow`, we return a
//! `ty::InferBorrow(upvar_id)` or something like that, but this would
10 changes: 8 additions & 2 deletions compiler/rustc_middle/src/hir/place.rs
Original file line number Diff line number Diff line change
@@ -53,7 +53,10 @@ pub struct Projection<'tcx> {
pub kind: ProjectionKind,
}

/// A `Place` represents how a value is located in memory.
/// A `Place` represents how a value is located in memory. This does not
/// always correspond to a syntactic place expression. For example, when
/// processing a pattern, a `Place` can be used to refer to the sub-value
/// currently being inspected.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
@@ -67,7 +70,10 @@ pub struct Place<'tcx> {
pub projections: Vec<Projection<'tcx>>,
}

/// A `PlaceWithHirId` represents how a value is located in memory.
/// A `PlaceWithHirId` represents how a value is located in memory. This does not
/// always correspond to a syntactic place expression. For example, when
/// processing a pattern, a `Place` can be used to refer to the sub-value
/// currently being inspected.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
File renamed without changes.
15 changes: 15 additions & 0 deletions tests/crashes/119786-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ known-bug: #119786
//@ edition:2021

fn enum_upvar() {
type T = impl Copy;
let foo: T = Some((1u32, 2u32));
let x = move || {
match foo {
None => (),
Some(_) => (),
}
};
}

pub fn main() {}
15 changes: 15 additions & 0 deletions tests/crashes/119786-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ known-bug: #119786
//@ edition:2021

fn enum_upvar() {
type T = impl Copy;
let foo: T = Some((1u32, 2u32));
let x = move || {
match foo {
None => (),
Some((a, b)) => (),
}
};
}

pub fn main() {}
17 changes: 0 additions & 17 deletions tests/crashes/137467-1.rs

This file was deleted.

18 changes: 0 additions & 18 deletions tests/crashes/137467-2.rs

This file was deleted.

8 changes: 0 additions & 8 deletions tests/crashes/137467-3.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -4,18 +4,16 @@ fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake
yields ()
{
debug _task_context => _2;
debug f => (*(_1.0: &&Foo));
debug f => (*(_1.0: &Foo));
let mut _0: ();
let mut _3: &Foo;
let mut _4: &&Foo;
let mut _5: &&&Foo;
let mut _6: isize;
let mut _7: bool;
let mut _5: isize;
let mut _6: bool;

bb0: {
PlaceMention((*(_1.0: &&Foo)));
_6 = discriminant((*(*(_1.0: &&Foo))));
switchInt(move _6) -> [0: bb2, otherwise: bb1];
_5 = discriminant((*(_1.0: &Foo)));
switchInt(move _5) -> [0: bb2, otherwise: bb1];
}

bb1: {
@@ -32,28 +30,25 @@ yields ()
}

bb4: {
FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo)));
unreachable;
}

bb5: {
_3 = &fake shallow (*(*(_1.0: &&Foo)));
_4 = &fake shallow (*(_1.0: &&Foo));
_5 = &fake shallow (_1.0: &&Foo);
StorageLive(_7);
_7 = const true;
switchInt(move _7) -> [0: bb8, otherwise: bb7];
_3 = &fake shallow (*(_1.0: &Foo));
_4 = &fake shallow (_1.0: &Foo);
StorageLive(_6);
_6 = const true;
switchInt(move _6) -> [0: bb8, otherwise: bb7];
}

bb6: {
falseEdge -> [real: bb3, imaginary: bb1];
}

bb7: {
StorageDead(_7);
StorageDead(_6);
FakeRead(ForMatchGuard, _3);
FakeRead(ForMatchGuard, _4);
FakeRead(ForMatchGuard, _5);
_0 = const ();
goto -> bb10;
}
@@ -63,7 +58,7 @@ yields ()
}

bb9: {
StorageDead(_7);
StorageDead(_6);
goto -> bb6;
}

Original file line number Diff line number Diff line change
@@ -4,18 +4,16 @@ fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake
yields ()
{
debug _task_context => _2;
debug f => (_1.0: &Foo);
debug f => (*(_1.0: &Foo));
let mut _0: ();
let mut _3: &Foo;
let mut _4: &&Foo;
let mut _5: &&&Foo;
let mut _6: isize;
let mut _7: bool;
let mut _5: isize;
let mut _6: bool;

bb0: {
PlaceMention((_1.0: &Foo));
_6 = discriminant((*(_1.0: &Foo)));
switchInt(move _6) -> [0: bb2, otherwise: bb1];
_5 = discriminant((*(_1.0: &Foo)));
switchInt(move _5) -> [0: bb2, otherwise: bb1];
}

bb1: {
@@ -29,24 +27,22 @@ yields ()

bb3: {
_3 = &fake shallow (*(_1.0: &Foo));
_4 = &fake shallow (_1.0: &Foo);
nop;
StorageLive(_7);
_7 = const true;
switchInt(move _7) -> [0: bb5, otherwise: bb4];
StorageLive(_6);
_6 = const true;
switchInt(move _6) -> [0: bb5, otherwise: bb4];
}

bb4: {
StorageDead(_7);
StorageDead(_6);
FakeRead(ForMatchGuard, _3);
FakeRead(ForMatchGuard, _4);
FakeRead(ForMatchGuard, _5);
_0 = const ();
goto -> bb6;
}

bb5: {
StorageDead(_7);
StorageDead(_6);
falseEdge -> [real: bb1, imaginary: bb1];
}

2 changes: 2 additions & 0 deletions tests/ui/closures/2229_closure_analysis/capture-enums.rs
Original file line number Diff line number Diff line change
@@ -22,13 +22,15 @@ fn multi_variant_enum() {
//~| Min Capture analysis includes:
if let Info::Point(_, _, str) = point {
//~^ NOTE: Capturing point[] -> Immutable
//~| NOTE: Capturing point[] -> Immutable
//~| NOTE: Capturing point[(2, 0)] -> ByValue
//~| NOTE: Min Capture point[] -> ByValue
println!("{}", str);
}

if let Info::Meta(_, v) = meta {
//~^ NOTE: Capturing meta[] -> Immutable
//~| NOTE: Capturing meta[] -> Immutable
//~| NOTE: Capturing meta[(1, 1)] -> ByValue
//~| NOTE: Min Capture meta[] -> ByValue
println!("{:?}", v);
26 changes: 18 additions & 8 deletions tests/ui/closures/2229_closure_analysis/capture-enums.stderr
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ LL | let c = #[rustc_capture_analysis]
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: attributes on expressions are experimental
--> $DIR/capture-enums.rs:48:13
--> $DIR/capture-enums.rs:50:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,18 +34,28 @@ note: Capturing point[] -> Immutable
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing point[] -> Immutable
--> $DIR/capture-enums.rs:23:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:23:41
|
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Capturing meta[] -> Immutable
--> $DIR/capture-enums.rs:30:35
--> $DIR/capture-enums.rs:31:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
note: Capturing meta[] -> Immutable
--> $DIR/capture-enums.rs:31:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
note: Capturing meta[(1, 1)] -> ByValue
--> $DIR/capture-enums.rs:30:35
--> $DIR/capture-enums.rs:31:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^
@@ -67,13 +77,13 @@ note: Min Capture point[] -> ByValue
LL | if let Info::Point(_, _, str) = point {
| ^^^^^
note: Min Capture meta[] -> ByValue
--> $DIR/capture-enums.rs:30:35
--> $DIR/capture-enums.rs:31:35
|
LL | if let Info::Meta(_, v) = meta {
| ^^^^

error: First Pass analysis includes:
--> $DIR/capture-enums.rs:52:5
--> $DIR/capture-enums.rs:54:5
|
LL | / || {
LL | |
@@ -85,13 +95,13 @@ LL | | };
| |_____^
|
note: Capturing point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:55:47
--> $DIR/capture-enums.rs:57:47
|
LL | let SingleVariant::Point(_, _, str) = point;
| ^^^^^

error: Min Capture analysis includes:
--> $DIR/capture-enums.rs:52:5
--> $DIR/capture-enums.rs:54:5
|
LL | / || {
LL | |
@@ -103,7 +113,7 @@ LL | | };
| |_____^
|
note: Min Capture point[(2, 0)] -> ByValue
--> $DIR/capture-enums.rs:55:47
--> $DIR/capture-enums.rs:57:47
|
LL | let SingleVariant::Point(_, _, str) = point;
| ^^^^^
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ error[E0505]: cannot move out of `ts` because it is borrowed
LL | let _b = || { match ts {
| -- -- borrow occurs due to use in closure
| |
| borrow of `ts` occurs here
| borrow of `ts.x` occurs here
...
LL | let mut mut_ts = ts;
| ^^ move out of `ts` occurs here
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.