-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
auto merge of #12764 : Kimundi/rust/partial_typehint, r=nikomatsakis
# Summary This patch introduces the `_` token into the type grammar, with the meaning "infer this type". With this change, the following two lines become equivalent: ``` let x = foo(); let x: _ = foo(); ``` But due to its composability, it enables partial type hints like this: ``` let x: Bar<_> = baz(); ``` Using it on the item level is explicitly forbidden, as the Rust language does not enable global type inference by design. This implements the feature requested in #9508. # Things requiring clarification - The change to enable it is very small, but I have only limited understanding of the related code, so the approach here might be wrong. - In particular, while this patch works, it does so in a way not originally intended according to the code comments. - This probably needs more tests, or rather feedback for which tests are still missing. - I'm unsure how this interacts with lifetime parameters, and whether it is correct in regard to them. - Partial type hints on the right side of `as` like `&foo as *_` work in both a normal function contexts and in constexprs like `static foo: *int = &'static 123 as *_`. The question is whether this should be allowed in general. # Todo for this PR - The manual and tutorial still needs updating. # Bugs I'm unsure how to fix - Requesting inference for the top level of the right hand side of a `as` fails to infer correctly, even if all possible hints are given: ``` .../type_hole_1.rs:35:18: 35:22 error: the type of this value must be known in this context .../type_hole_1.rs:35 let a: int = 1u32 as _; ^~~~ ```
- Loading branch information
Showing
10 changed files
with
236 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
21
src/test/compile-fail/typeck_type_placeholder_lifetime_1.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
21
src/test/compile-fail/typeck_type_placeholder_lifetime_2.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |