-
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
Open
Neo-Zhixing
wants to merge
19
commits into
rust-lang:master
Choose a base branch
from
Neo-Zhixing:const_type_inference
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 12 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
02b547a
new RFC: const_type_inference
Neo-Zhixing af46bdb
Updates
Neo-Zhixing 7c3a963
updates
Neo-Zhixing 59a402c
typo
Neo-Zhixing ad81b61
Update text/0000-const-type-inference.md
Neo-Zhixing a9b7cf9
Update text/0000-const-type-inference.md
Neo-Zhixing 9ec4198
Update text/0000-const-type-inference.md
Neo-Zhixing 76d6086
Updates
Neo-Zhixing 72dd92a
typo
Neo-Zhixing 1ba81db
Update text/0000-const-type-inference.md
Neo-Zhixing a0e2a39
Update text/0000-const-type-inference.md
Neo-Zhixing ce63778
updates
Neo-Zhixing 2642e55
update
Neo-Zhixing dfc7727
Address #2010
Neo-Zhixing f7ee9b4
Updates
Neo-Zhixing 6104660
update
Neo-Zhixing 858a178
Update
Neo-Zhixing 007e0cb
address clippy lint
Neo-Zhixing bf115d2
typo
Neo-Zhixing File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
- 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. | ||
It was decided that all public API points should be "obviously semver stable" rather than "quick to type". | ||
|
||
|
||
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
|
||
Inferring constant types also improves the ergonomics of the language, particularly for new users. Some users are | ||
coming from languages where most (or all) types are inferred, so inferring obvious types matches their | ||
expectations. Other new users are focused on learning ownership, or other core Rust concepts. Reducing the | ||
amount of boilerplate reduces their mental load. This reduction in mental load also helps experienced programmers. | ||
|
||
|
||
# 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, subjecting to the following constraints: | ||
- All numerical types contributing to the inference must be specified. | ||
Neo-Zhixing marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- The type must be partially specified. At the very least, a `_` placeholder must be used, but the `_` placeholder | ||
may also appear anywhere in a nested type. | ||
|
||
For example: | ||
|
||
```rs | ||
const NO = false; // missing type for `const` item; hint: provide a type or add `_` placeholder | ||
const PI: _ = 3.1415; // Ambiguous numeric type | ||
const PI: _ = 3.1415_f32; // Ok | ||
const WRAPPED_PI: MyStruct<_> = MyStruct(3.1415_f32); // Ok | ||
|
||
|
||
static MESSAGE: _ = "Hello, World!"; // inferred as &'static str | ||
static ARR: [u8; _] = [12, 23, 34, 45]; // inferred as [u8; 4] | ||
const FN_PTR: _ = std::string::String::default; // inferred as fn() -> String | ||
``` | ||
|
||
# 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 when explicit types are needed to understanding the purpose of the item. | ||
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
|
||
- Semver compatibilty: The API surface of the type is implicit, changing the right-hand side in subtle ways can change the type in a way that can be hard to notice, for example between different integer types. | ||
However, not all `const` or `static` items are public, and in many cases the type is obvious enough that semver isn't a concern. Requiring explicit typing for this reason seems a bit heavy handed. | ||
|
||
|
||
# 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. | ||
|
||
## Alternatives | ||
|
||
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. | ||
|
||
`type_alias_impl_trait` may also partially address the problem. In particular, it helps with unnameable types | ||
and macro / code generator output, without the drawbacks of loss of clarity and semvar trouble. | ||
However, there might be cases where we do not want the type to be hidden behind an `impl Trait`. | ||
This also won't help with array lengths or types that do not implement a particular trait. | ||
|
||
# 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 | ||
|
||
None. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.