Skip to content

Commit 9070aba

Browse files
Structurally resolve in may_coerce
1 parent e3eba2d commit 9070aba

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -1094,12 +1094,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10941094
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10951095
// We don't ever need two-phase here since we throw out the result of the coercion.
10961096
// We also just always set `coerce_never` to true, since this is a heuristic.
1097-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
1097+
let coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
10981098
self.probe(|_| {
1099+
// Make sure to structurally resolve the types, since we use
1100+
// the `TyKind`s heavily in coercion.
1101+
let ocx = ObligationCtxt::new(self);
1102+
let structurally_resolve = |ty| {
1103+
let ty = self.shallow_resolve(ty);
1104+
if self.next_trait_solver()
1105+
&& let ty::Alias(..) = ty.kind()
1106+
{
1107+
ocx.structurally_normalize(&cause, self.param_env, ty)
1108+
} else {
1109+
Ok(ty)
1110+
}
1111+
};
1112+
let Ok(expr_ty) = structurally_resolve(expr_ty) else {
1113+
return false;
1114+
};
1115+
let Ok(target_ty) = structurally_resolve(target_ty) else {
1116+
return false;
1117+
};
1118+
10991119
let Ok(ok) = coerce.coerce(expr_ty, target_ty) else {
11001120
return false;
11011121
};
1102-
let ocx = ObligationCtxt::new(self);
11031122
ocx.register_obligations(ok.obligations);
11041123
ocx.select_where_possible().is_empty()
11051124
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ compile-flags: -Znext-solver
2+
3+
trait Mirror {
4+
type Assoc;
5+
}
6+
impl<T> Mirror for T {
7+
type Assoc = T;
8+
}
9+
10+
fn arg() -> &'static [i32; 1] { todo!() }
11+
12+
fn arg_error(x: <fn() as Mirror>::Assoc, y: ()) { todo!() }
13+
14+
fn main() {
15+
// Should suggest to reverse the args...
16+
// but if we don't normalize the expected, then we don't.
17+
arg_error((), || ());
18+
//~^ ERROR arguments to this function are incorrect
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: arguments to this function are incorrect
2+
--> $DIR/coerce-in-may-coerce.rs:17:5
3+
|
4+
LL | arg_error((), || ());
5+
| ^^^^^^^^^ -- ----- expected `()`, found `{closure@$DIR/coerce-in-may-coerce.rs:17:19: 17:21}`
6+
| |
7+
| expected `<fn() as Mirror>::Assoc`, found `()`
8+
|
9+
note: function defined here
10+
--> $DIR/coerce-in-may-coerce.rs:12:4
11+
|
12+
LL | fn arg_error(x: <fn() as Mirror>::Assoc, y: ()) { todo!() }
13+
| ^^^^^^^^^ -------------------------- -----
14+
help: swap these arguments
15+
|
16+
LL | arg_error(|| (), ());
17+
| ~~~~~~~~~~~
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)