diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-23 14:09:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-23 14:09:22 +0200 |
| commit | abcf400a2835e1db65d034128b25a276b61080a3 (patch) | |
| tree | 6b14a27b23931535e457dd5fd7c4b28937021ff7 /tests | |
| parent | 39d2f2affdd6b2856ab4b91359cc0d32b90bd26f (diff) | |
| parent | c24148ef7b1d4a280cca60e2001848da70ff07dc (diff) | |
| download | rust-abcf400a2835e1db65d034128b25a276b61080a3.tar.gz rust-abcf400a2835e1db65d034128b25a276b61080a3.zip | |
Rollup merge of #124297 - oli-obk:define_opaque_types13, r=jackh726
Allow coercing functions whose signature differs in opaque types in their defining scope into a shared function pointer type
r? `@compiler-errors`
This accepts more code on stable. It is now possible to have match arms return a function item `foo` and a different function item `bar` in another, and that will constrain OpaqueTypeInDefiningScope to have the hidden type ConcreteType and make the type of the match arms a function pointer that matches the signature. So the following function will now compile, but on master it errors with a type mismatch on the second match arm
```rust
fn foo<T>(t: T) -> T {
t
}
fn bar<T>(t: T) -> T {
t
}
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 => bar::<()>,
};
todo!()
}
```
cc https://github.com/rust-lang/rust/issues/116652
This is very similar to https://github.com/rust-lang/rust/pull/123794, and with the same rationale:
> this is for consistency with `-Znext-solver`. the new solver does not have the concept of "non-defining use of opaque" right now and we would like to ideally keep it that way. Moving to `DefineOpaqueTypes::Yes` in more cases removes subtlety from the type system. Right now we have to be careful when relating `Opaque` with another type as the behavior changes depending on whether we later use the `Opaque` or its hidden type directly (even though they are equal), if that later use is with `DefineOpaqueTypes::No`*
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs | 57 | ||||
| -rw-r--r-- | tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr | 38 |
2 files changed, 95 insertions, 0 deletions
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs new file mode 100644 index 00000000000..5250e3a3d93 --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs @@ -0,0 +1,57 @@ +//! Test that coercing between function items of different functions works, +//! as long as their signatures match. The resulting value is a function pointer. + +#![feature(type_alias_impl_trait)] + +fn foo<T>(t: T) -> T { + t +} + +fn bar<T>(t: T) -> T { + t +} + +type F = impl Sized; + +fn f(a: F) { + let mut x = bar::<F>; + x = foo::<()>; //~ ERROR: mismatched types + x(a); + x(()); +} + +type I = impl Sized; + +fn i(a: I) { + let mut x = bar::<()>; + x = foo::<I>; //~ ERROR: mismatched types + x(a); + x(()); +} + +type J = impl Sized; + +fn j(a: J) { + let x = match true { + true => bar::<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 => bar::<()>, + }; + todo!() +} + +fn main() {} diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr new file mode 100644 index 00000000000..0b3331b040d --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:18:9 + | +LL | type F = impl Sized; + | ---------- the expected opaque type +... +LL | let mut x = bar::<F>; + | -------- expected due to this value +LL | x = foo::<()>; + | ^^^^^^^^^ expected fn item, found a different fn item + | + = note: expected fn item `fn(F) -> F {bar::<F>}` + found fn item `fn(()) {foo::<()>}` + +error[E0308]: mismatched types + --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9 + | +LL | fn foo<T>(t: T) -> T { + | -------------------- function `foo` defined here +... +LL | type I = impl Sized; + | ---------- the found opaque type +... +LL | let mut x = bar::<()>; + | --------- expected due to this value +LL | x = foo::<I>; + | ^^^^^^^^ expected fn item, found a different fn item + | + = note: expected fn item `fn(()) {bar::<()>}` + found fn item `fn(I) -> I {foo::<I>}` +help: use parentheses to call this function + | +LL | x = foo::<I>(/* I */); + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. |
