Skip to content

Commit 3861583

Browse files
nikomatsakisMark-Simulacrum
authored andcommitted
create Coercion obligations given 2 unbound type variables
Motivation: in upcoming commits, we are going to create a graph of the coercion relationships between variables. We want to distinguish *coercion* specifically from other sorts of subtyping, as it indicates values flowing from one place to another via assignment.
1 parent 536da6f commit 3861583

File tree

1 file changed

+48
-5
lines changed

1 file changed

+48
-5
lines changed

compiler/rustc_typeck/src/check/coercion.rs

+48-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use rustc_hir as hir;
4242
use rustc_hir::def_id::DefId;
4343
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4444
use rustc_infer::infer::{Coercion, InferOk, InferResult};
45+
use rustc_infer::traits::Obligation;
4546
use rustc_middle::lint::in_external_macro;
4647
use rustc_middle::ty::adjustment::{
4748
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -50,7 +51,7 @@ use rustc_middle::ty::error::TypeError;
5051
use rustc_middle::ty::fold::TypeFoldable;
5152
use rustc_middle::ty::relate::RelateResult;
5253
use rustc_middle::ty::subst::SubstsRef;
53-
use rustc_middle::ty::{self, Ty, TypeAndMut};
54+
use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut};
5455
use rustc_session::parse::feature_err;
5556
use rustc_span::symbol::sym;
5657
use rustc_span::{self, BytePos, Span};
@@ -172,7 +173,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
172173
kind: TypeVariableOriginKind::AdjustmentType,
173174
span: self.cause.span,
174175
});
175-
self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
176+
self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
176177
} else {
177178
success(simple(Adjust::NeverToAny)(b), b, vec![])
178179
};
@@ -182,7 +183,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
182183
// we have no information about the source type. This will always
183184
// ultimately fall back to some form of subtyping.
184185
if a.is_ty_var() {
185-
return self.coerce_from_inference_variable(a, b);
186+
return self.coerce_from_inference_variable(a, b, identity);
186187
}
187188

188189
// Consider coercing the subtype to a DST
@@ -245,11 +246,53 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
245246
/// Coercing *from* an inference variable. In this case, we have no information
246247
/// about the source type, so we can't really do a true coercion and we always
247248
/// fall back to subtyping (`unify_and`).
248-
fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
249+
fn coerce_from_inference_variable(
250+
&self,
251+
a: Ty<'tcx>,
252+
b: Ty<'tcx>,
253+
make_adjustments: impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
254+
) -> CoerceResult<'tcx> {
255+
debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b);
249256
assert!(a.is_ty_var() && self.infcx.shallow_resolve(a) == a);
250257
assert!(self.infcx.shallow_resolve(b) == b);
251258

252-
self.unify_and(a, b, identity)
259+
if b.is_ty_var() {
260+
// Two unresolved type variables: create a `Coerce` predicate.
261+
let target_ty = if self.use_lub {
262+
self.infcx.next_ty_var(TypeVariableOrigin {
263+
kind: TypeVariableOriginKind::LatticeVariable,
264+
span: self.cause.span,
265+
})
266+
} else {
267+
b
268+
};
269+
270+
let mut obligations = Vec::with_capacity(2);
271+
for &source_ty in &[a, b] {
272+
if source_ty != target_ty {
273+
obligations.push(Obligation::new(
274+
self.cause.clone(),
275+
self.param_env,
276+
ty::PredicateKind::Coerce(ty::CoercePredicate {
277+
a: source_ty,
278+
b: target_ty,
279+
})
280+
.to_predicate(self.tcx()),
281+
));
282+
}
283+
}
284+
285+
debug!(
286+
"coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}",
287+
target_ty, obligations
288+
);
289+
let adjustments = make_adjustments(target_ty);
290+
InferResult::Ok(InferOk { value: (adjustments, target_ty), obligations })
291+
} else {
292+
// One unresolved type variable: just apply subtyping, we may be able
293+
// to do something useful.
294+
self.unify_and(a, b, make_adjustments)
295+
}
253296
}
254297

255298
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.

0 commit comments

Comments
 (0)