1
Fork 0

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:
Niko Matsakis 2018-10-17 14:55:42 -04:00
parent e7ab33e7a6
commit f99300fcbd
2 changed files with 100 additions and 133 deletions

View file

@ -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(())
}

View file

@ -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>>,