]> git.lizzy.rs Git - rust.git/commitdiff
librustc: Allow coercions through arrays.
authorLuqman Aden <laden@csclub.uwaterloo.ca>
Sat, 21 Jun 2014 04:16:14 +0000 (00:16 -0400)
committerLuqman Aden <me@luqman.ca>
Sun, 29 Jun 2014 07:56:40 +0000 (00:56 -0700)
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/test/run-pass/issue-11205.rs [new file with mode: 0644]

index 8d84d089c01b2adff75514cf313a74df9196d7b6..e983830a4c3fdbc62e41d13641395bd16c273862 100644 (file)
@@ -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,
index bb20c3ce0b4aabbe646e69a4409c74b2cf71a58f..54cd88a1163d7d9e9b4a342cf80ee49bf4054e38 100644 (file)
@@ -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_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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_struct_enum_variant(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);
diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs
new file mode 100644 (file)
index 0000000..5b52bc3
--- /dev/null
@@ -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
+    };
+}