mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
librustc: Allow coercions through arrays.
This commit is contained in:
parent
6a3695d54f
commit
e11503f6d2
@ -1533,7 +1533,7 @@ pub fn type_is_self(ty: t) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn type_is_slice(ty:t) -> bool {
|
||||
fn type_is_slice(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rptr(_, mt) => match get(mt.ty).sty {
|
||||
ty_vec(_, None) | ty_str => true,
|
||||
@ -1543,6 +1543,18 @@ fn type_is_slice(ty:t) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_vec(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_vec(..) => true,
|
||||
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
|
||||
ty_box(t) | ty_uniq(t) => match get(t).sty {
|
||||
ty_vec(_, None) => true,
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_structural(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
|
||||
@ -1560,7 +1572,7 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
|
||||
|
||||
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
|
||||
match get(ty).sty {
|
||||
ty_vec(mt, Some(_)) => mt.ty,
|
||||
ty_vec(mt, _) => mt.ty,
|
||||
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
|
||||
ty_box(t) | ty_uniq(t) => match get(t).sty {
|
||||
ty_vec(mt, None) => mt.ty,
|
||||
|
@ -1146,24 +1146,9 @@ fn check_cast(fcx: &FnCtxt,
|
||||
.span_err(span,
|
||||
"cannot cast as `bool`, compare with zero instead");
|
||||
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
|
||||
fn is_vec(t: ty::t) -> bool {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_vec(..) => true,
|
||||
ty::ty_ptr(ty::mt{ty: t, ..}) |
|
||||
ty::ty_rptr(_, ty::mt{ty: t, ..}) |
|
||||
ty::ty_box(t) |
|
||||
ty::ty_uniq(t) => {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_vec(_, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
fn types_compatible(fcx: &FnCtxt, sp: Span,
|
||||
t1: ty::t, t2: ty::t) -> bool {
|
||||
if !is_vec(t1) {
|
||||
if !ty::type_is_vec(t1) {
|
||||
// If the type being casted from is not a vector, this special
|
||||
// case does not apply.
|
||||
return false
|
||||
@ -2779,10 +2764,30 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
fcx.write_ty(id, enum_type);
|
||||
}
|
||||
|
||||
type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
|
||||
|
||||
fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
|
||||
expected: Expectation)
|
||||
-> (ExprCheckerWithTy, ty::t) {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let (coerce, t) = match expected {
|
||||
// If we're given an expected type, we can try to coerce to it
|
||||
ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
|
||||
// Otherwise we just leave the type to be resolved later
|
||||
_ => (false, fcx.infcx().next_ty_var())
|
||||
};
|
||||
if coerce {
|
||||
(check_expr_coercable_to_type, t)
|
||||
} else {
|
||||
(check_expr_has_type, t)
|
||||
}
|
||||
}
|
||||
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let id = expr.id;
|
||||
match expr.node {
|
||||
ast::ExprVstore(ev, vst) => {
|
||||
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
|
||||
let typ = match ev.node {
|
||||
ast::ExprVec(ref args) => {
|
||||
let mutability = match vst {
|
||||
@ -2791,9 +2796,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
};
|
||||
let mut any_error = false;
|
||||
let mut any_bot = false;
|
||||
let t: ty::t = fcx.infcx().next_ty_var();
|
||||
for e in args.iter() {
|
||||
check_expr_has_type(fcx, &**e, t);
|
||||
check(fcx, &**e, t);
|
||||
let arg_t = fcx.expr_ty(&**e);
|
||||
if ty::type_is_error(arg_t) {
|
||||
any_error = true;
|
||||
@ -2821,8 +2825,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
ast::ExprVstoreMutSlice => ast::MutMutable,
|
||||
_ => ast::MutImmutable,
|
||||
};
|
||||
let t = fcx.infcx().next_ty_var();
|
||||
check_expr_has_type(fcx, &**element, t);
|
||||
check(fcx, &**element, t);
|
||||
let arg_t = fcx.expr_ty(&**element);
|
||||
if ty::type_is_error(arg_t) {
|
||||
ty::mk_err()
|
||||
@ -3211,9 +3214,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
check_cast(fcx, &**e, &**t, id, expr.span);
|
||||
}
|
||||
ast::ExprVec(ref args) => {
|
||||
let t: ty::t = fcx.infcx().next_ty_var();
|
||||
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
|
||||
for e in args.iter() {
|
||||
check_expr_has_type(fcx, &**e, t);
|
||||
check(fcx, &**e, t);
|
||||
}
|
||||
let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
|
||||
Some(args.len()));
|
||||
@ -3222,8 +3225,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
ast::ExprRepeat(ref element, ref count_expr) => {
|
||||
check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
|
||||
let count = ty::eval_repeat_count(fcx, &**count_expr);
|
||||
let t: ty::t = fcx.infcx().next_ty_var();
|
||||
check_expr_has_type(fcx, &**element, t);
|
||||
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
|
||||
check(fcx, &**element, t);
|
||||
let element_ty = fcx.expr_ty(&**element);
|
||||
if ty::type_is_error(element_ty) {
|
||||
fcx.write_error(id);
|
||||
|
92
src/test/run-pass/issue-11205.rs
Normal file
92
src/test/run-pass/issue-11205.rs
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Foo {}
|
||||
impl Foo for int {}
|
||||
fn foo(_: [&Foo, ..2]) {}
|
||||
fn foos(_: &[&Foo]) {}
|
||||
fn foog<T>(_: &[T], _: &[T]) {}
|
||||
|
||||
fn bar(_: [Box<Foo>, ..2]) {}
|
||||
fn bars(_: &[Box<Foo>]) {}
|
||||
|
||||
fn main() {
|
||||
let x: [&Foo, ..2] = [&1i, &2i];
|
||||
foo(x);
|
||||
foo([&1i, &2i]);
|
||||
|
||||
let r = &1i;
|
||||
let x: [&Foo, ..2] = [r, ..2];
|
||||
foo(x);
|
||||
foo([&1i, ..2]);
|
||||
|
||||
let x: &[&Foo] = &[&1i, &2i];
|
||||
foos(x);
|
||||
foos(&[&1i, &2i]);
|
||||
|
||||
let x: &[&Foo] = &[&1i, &2i];
|
||||
let r = &1i;
|
||||
foog(x, &[r]);
|
||||
|
||||
let x: [Box<Foo>, ..2] = [box 1i, box 2i];
|
||||
bar(x);
|
||||
bar([box 1i, box 2i]);
|
||||
|
||||
let x: &[Box<Foo>] = &[box 1i, box 2i];
|
||||
bars(x);
|
||||
bars(&[box 1i, box 2i]);
|
||||
|
||||
let x: &[Box<Foo>] = &[box 1i, box 2i];
|
||||
foog(x, &[box 1i]);
|
||||
|
||||
struct T<'a> {
|
||||
t: [&'a Foo, ..2]
|
||||
}
|
||||
let _n = T {
|
||||
t: [&1i, &2i]
|
||||
};
|
||||
let r = &1i;
|
||||
let _n = T {
|
||||
t: [r, ..2]
|
||||
};
|
||||
let x: [&Foo, ..2] = [&1i, &2i];
|
||||
let _n = T {
|
||||
t: x
|
||||
};
|
||||
|
||||
struct F<'b> {
|
||||
t: &'b [&'b Foo]
|
||||
}
|
||||
let _n = F {
|
||||
t: &[&1i, &2i]
|
||||
};
|
||||
let r = &1i;
|
||||
let r: [&Foo, ..2] = [r, ..2];
|
||||
let _n = F {
|
||||
t: r
|
||||
};
|
||||
let x: [&Foo, ..2] = [&1i, &2i];
|
||||
let _n = F {
|
||||
t: x
|
||||
};
|
||||
|
||||
struct M<'a> {
|
||||
t: &'a [Box<Foo>]
|
||||
}
|
||||
let _n = M {
|
||||
t: &[box 1i, box 2i]
|
||||
};
|
||||
let x: [Box<Foo>, ..2] = [box 1i, box 2i];
|
||||
let _n = M {
|
||||
t: x
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user