Skip to content

Commit cf80f75

Browse files
authored
Unrolled build for rust-lang#124297
Rollup merge of rust-lang#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 rust-lang#116652 This is very similar to rust-lang#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`*
2 parents 39d2f2a + c24148e commit cf80f75

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11591159
let sig = self
11601160
.at(cause, self.param_env)
11611161
.trace(prev_ty, new_ty)
1162-
.lub(DefineOpaqueTypes::No, a_sig, b_sig)
1162+
.lub(DefineOpaqueTypes::Yes, a_sig, b_sig)
11631163
.map(|ok| self.register_infer_ok_obligations(ok))?;
11641164

11651165
// Reify both sides and return the reified fn pointer type.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! Test that coercing between function items of different functions works,
2+
//! as long as their signatures match. The resulting value is a function pointer.
3+
4+
#![feature(type_alias_impl_trait)]
5+
6+
fn foo<T>(t: T) -> T {
7+
t
8+
}
9+
10+
fn bar<T>(t: T) -> T {
11+
t
12+
}
13+
14+
type F = impl Sized;
15+
16+
fn f(a: F) {
17+
let mut x = bar::<F>;
18+
x = foo::<()>; //~ ERROR: mismatched types
19+
x(a);
20+
x(());
21+
}
22+
23+
type I = impl Sized;
24+
25+
fn i(a: I) {
26+
let mut x = bar::<()>;
27+
x = foo::<I>; //~ ERROR: mismatched types
28+
x(a);
29+
x(());
30+
}
31+
32+
type J = impl Sized;
33+
34+
fn j(a: J) {
35+
let x = match true {
36+
true => bar::<J>,
37+
false => foo::<()>,
38+
};
39+
x(a);
40+
x(());
41+
}
42+
43+
fn k() -> impl Sized {
44+
fn bind<T, F: FnOnce(T) -> T>(_: T, f: F) -> F {
45+
f
46+
}
47+
let x = match true {
48+
true => {
49+
let f = foo;
50+
bind(k(), f)
51+
}
52+
false => bar::<()>,
53+
};
54+
todo!()
55+
}
56+
57+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:18:9
3+
|
4+
LL | type F = impl Sized;
5+
| ---------- the expected opaque type
6+
...
7+
LL | let mut x = bar::<F>;
8+
| -------- expected due to this value
9+
LL | x = foo::<()>;
10+
| ^^^^^^^^^ expected fn item, found a different fn item
11+
|
12+
= note: expected fn item `fn(F) -> F {bar::<F>}`
13+
found fn item `fn(()) {foo::<()>}`
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9
17+
|
18+
LL | fn foo<T>(t: T) -> T {
19+
| -------------------- function `foo` defined here
20+
...
21+
LL | type I = impl Sized;
22+
| ---------- the found opaque type
23+
...
24+
LL | let mut x = bar::<()>;
25+
| --------- expected due to this value
26+
LL | x = foo::<I>;
27+
| ^^^^^^^^ expected fn item, found a different fn item
28+
|
29+
= note: expected fn item `fn(()) {bar::<()>}`
30+
found fn item `fn(I) -> I {foo::<I>}`
31+
help: use parentheses to call this function
32+
|
33+
LL | x = foo::<I>(/* I */);
34+
| +++++++++
35+
36+
error: aborting due to 2 previous errors
37+
38+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)