Auto merge of #55274 - pnkfelix:issue-54570-proj-path-into-pats-with-type-take-2, r=nikomatsakis
Handle bindings in substructure of patterns with type ascriptions This attempts to follow the outline described by @nikomatsakis [here](https://github.com/rust-lang/rust/issues/47184#issuecomment-420041056). Its a bit more complicated than expected for two reasons: 1. In general it handles sets of type ascriptions, because such ascriptions can be nested within patterns 2. It has a separate types in the HAIR, `PatternTypeProjections` and `PatternTypeProjection`, which are analogues to the corresponding types in the MIR. The main reason I added the new HAIR types was because I am worried that the current implementation is inefficent, and asymptotically so: It makes copies of vectors as it descends the patterns, even when those accumulated vectors are never used. Longer term, I would like to used a linked tree structure for the `PatternTypeProjections` and `PatternTypeProjection`, and save the construction of standalone vectors for the MIR types. I didn't want to block landing this on that hypoethetical revision; but I figured I could at least make the future change easier by differentiating between the two types now. Oh, one more thing: This doesn't attempt to handle `ref x` (in terms of ensuring that any necessary types are ascribed to `x` in that scenario as well). We should open an issue to investigate supporting that as well. But I didn't want to block this PR on that future work. Fix #54570
This commit is contained in:
commit
10f42cbde0
29 changed files with 622 additions and 127 deletions
|
|
@ -0,0 +1,31 @@
|
|||
// compile-pass
|
||||
#![feature(nll)]
|
||||
|
||||
// This test is reduced from a scenario pnkfelix encountered while
|
||||
// bootstrapping the compiler.
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Spanned<T> {
|
||||
pub node: T,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
pub type Variant = Spanned<VariantKind>;
|
||||
// #[derive(Clone)] pub struct Variant { pub node: VariantKind, pub span: Span, }
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VariantKind { }
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Span;
|
||||
|
||||
pub fn variant_to_span(variant: Variant) {
|
||||
match variant {
|
||||
Variant {
|
||||
span: _span,
|
||||
..
|
||||
} => { }
|
||||
};
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -9,11 +9,11 @@ fn variable_no_initializer() {
|
|||
}
|
||||
|
||||
fn tuple_no_initializer() {
|
||||
// FIXME(#47187): We are not propagating ascribed type through tuples.
|
||||
|
||||
|
||||
let x = 22;
|
||||
let (y, z): (&'static u32, &'static u32);
|
||||
y = &x;
|
||||
y = &x; //~ ERROR
|
||||
}
|
||||
|
||||
fn ref_with_ascribed_static_type() -> u32 {
|
||||
|
|
@ -34,11 +34,23 @@ fn ref_with_ascribed_any_type() -> u32 {
|
|||
struct Single<T> { value: T }
|
||||
|
||||
fn struct_no_initializer() {
|
||||
// FIXME(#47187): We are not propagating ascribed type through patterns.
|
||||
|
||||
|
||||
let x = 22;
|
||||
let Single { value: y }: Single<&'static u32>;
|
||||
y = &x;
|
||||
y = &x; //~ ERROR
|
||||
}
|
||||
|
||||
|
||||
fn struct_no_initializer_must_normalize() {
|
||||
trait Indirect { type Assoc; }
|
||||
struct StaticU32;
|
||||
impl Indirect for StaticU32 { type Assoc = &'static u32; }
|
||||
struct Single2<T: Indirect> { value: <T as Indirect>::Assoc }
|
||||
|
||||
let x = 22;
|
||||
let Single2 { value: mut _y }: Single2<StaticU32>;
|
||||
_y = &x; //~ ERROR
|
||||
}
|
||||
|
||||
fn variable_with_initializer() {
|
||||
|
|
@ -91,26 +103,31 @@ fn struct_double_field_underscore_with_initializer() {
|
|||
}
|
||||
|
||||
fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
|
||||
// The error in this test is inconsistency with
|
||||
// `static_to_a_to_static_through_tuple`, but "feels right" to
|
||||
// me. It occurs because we special case the single binding case
|
||||
// and force the type of `y` to be `&'a u32`, even though the
|
||||
// right-hand side has type `&'static u32`.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
let y: &'a u32 = &22;
|
||||
y //~ ERROR
|
||||
}
|
||||
|
||||
fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
|
||||
// FIXME(#47187): The fact that this type-checks is perhaps surprising.
|
||||
// What happens is that the right-hand side is constrained to have
|
||||
// type `&'a u32`, which is possible, because it has type
|
||||
// `&'static u32`. The variable `y` is then forced to have type
|
||||
// `&'static u32`, but it is constrained only by the right-hand
|
||||
// side, not the ascribed type, and hence it passes.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
let (y, _z): (&'a u32, u32) = (&22, 44);
|
||||
y
|
||||
y //~ ERROR
|
||||
}
|
||||
|
||||
fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
|
||||
let Single { value: y }: Single<&'a u32> = Single { value: &22 };
|
||||
y //~ ERROR
|
||||
}
|
||||
|
||||
fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,16 @@ LL | y = &x; //~ ERROR
|
|||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:16:9
|
||||
|
|
||||
LL | let (y, z): (&'static u32, &'static u32);
|
||||
| ---------------------------- type annotation requires that `x` is borrowed for `'static`
|
||||
LL | y = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:22:13
|
||||
|
|
||||
|
|
@ -20,7 +30,27 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:46:27
|
||||
--> $DIR/patterns.rs:41:9
|
||||
|
|
||||
LL | let Single { value: y }: Single<&'static u32>;
|
||||
| -------------------- type annotation requires that `x` is borrowed for `'static`
|
||||
LL | y = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:53:10
|
||||
|
|
||||
LL | let Single2 { value: mut _y }: Single2<StaticU32>;
|
||||
| ------------------ type annotation requires that `x` is borrowed for `'static`
|
||||
LL | _y = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:58:27
|
||||
|
|
||||
LL | let y: &'static u32 = &x; //~ ERROR
|
||||
| ------------ ^^ borrowed value does not live long enough
|
||||
|
|
@ -30,7 +60,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:51:27
|
||||
--> $DIR/patterns.rs:63:27
|
||||
|
|
||||
LL | let _: &'static u32 = &x; //~ ERROR
|
||||
| ------------ ^^ borrowed value does not live long enough
|
||||
|
|
@ -41,7 +71,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/patterns.rs:53:41
|
||||
--> $DIR/patterns.rs:65:41
|
||||
|
|
||||
LL | let _: Vec<&'static String> = vec![&String::new()];
|
||||
| -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
|
|
@ -50,7 +80,7 @@ LL | let _: Vec<&'static String> = vec![&String::new()];
|
|||
| type annotation requires that borrow lasts for `'static`
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/patterns.rs:56:52
|
||||
--> $DIR/patterns.rs:68:52
|
||||
|
|
||||
LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
||||
| ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
|
|
@ -59,7 +89,7 @@ LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
|||
| type annotation requires that borrow lasts for `'static`
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/patterns.rs:59:53
|
||||
--> $DIR/patterns.rs:71:53
|
||||
|
|
||||
LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
||||
| ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
|
|
@ -68,7 +98,7 @@ LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
|||
| type annotation requires that borrow lasts for `'static`
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:65:40
|
||||
--> $DIR/patterns.rs:77:40
|
||||
|
|
||||
LL | let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR
|
||||
| ------------------- ^^ borrowed value does not live long enough
|
||||
|
|
@ -78,7 +108,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:70:40
|
||||
--> $DIR/patterns.rs:82:40
|
||||
|
|
||||
LL | let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR
|
||||
| ------------------- ^^ borrowed value does not live long enough
|
||||
|
|
@ -88,7 +118,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:75:69
|
||||
--> $DIR/patterns.rs:87:69
|
||||
|
|
||||
LL | let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR
|
||||
| -------------------- ^^ borrowed value does not live long enough
|
||||
|
|
@ -98,7 +128,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:80:69
|
||||
--> $DIR/patterns.rs:92:69
|
||||
|
|
||||
LL | let Single { value: _ }: Single<&'static u32> = Single { value: &x }; //~ ERROR
|
||||
| -------------------- ^^ borrowed value does not live long enough
|
||||
|
|
@ -108,7 +138,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:88:17
|
||||
--> $DIR/patterns.rs:100:17
|
||||
|
|
||||
LL | let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
|
||||
| -------------------- type annotation requires that `x` is borrowed for `'static`
|
||||
|
|
@ -119,7 +149,7 @@ LL | }
|
|||
| - `x` dropped here while still borrowed
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:101:5
|
||||
--> $DIR/patterns.rs:113:5
|
||||
|
|
||||
LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
|
|
@ -128,14 +158,32 @@ LL | y //~ ERROR
|
|||
| ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:117:18
|
||||
--> $DIR/patterns.rs:125:5
|
||||
|
|
||||
LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | y //~ ERROR
|
||||
| ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:130:5
|
||||
|
|
||||
LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let Single { value: y }: Single<&'a u32> = Single { value: &22 };
|
||||
LL | y //~ ERROR
|
||||
| ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:134:18
|
||||
|
|
||||
LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
|
||||
| ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: aborting due to 19 previous errors
|
||||
|
||||
Some errors occurred: E0597, E0716.
|
||||
For more information about an error, try `rustc --explain E0597`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue