From 105ec7e3bbbef50076f0e6963e8a9327bacf7b5f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 10 Mar 2017 05:21:27 -0500 Subject: [PATCH] use obligations to propagate sub-typing instead of the TV code --- src/librustc/infer/sub.rs | 25 +++++++++++++++++++++---- src/librustc/traits/mod.rs | 5 ++++- src/test/compile-fail/issue-7813.rs | 5 ++--- 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::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)), _) => { 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 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>, + 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 `_` } -- 2.44.0