diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-10-17 14:55:42 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-10-19 09:32:30 -0400 |
| commit | f99300fcbdfec2908aeb93c823fc37f92a4d2d30 (patch) | |
| tree | d20774e43c5a4465a27a1e62a396a0fb535edfb8 /src | |
| parent | e7ab33e7a61ff046f1736f1b027c16d9494e20b8 (diff) | |
| download | rust-f99300fcbdfec2908aeb93c823fc37f92a4d2d30.tar.gz rust-f99300fcbdfec2908aeb93c823fc37f92a4d2d30.zip | |
pull `relate_type_and_user_type` code into `type_check` module
It's really layered atop the core "relate-types" code
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 111 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs | 120 |
2 files changed, 99 insertions, 132 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 11ea46fdef2..823a249760f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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,23 +901,37 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn sub_types( + /// Convenient wrapper around `relate_tys::relate_types` -- see + /// that fn for docs. + fn relate_types( &mut self, - sub: Ty<'tcx>, - sup: Ty<'tcx>, + a: Ty<'tcx>, + v: ty::Variance, + b: Ty<'tcx>, locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { - relate_tys::sub_types( + relate_tys::relate_types( self.infcx, - sub, - sup, + a, + v, + b, locations, category, self.borrowck_context.as_mut().map(|x| &mut **x), ) } + fn sub_types( + &mut self, + sub: Ty<'tcx>, + sup: Ty<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) -> Fallible<()> { + self.relate_types(sub, ty::Variance::Covariant, sup, locations, category) + } + /// Try to relate `sub <: sup`; if this fails, instantiate opaque /// variables in `sub` with their inferred definitions and try /// again. This is used for opaque types in places (e.g., `let x: @@ -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(()) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index 665ed24ac3d..13ebf46bdb1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -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; - -/// 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>( +use rustc::ty::{self, Ty}; + +/// 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>>, |
