Skip to content

Commit 58609ef

Browse files
committed
add Subtype predicate
1 parent 18ea55f commit 58609ef

File tree

17 files changed

+193
-4
lines changed

17 files changed

+193
-4
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ impl_stable_hash_for!(enum ty::Visibility {
170170
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
171171
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
172172
impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
173+
impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
173174

174175
impl<'a, 'tcx, A, B> HashStable<StableHashingContext<'a, 'tcx>> for ty::OutlivesPredicate<A, B>
175176
where A: HashStable<StableHashingContext<'a, 'tcx>>,
@@ -200,6 +201,9 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Predicate<'tcx
200201
ty::Predicate::Equate(ref pred) => {
201202
pred.hash_stable(hcx, hasher);
202203
}
204+
ty::Predicate::Subtype(ref pred) => {
205+
pred.hash_stable(hcx, hasher);
206+
}
203207
ty::Predicate::RegionOutlives(ref pred) => {
204208
pred.hash_stable(hcx, hasher);
205209
}

src/librustc/infer/mod.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
551551
}
552552

553553
impl<T> ExpectedFound<T> {
554-
fn new(a_is_expected: bool, a: T, b: T) -> Self {
554+
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
555555
if a_is_expected {
556556
ExpectedFound {expected: a, found: b}
557557
} else {
@@ -1129,6 +1129,43 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11291129
})
11301130
}
11311131

1132+
pub fn subtype_predicate(&self,
1133+
cause: &ObligationCause<'tcx>,
1134+
predicate: &ty::PolySubtypePredicate<'tcx>)
1135+
-> Option<InferResult<'tcx, ()>>
1136+
{
1137+
// Subtle: it's ok to skip the binder here and resolve because
1138+
// `shallow_resolve` just ignores anything that is not a type
1139+
// variable, and because type variable's can't (at present, at
1140+
// least) capture any of the things bound by this binder.
1141+
//
1142+
// Really, there is no *particular* reason to do this
1143+
// `shallow_resolve` here except as a
1144+
// micro-optimization. Naturally I could not
1145+
// resist. -nmatsakis
1146+
let two_unbound_type_vars = {
1147+
let a = self.shallow_resolve(predicate.skip_binder().a);
1148+
let b = self.shallow_resolve(predicate.skip_binder().b);
1149+
a.is_ty_var() && b.is_ty_var()
1150+
};
1151+
1152+
if two_unbound_type_vars {
1153+
// Two unbound type variables? Can't make progress.
1154+
return None;
1155+
}
1156+
1157+
Some(self.commit_if_ok(|snapshot| {
1158+
let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) =
1159+
self.skolemize_late_bound_regions(predicate, snapshot);
1160+
1161+
let cause_span = cause.span;
1162+
let ok = self.sub_types(a_is_expected, cause, a, b)?;
1163+
self.leak_check(false, cause_span, &skol_map, snapshot)?;
1164+
self.pop_skolemized(skol_map, snapshot);
1165+
Ok(ok.unit())
1166+
}))
1167+
}
1168+
11321169
pub fn region_outlives_predicate(&self,
11331170
cause: &traits::ObligationCause<'tcx>,
11341171
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>)

src/librustc/middle/free_region.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl FreeRegionMap {
6060
ty::Predicate::Projection(..) |
6161
ty::Predicate::Trait(..) |
6262
ty::Predicate::Equate(..) |
63+
ty::Predicate::Subtype(..) |
6364
ty::Predicate::WellFormed(..) |
6465
ty::Predicate::ObjectSafe(..) |
6566
ty::Predicate::ClosureKind(..) |

src/librustc/traits/error_reporting.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use ty::error::ExpectedFound;
3939
use ty::fast_reject;
4040
use ty::fold::TypeFolder;
4141
use ty::subst::Subst;
42+
use ty::SubtypePredicate;
4243
use util::nodemap::{FxHashMap, FxHashSet};
4344

4445
use syntax_pos::{DUMMY_SP, Span};
@@ -112,6 +113,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
112113
FulfillmentErrorCode::CodeAmbiguity => {
113114
self.maybe_report_ambiguity(&error.obligation);
114115
}
116+
FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
117+
self.report_mismatched_types(&error.obligation.cause,
118+
expected_found.expected,
119+
expected_found.found,
120+
err.clone())
121+
.emit();
122+
}
115123
}
116124
}
117125

@@ -555,6 +563,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
555563
err
556564
}
557565

566+
ty::Predicate::Subtype(ref predicate) => {
567+
// TODO
568+
panic!("subtype requirement not satisfied {:?}", predicate)
569+
}
570+
558571
ty::Predicate::Equate(ref predicate) => {
559572
let predicate = self.resolve_type_vars_if_possible(predicate);
560573
let err = self.equality_predicate(&obligation.cause,
@@ -761,6 +774,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
761774
}
762775
}
763776

777+
ty::Predicate::Subtype(ref data) => {
778+
if data.references_error() || self.tcx.sess.has_errors() {
779+
// no need to overload user in such cases
780+
} else {
781+
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
782+
assert!(a.is_ty_var() && b.is_ty_var()); // else other would've been instantiated
783+
self.need_type_info(obligation, a);
784+
}
785+
}
786+
764787
_ => {
765788
if !self.tcx.sess.has_errors() {
766789
let mut err = struct_span_err!(self.tcx.sess,

src/librustc/traits/fulfill.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use dep_graph::DepGraph;
1212
use infer::{InferCtxt, InferOk};
1313
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
14+
use ty::error::ExpectedFound;
1415
use rustc_data_structures::obligation_forest::{ObligationForest, Error};
1516
use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
1617
use std::marker::PhantomData;
@@ -496,6 +497,26 @@ fn process_predicate<'a, 'gcx, 'tcx>(
496497
s => Ok(s)
497498
}
498499
}
500+
501+
ty::Predicate::Subtype(ref subtype) => {
502+
match selcx.infcx().subtype_predicate(&obligation.cause, subtype) {
503+
None => {
504+
// none means that both are unresolved
505+
pending_obligation.stalled_on = vec![subtype.skip_binder().a,
506+
subtype.skip_binder().b];
507+
Ok(None)
508+
}
509+
Some(Ok(ok)) => {
510+
Ok(Some(ok.obligations))
511+
}
512+
Some(Err(err)) => {
513+
let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected,
514+
subtype.skip_binder().a,
515+
subtype.skip_binder().b);
516+
Err(FulfillmentErrorCode::CodeSubtypeError(expected_found, err))
517+
}
518+
}
519+
}
499520
}
500521
}
501522

src/librustc/traits/object_safety.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
178178
ty::Predicate::TypeOutlives(..) |
179179
ty::Predicate::RegionOutlives(..) |
180180
ty::Predicate::ClosureKind(..) |
181+
ty::Predicate::Subtype(..) |
181182
ty::Predicate::Equate(..) => {
182183
false
183184
}
@@ -209,6 +210,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
209210
ty::Predicate::Projection(..) |
210211
ty::Predicate::Trait(..) |
211212
ty::Predicate::Equate(..) |
213+
ty::Predicate::Subtype(..) |
212214
ty::Predicate::RegionOutlives(..) |
213215
ty::Predicate::WellFormed(..) |
214216
ty::Predicate::ObjectSafe(..) |

src/librustc/traits/select.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
568568
}
569569
}
570570

571+
ty::Predicate::Subtype(ref p) => {
572+
// does this code ever run?
573+
match self.infcx.subtype_predicate(&obligation.cause, p) {
574+
Some(Ok(InferOk { obligations, .. })) => {
575+
self.inferred_obligations.extend(obligations);
576+
EvaluatedToOk
577+
},
578+
Some(Err(_)) => EvaluatedToErr,
579+
None => EvaluatedToAmbig,
580+
}
581+
}
582+
571583
ty::Predicate::WellFormed(ty) => {
572584
match ty::wf::obligations(self.infcx, obligation.cause.body_id,
573585
ty, obligation.cause.span) {

src/librustc/traits/structural_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
130130
match *self {
131131
super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
132132
super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
133+
super::CodeSubtypeError(ref a, ref b) => write!(f, "CodeSubtypeError({:?}, {:?})", a, b),
133134
super::CodeAmbiguity => write!(f, "Ambiguity")
134135
}
135136
}

src/librustc/traits/util.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
4242
ty::Predicate::ObjectSafe(data),
4343

4444
ty::Predicate::ClosureKind(closure_def_id, kind) =>
45-
ty::Predicate::ClosureKind(closure_def_id, kind)
45+
ty::Predicate::ClosureKind(closure_def_id, kind),
46+
47+
ty::Predicate::Subtype(ref data) =>
48+
ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)),
4649
}
4750
}
4851

@@ -160,6 +163,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
160163
// `X == Y`, though conceivably we might. For example,
161164
// `&X == &Y` implies that `X == Y`.
162165
}
166+
ty::Predicate::Subtype(..) => {
167+
// Currently, we do not "elaborate" predicates like `X
168+
// <: Y`, though conceivably we might.
169+
}
163170
ty::Predicate::Projection(..) => {
164171
// Nothing to elaborate in a projection predicate.
165172
}

src/librustc/ty/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,9 @@ pub enum Predicate<'tcx> {
755755
/// for some substitutions `...` and T being a closure type.
756756
/// Satisfied (or refuted) once we know the closure's kind.
757757
ClosureKind(DefId, ClosureKind),
758+
759+
/// `T1 <: T2`
760+
Subtype(PolySubtypePredicate<'tcx>),
758761
}
759762

760763
impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
@@ -833,6 +836,8 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
833836
Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
834837
Predicate::Equate(ty::Binder(ref data)) =>
835838
Predicate::Equate(ty::Binder(data.subst(tcx, substs))),
839+
Predicate::Subtype(ty::Binder(ref data)) =>
840+
Predicate::Subtype(ty::Binder(data.subst(tcx, substs))),
836841
Predicate::RegionOutlives(ty::Binder(ref data)) =>
837842
Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))),
838843
Predicate::TypeOutlives(ty::Binder(ref data)) =>
@@ -912,6 +917,14 @@ pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<&'tcx ty::Reg
912917
&'tcx ty::Region>;
913918
pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, &'tcx ty::Region>;
914919

920+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
921+
pub struct SubtypePredicate<'tcx> {
922+
pub a_is_expected: bool,
923+
pub a: Ty<'tcx>,
924+
pub b: Ty<'tcx>
925+
}
926+
pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
927+
915928
/// This kind of predicate has no *direct* correspondent in the
916929
/// syntax, but it roughly corresponds to the syntactic forms:
917930
///
@@ -1025,6 +1038,9 @@ impl<'tcx> Predicate<'tcx> {
10251038
ty::Predicate::Equate(ty::Binder(ref data)) => {
10261039
vec![data.0, data.1]
10271040
}
1041+
ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => {
1042+
vec![a, b]
1043+
}
10281044
ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
10291045
vec![data.0]
10301046
}
@@ -1061,6 +1077,7 @@ impl<'tcx> Predicate<'tcx> {
10611077
}
10621078
Predicate::Projection(..) |
10631079
Predicate::Equate(..) |
1080+
Predicate::Subtype(..) |
10641081
Predicate::RegionOutlives(..) |
10651082
Predicate::WellFormed(..) |
10661083
Predicate::ObjectSafe(..) |

0 commit comments

Comments
 (0)