}
}
-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,
}
}
+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(_) |
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,
.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
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 {
};
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;
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()
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()));
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);
--- /dev/null
+// 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
+ };
+}