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.
This commit is contained in:
parent
e6a1936d26
commit
5c505b75b1
|
@ -72,7 +72,6 @@ use middle::typeck::infer::{CoerceResult, resolve_type, Coercion};
|
||||||
use middle::typeck::infer::combine::{CombineFields, Combine};
|
use middle::typeck::infer::combine::{CombineFields, Combine};
|
||||||
use middle::typeck::infer::sub::Sub;
|
use middle::typeck::infer::sub::Sub;
|
||||||
use middle::typeck::infer::resolve::try_resolve_tvar_shallow;
|
use middle::typeck::infer::resolve::try_resolve_tvar_shallow;
|
||||||
use util::common::indenter;
|
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
|
@ -93,7 +92,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
debug!("Coerce.tys({} => {})",
|
debug!("Coerce.tys({} => {})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.get_ref().infcx.tcx),
|
||||||
b.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]`),
|
// 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
|
// then it would get auto-borrowed to `&[T, ..n]` and then DST-ified
|
||||||
|
@ -411,7 +409,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
|
|
||||||
self.unpack_actual_value(ty_b, |sty_b|
|
self.unpack_actual_value(ty_b, |sty_b|
|
||||||
match (sty_a, 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);
|
let ty = ty::mk_vec(tcx, t_a, None);
|
||||||
Some((ty, ty::UnsizeLength(len)))
|
Some((ty, ty::UnsizeLength(len)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,28 +363,6 @@ pub fn super_fn_sigs<'tcx, C: Combine<'tcx>>(this: &C,
|
||||||
|
|
||||||
pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
|
pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
|
||||||
|
|
||||||
// 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<ty::t> {
|
|
||||||
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 tcx = this.infcx().tcx;
|
||||||
let a_sty = &ty::get(a).sty;
|
let a_sty = &ty::get(a).sty;
|
||||||
let b_sty = &ty::get(b).sty;
|
let b_sty = &ty::get(b).sty;
|
||||||
|
@ -402,6 +380,10 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
|
||||||
b.repr(this.infcx().tcx)).as_slice());
|
b.repr(this.infcx().tcx)).as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(&ty::ty_err, _) | (_, &ty::ty_err) => {
|
||||||
|
Ok(ty::mk_err())
|
||||||
|
}
|
||||||
|
|
||||||
// Relate integral variables to other types
|
// Relate integral variables to other types
|
||||||
(&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
|
(&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
|
||||||
try!(this.infcx().simple_vars(this.a_is_expected(),
|
try!(this.infcx().simple_vars(this.a_is_expected(),
|
||||||
|
@ -442,8 +424,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
|
||||||
(&ty::ty_bool, _) |
|
(&ty::ty_bool, _) |
|
||||||
(&ty::ty_int(_), _) |
|
(&ty::ty_int(_), _) |
|
||||||
(&ty::ty_uint(_), _) |
|
(&ty::ty_uint(_), _) |
|
||||||
(&ty::ty_float(_), _) |
|
(&ty::ty_float(_), _) => {
|
||||||
(&ty::ty_err, _) => {
|
|
||||||
if ty::get(a).sty == ty::get(b).sty {
|
if ty::get(a).sty == ty::get(b).sty {
|
||||||
Ok(a)
|
Ok(a)
|
||||||
} else {
|
} else {
|
||||||
|
@ -494,13 +475,13 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
|
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
|
||||||
let typ = try!(this.tys(a_inner, 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))
|
Ok(ty::mk_uniq(tcx, typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
|
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
|
||||||
let mt = try!(this.mts(a_mt, 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))
|
Ok(ty::mk_ptr(tcx, mt))
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
|
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
|
||||||
|
@ -516,7 +497,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
|
||||||
}
|
}
|
||||||
_ => try!(this.mts(a_mt, b_mt))
|
_ => 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)) => {
|
(&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
|
||||||
|
|
|
@ -139,30 +139,21 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
|
||||||
.relate_vars(a_id, SubtypeOf, b_id);
|
.relate_vars(a_id, SubtypeOf, b_id);
|
||||||
Ok(a)
|
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)), _) => {
|
(&ty::ty_infer(TyVar(a_id)), _) => {
|
||||||
try!(self.fields
|
try!(self.fields
|
||||||
.switch_expected()
|
.switch_expected()
|
||||||
.instantiate(b, SupertypeOf, a_id));
|
.instantiate(b, SupertypeOf, a_id));
|
||||||
Ok(a)
|
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))) => {
|
(_, &ty::ty_infer(TyVar(b_id))) => {
|
||||||
try!(self.fields.instantiate(a, SubtypeOf, b_id));
|
try!(self.fields.instantiate(a, SubtypeOf, b_id));
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(&ty::ty_err, _) | (_, &ty::ty_err) => {
|
||||||
|
Ok(ty::mk_err())
|
||||||
|
}
|
||||||
|
|
||||||
(_, &ty::ty_bot) => {
|
(_, &ty::ty_bot) => {
|
||||||
Err(ty::terr_sorts(expected_found(self, a, b)))
|
Err(ty::terr_sorts(expected_found(self, a, b)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue