pull relate_type_and_user_type
code into type_check
module
It's really layered atop the core "relate-types" code
This commit is contained in:
parent
e7ab33e7a6
commit
f99300fcbd
2 changed files with 100 additions and 133 deletions
|
@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
|
|||
use rustc::traits::query::{Fallible, NoSolution};
|
||||
use rustc::traits::{ObligationCause, PredicateObligations};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
|
||||
use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts, UserSelfTy};
|
||||
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
|
||||
use std::rc::Rc;
|
||||
use std::{fmt, iter};
|
||||
|
@ -901,6 +901,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convenient wrapper around `relate_tys::relate_types` -- see
|
||||
/// that fn for docs.
|
||||
fn relate_types(
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
b: Ty<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
relate_tys::relate_types(
|
||||
self.infcx,
|
||||
a,
|
||||
v,
|
||||
b,
|
||||
locations,
|
||||
category,
|
||||
self.borrowck_context.as_mut().map(|x| &mut **x),
|
||||
)
|
||||
}
|
||||
|
||||
fn sub_types(
|
||||
&mut self,
|
||||
sub: Ty<'tcx>,
|
||||
|
@ -908,14 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
relate_tys::sub_types(
|
||||
self.infcx,
|
||||
sub,
|
||||
sup,
|
||||
locations,
|
||||
category,
|
||||
self.borrowck_context.as_mut().map(|x| &mut **x),
|
||||
)
|
||||
self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
|
||||
}
|
||||
|
||||
/// Try to relate `sub <: sup`; if this fails, instantiate opaque
|
||||
|
@ -950,34 +964,79 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
relate_tys::eq_types(
|
||||
self.infcx,
|
||||
a,
|
||||
b,
|
||||
locations,
|
||||
category,
|
||||
self.borrowck_context.as_mut().map(|x| &mut **x),
|
||||
)
|
||||
self.relate_types(a, ty::Variance::Invariant, b, locations, category)
|
||||
}
|
||||
|
||||
fn relate_type_and_user_type(
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
b: UserTypeAnnotation<'tcx>,
|
||||
user_ty: UserTypeAnnotation<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
let ty = relate_tys::relate_type_and_user_type(
|
||||
self.infcx,
|
||||
a,
|
||||
v,
|
||||
b,
|
||||
locations,
|
||||
category,
|
||||
self.borrowck_context.as_mut().map(|x| &mut **x),
|
||||
)?;
|
||||
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
|
||||
let tcx = self.tcx();
|
||||
|
||||
debug!(
|
||||
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
|
||||
a, v, user_ty, locations
|
||||
);
|
||||
|
||||
// The `TypeRelating` code assumes that "unresolved inference
|
||||
// variables" appear in the "a" side, so flip `Contravariant`
|
||||
// ambient variance to get the right relationship.
|
||||
let v1 = ty::Contravariant.xform(v);
|
||||
|
||||
match user_ty {
|
||||
UserTypeAnnotation::Ty(canonical_ty) => {
|
||||
let (ty, _) = self.infcx
|
||||
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
|
||||
|
||||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
|
||||
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
|
||||
}
|
||||
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
|
||||
let (
|
||||
UserSubsts {
|
||||
substs,
|
||||
user_self_ty,
|
||||
},
|
||||
_,
|
||||
) = self.infcx
|
||||
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
|
||||
|
||||
let ty = self.tcx().type_of(def_id);
|
||||
let ty = ty.subst(tcx, substs);
|
||||
|
||||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
|
||||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
self_ty,
|
||||
}) = user_self_ty
|
||||
{
|
||||
let impl_self_ty = tcx.type_of(impl_def_id);
|
||||
let impl_self_ty = impl_self_ty.subst(tcx, &substs);
|
||||
|
||||
// There may be type variables in `substs` and hence
|
||||
// in `impl_self_ty`, but they should all have been
|
||||
// resolved to some fixed value during the first call
|
||||
// to `relate`, above. Therefore, if we use
|
||||
// `resolve_type_vars_if_possible` we should get to
|
||||
// something without type variables. This is important
|
||||
// because the `b` type in `relate_with_variance`
|
||||
// below is not permitted to have inference variables.
|
||||
let impl_self_ty = self.infcx.resolve_type_vars_if_possible(&impl_self_ty);
|
||||
assert!(!impl_self_ty.has_infer_types());
|
||||
|
||||
self.eq_types(self_ty, impl_self_ty, locations, category)?;
|
||||
}
|
||||
|
||||
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -12,35 +12,23 @@ use borrow_check::nll::constraints::OutlivesConstraint;
|
|||
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
|
||||
use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
|
||||
use rustc::mir::ConstraintCategory;
|
||||
use rustc::traits::query::Fallible;
|
||||
use rustc::ty::relate::TypeRelation;
|
||||
use rustc::ty::subst::{Subst, UserSelfTy, UserSubsts};
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use rustc::ty::{self, Ty};
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a <: b`.
|
||||
pub(super) fn sub_types<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
|
||||
) -> Fallible<()> {
|
||||
debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
|
||||
TypeRelating::new(
|
||||
infcx,
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
|
||||
ty::Variance::Covariant,
|
||||
).relate(&a, &b)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a == b`.
|
||||
pub(super) fn eq_types<'tcx>(
|
||||
/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
|
||||
///
|
||||
/// - "Covariant" `a <: b`
|
||||
/// - "Invariant" `a == b`
|
||||
/// - "Contravariant" `a :> b`
|
||||
///
|
||||
/// NB. The type `a` is permitted to have unresolved inference
|
||||
/// variables, but not the type `b`.
|
||||
pub(super) fn relate_types<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
b: Ty<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
|
@ -50,91 +38,11 @@ pub(super) fn eq_types<'tcx>(
|
|||
TypeRelating::new(
|
||||
infcx,
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
|
||||
ty::Variance::Invariant,
|
||||
v,
|
||||
).relate(&a, &b)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
|
||||
/// a user-given type (which means it may have canonical variables
|
||||
/// encoding things like `_`).
|
||||
pub(super) fn relate_type_and_user_type<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
user_ty: UserTypeAnnotation<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
|
||||
) -> Fallible<Ty<'tcx>> {
|
||||
debug!(
|
||||
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
|
||||
a, v, user_ty, locations
|
||||
);
|
||||
|
||||
// The `TypeRelating` code assumes that the "canonical variables"
|
||||
// appear in the "a" side, so flip `Contravariant` ambient
|
||||
// variance to get the right relationship.
|
||||
let v1 = ty::Contravariant.xform(v);
|
||||
|
||||
let mut type_relating = TypeRelating::new(
|
||||
infcx,
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
|
||||
v1,
|
||||
);
|
||||
|
||||
match user_ty {
|
||||
UserTypeAnnotation::Ty(canonical_ty) => {
|
||||
let (ty, _) =
|
||||
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
|
||||
type_relating.relate(&ty, &a)?;
|
||||
Ok(ty)
|
||||
}
|
||||
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
|
||||
let (
|
||||
UserSubsts {
|
||||
substs,
|
||||
user_self_ty,
|
||||
},
|
||||
_,
|
||||
) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
|
||||
|
||||
let ty = infcx.tcx.type_of(def_id);
|
||||
let ty = ty.subst(infcx.tcx, substs);
|
||||
|
||||
type_relating.relate(&ty, &a)?;
|
||||
|
||||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
self_ty,
|
||||
}) = user_self_ty
|
||||
{
|
||||
let impl_self_ty = infcx.tcx.type_of(impl_def_id);
|
||||
let impl_self_ty = impl_self_ty.subst(infcx.tcx, &substs);
|
||||
|
||||
// There may be type variables in `substs` and hence
|
||||
// in `impl_self_ty`, but they should all have been
|
||||
// resolved to some fixed value during the first call
|
||||
// to `relate`, above. Therefore, if we use
|
||||
// `resolve_type_vars_if_possible` we should get to
|
||||
// something without type variables. This is important
|
||||
// because the `b` type in `relate_with_variance`
|
||||
// below is not permitted to have inference variables.
|
||||
let impl_self_ty = infcx.resolve_type_vars_if_possible(&impl_self_ty);
|
||||
assert!(!impl_self_ty.has_infer_types());
|
||||
|
||||
type_relating.relate_with_variance(
|
||||
ty::Variance::Invariant,
|
||||
&self_ty,
|
||||
&impl_self_ty,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'gcx: 'tcx, 'tcx: 'bccx> {
|
||||
infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
|
||||
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue