-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
RFC: Allow type inference for const or static #3546
base: master
Are you sure you want to change the base?
Changes from 4 commits
02b547a
af46bdb
7c3a963
59a402c
ad81b61
a9b7cf9
9ec4198
76d6086
72dd92a
1ba81db
a0e2a39
ce63778
2642e55
dfc7727
f7ee9b4
6104660
858a178
007e0cb
bf115d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
- Feature Name: const_type_inference | ||
- Start Date: 2023-12-21 | ||
- RFC PR: [rust-lang/rfcs#3546](https://github.com/rust-lang/rfcs/pull/3546) | ||
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
Allow type inference for `const` or `static` when the type of the initial value is known. | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
Rust currently requires explicit type annotations for `const` and `static` items. | ||
|
||
|
||
In simple cases, explicitly writing out | ||
the type of the const seems trivial. However, this isn't always the case: | ||
|
||
- Sometimes the constant's value is complex, making the explicit type overly verbose. | ||
- In some cases, the type may be unnameable. | ||
- When creating macros, the precise type might not be known to the macro author. | ||
- Code generators may not have enough information to easily determine the type. | ||
|
||
This change aims to make Rust code more concise and maintainable, especially in scenarios where the types of | ||
const items are complicated or not easily expressible. | ||
|
||
Neo-Zhixing marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
You may declare constants and static variables without specifying their types when the type can be inferred | ||
from the initial value. For example: | ||
|
||
```rs | ||
const PI = 3.1415; // inferred as f64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would personally prefer that the actual type of numeric or float types be known rather than picking arbitrary defaults (e.g. const PI = 3.1415; // error
const PI = 3.1415_f64; // inferred as f64 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer more consistent behavior with let bindings. So let's make a simple vote here: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a big issue for me either way it's just that a few times I've only later realised a type has been unexpectedly made There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it follows the normal rust inference default types then it's at least no worse than what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well it's worse in the sense that let can use future code to infer the type, so mostly this is a non issue there unless there's a lot of generics involved. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly I would most like if the const was of |
||
static MESSAGE = "Hello, World!"; // inferred as &'static str | ||
const FN_PTR = std::string::String::default; // inferred as fn() -> String | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually a good point - I guess there's not much point to coerce the function item's type into function pointer type for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused about why a person would want it as a static at all, so perhaps we shouldn't allow it at all in the first version of this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Lokathor maybe they just use the const as a quick switch between two cfg implementations? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes sense as a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when the type is a ZST, like function item types, at runtime, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing implicit coercions into an unknown target type sounds very confusing. If the right-hand side is |
||
``` | ||
|
||
# Reference-level explanation | ||
[reference-level-explanation]: #reference-level-explanation | ||
|
||
|
||
The type inference for `const` and `static` will leverage Rust's existing type inference mechanisms. The compiler will infer the type exclusively based on the RHS. If the type cannot be determined or if it leads to ambiguities, the compiler will emit an error, prompting the programmer to specify the type explicitly. | ||
|
||
|
||
Today, the compiler already gives hint for most cases where the const or static item is missing a type: | ||
|
||
``` | ||
802 | const A = 0; | ||
| ^ help: provide a type for the constant: `: i32` | ||
``` | ||
|
||
|
||
``` | ||
error: missing type for `const` item | ||
--> file.rs:27:26 | ||
| | ||
27 | pub const update_blas = SystemStage { system: test_system, stage: vk::Pipeli... | ||
| ^ help: provide a type for the constant: `: render_pass::SystemStage<for<'a> fn(ResMut<'a, AsyncQueues>)>` | ||
``` | ||
|
||
The implementation should only need to carry over this information and set the type correspondingly | ||
instead of emitting an error. | ||
|
||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
- Potential Loss of Clarity: In some cases, omitting the type might make the code less clear, | ||
especially to newcomers or in codebases where explicit types are part of the documentation style. | ||
It is my belief that this is a choice better left for the developers as in the case of `let` bindings. | ||
Neo-Zhixing marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- Anything else? | ||
|
||
# Rationale and alternatives | ||
[rationale-and-alternatives]: #rationale-and-alternatives | ||
|
||
- Impact of Not Doing This: Rust code remains more verbose than necessary, especially in complex scenarios, and macro authors face challenges with type specifications. | ||
- Alternative: Allowing the naming of function types as in [#3476](https://github.com/rust-lang/rfcs/pull/3476) may help resolve some of the cases where type inference is needed. | ||
|
||
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
In [RFC#1623](https://github.com/rust-lang/rfcs/pull/1623) we added `'static` lifetimes to every reference or generics lifetime value in `static` or `const` declarations. | ||
|
||
|
||
# Unresolved questions | ||
[unresolved-questions]: #unresolved-questions | ||
|
||
Should we allow assignment of unnameable types? For example, | ||
```rs | ||
let A = |a: u32| { | ||
Neo-Zhixing marked this conversation as resolved.
Show resolved
Hide resolved
|
||
123_i32 | ||
}; | ||
|
||
``` | ||
|
||
``` | ||
error: missing type for `const` item | ||
| | ||
28 | const A = |a: u32| { | ||
| ^ | ||
| | ||
note: however, the inferred type `[closure@render_pass.rs:28:11]` cannot be named | ||
| | ||
28 | const A = |a: u32| { | ||
| ___________^ | ||
29 | | 1_i32 | ||
30 | | }; | ||
| |_^ | ||
``` | ||
|
||
If this significantly complicates the implementation, we can leave it outside the scope of this RFC. | ||
Neo-Zhixing marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to write a little bit about why Rust is like this currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, this should have a longer explanation of Rusts "rule" of "no inference in signatures", how this RFC is breaking it and why this is okay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great suggestion! I actually don't know why the design was made that way. Maybe someone from the Rust team can help explain?
The "type is missing in const" error was emitted from the parser so my guess would be that it was just difficult to infer types when consts were implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's like this currently because it was decided that all public API points should be "obviously semver stable" rather than "quick to type".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for explaining this. I've incorporated it into the RFC.