Fix an ICE on a cast from an inferred nil to uint

Fixes #10991.
This commit is contained in:
Jakub Wieczorek 2014-06-12 22:54:27 +02:00
parent 6d8342f5e9
commit f6efb54d44
2 changed files with 29 additions and 57 deletions

View File

@ -3023,6 +3023,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
ty::ty_trait(..) => (),
_ => {
let t_1 = structurally_resolved_type(fcx, e.span, t_1);
let t_e = structurally_resolved_type(fcx, e.span, t_e);
if ty::type_is_nil(t_e) {
fcx.type_error_message(expr.span, |actual| {
format!("cast from nil: `{}` as `{}`",
@ -3037,21 +3040,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
}, t_e, None);
}
let t1 = structurally_resolved_type(fcx, e.span, t_1);
let te = structurally_resolved_type(fcx, e.span, t_e);
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
let t_1_is_char = type_is_char(fcx, expr.span, t_1);
let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
let t_1_is_float = type_is_floating_point(fcx,
expr.span,
t_1);
let t_1_is_scalar = ty::type_is_scalar(t_1);
let t_1_is_char = ty::type_is_char(t_1);
let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
let t_1_is_float = ty::type_is_floating_point(t_1);
// casts to scalars other than `char` and `bare fn` are trivial
let t_1_is_trivial = t_1_is_scalar &&
!t_1_is_char && !t_1_is_bare_fn;
if type_is_c_like_enum(fcx, expr.span, t_e) &&
t_1_is_trivial {
let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
if t_1_is_float {
fcx.type_error_message(expr.span, |actual| {
format!("illegal cast; cast through an \
@ -3062,22 +3058,20 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
}
// casts from C-like enums are allowed
} else if t_1_is_char {
let te = fcx.infcx().resolve_type_vars_if_possible(te);
if ty::get(te).sty != ty::ty_uint(ast::TyU8) {
let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
fcx.type_error_message(expr.span, |actual| {
format!("only `u8` can be cast as \
`char`, not `{}`", actual)
}, t_e, None);
}
} else if ty::get(t1).sty == ty::ty_bool {
} else if ty::get(t_1).sty == ty::ty_bool {
fcx.tcx()
.sess
.span_err(expr.span,
"cannot cast as `bool`, compare with \
zero instead");
} else if type_is_region_ptr(fcx, expr.span, t_e) &&
type_is_unsafe_ptr(fcx, expr.span, t_1) {
} 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,
@ -3110,7 +3104,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
/* this cast is only allowed from &[T] to *T or
&T to *T. */
match (&ty::get(te).sty, &ty::get(t_1).sty) {
match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
&ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
if types_compatible(fcx, e.span, mt1, mt2) => {
@ -3120,8 +3114,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
demand::coerce(fcx, e.span, t_1, &**e);
}
}
} else if !(type_is_scalar(fcx,expr.span,t_e)
&& t_1_is_trivial) {
} else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
/*
If more type combinations should be supported than are
supported here, then file an enhancement issue and
@ -4203,41 +4196,6 @@ pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
return ty::type_is_uint(typ_s);
}
pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_scalar(typ_s);
}
pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_char(typ_s);
}
pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_bare_fn(typ_s);
}
pub fn type_is_floating_point(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_floating_point(typ_s);
}
pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_unsafe_ptr(typ_s);
}
pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_region_ptr(typ_s);
}
pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
let typ_s = structurally_resolved_type(fcx, sp, typ);
return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
}
pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
e: &ast::Expr,
v: ast::ExprVstore,

View File

@ -0,0 +1,14 @@
// 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.
fn main() {
let nil = ();
let _t = nil as uint; //~ ERROR: cast from nil: `()` as `uint`
}