mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
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
@ -42,6 +42,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{Coercion, InferOk, InferResult};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
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::relate::RelateResult;
|
||||
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_span::symbol::sym;
|
||||
use rustc_span::{self, BytePos, Span};
|
||||
@ -172,7 +173,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
kind: TypeVariableOriginKind::AdjustmentType,
|
||||
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 {
|
||||
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
|
||||
// ultimately fall back to some form of subtyping.
|
||||
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
|
||||
@ -245,11 +246,53 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
/// 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
|
||||
/// 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!(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`.
|
||||
|
Loading…
Reference in New Issue
Block a user