Skip to content

Commit 5a8edc0

Browse files
nikomatsakisMark-Simulacrum
authored andcommitted
cleanup: extract a helper for coercion from inference variables
1 parent 5eca626 commit 5a8edc0

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

compiler/rustc_typeck/src/check/coercion.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
146146
}
147147

148148
fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
149+
// First, remove any resolved type variables (at the top level, at least):
149150
let a = self.shallow_resolve(a);
150151
let b = self.shallow_resolve(b);
151152
debug!("Coerce.tys({:?} => {:?})", a, b);
@@ -155,6 +156,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
155156
return success(vec![], self.fcx.tcx.ty_error(), vec![]);
156157
}
157158

159+
// Coercing from `!` to any type is allowed:
158160
if a.is_never() {
159161
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
160162
// type variable, we want `?T` to fallback to `!` if not
@@ -176,6 +178,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
176178
};
177179
}
178180

181+
// Coercing *from* an unresolved inference variable means that
182+
// we have no information about the source type. This will always
183+
// ultimately fall back to some form of subtyping.
184+
if a.is_ty_var() {
185+
return self.coerce_from_inference_variable(a, b);
186+
}
187+
179188
// Consider coercing the subtype to a DST
180189
//
181190
// NOTE: this is wrapped in a `commit_if_ok` because it creates
@@ -233,6 +242,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
233242
}
234243
}
235244

245+
/// Coercing *from* an inference variable. In this case, we have no information
246+
/// about the source type, so we can't really do a true coercion and we always
247+
/// fall back to subtyping (`unify_and`).
248+
fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
249+
assert!(a.is_ty_var() && self.infcx.shallow_resolve(a) == a);
250+
assert!(self.infcx.shallow_resolve(b) == b);
251+
252+
self.unify_and(a, b, identity)
253+
}
254+
236255
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
237256
/// To match `A` with `B`, autoderef will be performed,
238257
/// calling `deref`/`deref_mut` where necessary.

0 commit comments

Comments
 (0)