about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJakub Wieczorek <jakub@jakub.cc>2014-06-12 22:54:27 +0200
committerJakub Wieczorek <jakub@jakub.cc>2014-06-14 23:32:28 +0200
commitf6efb54d4446313d6dba93dd6bde33cd79354543 (patch)
tree068b4388824786897f63d70bf3541198dd2e4404 /src
parent6d8342f5e9f7093694548e761ee7df4f55243f3f (diff)
downloadrust-f6efb54d4446313d6dba93dd6bde33cd79354543.tar.gz
rust-f6efb54d4446313d6dba93dd6bde33cd79354543.zip
Fix an ICE on a cast from an inferred nil to uint
Fixes #10991.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/typeck/check/mod.rs72
-rw-r--r--src/test/compile-fail/issue-10991.rs14
2 files changed, 29 insertions, 57 deletions
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index b24b32bc81f..993b88a6eeb 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -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,
diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs
new file mode 100644
index 00000000000..8f7e6470f90
--- /dev/null
+++ b/src/test/compile-fail/issue-10991.rs
@@ -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`
+}