Structurally resolve in may_coerce
This commit is contained in:
parent
e3eba2d920
commit
9070abab4b
@ -1094,12 +1094,31 @@ pub(crate) fn may_coerce(&self, expr_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> bool
|
||||
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()
|
||||
})
|
||||
|
@ -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
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user