Skip to content

Fallback {float} to f32 when f32: From<{float}> and add impl From<f16> for f32#139087

Open
beetrees wants to merge 3 commits intorust-lang:mainfrom
beetrees:impl-from-f16-for-f32
Open

Fallback {float} to f32 when f32: From<{float}> and add impl From<f16> for f32#139087
beetrees wants to merge 3 commits intorust-lang:mainfrom
beetrees:impl-from-f16-for-f32

Conversation

@beetrees
Copy link
Contributor

@beetrees beetrees commented Mar 28, 2025

View all comments

Currently, the following code compiles:

fn foo<T: Into<f32>>(_: T) {}

fn main() {
    foo(1.0);
}

This is because the only From<{float}> impl for f32 is currently From<f32>. However, once impl From<f16> for f32 is added this is no longer the case. This would cause the float literal to fallback to f64, subsequently causing a type error as f32 does not implement From<f64>. While this kind of change to type inference isn't technically a breaking change according to Rust's breaking change policy, the previous attempt to add impl From<f16> for f32 was removed #123830 due to the large number of crates affected (by my count, there were root regressions in 42 crates and 52 GitHub repos, not including duplicates). This PR solves this problem by using f32 as the fallback type for {float} when there is a trait predicate of f32: From<{float}>. This allows adding impl From<f16> for f32 without affecting the code that currently compiles (such as the example above; this PR shouldn't affect what is possible on stable).

This PR also allows adding a future-incompatibility warning for the fallback to f32 (currently implemented in the third commit) if the lang team wants one (allowing the f32 fallback to be removed in the future); alternatively this could be expanded in the future into something more general like @tgross35 suggested in #123831 (comment). I think it would be also possible to disallow the f32 fallback in a future edition.

As expected, a crater check showed no non-spurious regressions.

For reference, I've based the implementation loosely on the existing calculate_diverging_fallback. This first commit adds the f32 fallback, the second adds impl From<f16> for f32, and the third adds a FCW lint for the f32 fallback. I think this falls under the types team, so
r? types

Fixes: #123831
Tracking issue: #116909

@rustbot label +T-lang +T-types +T-libs-api +F-f16_and_f128

To decide on whether a future-incompatibility warning is desired or otherwise (see above):
@rustbot label +I-lang-nominated

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 28, 2025
@rustbot
Copy link
Collaborator

rustbot commented Mar 28, 2025

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot rustbot added T-lang Relevant to the language team T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. I-lang-nominated Nominated for discussion during a lang team meeting. F-f16_and_f128 `#![feature(f16)]`, `#![feature(f128)]` labels Mar 28, 2025
@beetrees beetrees force-pushed the impl-from-f16-for-f32 branch from ef59666 to bb79c28 Compare March 28, 2025 21:34
@rust-log-analyzer

This comment has been minimized.

@beetrees beetrees force-pushed the impl-from-f16-for-f32 branch from bb79c28 to afe5b7f Compare March 28, 2025 22:35
@rust-log-analyzer

This comment has been minimized.

@beetrees beetrees force-pushed the impl-from-f16-for-f32 branch from afe5b7f to f4cb5a7 Compare March 28, 2025 23:32
@compiler-errors
Copy link
Contributor

@bors try

@bors
Copy link
Collaborator

bors commented Mar 28, 2025

⌛ Trying commit f4cb5a7 with merge 3ec2a77...

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 28, 2025
Fallback `{float}` to `f32` when `f32: From<{float}>` and add `impl From<f16> for f32`

Currently, the following code compiles:
```rust
fn foo::<T: Into<f32>>(_: T) {}

fn main() {
    foo(1.0);
}
```

This is because the only `From<{float}>` impl for `f32` is currently `From<f32>`. However, once `impl From<f16> for f32` is added this is no longer the case. This would cause the float literal to fallback to `f64`, subsequently causing a type error as `f32` does not implement `From<f64>`. While this kind of change to type inference isn't technically a breaking change according to Rust's breaking change policy, the previous attempt to add `impl From<f16> for f32` was removed rust-lang#123830 due to the large number of crates affected (by my count, there were root regressions in 42 crates and 52 GitHub repos, not including duplicates). This PR solves this problem by using `f32` as the fallback type for `{float}` when there is a trait predicate of `f32: From<{float}>`. This allows adding `impl From<f16> for f32` without affecting the code that currently compiles (such as the example above; this PR shouldn't affect what is possible on stable).

This PR also allows adding a future-incompatibility warning if the lang team wants one; alternatively this could be expanded in the future into something more general like `@tgross35` suggested in rust-lang#123831 (comment). I think it would be also possible to disallow the `f32` fallback in a future edition.

This will need a crater check.

For reference, I've based the implementation loosely on the existing `calculate_diverging_fallback`. This first commit adds the `f32` fallback and the second adds `impl From<f16> for f32`. I think this falls under the types team, so
r? types

Fixes: rust-lang#123831
Tracking issue: rust-lang#116909

`@rustbot` label +T-lang +T-types +T-libs-api +F-f16_and_f128

To decide on whether a future-incompatibility warning is desired or otherwise (see above):
`@rustbot` label +I-lang-nominated
@bors
Copy link
Collaborator

bors commented Mar 29, 2025

☀️ Try build successful - checks-actions
Build commit: 3ec2a77 (3ec2a775459d36c7d90654e47c56ff7bb0d542ab)

@compiler-errors
Copy link
Contributor

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-139087 created and queued.
🤖 Automatically detected try build 3ec2a77
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 29, 2025
@craterbot
Copy link
Collaborator

🚧 Experiment pr-139087 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🚨 Report generation of pr-139087 failed: timed out waiting for connection
🛠️ If the error is fixed use the retry-report command.

🆘 Can someone from the infra team check in on this? @rust-lang/infra
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@compiler-errors
Copy link
Contributor

@craterbot retry-report

@craterbot
Copy link
Collaborator

🛠️ Generation of the report for pr-139087 queued again.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🎉 Experiment pr-139087 is completed!
📊 9 regressed and 2 fixed (605729 total)
📰 Open the full report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Mar 30, 2025
@beetrees
Copy link
Contributor Author

I've opened a PR to run Crater to measure the impact of the trait impl and FCW at #142723.

@beetrees beetrees force-pushed the impl-from-f16-for-f32 branch from bac7aea to 71c00e2 Compare June 19, 2025 15:25
rust-bors bot added a commit that referenced this pull request Jun 19, 2025
[crater] Add `impl From<f16> for f32`

Crater run to see what the effects of adding `impl From<f16> for f32` without changing the fallback (a.k.a. things that would be caught by the FCW in #139087). This needs a ``@craterbot` check`.
@bors
Copy link
Collaborator

bors commented Aug 15, 2025

☔ The latest upstream changes (presumably #145423) made this pull request unmergeable. Please resolve the merge conflicts.

@lcnr lcnr added S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 17, 2025
@Urgau Urgau added S-waiting-on-t-lang Status: Awaiting decision from T-lang and removed S-waiting-on-team labels Oct 6, 2025
@joshtriplett
Copy link
Member

There seems to be a bit of a split of opinion between "add a FCW and eventually remove the f32 fallback" and "don't add a FCW and expand the fallback so that it works for all literals constrained by From<{float}> for fN or From<{integer}> for iN/uN". I'm guessing this needs to be nominated lang team and/or types team discussion to decide which direction to head in?

Yes.

@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Nov 28, 2025
@traviscross traviscross removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Jan 21, 2026
@jackh726
Copy link
Member

I'm going to nominate this for T-types. I think we should have a meeting and discuss this at some point - I'm not sure if Niko still has impl concerns, but I still have complexity concerns. These could be easily dismissed, but seems useful to just have a sync discussion about this.

@jackh726 jackh726 added the I-types-nominated Nominated for discussion during a types team meeting. label Jan 21, 2026
@folkertdev
Copy link
Contributor

Alternatively, adding the impl From<f16> for f32 could be delayed until after stabilization.

The absence of the From impl is mildly annoying, but an as cast works just as well. I don't think any doors are closed by first stabilizing the type and later adding the impl.

In light of the stabilizing f16 we'd like to unblock stabilizing the f16 type.

@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Mar 7, 2026
@folkertdev
Copy link
Contributor

@traviscross This was discussed in the lang meeting https://hackmd.io/FZR0FoQ4RkC4G3i-dKiyzg#Fallback-float-to-f32-when-f32-Fromltfloatgt-and-add-impl-Fromltf16gt-for-f32-rust139087, however I'm not exactly sure where you ended up.

Looks like you want to see a FCW lint? What would that lint on exactly, just any use of From<{float}>?

@traviscross
Copy link
Contributor

traviscross commented Mar 15, 2026

We talked about this in the lang call. We're interested in unblocking the stabilization of f16. At the same time, some had reservations about doing that without some plan for being able to add this impl in a finite amount of time.

The option we discussed in the meeting went as follows:

If we could add an FCW against reliance on the fallback behavior when that fallback would be a problem for adding this impl (and it's OK if it approximates on this), then we can move maintained code off of this reliance. Then, after some time, we can take the minor (in an RFC 1105 sense) breakage due to adding this impl.

(This plan uses our normal tools for evolving the language and doesn't require us to speculate about future features. We're doing something similar to this for stabilizing the never type.)

Such a plan would give us confidence that we can likely add the impl in a finite amount of time, and that confidence would give us confidence to ship f16 today.

@folkertdev, what do you think? Is such a lint feasible? What would you propose in terms of how it could be best targeted at this problem?

Comment on lines +5026 to +5073
declare_lint! {
/// The `float_literal_f32_fallback` lint detects situations where the type of an unsuffixed
/// float literal falls back to `f32` instead of `f64` to avoid a compilation error. This occurs
/// when there is a trait bound `f32: From<T>` (or equivalent, such as `T: Into<f32>`) and the
/// literal is inferred to have the same type as `T`.
///
/// ### Example
///
/// ```rust
/// fn foo(x: impl Into<f32>) -> f32 {
/// x.into()
/// }
///
/// fn main() {
/// dbg!(foo(2.5));
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Rust allows traits that are only implemented for a single floating point type to guide type
/// inferrence for floating point literals. This used to apply in the case of `f32: From<T>`
/// (where `T` was inferred to be the same type as a floating point literal), as the only
/// floating point type impl was `f32: From<f32>`. However, as Rust is in the process of adding
/// support for `f16`, there are now two implementations for floating point types:
/// `f32: From<f16>` and `f32: From<f32>`. This means that the trait bound `f32: From<T>` can no
/// longer guide inferrence for the type of the floating point literal. The default fallback for
/// unsuffixed floating point literals is `f64`. As `f32` does not implement `From<f64>`,
/// falling back to `f64` would cause a compilation error; therefore, the float type fallback
/// has been tempoarily adjusted to fallback to `f32` in this scenario.
///
/// The lint will automatically provide a machine-applicable suggestion to add a `_f32` suffix
/// to the literal, which will fix the problem.
///
/// This is a [future-incompatible] lint to transition this to a hard error in the future. See
/// [issue #FIXME] for more details.
///
/// [issue #FIXME]: https://github.com/rust-lang/rust/issues/FIXME
pub FLOAT_LITERAL_F32_FALLBACK,
Warn,
"detects unsuffixed floating point literals whose type fallback to `f32`",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #FIXME <https://github.com/rust-lang/rust/issues/FIXME>",
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@traviscross this PR already includes a FCW, @beetrees did all of the hard work already. I think this can be extracted (needs an update given all of the merge conflicts) and then that should do?

At least reading through the comments the T-types folks don't seem to have major issues with the approach here, though we'll see if anything else pops up.

note to self: I like the example from the issue better #123824

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the lint here only works when adding the additional f16 instance (creating the ambiguity).

I'll push the rebased version anyway in case it's helpful, but a different approach to trigger the lint is needed and my knowledge of the type checker is insufficient to know what that would look like, so I'll need some help there.

@folkertdev folkertdev force-pushed the impl-from-f16-for-f32 branch from 71c00e2 to cacf239 Compare March 15, 2026 12:09
@rustbot
Copy link
Collaborator

rustbot commented Mar 15, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer
Copy link
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
     ╭▸ compiler/rustc_lint_defs/src/builtin.rs:5644:22
     │
5644 │     /// longer guide inferrence for the type of the floating point literal. The default fallback for
     ╰╴                     ━━━━━━━━━━
error: `occurences` should be `occurrences`
    ╭▸ compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs:227:42
    │
227 │         // 3 is more than enough for all occurences in practice (a.k.a. `Into`).
    ╰╴                                         ━━━━━━━━━━
rerun tidy with `--extra-checks=spellcheck --bless` to fix typos
tidy [extra_checks:spellcheck]: checks with external tool 'typos' failed
tidy [extra_checks:spellcheck]: FAIL
yarn install v1.22.22
warning package.json: No license field
warning ../../package.json: License should be a valid SPDX license expression
warning No license field
[1/4] Resolving packages...
---
linting javascript files
Running eslint on rustdoc JS files
info: ES-Check: there were no ES version matching errors!  🎉
typechecking javascript files
tidy: The following check failed: extra_checks:spellcheck
Command `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools-bin/rust-tidy --root-path=/checkout --cargo-path=/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo --output-dir=/checkout/obj/build --concurrency=4 --npm-path=/node/bin/yarn --ci=true --extra-checks=py,cpp,js,spellcheck` failed with exit code 1
Created at: src/bootstrap/src/core/build_steps/tool.rs:1618:23
Executed at: src/bootstrap/src/core/build_steps/test.rs:1387:29

Command has failed. Rerun with -v to see more details.
Bootstrap failed while executing `test src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck`
Build completed unsuccessfully in 0:03:06
  local time: Sun Mar 15 12:15:49 UTC 2026
  network time: Sun, 15 Mar 2026 12:15:49 GMT
##[error]Process completed with exit code 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. F-f16_and_f128 `#![feature(f16)]`, `#![feature(f128)]` I-lang-nominated Nominated for discussion during a lang team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. I-types-nominated Nominated for discussion during a types team meeting. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. S-blocked Status: Blocked on something else such as an RFC or other implementation work. S-waiting-on-concerns Status: Awaiting concerns to be addressed by the author S-waiting-on-documentation Status: Waiting on approved PRs to documentation before merging S-waiting-on-fcp Status: PR is in FCP and is awaiting for FCP to complete. S-waiting-on-t-lang Status: Awaiting decision from T-lang T-lang Relevant to the language team T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

f32::from(<untyped float>) inference with f16 and f128