Skip to content

Commit

Permalink
Structurally resolve in may_coerce
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Oct 15, 2024
1 parent 5d72a40 commit 07ec258
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 2 deletions.
23 changes: 21 additions & 2 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,12 +1092,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable);
// We don't ever need two-phase here since we throw out the result of the coercion.
// We also just always set `coerce_never` to true, since this is a heuristic.
let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true);
let coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true);
self.probe(|_| {
// Make sure to structurally resolve the types, since we use
// the `TyKind`s heavily in coercion.
let ocx = ObligationCtxt::new(self);
let structurally_resolve = |ty| {
let ty = self.shallow_resolve(ty);
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
ocx.structurally_normalize(&cause, self.param_env, ty)
} else {
Ok(ty)
}
};
let Ok(expr_ty) = structurally_resolve(expr_ty) else {
return false;
};
let Ok(target_ty) = structurally_resolve(target_ty) else {
return false;
};

let Ok(ok) = coerce.coerce(expr_ty, target_ty) else {
return false;
};
let ocx = ObligationCtxt::new(self);
ocx.register_obligations(ok.obligations);
ocx.select_where_possible().is_empty()
})
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/traits/next-solver/diagnostics/coerce-in-may-coerce.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//@ compile-flags: -Znext-solver

trait Mirror {
type Assoc;
}
impl<T> Mirror for T {
type Assoc = T;
}

fn arg() -> &'static [i32; 1] { todo!() }

fn arg_error(x: <fn() as Mirror>::Assoc, y: ()) { todo!() }

fn main() {
// Should suggest to reverse the args...
// but if we don't normalize the expected, then we don't.
arg_error((), || ());
//~^ ERROR arguments to this function are incorrect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: arguments to this function are incorrect
--> $DIR/coerce-in-may-coerce.rs:17:5
|
LL | arg_error((), || ());
| ^^^^^^^^^ -- ----- expected `()`, found `{closure@$DIR/coerce-in-may-coerce.rs:17:19: 17:21}`
| |
| expected `<fn() as Mirror>::Assoc`, found `()`
|
note: function defined here
--> $DIR/coerce-in-may-coerce.rs:12:4
|
LL | fn arg_error(x: <fn() as Mirror>::Assoc, y: ()) { todo!() }
| ^^^^^^^^^ -------------------------- -----
help: swap these arguments
|
LL | arg_error(|| (), ());
| ~~~~~~~~~~~

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit 07ec258

Please sign in to comment.