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( 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>, 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 or the MIT license +// , 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 or the MIT license +// , 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 or the MIT license +// , 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 or the MIT license +// , 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; +struct Bar; + +pub fn main() { +} + +fn test1() { + let x: Foo<_> = Bar::; + //~^ ERROR mismatched types: expected `Foo<>` but found `Bar` + let y: Foo = x; +} + +fn test2() { + let x: Foo<_> = Bar::; + //~^ ERROR mismatched types: expected `Foo<>` but found `Bar` + //~^^ 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 or the MIT license +// , 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::>(); + 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); +}