Skip to content

Commit 1897d05

Browse files
committed
Make some float methods unstable const fn
Some float methods are now `const fn` under the `const_float_methods` feature gate. In order to support `min`, `max`, `abs` and `copysign`, the implementation of some intrinsics had to be moved from Miri to rustc_const_eval.
1 parent 4f124de commit 1897d05

File tree

11 files changed

+371
-204
lines changed

11 files changed

+371
-204
lines changed

core/src/intrinsics.rs

+239-148
Large diffs are not rendered by default.

core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
#![feature(const_char_encode_utf16)]
121121
#![feature(const_eval_select)]
122122
#![feature(const_exact_div)]
123+
#![feature(const_float_methods)]
123124
#![feature(const_fmt_arguments_new)]
124125
#![feature(const_hash)]
125126
#![feature(const_heap)]

core/src/num/f128.rs

+29-13
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl f128 {
471471
#[inline]
472472
#[must_use]
473473
#[unstable(feature = "f128", issue = "116909")]
474-
pub fn is_sign_positive(self) -> bool {
474+
pub const fn is_sign_positive(self) -> bool {
475475
!self.is_sign_negative()
476476
}
477477

@@ -497,7 +497,7 @@ impl f128 {
497497
#[inline]
498498
#[must_use]
499499
#[unstable(feature = "f128", issue = "116909")]
500-
pub fn is_sign_negative(self) -> bool {
500+
pub const fn is_sign_negative(self) -> bool {
501501
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
502502
// applies to zeros and NaNs as well.
503503
// SAFETY: This is just transmuting to get the sign bit, it's fine.
@@ -538,7 +538,7 @@ impl f128 {
538538
#[inline]
539539
#[unstable(feature = "f128", issue = "116909")]
540540
// #[unstable(feature = "float_next_up_down", issue = "91399")]
541-
pub fn next_up(self) -> Self {
541+
pub const fn next_up(self) -> Self {
542542
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
543543
// denormals to zero. This is in general unsound and unsupported, but here
544544
// we do our best to still produce the correct result on such targets.
@@ -592,7 +592,7 @@ impl f128 {
592592
#[inline]
593593
#[unstable(feature = "f128", issue = "116909")]
594594
// #[unstable(feature = "float_next_up_down", issue = "91399")]
595-
pub fn next_down(self) -> Self {
595+
pub const fn next_down(self) -> Self {
596596
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
597597
// denormals to zero. This is in general unsound and unsupported, but here
598598
// we do our best to still produce the correct result on such targets.
@@ -627,8 +627,9 @@ impl f128 {
627627
/// ```
628628
#[inline]
629629
#[unstable(feature = "f128", issue = "116909")]
630+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
630631
#[must_use = "this returns the result of the operation, without modifying the original"]
631-
pub fn recip(self) -> Self {
632+
pub const fn recip(self) -> Self {
632633
1.0 / self
633634
}
634635

@@ -647,8 +648,9 @@ impl f128 {
647648
/// ```
648649
#[inline]
649650
#[unstable(feature = "f128", issue = "116909")]
651+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
650652
#[must_use = "this returns the result of the operation, without modifying the original"]
651-
pub fn to_degrees(self) -> Self {
653+
pub const fn to_degrees(self) -> Self {
652654
// Use a literal for better precision.
653655
const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
654656
self * PIS_IN_180
@@ -670,8 +672,9 @@ impl f128 {
670672
/// ```
671673
#[inline]
672674
#[unstable(feature = "f128", issue = "116909")]
675+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
673676
#[must_use = "this returns the result of the operation, without modifying the original"]
674-
pub fn to_radians(self) -> f128 {
677+
pub const fn to_radians(self) -> f128 {
675678
// Use a literal for better precision.
676679
const RADS_PER_DEG: f128 =
677680
0.0174532925199432957692369076848861271344287188854172545609719_f128;
@@ -698,8 +701,9 @@ impl f128 {
698701
/// ```
699702
#[inline]
700703
#[unstable(feature = "f128", issue = "116909")]
704+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
701705
#[must_use = "this returns the result of the comparison, without modifying either input"]
702-
pub fn max(self, other: f128) -> f128 {
706+
pub const fn max(self, other: f128) -> f128 {
703707
intrinsics::maxnumf128(self, other)
704708
}
705709

@@ -723,8 +727,9 @@ impl f128 {
723727
/// ```
724728
#[inline]
725729
#[unstable(feature = "f128", issue = "116909")]
730+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
726731
#[must_use = "this returns the result of the comparison, without modifying either input"]
727-
pub fn min(self, other: f128) -> f128 {
732+
pub const fn min(self, other: f128) -> f128 {
728733
intrinsics::minnumf128(self, other)
729734
}
730735

@@ -757,7 +762,7 @@ impl f128 {
757762
#[unstable(feature = "f128", issue = "116909")]
758763
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
759764
#[must_use = "this returns the result of the comparison, without modifying either input"]
760-
pub fn maximum(self, other: f128) -> f128 {
765+
pub const fn maximum(self, other: f128) -> f128 {
761766
if self > other {
762767
self
763768
} else if other > self {
@@ -798,7 +803,7 @@ impl f128 {
798803
#[unstable(feature = "f128", issue = "116909")]
799804
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
800805
#[must_use = "this returns the result of the comparison, without modifying either input"]
801-
pub fn minimum(self, other: f128) -> f128 {
806+
pub const fn minimum(self, other: f128) -> f128 {
802807
if self < other {
803808
self
804809
} else if other < self {
@@ -1269,9 +1274,20 @@ impl f128 {
12691274
/// ```
12701275
#[inline]
12711276
#[unstable(feature = "f128", issue = "116909")]
1277+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
12721278
#[must_use = "method returns a new number and does not mutate the original value"]
1273-
pub fn clamp(mut self, min: f128, max: f128) -> f128 {
1274-
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1279+
pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
1280+
#[inline] // inline to avoid LLVM crash
1281+
const fn assert_at_const(min: f128, max: f128) {
1282+
// Note that we cannot format in constant expressions.
1283+
assert!(min <= max, "min > max, or either was NaN");
1284+
}
1285+
#[inline] // inline to avoid codegen regression
1286+
fn assert_at_rt(min: f128, max: f128) {
1287+
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1288+
}
1289+
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
1290+
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
12751291
if self < min {
12761292
self = min;
12771293
}

core/src/num/f16.rs

+29-13
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl f16 {
459459
#[inline]
460460
#[must_use]
461461
#[unstable(feature = "f16", issue = "116909")]
462-
pub fn is_sign_positive(self) -> bool {
462+
pub const fn is_sign_positive(self) -> bool {
463463
!self.is_sign_negative()
464464
}
465465

@@ -488,7 +488,7 @@ impl f16 {
488488
#[inline]
489489
#[must_use]
490490
#[unstable(feature = "f16", issue = "116909")]
491-
pub fn is_sign_negative(self) -> bool {
491+
pub const fn is_sign_negative(self) -> bool {
492492
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
493493
// applies to zeros and NaNs as well.
494494
// SAFETY: This is just transmuting to get the sign bit, it's fine.
@@ -529,7 +529,7 @@ impl f16 {
529529
#[inline]
530530
#[unstable(feature = "f16", issue = "116909")]
531531
// #[unstable(feature = "float_next_up_down", issue = "91399")]
532-
pub fn next_up(self) -> Self {
532+
pub const fn next_up(self) -> Self {
533533
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
534534
// denormals to zero. This is in general unsound and unsupported, but here
535535
// we do our best to still produce the correct result on such targets.
@@ -583,7 +583,7 @@ impl f16 {
583583
#[inline]
584584
#[unstable(feature = "f16", issue = "116909")]
585585
// #[unstable(feature = "float_next_up_down", issue = "91399")]
586-
pub fn next_down(self) -> Self {
586+
pub const fn next_down(self) -> Self {
587587
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
588588
// denormals to zero. This is in general unsound and unsupported, but here
589589
// we do our best to still produce the correct result on such targets.
@@ -618,8 +618,9 @@ impl f16 {
618618
/// ```
619619
#[inline]
620620
#[unstable(feature = "f16", issue = "116909")]
621+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
621622
#[must_use = "this returns the result of the operation, without modifying the original"]
622-
pub fn recip(self) -> Self {
623+
pub const fn recip(self) -> Self {
623624
1.0 / self
624625
}
625626

@@ -638,8 +639,9 @@ impl f16 {
638639
/// ```
639640
#[inline]
640641
#[unstable(feature = "f16", issue = "116909")]
642+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
641643
#[must_use = "this returns the result of the operation, without modifying the original"]
642-
pub fn to_degrees(self) -> Self {
644+
pub const fn to_degrees(self) -> Self {
643645
// Use a literal for better precision.
644646
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
645647
self * PIS_IN_180
@@ -661,8 +663,9 @@ impl f16 {
661663
/// ```
662664
#[inline]
663665
#[unstable(feature = "f16", issue = "116909")]
666+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
664667
#[must_use = "this returns the result of the operation, without modifying the original"]
665-
pub fn to_radians(self) -> f16 {
668+
pub const fn to_radians(self) -> f16 {
666669
// Use a literal for better precision.
667670
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
668671
self * RADS_PER_DEG
@@ -687,8 +690,9 @@ impl f16 {
687690
/// ```
688691
#[inline]
689692
#[unstable(feature = "f16", issue = "116909")]
693+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
690694
#[must_use = "this returns the result of the comparison, without modifying either input"]
691-
pub fn max(self, other: f16) -> f16 {
695+
pub const fn max(self, other: f16) -> f16 {
692696
intrinsics::maxnumf16(self, other)
693697
}
694698

@@ -711,8 +715,9 @@ impl f16 {
711715
/// ```
712716
#[inline]
713717
#[unstable(feature = "f16", issue = "116909")]
718+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
714719
#[must_use = "this returns the result of the comparison, without modifying either input"]
715-
pub fn min(self, other: f16) -> f16 {
720+
pub const fn min(self, other: f16) -> f16 {
716721
intrinsics::minnumf16(self, other)
717722
}
718723

@@ -744,7 +749,7 @@ impl f16 {
744749
#[unstable(feature = "f16", issue = "116909")]
745750
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
746751
#[must_use = "this returns the result of the comparison, without modifying either input"]
747-
pub fn maximum(self, other: f16) -> f16 {
752+
pub const fn maximum(self, other: f16) -> f16 {
748753
if self > other {
749754
self
750755
} else if other > self {
@@ -784,7 +789,7 @@ impl f16 {
784789
#[unstable(feature = "f16", issue = "116909")]
785790
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
786791
#[must_use = "this returns the result of the comparison, without modifying either input"]
787-
pub fn minimum(self, other: f16) -> f16 {
792+
pub const fn minimum(self, other: f16) -> f16 {
788793
if self < other {
789794
self
790795
} else if other < self {
@@ -1244,9 +1249,20 @@ impl f16 {
12441249
/// ```
12451250
#[inline]
12461251
#[unstable(feature = "f16", issue = "116909")]
1252+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
12471253
#[must_use = "method returns a new number and does not mutate the original value"]
1248-
pub fn clamp(mut self, min: f16, max: f16) -> f16 {
1249-
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1254+
pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
1255+
#[inline] // inline to avoid LLVM crash
1256+
const fn assert_at_const(min: f16, max: f16) {
1257+
// Note that we cannot format in constant expressions.
1258+
assert!(min <= max, "min > max, or either was NaN");
1259+
}
1260+
#[inline] // inline to avoid codegen regression
1261+
fn assert_at_rt(min: f16, max: f16) {
1262+
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1263+
}
1264+
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
1265+
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
12501266
if self < min {
12511267
self = min;
12521268
}

core/src/num/f32.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,9 @@ impl f32 {
828828
/// ```
829829
#[must_use = "this returns the result of the operation, without modifying the original"]
830830
#[stable(feature = "rust1", since = "1.0.0")]
831+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
831832
#[inline]
832-
pub fn recip(self) -> f32 {
833+
pub const fn recip(self) -> f32 {
833834
1.0 / self
834835
}
835836

@@ -845,8 +846,9 @@ impl f32 {
845846
#[must_use = "this returns the result of the operation, \
846847
without modifying the original"]
847848
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
849+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
848850
#[inline]
849-
pub fn to_degrees(self) -> f32 {
851+
pub const fn to_degrees(self) -> f32 {
850852
// Use a constant for better precision.
851853
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
852854
self * PIS_IN_180
@@ -864,8 +866,9 @@ impl f32 {
864866
#[must_use = "this returns the result of the operation, \
865867
without modifying the original"]
866868
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
869+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
867870
#[inline]
868-
pub fn to_radians(self) -> f32 {
871+
pub const fn to_radians(self) -> f32 {
869872
const RADS_PER_DEG: f32 = consts::PI / 180.0;
870873
self * RADS_PER_DEG
871874
}
@@ -885,8 +888,9 @@ impl f32 {
885888
/// ```
886889
#[must_use = "this returns the result of the comparison, without modifying either input"]
887890
#[stable(feature = "rust1", since = "1.0.0")]
891+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
888892
#[inline]
889-
pub fn max(self, other: f32) -> f32 {
893+
pub const fn max(self, other: f32) -> f32 {
890894
intrinsics::maxnumf32(self, other)
891895
}
892896

@@ -905,8 +909,9 @@ impl f32 {
905909
/// ```
906910
#[must_use = "this returns the result of the comparison, without modifying either input"]
907911
#[stable(feature = "rust1", since = "1.0.0")]
912+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
908913
#[inline]
909-
pub fn min(self, other: f32) -> f32 {
914+
pub const fn min(self, other: f32) -> f32 {
910915
intrinsics::minnumf32(self, other)
911916
}
912917

@@ -933,7 +938,7 @@ impl f32 {
933938
#[must_use = "this returns the result of the comparison, without modifying either input"]
934939
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
935940
#[inline]
936-
pub fn maximum(self, other: f32) -> f32 {
941+
pub const fn maximum(self, other: f32) -> f32 {
937942
if self > other {
938943
self
939944
} else if other > self {
@@ -968,7 +973,7 @@ impl f32 {
968973
#[must_use = "this returns the result of the comparison, without modifying either input"]
969974
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
970975
#[inline]
971-
pub fn minimum(self, other: f32) -> f32 {
976+
pub const fn minimum(self, other: f32) -> f32 {
972977
if self < other {
973978
self
974979
} else if other < self {
@@ -1401,9 +1406,19 @@ impl f32 {
14011406
/// ```
14021407
#[must_use = "method returns a new number and does not mutate the original value"]
14031408
#[stable(feature = "clamp", since = "1.50.0")]
1409+
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
14041410
#[inline]
1405-
pub fn clamp(mut self, min: f32, max: f32) -> f32 {
1406-
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1411+
pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
1412+
const fn assert_at_const(min: f32, max: f32) {
1413+
// Note that we cannot format in constant expressions.
1414+
assert!(min <= max, "min > max, or either was NaN");
1415+
}
1416+
#[inline] // inline to avoid codegen regression
1417+
fn assert_at_rt(min: f32, max: f32) {
1418+
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
1419+
}
1420+
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
1421+
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
14071422
if self < min {
14081423
self = min;
14091424
}

0 commit comments

Comments
 (0)