Type inference of integer literals is inconsistenct with the reference
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- rust
- Domain
- compilers, documentation
Research direction
Reproduce the two integer-literal examples and compare their behavior with the reference's integer-literals section. Review related issues #39255 and #40985, then reconcile the intended inference behavior with the documentation, including whether floating-point literals are affected.
Written by the indexing model from the issue text.
Description
Originally at https://github.com/rust-lang/rust/issues/41060
The reference currently says the following for integer literals
The type of an unsuffixed integer literal is determined by type inference:
[...]
If the program context under-constrains the type, it defaults to the signed 32-bit integeri32.
This does however not work for some inherent methods of signed integer types:
trait A {
fn what_type(&self);
}
impl A for i16 {
fn what_type(&self) {
println!("i16");
}
}
impl A for i32 {
fn what_type(&self) {
println!("i32");
}
}
fn main() {
let z = 1;
z.what_type();
//z.is_positive(); // <- uncomment this line
}
As you can see, z is under-constrained in this case. The compiler does the right thing and defaults to type i32, so calling the trait method what_type() works.
If you uncomment the inherent method call to is_positive(), z still is under-constrained in pretty much the same way as before, however, the compiler fails to default to i32 and instead prints
error: no method named `is_positive` found for type `{integer}` in the current scope
Also note that the reference says
If an integer type can be uniquely determined from the surrounding program context, the unsuffixed integer literal has that type.
But the following example show that the order of statements is important:
fn one() { // compiles
let a = 0;
take_some(a);
a.is_positive();
}
fn two() { // does not compile
let a = 0;
a.is_positive();
take_some(a);
}
fn take_some(var: i32) {
// do nothing
}
I think floating-point literals have the same issue, but I haven't checked.
rust-lang/rust#39255 and rust-lang/rust#40985 may be related.
- Dominant language
- Rust
- Stars
- 1.6k
- Forks
- 607
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 12
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rust-lang/reference
-
A-const-eval A-undefined-behavior
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
A-resolve
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
-
A-coercions
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
All issues in rust-lang/reference
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100