about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/ty.rs7
-rw-r--r--src/librustc/middle/typeck/check/mod.rs16
-rw-r--r--src/test/compile-fail/indexing-requires-a-uint.rs25
3 files changed, 47 insertions, 1 deletions
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 8a616496f06..e8082e149af 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2602,6 +2602,13 @@ pub fn type_is_integral(ty: t) -> bool {
     }
 }
 
+pub fn type_is_uint(ty: t) -> bool {
+    match get(ty).sty {
+      ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
+      _ => false
+    }
+}
+
 pub fn type_is_char(ty: t) -> bool {
     match get(ty).sty {
         ty_char => true,
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 9aa98ee5f8e..4cf3cc51cc1 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3151,7 +3151,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                           lvalue_pref, |base_t, _| ty::index(base_t));
               match field_ty {
                   Some(mt) => {
-                      require_integral(fcx, idx.span, idx_t);
+                      check_expr_has_type(fcx, idx, ty::mk_uint());
                       fcx.write_ty(id, mt.ty);
                       fcx.write_autoderef_adjustment(base.id, autoderefs);
                   }
@@ -3195,6 +3195,15 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     unifier();
 }
 
+pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
+    if !type_is_uint(fcx, sp, t) {
+        fcx.type_error_message(sp, |actual| {
+            format!("mismatched types: expected `uint` type but found `{}`",
+                 actual)
+        }, t, None);
+    }
+}
+
 pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
     if !type_is_integral(fcx, sp, t) {
         fcx.type_error_message(sp, |actual| {
@@ -3854,6 +3863,11 @@ pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     return ty::type_is_integral(typ_s);
 }
 
+pub fn type_is_uint(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
+    let typ_s = structurally_resolved_type(fcx, sp, typ);
+    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);
diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs
new file mode 100644
index 00000000000..9ac4bd2566e
--- /dev/null
+++ b/src/test/compile-fail/indexing-requires-a-uint.rs
@@ -0,0 +1,25 @@
+// 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.
+
+// Make sure that indexing an array is only valid with a `uint`, not any other
+// integral type.
+
+fn main() {
+    fn bar<T>(_: T) {}
+    [0][0u8]; //~ ERROR: mismatched types
+
+    [0][0]; // should infer to be a uint
+
+    let i = 0;      // i is an IntVar
+    [0][i];         // i should be locked to uint
+    bar::<int>(i);  // i should not be re-coerced back to an int
+    //~^ ERROR: mismatched types
+}
+