about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/typeck/astconv.rs12
-rw-r--r--src/librustc/middle/typeck/collect.rs4
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/parse/parser.rs3
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/test/compile-fail/typeck_type_placeholder_item.rs119
-rw-r--r--src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs21
-rw-r--r--src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs21
-rw-r--r--src/test/compile-fail/typeck_type_placeholder_mismatch.rs30
-rw-r--r--src/test/run-pass/typeck_type_placeholder_1.rs32
10 files changed, 236 insertions, 11 deletions
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index e8770f9d142..8336fa2d6b5 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -640,13 +640,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
             }
             ast::TyInfer => {
-                // ty_infer should only appear as the type of arguments or return
-                // values in a fn_expr, or as the type of local variables.  Both of
-                // these cases are handled specially and should not descend into this
-                // routine.
-                this.tcx().sess.span_bug(
-                    ast_ty.span,
-                    "found `ty_infer` in unexpected place");
+                // TyInfer also appears as the type of arguments or return
+                // values in a ExprFnBlock or ExprProc, or as the type of
+                // local variables. Both of these cases are handled specially
+                // and will not descend into this routine.
+                this.ty_infer(ast_ty.span)
             }
         });
 
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 402f06f928c..0c6aeda4258 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -132,7 +132,9 @@ impl AstConv for CrateCtxt {
     }
 
     fn ty_infer(&self, span: Span) -> ty::t {
-        self.tcx.sess.span_bug(span, "found `ty_infer` in unexpected place");
+        self.tcx.sess.span_err(span, "the type placeholder `_` is not \
+                                      allowed within types on item signatures.");
+        ty::mk_err()
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 7fef6da5607..3e600249a7d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -830,8 +830,7 @@ pub enum Ty_ {
     TyPath(Path, Option<OptVec<TyParamBound>>, NodeId), // for #7264; see above
     TyTypeof(@Expr),
     // TyInfer means the type should be inferred instead of it having been
-    // specified. This should only appear at the "top level" of a type and not
-    // nested in one.
+    // specified. This can appear anywhere in a type.
     TyInfer,
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a4877491990..b4f7238c9c7 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1274,6 +1274,9 @@ impl Parser {
                 bounds
             } = self.parse_path(LifetimeAndTypesAndBounds);
             TyPath(path, bounds, ast::DUMMY_NODE_ID)
+        } else if self.eat(&token::UNDERSCORE) {
+            // TYPE TO BE INFERRED
+            TyInfer
         } else {
             let msg = format!("expected type, found token {:?}", self.token);
             self.fatal(msg);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 6894d6a2b05..36c39220483 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -504,7 +504,7 @@ pub fn print_type(s: &mut State, ty: &ast::Ty) -> io::IoResult<()> {
             try!(word(&mut s.s, ")"));
         }
         ast::TyInfer => {
-            fail!("print_type shouldn't see a ty_infer");
+            try!(word(&mut s.s, "_"));
         }
     }
     end(s)
diff --git a/src/test/compile-fail/typeck_type_placeholder_item.rs b/src/test/compile-fail/typeck_type_placeholder_item.rs
new file mode 100644
index 00000000000..67300f9bb9b
--- /dev/null
+++ b/src/test/compile-fail/typeck_type_placeholder_item.rs
@@ -0,0 +1,119 @@
+// 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.
+
+// This test checks that it is not possible to enable global type
+// inference by using the `_` type placeholder.
+
+fn test() -> _ { 5 }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test2() -> (_, _) { (5u, 5u) }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST3: _ = "test";
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST4: _ = 145u16;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST5: (_, _) = (1, 2);
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test6(_: _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test7(x: _) { let _x: uint = x; }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test8(_f: fn() -> _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+struct Test9;
+
+impl Test9 {
+    fn test9(&self) -> _ { () }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn test10(&self, _x : _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+impl Clone for Test9 {
+    fn clone(&self) -> _ { Test9 }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn clone_from(&mut self, other: _) { *self = Test9; }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+struct Test10 {
+    a: _,
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    b: (_, _),
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+pub fn main() {
+    fn fn_test() -> _ { 5 }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn fn_test2() -> (_, _) { (5u, 5u) }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    static FN_TEST3: _ = "test";
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    static FN_TEST4: _ = 145u16;
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    static FN_TEST5: (_, _) = (1, 2);
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn fn_test6(_: _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn fn_test7(x: _) { let _x: uint = x; }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    fn fn_test8(_f: fn() -> _) { }
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+    struct FnTest9;
+
+    impl FnTest9 {
+        fn fn_test9(&self) -> _ { () }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+        fn fn_test10(&self, _x : _) { }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    }
+
+    impl Clone for FnTest9 {
+        fn clone(&self) -> _ { FnTest9 }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+        fn clone_from(&mut self, other: _) { *self = FnTest9; }
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    }
+
+    struct FnTest10 {
+        a: _,
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+        b: (_, _),
+        //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+        //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+    }
+
+}
diff --git a/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs b/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs
new file mode 100644
index 00000000000..fae4f541b17
--- /dev/null
+++ b/src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs
@@ -0,0 +1,21 @@
+// 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.
+
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T> {
+    r: &'a T
+}
+
+pub fn main() {
+    let c: Foo<_, _> = Foo { r: &5u };
+    //~^ ERROR wrong number of type arguments: expected 1 but found 2
+}
diff --git a/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs b/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs
new file mode 100644
index 00000000000..e879ddb951f
--- /dev/null
+++ b/src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs
@@ -0,0 +1,21 @@
+// 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.
+
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T> {
+    r: &'a T
+}
+
+pub fn main() {
+    let c: Foo<_, uint> = Foo { r: &5 };
+    //~^ ERROR wrong number of type arguments: expected 1 but found 2
+}
diff --git a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs
new file mode 100644
index 00000000000..492a0afff30
--- /dev/null
+++ b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// This test checks that genuine type errors with partial
+// type hints are understandable.
+
+struct Foo<T>;
+struct Bar<U>;
+
+pub fn main() {
+}
+
+fn test1() {
+    let x: Foo<_> = Bar::<uint>;
+    //~^ ERROR mismatched types: expected `Foo<<generic #0>>` but found `Bar<uint>`
+    let y: Foo<uint> = x;
+}
+
+fn test2() {
+    let x: Foo<_> = Bar::<uint>;
+    //~^ ERROR mismatched types: expected `Foo<<generic #0>>` but found `Bar<uint>`
+    //~^^ ERROR cannot determine a type for this local variable: unconstrained type
+}
diff --git a/src/test/run-pass/typeck_type_placeholder_1.rs b/src/test/run-pass/typeck_type_placeholder_1.rs
new file mode 100644
index 00000000000..789a95dd6e5
--- /dev/null
+++ b/src/test/run-pass/typeck_type_placeholder_1.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// This test checks that the `_` type placeholder works
+// correctly for enabling type inference.
+
+static CONSTEXPR: *int = &'static 413 as *_;
+
+pub fn main() {
+    use std::vec_ng::Vec;
+
+    let x: Vec<_> = range(0u, 5).collect();
+    assert_eq!(x.as_slice(), &[0u,1,2,3,4]);
+
+    let x = range(0u, 5).collect::<Vec<_>>();
+    assert_eq!(x.as_slice(), &[0u,1,2,3,4]);
+
+    let y: _ = "hello";
+    assert_eq!(y.len(), 5);
+
+    let ptr = &5u;
+    let ptr2 = ptr as *_;
+
+    assert_eq!(ptr as *uint as uint, ptr2 as uint);
+}