Skip to content

Commit bd893d1

Browse files
committed
auto merge of #15069 : luqmana/rust/cia, r=pcwalton
Fixes #11205.
2 parents e76369e + e11503f commit bd893d1

File tree

3 files changed

+133
-26
lines changed

3 files changed

+133
-26
lines changed

src/librustc/middle/ty.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,7 @@ pub fn type_is_self(ty: t) -> bool {
15331533
}
15341534
}
15351535

1536-
fn type_is_slice(ty:t) -> bool {
1536+
fn type_is_slice(ty: t) -> bool {
15371537
match get(ty).sty {
15381538
ty_rptr(_, mt) => match get(mt.ty).sty {
15391539
ty_vec(_, None) | ty_str => true,
@@ -1543,6 +1543,18 @@ fn type_is_slice(ty:t) -> bool {
15431543
}
15441544
}
15451545

1546+
pub fn type_is_vec(ty: t) -> bool {
1547+
match get(ty).sty {
1548+
ty_vec(..) => true,
1549+
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
1550+
ty_box(t) | ty_uniq(t) => match get(t).sty {
1551+
ty_vec(_, None) => true,
1552+
_ => false
1553+
},
1554+
_ => false
1555+
}
1556+
}
1557+
15461558
pub fn type_is_structural(ty: t) -> bool {
15471559
match get(ty).sty {
15481560
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
@@ -1560,7 +1572,7 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
15601572

15611573
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
15621574
match get(ty).sty {
1563-
ty_vec(mt, Some(_)) => mt.ty,
1575+
ty_vec(mt, _) => mt.ty,
15641576
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
15651577
ty_box(t) | ty_uniq(t) => match get(t).sty {
15661578
ty_vec(mt, None) => mt.ty,

src/librustc/middle/typeck/check/mod.rs

+27-24
Original file line numberDiff line numberDiff line change
@@ -1146,24 +1146,9 @@ fn check_cast(fcx: &FnCtxt,
11461146
.span_err(span,
11471147
"cannot cast as `bool`, compare with zero instead");
11481148
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1149-
fn is_vec(t: ty::t) -> bool {
1150-
match ty::get(t).sty {
1151-
ty::ty_vec(..) => true,
1152-
ty::ty_ptr(ty::mt{ty: t, ..}) |
1153-
ty::ty_rptr(_, ty::mt{ty: t, ..}) |
1154-
ty::ty_box(t) |
1155-
ty::ty_uniq(t) => {
1156-
match ty::get(t).sty {
1157-
ty::ty_vec(_, None) => true,
1158-
_ => false,
1159-
}
1160-
}
1161-
_ => false
1162-
}
1163-
}
11641149
fn types_compatible(fcx: &FnCtxt, sp: Span,
11651150
t1: ty::t, t2: ty::t) -> bool {
1166-
if !is_vec(t1) {
1151+
if !ty::type_is_vec(t1) {
11671152
// If the type being casted from is not a vector, this special
11681153
// case does not apply.
11691154
return false
@@ -2779,10 +2764,30 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
27792764
fcx.write_ty(id, enum_type);
27802765
}
27812766

2767+
type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
2768+
2769+
fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
2770+
expected: Expectation)
2771+
-> (ExprCheckerWithTy, ty::t) {
2772+
let tcx = fcx.ccx.tcx;
2773+
let (coerce, t) = match expected {
2774+
// If we're given an expected type, we can try to coerce to it
2775+
ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
2776+
// Otherwise we just leave the type to be resolved later
2777+
_ => (false, fcx.infcx().next_ty_var())
2778+
};
2779+
if coerce {
2780+
(check_expr_coercable_to_type, t)
2781+
} else {
2782+
(check_expr_has_type, t)
2783+
}
2784+
}
2785+
27822786
let tcx = fcx.ccx.tcx;
27832787
let id = expr.id;
27842788
match expr.node {
27852789
ast::ExprVstore(ev, vst) => {
2790+
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
27862791
let typ = match ev.node {
27872792
ast::ExprVec(ref args) => {
27882793
let mutability = match vst {
@@ -2791,9 +2796,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
27912796
};
27922797
let mut any_error = false;
27932798
let mut any_bot = false;
2794-
let t: ty::t = fcx.infcx().next_ty_var();
27952799
for e in args.iter() {
2796-
check_expr_has_type(fcx, &**e, t);
2800+
check(fcx, &**e, t);
27972801
let arg_t = fcx.expr_ty(&**e);
27982802
if ty::type_is_error(arg_t) {
27992803
any_error = true;
@@ -2821,8 +2825,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
28212825
ast::ExprVstoreMutSlice => ast::MutMutable,
28222826
_ => ast::MutImmutable,
28232827
};
2824-
let t = fcx.infcx().next_ty_var();
2825-
check_expr_has_type(fcx, &**element, t);
2828+
check(fcx, &**element, t);
28262829
let arg_t = fcx.expr_ty(&**element);
28272830
if ty::type_is_error(arg_t) {
28282831
ty::mk_err()
@@ -3211,9 +3214,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
32113214
check_cast(fcx, &**e, &**t, id, expr.span);
32123215
}
32133216
ast::ExprVec(ref args) => {
3214-
let t: ty::t = fcx.infcx().next_ty_var();
3217+
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
32153218
for e in args.iter() {
3216-
check_expr_has_type(fcx, &**e, t);
3219+
check(fcx, &**e, t);
32173220
}
32183221
let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
32193222
Some(args.len()));
@@ -3222,8 +3225,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
32223225
ast::ExprRepeat(ref element, ref count_expr) => {
32233226
check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
32243227
let count = ty::eval_repeat_count(fcx, &**count_expr);
3225-
let t: ty::t = fcx.infcx().next_ty_var();
3226-
check_expr_has_type(fcx, &**element, t);
3228+
let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
3229+
check(fcx, &**element, t);
32273230
let element_ty = fcx.expr_ty(&**element);
32283231
if ty::type_is_error(element_ty) {
32293232
fcx.write_error(id);

src/test/run-pass/issue-11205.rs

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(dead_code)]
12+
13+
trait Foo {}
14+
impl Foo for int {}
15+
fn foo(_: [&Foo, ..2]) {}
16+
fn foos(_: &[&Foo]) {}
17+
fn foog<T>(_: &[T], _: &[T]) {}
18+
19+
fn bar(_: [Box<Foo>, ..2]) {}
20+
fn bars(_: &[Box<Foo>]) {}
21+
22+
fn main() {
23+
let x: [&Foo, ..2] = [&1i, &2i];
24+
foo(x);
25+
foo([&1i, &2i]);
26+
27+
let r = &1i;
28+
let x: [&Foo, ..2] = [r, ..2];
29+
foo(x);
30+
foo([&1i, ..2]);
31+
32+
let x: &[&Foo] = &[&1i, &2i];
33+
foos(x);
34+
foos(&[&1i, &2i]);
35+
36+
let x: &[&Foo] = &[&1i, &2i];
37+
let r = &1i;
38+
foog(x, &[r]);
39+
40+
let x: [Box<Foo>, ..2] = [box 1i, box 2i];
41+
bar(x);
42+
bar([box 1i, box 2i]);
43+
44+
let x: &[Box<Foo>] = &[box 1i, box 2i];
45+
bars(x);
46+
bars(&[box 1i, box 2i]);
47+
48+
let x: &[Box<Foo>] = &[box 1i, box 2i];
49+
foog(x, &[box 1i]);
50+
51+
struct T<'a> {
52+
t: [&'a Foo, ..2]
53+
}
54+
let _n = T {
55+
t: [&1i, &2i]
56+
};
57+
let r = &1i;
58+
let _n = T {
59+
t: [r, ..2]
60+
};
61+
let x: [&Foo, ..2] = [&1i, &2i];
62+
let _n = T {
63+
t: x
64+
};
65+
66+
struct F<'b> {
67+
t: &'b [&'b Foo]
68+
}
69+
let _n = F {
70+
t: &[&1i, &2i]
71+
};
72+
let r = &1i;
73+
let r: [&Foo, ..2] = [r, ..2];
74+
let _n = F {
75+
t: r
76+
};
77+
let x: [&Foo, ..2] = [&1i, &2i];
78+
let _n = F {
79+
t: x
80+
};
81+
82+
struct M<'a> {
83+
t: &'a [Box<Foo>]
84+
}
85+
let _n = M {
86+
t: &[box 1i, box 2i]
87+
};
88+
let x: [Box<Foo>, ..2] = [box 1i, box 2i];
89+
let _n = M {
90+
t: x
91+
};
92+
}

0 commit comments

Comments
 (0)