Skip to content

Commit f99300f

Browse files
committed
pull relate_type_and_user_type code into type_check module
It's really layered atop the core "relate-types" code
1 parent e7ab33e commit f99300f

File tree

2 files changed

+99
-132
lines changed

2 files changed

+99
-132
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
4242
use rustc::traits::query::{Fallible, NoSolution};
4343
use rustc::traits::{ObligationCause, PredicateObligations};
4444
use rustc::ty::fold::TypeFoldable;
45-
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
45+
use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts, UserSelfTy};
4646
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
4747
use std::rc::Rc;
4848
use std::{fmt, iter};
@@ -901,23 +901,37 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
901901
}
902902
}
903903

904-
fn sub_types(
904+
/// Convenient wrapper around `relate_tys::relate_types` -- see
905+
/// that fn for docs.
906+
fn relate_types(
905907
&mut self,
906-
sub: Ty<'tcx>,
907-
sup: Ty<'tcx>,
908+
a: Ty<'tcx>,
909+
v: ty::Variance,
910+
b: Ty<'tcx>,
908911
locations: Locations,
909912
category: ConstraintCategory,
910913
) -> Fallible<()> {
911-
relate_tys::sub_types(
914+
relate_tys::relate_types(
912915
self.infcx,
913-
sub,
914-
sup,
916+
a,
917+
v,
918+
b,
915919
locations,
916920
category,
917921
self.borrowck_context.as_mut().map(|x| &mut **x),
918922
)
919923
}
920924

925+
fn sub_types(
926+
&mut self,
927+
sub: Ty<'tcx>,
928+
sup: Ty<'tcx>,
929+
locations: Locations,
930+
category: ConstraintCategory,
931+
) -> Fallible<()> {
932+
self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
933+
}
934+
921935
/// Try to relate `sub <: sup`; if this fails, instantiate opaque
922936
/// variables in `sub` with their inferred definitions and try
923937
/// 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> {
950964
locations: Locations,
951965
category: ConstraintCategory,
952966
) -> Fallible<()> {
953-
relate_tys::eq_types(
954-
self.infcx,
955-
a,
956-
b,
957-
locations,
958-
category,
959-
self.borrowck_context.as_mut().map(|x| &mut **x),
960-
)
967+
self.relate_types(a, ty::Variance::Invariant, b, locations, category)
961968
}
962969

963970
fn relate_type_and_user_type(
964971
&mut self,
965972
a: Ty<'tcx>,
966973
v: ty::Variance,
967-
b: UserTypeAnnotation<'tcx>,
974+
user_ty: UserTypeAnnotation<'tcx>,
968975
locations: Locations,
969976
category: ConstraintCategory,
970977
) -> Fallible<()> {
971-
let ty = relate_tys::relate_type_and_user_type(
972-
self.infcx,
973-
a,
974-
v,
975-
b,
976-
locations,
977-
category,
978-
self.borrowck_context.as_mut().map(|x| &mut **x),
979-
)?;
980-
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
978+
let tcx = self.tcx();
979+
980+
debug!(
981+
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
982+
a, v, user_ty, locations
983+
);
984+
985+
// The `TypeRelating` code assumes that "unresolved inference
986+
// variables" appear in the "a" side, so flip `Contravariant`
987+
// ambient variance to get the right relationship.
988+
let v1 = ty::Contravariant.xform(v);
989+
990+
match user_ty {
991+
UserTypeAnnotation::Ty(canonical_ty) => {
992+
let (ty, _) = self.infcx
993+
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
994+
995+
self.relate_types(ty, v1, a, locations, category)?;
996+
997+
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
998+
}
999+
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
1000+
let (
1001+
UserSubsts {
1002+
substs,
1003+
user_self_ty,
1004+
},
1005+
_,
1006+
) = self.infcx
1007+
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
1008+
1009+
let ty = self.tcx().type_of(def_id);
1010+
let ty = ty.subst(tcx, substs);
1011+
1012+
self.relate_types(ty, v1, a, locations, category)?;
1013+
1014+
if let Some(UserSelfTy {
1015+
impl_def_id,
1016+
self_ty,
1017+
}) = user_self_ty
1018+
{
1019+
let impl_self_ty = tcx.type_of(impl_def_id);
1020+
let impl_self_ty = impl_self_ty.subst(tcx, &substs);
1021+
1022+
// There may be type variables in `substs` and hence
1023+
// in `impl_self_ty`, but they should all have been
1024+
// resolved to some fixed value during the first call
1025+
// to `relate`, above. Therefore, if we use
1026+
// `resolve_type_vars_if_possible` we should get to
1027+
// something without type variables. This is important
1028+
// because the `b` type in `relate_with_variance`
1029+
// below is not permitted to have inference variables.
1030+
let impl_self_ty = self.infcx.resolve_type_vars_if_possible(&impl_self_ty);
1031+
assert!(!impl_self_ty.has_infer_types());
1032+
1033+
self.eq_types(self_ty, impl_self_ty, locations, category)?;
1034+
}
1035+
1036+
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
1037+
}
1038+
}
1039+
9811040
Ok(())
9821041
}
9831042

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

Lines changed: 14 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,23 @@ use borrow_check::nll::constraints::OutlivesConstraint;
1212
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
1313
use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
1414
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
15-
use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
15+
use rustc::mir::ConstraintCategory;
1616
use rustc::traits::query::Fallible;
1717
use rustc::ty::relate::TypeRelation;
18-
use rustc::ty::subst::{Subst, UserSelfTy, UserSubsts};
19-
use rustc::ty::{self, Ty, TypeFoldable};
20-
use syntax_pos::DUMMY_SP;
21-
22-
/// Adds sufficient constraints to ensure that `a <: b`.
23-
pub(super) fn sub_types<'tcx>(
24-
infcx: &InferCtxt<'_, '_, 'tcx>,
25-
a: Ty<'tcx>,
26-
b: Ty<'tcx>,
27-
locations: Locations,
28-
category: ConstraintCategory,
29-
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
30-
) -> Fallible<()> {
31-
debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
32-
TypeRelating::new(
33-
infcx,
34-
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
35-
ty::Variance::Covariant,
36-
).relate(&a, &b)?;
37-
Ok(())
38-
}
39-
40-
/// Adds sufficient constraints to ensure that `a == b`.
41-
pub(super) fn eq_types<'tcx>(
18+
use rustc::ty::{self, Ty};
19+
20+
/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
21+
///
22+
/// - "Covariant" `a <: b`
23+
/// - "Invariant" `a == b`
24+
/// - "Contravariant" `a :> b`
25+
///
26+
/// NB. The type `a` is permitted to have unresolved inference
27+
/// variables, but not the type `b`.
28+
pub(super) fn relate_types<'tcx>(
4229
infcx: &InferCtxt<'_, '_, 'tcx>,
4330
a: Ty<'tcx>,
31+
v: ty::Variance,
4432
b: Ty<'tcx>,
4533
locations: Locations,
4634
category: ConstraintCategory,
@@ -50,91 +38,11 @@ pub(super) fn eq_types<'tcx>(
5038
TypeRelating::new(
5139
infcx,
5240
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
53-
ty::Variance::Invariant,
41+
v,
5442
).relate(&a, &b)?;
5543
Ok(())
5644
}
5745

58-
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
59-
/// a user-given type (which means it may have canonical variables
60-
/// encoding things like `_`).
61-
pub(super) fn relate_type_and_user_type<'tcx>(
62-
infcx: &InferCtxt<'_, '_, 'tcx>,
63-
a: Ty<'tcx>,
64-
v: ty::Variance,
65-
user_ty: UserTypeAnnotation<'tcx>,
66-
locations: Locations,
67-
category: ConstraintCategory,
68-
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
69-
) -> Fallible<Ty<'tcx>> {
70-
debug!(
71-
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
72-
a, v, user_ty, locations
73-
);
74-
75-
// The `TypeRelating` code assumes that the "canonical variables"
76-
// appear in the "a" side, so flip `Contravariant` ambient
77-
// variance to get the right relationship.
78-
let v1 = ty::Contravariant.xform(v);
79-
80-
let mut type_relating = TypeRelating::new(
81-
infcx,
82-
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
83-
v1,
84-
);
85-
86-
match user_ty {
87-
UserTypeAnnotation::Ty(canonical_ty) => {
88-
let (ty, _) =
89-
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
90-
type_relating.relate(&ty, &a)?;
91-
Ok(ty)
92-
}
93-
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
94-
let (
95-
UserSubsts {
96-
substs,
97-
user_self_ty,
98-
},
99-
_,
100-
) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
101-
102-
let ty = infcx.tcx.type_of(def_id);
103-
let ty = ty.subst(infcx.tcx, substs);
104-
105-
type_relating.relate(&ty, &a)?;
106-
107-
if let Some(UserSelfTy {
108-
impl_def_id,
109-
self_ty,
110-
}) = user_self_ty
111-
{
112-
let impl_self_ty = infcx.tcx.type_of(impl_def_id);
113-
let impl_self_ty = impl_self_ty.subst(infcx.tcx, &substs);
114-
115-
// There may be type variables in `substs` and hence
116-
// in `impl_self_ty`, but they should all have been
117-
// resolved to some fixed value during the first call
118-
// to `relate`, above. Therefore, if we use
119-
// `resolve_type_vars_if_possible` we should get to
120-
// something without type variables. This is important
121-
// because the `b` type in `relate_with_variance`
122-
// below is not permitted to have inference variables.
123-
let impl_self_ty = infcx.resolve_type_vars_if_possible(&impl_self_ty);
124-
assert!(!impl_self_ty.has_infer_types());
125-
126-
type_relating.relate_with_variance(
127-
ty::Variance::Invariant,
128-
&self_ty,
129-
&impl_self_ty,
130-
)?;
131-
}
132-
133-
Ok(ty)
134-
}
135-
}
136-
}
137-
13846
struct NllTypeRelatingDelegate<'me, 'bccx: 'me, 'gcx: 'tcx, 'tcx: 'bccx> {
13947
infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
14048
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,

0 commit comments

Comments
 (0)