Skip to content

Commit 07ec258

Browse files
Structurally resolve in may_coerce
1 parent 5d72a40 commit 07ec258

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,12 +1092,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10921092
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
10931093
// We don't ever need two-phase here since we throw out the result of the coercion.
10941094
// We also just always set `coerce_never` to true, since this is a heuristic.
1095-
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
1095+
let coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
10961096
self.probe(|_| {
1097+
// Make sure to structurally resolve the types, since we use
1098+
// the `TyKind`s heavily in coercion.
1099+
let ocx = ObligationCtxt::new(self);
1100+
let structurally_resolve = |ty| {
1101+
let ty = self.shallow_resolve(ty);
1102+
if self.next_trait_solver()
1103+
&& let ty::Alias(..) = ty.kind()
1104+
{
1105+
ocx.structurally_normalize(&cause, self.param_env, ty)
1106+
} else {
1107+
Ok(ty)
1108+
}
1109+
};
1110+
let Ok(expr_ty) = structurally_resolve(expr_ty) else {
1111+
return false;
1112+
};
1113+
let Ok(target_ty) = structurally_resolve(target_ty) else {
1114+
return false;
1115+
};
1116+
10971117
let Ok(ok) = coerce.coerce(expr_ty, target_ty) else {
10981118
return false;
10991119
};
1100-
let ocx = ObligationCtxt::new(self);
11011120
ocx.register_obligations(ok.obligations);
11021121
ocx.select_where_possible().is_empty()
11031122
})
Lines changed: 19 additions & 0 deletions
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+
}
Lines changed: 21 additions & 0 deletions
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)