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.
This commit is contained in:
parent
020655b90d
commit
faf84263f2
1 changed files with 48 additions and 5 deletions
|
@ -42,6 +42,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
||||||
|
use rustc_infer::traits::Obligation;
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::adjustment::{
|
use rustc_middle::ty::adjustment::{
|
||||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
|
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
|
||||||
|
@ -50,7 +51,7 @@ use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::relate::RelateResult;
|
use rustc_middle::ty::relate::RelateResult;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, Ty, TypeAndMut};
|
use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{self, BytePos, Span};
|
use rustc_span::{self, BytePos, Span};
|
||||||
|
@ -172,7 +173,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
kind: TypeVariableOriginKind::AdjustmentType,
|
kind: TypeVariableOriginKind::AdjustmentType,
|
||||||
span: self.cause.span,
|
span: self.cause.span,
|
||||||
});
|
});
|
||||||
self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
|
self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
|
||||||
} else {
|
} else {
|
||||||
success(simple(Adjust::NeverToAny)(b), b, vec![])
|
success(simple(Adjust::NeverToAny)(b), b, vec![])
|
||||||
};
|
};
|
||||||
|
@ -182,7 +183,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
// we have no information about the source type. This will always
|
// we have no information about the source type. This will always
|
||||||
// ultimately fall back to some form of subtyping.
|
// ultimately fall back to some form of subtyping.
|
||||||
if a.is_ty_var() {
|
if a.is_ty_var() {
|
||||||
return self.coerce_from_inference_variable(a, b);
|
return self.coerce_from_inference_variable(a, b, identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider coercing the subtype to a DST
|
// Consider coercing the subtype to a DST
|
||||||
|
@ -245,11 +246,53 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
/// Coercing *from* an inference variable. In this case, we have no information
|
/// Coercing *from* an inference variable. In this case, we have no information
|
||||||
/// about the source type, so we can't really do a true coercion and we always
|
/// about the source type, so we can't really do a true coercion and we always
|
||||||
/// fall back to subtyping (`unify_and`).
|
/// fall back to subtyping (`unify_and`).
|
||||||
fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
fn coerce_from_inference_variable(
|
||||||
|
&self,
|
||||||
|
a: Ty<'tcx>,
|
||||||
|
b: Ty<'tcx>,
|
||||||
|
make_adjustments: impl FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
||||||
|
) -> CoerceResult<'tcx> {
|
||||||
|
debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b);
|
||||||
assert!(a.is_ty_var() && self.infcx.shallow_resolve(a) == a);
|
assert!(a.is_ty_var() && self.infcx.shallow_resolve(a) == a);
|
||||||
assert!(self.infcx.shallow_resolve(b) == b);
|
assert!(self.infcx.shallow_resolve(b) == b);
|
||||||
|
|
||||||
self.unify_and(a, b, identity)
|
if b.is_ty_var() {
|
||||||
|
// Two unresolved type variables: create a `Coerce` predicate.
|
||||||
|
let target_ty = if self.use_lub {
|
||||||
|
self.infcx.next_ty_var(TypeVariableOrigin {
|
||||||
|
kind: TypeVariableOriginKind::LatticeVariable,
|
||||||
|
span: self.cause.span,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
b
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut obligations = Vec::with_capacity(2);
|
||||||
|
for &source_ty in &[a, b] {
|
||||||
|
if source_ty != target_ty {
|
||||||
|
obligations.push(Obligation::new(
|
||||||
|
self.cause.clone(),
|
||||||
|
self.param_env,
|
||||||
|
ty::PredicateKind::Coerce(ty::CoercePredicate {
|
||||||
|
a: source_ty,
|
||||||
|
b: target_ty,
|
||||||
|
})
|
||||||
|
.to_predicate(self.tcx()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}",
|
||||||
|
target_ty, obligations
|
||||||
|
);
|
||||||
|
let adjustments = make_adjustments(target_ty);
|
||||||
|
InferResult::Ok(InferOk { value: (adjustments, target_ty), obligations })
|
||||||
|
} else {
|
||||||
|
// One unresolved type variable: just apply subtyping, we may be able
|
||||||
|
// to do something useful.
|
||||||
|
self.unify_and(a, b, make_adjustments)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
|
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
|
||||||
|
|
Loading…
Reference in a new issue