]> git.lizzy.rs Git - rust.git/commitdiff
use obligations to propagate sub-typing instead of the TV code
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 10 Mar 2017 10:21:27 +0000 (05:21 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 12 Apr 2017 00:32:46 +0000 (20:32 -0400)
src/librustc/infer/sub.rs
src/librustc/traits/mod.rs
src/test/compile-fail/issue-7813.rs

index a6b0e02d477224ebdf3cfd22441a0e3ae062bfcc..1a94f12973de8a26d22de9e0fd8c062f4535d423 100644 (file)
 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 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'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)), _) => {
index 47cbccdd2ab107ef673483a8e201cf88ead77ce4..ea243d65881ea23b2f2e0e0a2a587427839c9e70 100644 (file)
@@ -20,7 +20,8 @@
 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,
 }
 
index fdd89058fd3973498140ded97fe2f7b3d1c2d43c..662b9e894ba3a0d9f51aa93a2f41ac57325ba70b 100644 (file)
@@ -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 `_`
 }