forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#123794 - oli-obk:define_opaque_types2, r=lcnr More DefineOpaqueTypes::Yes This accepts more code on stable. It is now possible to have match arms return a function item `foo::<ConcreteType>` and a function item `foo::<OpaqueTypeInDefiningScope>` in another, and that will constrain `OpaqueTypeInDefiningScope` to have the hidden type `ConcreteType`. So the following function will now compile, but on master it errors with a type mismatch on the second match arm ```rust // The function item whose generic params we want to merge. fn foo<T>(t: T) -> T { t } // Helper ensuring we can constrain `T` on `F` without explicitly specifying it fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F { f } fn k() -> impl Sized { let x = match true { true => { // `f` is `FnDef(foo, [infer_var])` let f = foo; // Get a value of an opaque type on stable let t = k(); // this returns `FnDef(foo, [k::return])` bind(t, f) } false => foo::<()>, }; todo!() } ``` r? ``@compiler-errors`` cc rust-lang#116652
- Loading branch information
Showing
4 changed files
with
282 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
//! Test that coercing between function items of the same function, | ||
//! but with different generic args succeeds in typeck, but then fails | ||
//! in borrowck when the lifetimes can't actually be merged. | ||
|
||
fn foo<T>(t: T) -> T { | ||
t | ||
} | ||
|
||
fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough | ||
x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough | ||
x = foo::<&'c ()>; | ||
x(a); | ||
x(b); | ||
x(c); | ||
} | ||
|
||
fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let x = foo::<&'c ()>; | ||
let _: &'c () = x(a); //~ ERROR lifetime may not live long enough | ||
} | ||
|
||
fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let x = foo::<&'a ()>; | ||
let _: &'a () = x(c); | ||
} | ||
|
||
fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let mut x = foo::<&'c ()>; | ||
x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough | ||
x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough | ||
x(a); | ||
x(b); | ||
x(c); | ||
} | ||
|
||
fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let x = match true { | ||
true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough | ||
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough | ||
}; | ||
x(a); | ||
x(b); | ||
x(c); | ||
} | ||
|
||
fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
let x = match true { | ||
true => foo::<&'c ()>, | ||
false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough | ||
}; | ||
|
||
x(a); | ||
x(b); //~ ERROR lifetime may not live long enough | ||
x(c); | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:10:17 | ||
| | ||
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
LL | let mut x = foo::<&'a ()>; | ||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | ||
| | ||
= help: consider adding the following bound: `'a: 'b` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:11:5 | ||
| | ||
LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
LL | let mut x = foo::<&'a ()>; | ||
LL | x = foo::<&'b ()>; | ||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | ||
| | ||
= help: consider adding the following bound: `'b: 'a` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
help: `'a` and `'b` must be the same: replace one with the other | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:20:12 | ||
| | ||
LL | fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'c` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
LL | let x = foo::<&'c ()>; | ||
LL | let _: &'c () = x(a); | ||
| ^^^^^^ type annotation requires that `'a` must outlive `'c` | ||
| | ||
= help: consider adding the following bound: `'a: 'c` | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:30:5 | ||
| | ||
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
LL | let mut x = foo::<&'c ()>; | ||
LL | x = foo::<&'b ()>; | ||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | ||
| | ||
= help: consider adding the following bound: `'b: 'a` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:31:5 | ||
| | ||
LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
... | ||
LL | x = foo::<&'a ()>; | ||
| ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | ||
| | ||
= help: consider adding the following bound: `'a: 'b` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
help: `'a` and `'b` must be the same: replace one with the other | ||
| | ||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:39:17 | ||
| | ||
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
LL | let x = match true { | ||
LL | true => foo::<&'b ()>, | ||
| ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | ||
| | ||
= help: consider adding the following bound: `'b: 'a` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:40:18 | ||
| | ||
LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
... | ||
LL | false => foo::<&'a ()>, | ||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | ||
| | ||
= help: consider adding the following bound: `'a: 'b` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
help: `'a` and `'b` must be the same: replace one with the other | ||
| | ||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:50:18 | ||
| | ||
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'c` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
... | ||
LL | false => foo::<&'a ()>, | ||
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` | ||
| | ||
= help: consider adding the following bound: `'a: 'c` | ||
= note: requirement occurs because of a function pointer to `foo` | ||
= note: the function `foo` is invariant over the parameter `T` | ||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance | ||
|
||
error: lifetime may not live long enough | ||
--> $DIR/fn_def_coercion.rs:54:5 | ||
| | ||
LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | ||
| -- -- lifetime `'b` defined here | ||
| | | ||
| lifetime `'a` defined here | ||
... | ||
LL | x(b); | ||
| ^^^^ argument requires that `'b` must outlive `'a` | ||
| | ||
= help: consider adding the following bound: `'b: 'a` | ||
|
||
help: the following changes may resolve your lifetime errors | ||
| | ||
= help: add bound `'a: 'c` | ||
= help: add bound `'b: 'a` | ||
|
||
error: aborting due to 9 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//! Test that coercing between function items of the same function, | ||
//! but with different generic args works. | ||
|
||
//@check-pass | ||
|
||
#![feature(type_alias_impl_trait)] | ||
|
||
fn foo<T>(t: T) -> T { | ||
t | ||
} | ||
|
||
type F = impl Sized; | ||
|
||
fn f(a: F) { | ||
let mut x = foo::<F>; | ||
x = foo::<()>; | ||
x(a); | ||
x(()); | ||
} | ||
|
||
type G = impl Sized; | ||
|
||
fn g(a: G) { | ||
let x = foo::<()>; | ||
let _: () = x(a); | ||
} | ||
|
||
type H = impl Sized; | ||
|
||
fn h(a: H) { | ||
let x = foo::<H>; | ||
let _: H = x(()); | ||
} | ||
|
||
type I = impl Sized; | ||
|
||
fn i(a: I) { | ||
let mut x = foo::<()>; | ||
x = foo::<I>; | ||
x(a); | ||
x(()); | ||
} | ||
|
||
type J = impl Sized; | ||
|
||
fn j(a: J) { | ||
let x = match true { | ||
true => foo::<J>, | ||
false => foo::<()>, | ||
}; | ||
x(a); | ||
x(()); | ||
} | ||
|
||
fn k() -> impl Sized { | ||
fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F { | ||
f | ||
} | ||
let x = match true { | ||
true => { | ||
let f = foo; | ||
bind(k(), f) | ||
} | ||
false => foo::<()>, | ||
}; | ||
todo!() | ||
} | ||
|
||
fn main() {} |