Skip to content

Make min/max and copysign intrinsics generic - #162414

Open
N1ark wants to merge 7 commits into
rust-lang:mainfrom
N1ark:const-unstable-float-generics
Open

Make min/max and copysign intrinsics generic#162414
N1ark wants to merge 7 commits into
rust-lang:mainfrom
N1ark:const-unstable-float-generics

Conversation

@N1ark

@N1ark N1ark commented Sep 7, 2026

Copy link
Copy Markdown
Member

Split off from #162395

Make the following intrinsics generic over the float type:

  • copysign, with a shared fallback (bit manipulations). Note that this required adding #[rustc_const_unstable] to the whole intrinsic, which copysignf16 and copysignf128 didn't have. This was already FCP'd, see rust-lang/rust#153834 (comment).
  • minimum_number_nsz, maximum_number_nsz, minimum, maximum, with shared fallbacks.

Because these are generic and require const trait impls to have a fallback, I had to add #[rustc_allow_const_fn_unstable] to them:

  • copysign needs const_ops, const_trait_impl
  • minimum_number_nsz and maximum_number_nsz need const_cmp, const_trait_impl
  • minimum and maximum need const_cmp, const_ops, const_trait_impl

I have also bundled in the addition of the attribute to fabs, which used these features without having a formal approval (see #162409 -- this was introduced in #153834)

See #162395 (comment)

r? RalfJung

@rustbot

rustbot commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

⚠️ #[miri::intrinsic_fallback_is_spec] must only be used if the function actively checks for all UB cases,
and explores the possible non-determinism of the intrinsic.

cc @rust-lang/miri

rustc_codegen_gcc is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_gcc instead.

cc @antoyo, @GuillaumeGomez

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Any special-casing of Miri in the standard library requires review.

cc @rust-lang/miri

⚠️ #[rustc_intrinsic_const_stable_indirect] controls whether intrinsics can be exposed to stable const
code; adding it needs t-lang approval.

cc @rust-lang/wg-const-eval

⚠️ #[rustc_allow_const_fn_unstable] needs careful audit to avoid accidentally exposing unstable
implementation details on stable.

cc @rust-lang/wg-const-eval

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Sep 7, 2026
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. 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 Sep 7, 2026
@rustbot

rustbot commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

RalfJung is not on the review rotation at the moment.
They may take a while to respond.

@RalfJung

RalfJung commented Sep 7, 2026

Copy link
Copy Markdown
Member

Because these are generic and require const trait impls to have a fallback, I had to add #[rustc_allow_const_fn_unstable] to them:

I just realized that we can maybe just use rustc_do_not_const_check for all of them? They all have built-in implementations right?

@N1ark

N1ark commented Sep 7, 2026

Copy link
Copy Markdown
Member Author

doesn't that feel a bit hackier / risk prone that just doing it like this? though i don't mind, we are calling externs from const code in other fallbacks after all ^^'

Comment thread library/core/src/intrinsics/bounds.rs Outdated
@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented Sep 7, 2026

Copy link
Copy Markdown
Member

doesn't that feel a bit hackier / risk prone that just doing it like this? though i don't mind, we are calling externs from const code in other fallbacks after all ^^'

IMO it makes sense -- in both cases it's a fallback body that we don't want to use for const-eval, just the reason for not using it is different.

@RalfJung

RalfJung commented Sep 7, 2026

Copy link
Copy Markdown
Member

CI is red. Also please add the same kind of test as in your other PR. Yeah that means they will conflict -- sorry for that. Shouldn't be too hard of a conflict to deal with I hope.

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 7, 2026
@N1ark
N1ark force-pushed the const-unstable-float-generics branch from 1514b9c to 101eb51 Compare September 7, 2026 12:12
@N1ark

N1ark commented Sep 7, 2026

Copy link
Copy Markdown
Member Author

de-constified the trait, as done in #162409, and switched to #[rustc_do_not_const_check]

Comment thread compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

@RalfJung RalfJung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM on the Rust + LLVM side, but I can't review the other codegen backends. Looks like the GCC changes already got approved -- @bjorn3 could you look at the cranelift changes?

View changes since this review

} else if y < x {
#[rustc_do_not_const_check]
pub const fn maximum_number_nsz<T: bounds::FloatPrimitive>(x: T, y: T) -> T {
if x.is_nan() || y >= x {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this would have been easier to review if you had kept the original order of the intrinsics. Please keep that in mind when writing a PR that someone else is expected to review -- never reorder and change code at the same time, git can't really deal with that.

/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[rustc_intrinsic_const_stable_indirect]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this attribute needed? It was not needed before...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well it will be needed with my PR, so let's keep it. :) Just curious why you added it here as I didn't think anything would force you to add it before my PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Process-wise, adding the attribute is covered by the FCP in #130843 (comment).

@RalfJung RalfJung Sep 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No wait, that was for min/maximum_number_nsz. This here is min/maximum which is not yet stable. It really shouldn't get the attribute then.

Add #[rustc_const_unstable] instead.

/// Used to distinguish fallbacks of float intrinsics. For some we have a codegen fallback,
/// while for others we fallback to an external libcall.
enum IntrinsicFallback {
Fallback(&'static str),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So this does not refer to a Rust fallback body? Please pick a different name then, this is confusing. Maybe Libcall or so?

Or, given that this is pre-existing, at least please add a comment.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think all cases which use IntrinsicFallback::Fallback should be able to be removed and just use the Rust fallback body? In which case adding a FIXME here to remove it in a future PR seems like a good idea.

@rust-bors

rust-bors Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

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

Comment on lines +3 to +5
// Check that the float intrinsics carrying `#[rustc_do_not_const_check]` can actually be called in
// a const context, for every float width. Their bodies are never const-checked and never run by
// const-eval, which has to implement each of these intrinsics itself.

@RalfJung RalfJung Sep 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW there's no good reason to only cover rustc_do_not_const_check intrinsics here. All const intrinsics without const-capable fallback body should ideally be covered somewhere. Maybe we already test some of them somewhere? I don't know.

View changes since the review

let arg = AbiParam::new(ty);
fx.lib_call(name, vec![arg, arg], vec![arg], &[x, y])[0]
}
};

@bjorn3 bjorn3 Sep 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The fallback variant is never used here.

View changes since the review

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

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants