about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-03-10 05:21:27 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-04-11 20:32:46 -0400
commit105ec7e3bbbef50076f0e6963e8a9327bacf7b5f (patch)
treef54223d1bf3625ca4153db54f3da5b3be18e2ca6 /src
parent4e4bdea0ae8b3b1995b002374db1a7b7639eb52d (diff)
downloadrust-105ec7e3bbbef50076f0e6963e8a9327bacf7b5f.tar.gz
rust-105ec7e3bbbef50076f0e6963e8a9327bacf7b5f.zip
use obligations to propagate sub-typing instead of the TV code
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/sub.rs25
-rw-r--r--src/librustc/traits/mod.rs5
-rw-r--r--src/test/compile-fail/issue-7813.rs5
3 files changed, 27 insertions, 8 deletions
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index a6b0e02d477..1a94f12973d 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -12,8 +12,10 @@ use super::SubregionOrigin;
 use super::combine::CombineFields;
 use super::type_variable::{SubtypeOf, SupertypeOf};
 
+use traits::Obligation;
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
+use ty::fold::TypeFoldable;
 use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use std::mem;
 
@@ -79,10 +81,25 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
         let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
-            (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
-                infcx.type_variables
-                    .borrow_mut()
-                    .relate_vars(a_id, SubtypeOf, b_id);
+            (&ty::TyInfer(TyVar(_)), &ty::TyInfer(TyVar(_))) => {
+                // Shouldn't have any LBR here, so we can safely put
+                // this under a binder below without fear of accidental
+                // capture.
+                assert!(!a.has_escaping_regions());
+                assert!(!b.has_escaping_regions());
+
+                // can't make progress on `A <: B` if both A and B are
+                // type variables, so record an obligation.
+                self.fields.obligations.push(
+                    Obligation::new(
+                        self.fields.trace.cause.clone(),
+                        ty::Predicate::Subtype(
+                            ty::Binder(ty::SubtypePredicate {
+                                a_is_expected: self.a_is_expected,
+                                a,
+                                b,
+                            }))));
+
                 Ok(a)
             }
             (&ty::TyInfer(TyVar(a_id)), _) => {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 47cbccdd2ab..ea243d65881 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -20,7 +20,8 @@ use hir::def_id::DefId;
 use middle::free_region::FreeRegionMap;
 use ty::subst::Substs;
 use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
-use infer::InferCtxt;
+use ty::error::{ExpectedFound, TypeError};
+use infer::{InferCtxt};
 
 use std::rc::Rc;
 use syntax::ast;
@@ -214,6 +215,8 @@ pub struct FulfillmentError<'tcx> {
 pub enum FulfillmentErrorCode<'tcx> {
     CodeSelectionError(SelectionError<'tcx>),
     CodeProjectionError(MismatchedProjectionTypes<'tcx>),
+    CodeSubtypeError(ExpectedFound<Ty<'tcx>>,
+                     TypeError<'tcx>), // always comes from a SubtypePredicate
     CodeAmbiguity,
 }
 
diff --git a/src/test/compile-fail/issue-7813.rs b/src/test/compile-fail/issue-7813.rs
index fdd89058fd3..662b9e894ba 100644
--- a/src/test/compile-fail/issue-7813.rs
+++ b/src/test/compile-fail/issue-7813.rs
@@ -10,7 +10,6 @@
 
 fn main() {
     let v = &[];
-    let it = v.iter(); //~ ERROR type annotations needed [E0282]
-                       //~| NOTE cannot infer type for `T`
-                       //~| NOTE consider giving `it` a type
+    //~^ NOTE consider giving `it` a type
+    let it = v.iter(); //~ ERROR cannot infer type for `_`
 }