Skip to content

Commit a128563

Browse files
authored
Rollup merge of rust-lang#121926 - tgross35:f16-f128-step3-feature-gate, r=compiler-errors
`f16` and `f128` step 3: compiler support & feature gate Continuation of rust-lang#121841, another portion of rust-lang#114607 This PR exposes the new types to the world and adds a feature gate. Marking this as a draft because I need some feedback on where I did the feature gate check. It also does not yet catch type via suffixed literals (so the feature gate test will fail, probably some others too because I haven't belssed). If there is a better place to check all types after resolution, I can do that. If not, I figure maybe I can add a second gate location in AST when it checks numeric suffixes. Unfortunately I still don't think there is much testing to be done for correctness (codegen tests or parsed value checks) until we have basic library support. I think that will be the next step. Tracking issue: rust-lang#116909 r? ``@compiler-errors`` cc ``@Nilstrieb`` ``@rustbot`` label +F-f16_and_f128
2 parents 5cef608 + b8f45a3 commit a128563

File tree

20 files changed

+373
-119
lines changed

20 files changed

+373
-119
lines changed

compiler/rustc_ast/src/util/literal.rs

+2
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,10 @@ fn filtered_float_lit(
276276
Some(suffix) => LitKind::Float(
277277
symbol,
278278
ast::LitFloatType::Suffixed(match suffix {
279+
sym::f16 => ast::FloatTy::F16,
279280
sym::f32 => ast::FloatTy::F32,
280281
sym::f64 => ast::FloatTy::F64,
282+
sym::f128 => ast::FloatTy::F128,
281283
_ => return Err(LitError::InvalidFloatSuffix(suffix)),
282284
}),
283285
),

compiler/rustc_ast_passes/src/feature_gate.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
33
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
4-
use rustc_ast::{PatKind, RangeEnd};
4+
use rustc_ast::{token, PatKind, RangeEnd};
55
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
66
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
77
use rustc_session::Session;
@@ -375,6 +375,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
375375
ast::ExprKind::TryBlock(_) => {
376376
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
377377
}
378+
ast::ExprKind::Lit(token::Lit { kind: token::LitKind::Float, suffix, .. }) => {
379+
match suffix {
380+
Some(sym::f16) => {
381+
gate!(&self, f16, e.span, "the type `f16` is unstable")
382+
}
383+
Some(sym::f128) => {
384+
gate!(&self, f128, e.span, "the type `f128` is unstable")
385+
}
386+
_ => (),
387+
}
388+
}
378389
_ => {}
379390
}
380391
visit::walk_expr(self, e)

compiler/rustc_feature/src/unstable.rs

+4
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,10 @@ declare_features! (
461461
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
462462
/// Allows defining `extern type`s.
463463
(unstable, extern_types, "1.23.0", Some(43467)),
464+
/// Allow using 128-bit (quad precision) floating point numbers.
465+
(unstable, f128, "CURRENT_RUSTC_VERSION", Some(116909)),
466+
/// Allow using 16-bit (half precision) floating point numbers.
467+
(unstable, f16, "CURRENT_RUSTC_VERSION", Some(116909)),
464468
/// Allows the use of `#[ffi_const]` on foreign functions.
465469
(unstable, ffi_const, "1.45.0", Some(58328)),
466470
/// Allows the use of `#[ffi_pure]` on foreign functions.

compiler/rustc_hir/src/hir.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -2444,7 +2444,7 @@ pub enum PrimTy {
24442444

24452445
impl PrimTy {
24462446
/// All of the primitive types
2447-
pub const ALL: [Self; 17] = [
2447+
pub const ALL: [Self; 19] = [
24482448
// any changes here should also be reflected in `PrimTy::from_name`
24492449
Self::Int(IntTy::I8),
24502450
Self::Int(IntTy::I16),
@@ -2458,9 +2458,10 @@ impl PrimTy {
24582458
Self::Uint(UintTy::U64),
24592459
Self::Uint(UintTy::U128),
24602460
Self::Uint(UintTy::Usize),
2461+
Self::Float(FloatTy::F16),
24612462
Self::Float(FloatTy::F32),
24622463
Self::Float(FloatTy::F64),
2463-
// FIXME(f16_f128): add these when enabled below
2464+
Self::Float(FloatTy::F128),
24642465
Self::Bool,
24652466
Self::Char,
24662467
Self::Str,
@@ -2508,12 +2509,10 @@ impl PrimTy {
25082509
sym::u64 => Self::Uint(UintTy::U64),
25092510
sym::u128 => Self::Uint(UintTy::U128),
25102511
sym::usize => Self::Uint(UintTy::Usize),
2512+
sym::f16 => Self::Float(FloatTy::F16),
25112513
sym::f32 => Self::Float(FloatTy::F32),
25122514
sym::f64 => Self::Float(FloatTy::F64),
2513-
// FIXME(f16_f128): enabling these will open the gates of f16 and f128 being
2514-
// understood by rustc.
2515-
// sym::f16 => Self::Float(FloatTy::F16),
2516-
// sym::f128 => Self::Float(FloatTy::F128),
2515+
sym::f128 => Self::Float(FloatTy::F128),
25172516
sym::bool => Self::Bool,
25182517
sym::char => Self::Char,
25192518
sym::str => Self::Str,

compiler/rustc_lint/src/types.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,11 @@ fn lint_literal<'tcx>(
561561
ty::Float(t) => {
562562
let is_infinite = match lit.node {
563563
ast::LitKind::Float(v, _) => match t {
564-
ty::FloatTy::F16 => unimplemented!("f16_f128"),
564+
// FIXME(f16_f128): add this check once we have library support
565+
ty::FloatTy::F16 => Ok(false),
565566
ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
566567
ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
567-
ty::FloatTy::F128 => unimplemented!("f16_f128"),
568+
ty::FloatTy::F128 => Ok(false),
568569
},
569570
_ => bug!(),
570571
};

compiler/rustc_middle/src/mir/interpret/value.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fmt;
33
use either::{Either, Left, Right};
44

55
use rustc_apfloat::{
6-
ieee::{Double, Single},
6+
ieee::{Double, Half, Quad, Single},
77
Float,
88
};
99
use rustc_macros::HashStable;
@@ -201,6 +201,11 @@ impl<Prov> Scalar<Prov> {
201201
Self::from_int(i, cx.data_layout().pointer_size)
202202
}
203203

204+
#[inline]
205+
pub fn from_f16(f: Half) -> Self {
206+
Scalar::Int(f.into())
207+
}
208+
204209
#[inline]
205210
pub fn from_f32(f: Single) -> Self {
206211
Scalar::Int(f.into())
@@ -211,6 +216,11 @@ impl<Prov> Scalar<Prov> {
211216
Scalar::Int(f.into())
212217
}
213218

219+
#[inline]
220+
pub fn from_f128(f: Quad) -> Self {
221+
Scalar::Int(f.into())
222+
}
223+
214224
/// This is almost certainly not the method you want! You should dispatch on the type
215225
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
216226
///
@@ -422,6 +432,11 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
422432
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
423433
}
424434

435+
#[inline]
436+
pub fn to_f16(self) -> InterpResult<'tcx, Half> {
437+
self.to_float()
438+
}
439+
425440
#[inline]
426441
pub fn to_f32(self) -> InterpResult<'tcx, Single> {
427442
self.to_float()
@@ -431,4 +446,9 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
431446
pub fn to_f64(self) -> InterpResult<'tcx, Double> {
432447
self.to_float()
433448
}
449+
450+
#[inline]
451+
pub fn to_f128(self) -> InterpResult<'tcx, Quad> {
452+
self.to_float()
453+
}
434454
}

compiler/rustc_middle/src/ty/consts/int.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_apfloat::ieee::{Double, Single};
1+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
22
use rustc_apfloat::Float;
33
use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
44
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -369,6 +369,11 @@ impl ScalarInt {
369369
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
370370
}
371371

372+
#[inline]
373+
pub fn try_to_f16(self) -> Result<Half, Size> {
374+
self.try_to_float()
375+
}
376+
372377
#[inline]
373378
pub fn try_to_f32(self) -> Result<Single, Size> {
374379
self.try_to_float()
@@ -378,6 +383,11 @@ impl ScalarInt {
378383
pub fn try_to_f64(self) -> Result<Double, Size> {
379384
self.try_to_float()
380385
}
386+
387+
#[inline]
388+
pub fn try_to_f128(self) -> Result<Quad, Size> {
389+
self.try_to_float()
390+
}
381391
}
382392

383393
macro_rules! from {
@@ -450,6 +460,22 @@ impl TryFrom<ScalarInt> for char {
450460
}
451461
}
452462

463+
impl From<Half> for ScalarInt {
464+
#[inline]
465+
fn from(f: Half) -> Self {
466+
// We trust apfloat to give us properly truncated data.
467+
Self { data: f.to_bits(), size: NonZero::new((Half::BITS / 8) as u8).unwrap() }
468+
}
469+
}
470+
471+
impl TryFrom<ScalarInt> for Half {
472+
type Error = Size;
473+
#[inline]
474+
fn try_from(int: ScalarInt) -> Result<Self, Size> {
475+
int.to_bits(Size::from_bytes(2)).map(Self::from_bits)
476+
}
477+
}
478+
453479
impl From<Single> for ScalarInt {
454480
#[inline]
455481
fn from(f: Single) -> Self {
@@ -482,6 +508,22 @@ impl TryFrom<ScalarInt> for Double {
482508
}
483509
}
484510

511+
impl From<Quad> for ScalarInt {
512+
#[inline]
513+
fn from(f: Quad) -> Self {
514+
// We trust apfloat to give us properly truncated data.
515+
Self { data: f.to_bits(), size: NonZero::new((Quad::BITS / 8) as u8).unwrap() }
516+
}
517+
}
518+
519+
impl TryFrom<ScalarInt> for Quad {
520+
type Error = Size;
521+
#[inline]
522+
fn try_from(int: ScalarInt) -> Result<Self, Size> {
523+
int.to_bits(Size::from_bytes(16)).map(Self::from_bits)
524+
}
525+
}
526+
485527
impl fmt::Debug for ScalarInt {
486528
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487529
// Dispatch to LowerHex below.

compiler/rustc_mir_build/src/build/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::build::expr::as_place::PlaceBuilder;
22
use crate::build::scope::DropKind;
33
use itertools::Itertools;
4-
use rustc_apfloat::ieee::{Double, Single};
4+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
55
use rustc_apfloat::Float;
66
use rustc_ast::attr;
77
use rustc_data_structures::fx::FxHashMap;
@@ -1053,7 +1053,8 @@ pub(crate) fn parse_float_into_scalar(
10531053
) -> Option<Scalar> {
10541054
let num = num.as_str();
10551055
match float_ty {
1056-
ty::FloatTy::F16 => unimplemented!("f16_f128"),
1056+
// FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
1057+
ty::FloatTy::F16 => num.parse::<Half>().ok().map(Scalar::from_f16),
10571058
ty::FloatTy::F32 => {
10581059
let Ok(rust_f) = num.parse::<f32>() else { return None };
10591060
let mut f = num
@@ -1100,7 +1101,8 @@ pub(crate) fn parse_float_into_scalar(
11001101

11011102
Some(Scalar::from_f64(f))
11021103
}
1103-
ty::FloatTy::F128 => unimplemented!("f16_f128"),
1104+
// FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
1105+
ty::FloatTy::F128 => num.parse::<Quad>().ok().map(Scalar::from_f128),
11041106
}
11051107
}
11061108

compiler/rustc_resolve/src/ident.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use rustc_middle::bug;
55
use rustc_middle::ty;
66
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
77
use rustc_session::lint::BuiltinLintDiag;
8+
use rustc_session::parse::feature_err;
89
use rustc_span::def_id::LocalDefId;
910
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
11+
use rustc_span::sym;
1012
use rustc_span::symbol::{kw, Ident};
1113
use rustc_span::Span;
1214

@@ -598,7 +600,36 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
598600
result
599601
}
600602
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
601-
Some(binding) => Ok((*binding, Flags::empty())),
603+
Some(binding) => {
604+
match ident.name {
605+
sym::f16
606+
if !this.tcx.features().f16
607+
&& !ident.span.allows_unstable(sym::f16) =>
608+
{
609+
feature_err(
610+
this.tcx.sess,
611+
sym::f16,
612+
ident.span,
613+
"the type `f16` is unstable",
614+
)
615+
.emit();
616+
}
617+
sym::f128
618+
if !this.tcx.features().f128
619+
&& !ident.span.allows_unstable(sym::f128) =>
620+
{
621+
feature_err(
622+
this.tcx.sess,
623+
sym::f128,
624+
ident.span,
625+
"the type `f128` is unstable",
626+
)
627+
.emit();
628+
}
629+
_ => (),
630+
}
631+
Ok((*binding, Flags::empty()))
632+
}
602633
None => Err(Determinacy::Determined),
603634
},
604635
};

compiler/rustc_resolve/src/late.rs

+20
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
2727
use rustc_middle::{bug, span_bug};
2828
use rustc_session::config::{CrateType, ResolveDocLinks};
2929
use rustc_session::lint;
30+
use rustc_session::parse::feature_err;
3031
use rustc_span::source_map::{respan, Spanned};
3132
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3233
use rustc_span::{BytePos, Span, SyntaxContext};
@@ -4118,6 +4119,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
41184119
&& PrimTy::from_name(path[0].ident.name).is_some() =>
41194120
{
41204121
let prim = PrimTy::from_name(path[0].ident.name).unwrap();
4122+
let tcx = self.r.tcx();
4123+
4124+
let gate_err_sym_msg = match prim {
4125+
PrimTy::Float(FloatTy::F16) if !tcx.features().f16 => {
4126+
Some((sym::f16, "the type `f16` is unstable"))
4127+
}
4128+
PrimTy::Float(FloatTy::F128) if !tcx.features().f128 => {
4129+
Some((sym::f128, "the type `f128` is unstable"))
4130+
}
4131+
_ => None,
4132+
};
4133+
4134+
if let Some((sym, msg)) = gate_err_sym_msg {
4135+
let span = path[0].ident.span;
4136+
if !span.allows_unstable(sym) {
4137+
feature_err(tcx.sess, sym, span, msg).emit();
4138+
}
4139+
};
4140+
41214141
PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
41224142
}
41234143
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `f128`
2+
3+
The tracking issue for this feature is: [#116909]
4+
5+
[#116909]: https://github.com/rust-lang/rust/issues/116909
6+
7+
---
8+
9+
Enable the `f128` type for IEEE 128-bit floating numbers (quad precision).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `f16`
2+
3+
The tracking issue for this feature is: [#116909]
4+
5+
[#116909]: https://github.com/rust-lang/rust/issues/116909
6+
7+
---
8+
9+
Enable the `f16` type for IEEE 16-bit floating numbers (half precision).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![allow(unused)]
2+
3+
const A: f128 = 10.0; //~ ERROR the type `f128` is unstable
4+
5+
pub fn main() {
6+
let a: f128 = 100.0; //~ ERROR the type `f128` is unstable
7+
let b = 0.0f128; //~ ERROR the type `f128` is unstable
8+
foo(1.23);
9+
}
10+
11+
fn foo(a: f128) {} //~ ERROR the type `f128` is unstable
12+
13+
struct Bar {
14+
a: f128, //~ ERROR the type `f128` is unstable
15+
}

0 commit comments

Comments
 (0)