From c6a17bf8bcfa60c8b0436251d2cf70d8eca4d198 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Wed, 16 Nov 2022 13:11:44 +0300 Subject: make ascribe_user_type a TypeOp Projection types in user annotations may contain inference variables. This makes the normalization depend on the unification with the actual type and thus requires a separate TypeOp to track the obligations. Otherwise simply calling `TypeChecker::normalize` would ICE with "unexpected ambiguity" --- src/test/ui/nll/ty-outlives/wf-unreachable.stderr | 16 ++-- src/test/ui/nll/user-annotations/closure-sig.rs | 15 +++ .../ui/nll/user-annotations/normalization-infer.rs | 40 ++++++++ .../user-annotations/normalization-infer.stderr | 101 +++++++++++++++++++++ ...oc-type-in-supertrait-outlives-container.stderr | 2 +- .../regions-free-region-ordering-caller.stderr | 6 +- ...gions-outlives-projection-container-hrtb.stderr | 4 +- ...regions-outlives-projection-container-wc.stderr | 2 +- .../regions-outlives-projection-container.stderr | 4 +- 9 files changed, 173 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/nll/user-annotations/closure-sig.rs create mode 100644 src/test/ui/nll/user-annotations/normalization-infer.rs create mode 100644 src/test/ui/nll/user-annotations/normalization-infer.stderr (limited to 'src/test') diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr index a62157f44f5..da3bc208322 100644 --- a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr @@ -5,7 +5,7 @@ LL | fn uninit<'a>() { | -- lifetime `'a` defined here LL | return; LL | let x: &'static &'a (); - | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:11:12 @@ -14,7 +14,7 @@ LL | fn var_type<'a>() { | -- lifetime `'a` defined here LL | return; LL | let x: &'static &'a () = &&(); - | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:15:12 @@ -22,7 +22,7 @@ error: lifetime may not live long enough LL | fn uninit_infer<'a>() { | -- lifetime `'a` defined here LL | let x: &'static &'a _; - | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:21:12 @@ -31,7 +31,7 @@ LL | fn infer<'a>() { | -- lifetime `'a` defined here LL | return; LL | let x: &'static &'a _ = &&(); - | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:26:12 @@ -40,7 +40,7 @@ LL | fn uninit_no_var<'a>() { | -- lifetime `'a` defined here LL | return; LL | let _: &'static &'a (); - | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:31:12 @@ -49,7 +49,7 @@ LL | fn no_var<'a>() { | -- lifetime `'a` defined here LL | return; LL | let _: &'static &'a () = &&(); - | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:36:12 @@ -58,7 +58,7 @@ LL | fn infer_no_var<'a>() { | -- lifetime `'a` defined here LL | return; LL | let _: &'static &'a _ = &&(); - | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:49:12 @@ -67,7 +67,7 @@ LL | fn required_substs<'a>() { | -- lifetime `'a` defined here LL | return; LL | let _: C<'static, 'a, _> = C((), &(), &()); - | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` error: aborting due to 8 previous errors diff --git a/src/test/ui/nll/user-annotations/closure-sig.rs b/src/test/ui/nll/user-annotations/closure-sig.rs new file mode 100644 index 00000000000..4dbd3fd8d81 --- /dev/null +++ b/src/test/ui/nll/user-annotations/closure-sig.rs @@ -0,0 +1,15 @@ +// This test fails if #104478 is fixed before #104477. + +// check-pass + +struct Printer<'a, 'b>(&'a (), &'b ()); + +impl Printer<'_, '_> { + fn test(self) { + let clo = |_: &'_ Self| {}; + clo(&self); + clo(&self); + } +} + +fn main() {} diff --git a/src/test/ui/nll/user-annotations/normalization-infer.rs b/src/test/ui/nll/user-annotations/normalization-infer.rs new file mode 100644 index 00000000000..8bfc272d4ba --- /dev/null +++ b/src/test/ui/nll/user-annotations/normalization-infer.rs @@ -0,0 +1,40 @@ +// Annnotations may contain projection types with inference variables as input. +// Make sure we don't get ambiguities when normalizing them. + +// check-fail + +// Single impl. +fn test1(a: A, b: B, c: C) { + trait Tr { type Ty; } + impl Tr for (T,) { type Ty = T; } + + let _: <(_,) as Tr>::Ty = a; //~ ERROR type `A` + Some::<<(_,) as Tr>::Ty>(b); //~ ERROR type `B` + || -> <(_,) as Tr>::Ty { c }; //~ ERROR type `C` + |d: <(_,) as Tr>::Ty| -> D { d }; //~ ERROR type `D` +} + + +// Two impls. The selected impl depends on the actual type. +fn test2(a: A, b: B, c: C) { + trait Tr { type Ty; } + impl Tr for (u8, T) { type Ty = T; } + impl Tr for (i8, T) { type Ty = T; } + type Alias = (<(X, Y) as Tr>::Ty, X); + + fn temp() -> String { todo!() } + + // `u8` impl, requires static. + let _: Alias<_, _> = (a, 0u8); //~ ERROR type `A` + Some::>((b, 0u8)); //~ ERROR type `B` + || -> Alias<_, _> { (c, 0u8) }; //~ ERROR type `C` + + let _: Alias<_, _> = (&temp(), 0u8); //~ ERROR temporary value + Some::>((&temp(), 0u8)); //~ ERROR temporary value + + // `i8` impl, no region constraints. + let _: Alias<_, _> = (&temp(), 0i8); + Some::>((&temp(), 0i8)); +} + +fn main() {} diff --git a/src/test/ui/nll/user-annotations/normalization-infer.stderr b/src/test/ui/nll/user-annotations/normalization-infer.stderr new file mode 100644 index 00000000000..12854ab6816 --- /dev/null +++ b/src/test/ui/nll/user-annotations/normalization-infer.stderr @@ -0,0 +1,101 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/normalization-infer.rs:11:12 + | +LL | let _: <(_,) as Tr>::Ty = a; + | ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `B` may not live long enough + --> $DIR/normalization-infer.rs:12:5 + | +LL | Some::<<(_,) as Tr>::Ty>(b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `C` may not live long enough + --> $DIR/normalization-infer.rs:13:11 + | +LL | || -> <(_,) as Tr>::Ty { c }; + | ^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `D` may not live long enough + --> $DIR/normalization-infer.rs:14:6 + | +LL | |d: <(_,) as Tr>::Ty| -> D { d }; + | ^ ...so that the type `D` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/normalization-infer.rs:28:12 + | +LL | let _: Alias<_, _> = (a, 0u8); + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `B` may not live long enough + --> $DIR/normalization-infer.rs:29:5 + | +LL | Some::>((b, 0u8)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `C` may not live long enough + --> $DIR/normalization-infer.rs:30:11 + | +LL | || -> Alias<_, _> { (c, 0u8) }; + | ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0716]: temporary value dropped while borrowed + --> $DIR/normalization-infer.rs:32:28 + | +LL | let _: Alias<_, _> = (&temp(), 0u8); + | ----------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/normalization-infer.rs:33:27 + | +LL | Some::>((&temp(), 0u8)); + | --^^^^^^------ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | this usage requires that borrow lasts for `'static` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0310, E0716. +For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr index 87e33e1ccff..2a262520361 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr @@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() { | lifetime `'a` defined here ... LL | let _: &'a WithAssoc> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.stderr index c79ed50c6a4..cdf70d2a5be 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller.stderr @@ -6,7 +6,7 @@ LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { | | | lifetime `'a` defined here LL | let z: Option<&'b &'a usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` @@ -19,7 +19,7 @@ LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { | lifetime `'a` defined here LL | let y: Paramd<'a> = Paramd { x: a }; LL | let z: Option<&'b Paramd<'a>> = None; - | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` @@ -31,7 +31,7 @@ LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { | | | lifetime `'a` defined here LL | let z: Option<&'a &'b usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr index 187e9056e11..6a7c908fa40 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.stderr @@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() { | lifetime `'a` defined here ... LL | let _: &'a WithHrAssoc> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` @@ -20,7 +20,7 @@ LL | fn with_assoc_sub<'a,'b>() { | lifetime `'a` defined here ... LL | let _: &'a WithHrAssocSub> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr index 4178e951c86..eba2a0d5853 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr @@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() { | lifetime `'a` defined here ... LL | let _: &'a WithAssoc> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index 073a3190022..d20a2f06adf 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -7,7 +7,7 @@ LL | fn with_assoc<'a,'b>() { | lifetime `'a` defined here ... LL | let _x: &'a WithAssoc> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` @@ -20,7 +20,7 @@ LL | fn without_assoc<'a,'b>() { | lifetime `'a` defined here ... LL | let _x: &'a WithoutAssoc> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` -- cgit 1.4.1-3-g733a5