Skip to content

Added support for partial type hints (Foo<_>). #12764

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions src/librustc/middle/typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
});

Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
119 changes: 119 additions & 0 deletions src/test/compile-fail/typeck_type_placeholder_item.rs
Original file line number Diff line number Diff line change
@@ -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.
}

}
21 changes: 21 additions & 0 deletions src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs
Original file line number Diff line number Diff line change
@@ -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
}
21 changes: 21 additions & 0 deletions src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs
Original file line number Diff line number Diff line change
@@ -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
}
30 changes: 30 additions & 0 deletions src/test/compile-fail/typeck_type_placeholder_mismatch.rs
Original file line number Diff line number Diff line change
@@ -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
}
32 changes: 32 additions & 0 deletions src/test/run-pass/typeck_type_placeholder_1.rs
Original file line number Diff line number Diff line change
@@ -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);
}