From 5c505b75b1d0bf8ab63c26e9317fa9bc794b086e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 17 Oct 2014 08:54:31 -0400 Subject: [PATCH] Permit DST types to unify like other types. Also: 1. stop eagerly coercing from `[T, ..n]` to `[T]` only do so if requested. 2. permit error to be interact more freely. Fixes #17178. --- src/librustc/middle/typeck/infer/coercion.rs | 4 +- src/librustc/middle/typeck/infer/combine.rs | 39 +++++--------------- src/librustc/middle/typeck/infer/sub.rs | 17 ++------- 3 files changed, 15 insertions(+), 45 deletions(-) diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 9f88bec7f42..e44aa3e8221 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -72,7 +72,6 @@ fn foo(a: A, b: A) { ... } use middle::typeck::infer::combine::{CombineFields, Combine}; use middle::typeck::infer::sub::Sub; use middle::typeck::infer::resolve::try_resolve_tvar_shallow; -use util::common::indenter; use util::ppaux; use util::ppaux::Repr; @@ -93,7 +92,6 @@ pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult { debug!("Coerce.tys({} => {})", a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx)); - let _indent = indenter(); // Special case: if the subtype is a sized array literal (`[T, ..n]`), // then it would get auto-borrowed to `&[T, ..n]` and then DST-ified @@ -411,7 +409,7 @@ fn unsize_ty(&self, self.unpack_actual_value(ty_b, |sty_b| match (sty_a, sty_b) { - (&ty::ty_vec(t_a, Some(len)), _) => { + (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => { let ty = ty::mk_vec(tcx, t_a, None); Some((ty, ty::UnsizeLength(len))) } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 15c4830646d..d2e062a20d2 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -363,28 +363,6 @@ fn argvecs<'tcx, C: Combine<'tcx>>(this: &C, pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres { - // This is a horrible hack - historically, [T] was not treated as a type, - // so, for example, &T and &[U] should not unify. In fact the only thing - // &[U] should unify with is &[T]. We preserve that behaviour with this - // check. - fn check_ptr_to_unsized<'tcx, C: Combine<'tcx>>(this: &C, - a: ty::t, - b: ty::t, - a_inner: ty::t, - b_inner: ty::t, - result: ty::t) -> cres { - match (&ty::get(a_inner).sty, &ty::get(b_inner).sty) { - (&ty::ty_vec(_, None), &ty::ty_vec(_, None)) | - (&ty::ty_str, &ty::ty_str) | - (&ty::ty_trait(..), &ty::ty_trait(..)) => Ok(result), - (&ty::ty_vec(_, None), _) | (_, &ty::ty_vec(_, None)) | - (&ty::ty_str, _) | (_, &ty::ty_str) | - (&ty::ty_trait(..), _) | (_, &ty::ty_trait(..)) - => Err(ty::terr_sorts(expected_found(this, a, b))), - _ => Ok(result), - } - } - let tcx = this.infcx().tcx; let a_sty = &ty::get(a).sty; let b_sty = &ty::get(b).sty; @@ -402,6 +380,10 @@ fn check_ptr_to_unsized<'tcx, C: Combine<'tcx>>(this: &C, b.repr(this.infcx().tcx)).as_slice()); } + (&ty::ty_err, _) | (_, &ty::ty_err) => { + Ok(ty::mk_err()) + } + // Relate integral variables to other types (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => { try!(this.infcx().simple_vars(this.a_is_expected(), @@ -442,8 +424,7 @@ fn check_ptr_to_unsized<'tcx, C: Combine<'tcx>>(this: &C, (&ty::ty_bool, _) | (&ty::ty_int(_), _) | (&ty::ty_uint(_), _) | - (&ty::ty_float(_), _) | - (&ty::ty_err, _) => { + (&ty::ty_float(_), _) => { if ty::get(a).sty == ty::get(b).sty { Ok(a) } else { @@ -494,13 +475,13 @@ fn check_ptr_to_unsized<'tcx, C: Combine<'tcx>>(this: &C, } (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => { - let typ = try!(this.tys(a_inner, b_inner)); - check_ptr_to_unsized(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ)) + let typ = try!(this.tys(a_inner, b_inner)); + Ok(ty::mk_uniq(tcx, typ)) } (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => { - let mt = try!(this.mts(a_mt, b_mt)); - check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_ptr(tcx, mt)) + let mt = try!(this.mts(a_mt, b_mt)); + Ok(ty::mk_ptr(tcx, mt)) } (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => { @@ -516,7 +497,7 @@ fn check_ptr_to_unsized<'tcx, C: Combine<'tcx>>(this: &C, } _ => try!(this.mts(a_mt, b_mt)) }; - check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt)) + Ok(ty::mk_rptr(tcx, r, mt)) } (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => { diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 158fda802ff..cc9ea6528ee 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -139,30 +139,21 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres { .relate_vars(a_id, SubtypeOf, b_id); Ok(a) } - // The vec/str check here and below is so that we don't unify - // T with [T], this is necessary so we reflect subtyping of references - // (&T does not unify with &[T]) where that in turn is to reflect - // the historical non-typedness of [T]. - (&ty::ty_infer(TyVar(_)), &ty::ty_str) | - (&ty::ty_infer(TyVar(_)), &ty::ty_vec(_, None)) => { - Err(ty::terr_sorts(expected_found(self, a, b))) - } (&ty::ty_infer(TyVar(a_id)), _) => { try!(self.fields .switch_expected() .instantiate(b, SupertypeOf, a_id)); Ok(a) } - - (&ty::ty_str, &ty::ty_infer(TyVar(_))) | - (&ty::ty_vec(_, None), &ty::ty_infer(TyVar(_))) => { - Err(ty::terr_sorts(expected_found(self, a, b))) - } (_, &ty::ty_infer(TyVar(b_id))) => { try!(self.fields.instantiate(a, SubtypeOf, b_id)); Ok(a) } + (&ty::ty_err, _) | (_, &ty::ty_err) => { + Ok(ty::mk_err()) + } + (_, &ty::ty_bot) => { Err(ty::terr_sorts(expected_found(self, a, b))) } -- GitLab