Skip to content
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

f16 and f128 step 3: compiler support & feature gate #121926

Merged
merged 5 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/util/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,10 @@ fn filtered_float_lit(
Some(suffix) => LitKind::Float(
symbol,
ast::LitFloatType::Suffixed(match suffix {
sym::f16 => ast::FloatTy::F16,
sym::f32 => ast::FloatTy::F32,
sym::f64 => ast::FloatTy::F64,
sym::f128 => ast::FloatTy::F128,
_ => return Err(LitError::InvalidFloatSuffix(suffix)),
}),
),
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd};
use rustc_ast::{token, PatKind, RangeEnd};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::Session;
Expand Down Expand Up @@ -378,6 +378,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ExprKind::TryBlock(_) => {
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
}
ast::ExprKind::Lit(token::Lit { kind: token::LitKind::Float, suffix, .. }) => {
match suffix {
Some(sym::f16) => {
gate!(&self, f16, e.span, "the type `f16` is unstable")
}
Some(sym::f128) => {
gate!(&self, f128, e.span, "the type `f128` is unstable")
}
_ => (),
}
}
_ => {}
}
visit::walk_expr(self, e)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,10 @@ declare_features! (
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
/// Allows defining `extern type`s.
(unstable, extern_types, "1.23.0", Some(43467)),
/// Allow using 128-bit (quad precision) floating point numbers.
(unstable, f128, "CURRENT_RUSTC_VERSION", Some(116909)),
/// Allow using 16-bit (half precision) floating point numbers.
(unstable, f16, "CURRENT_RUSTC_VERSION", Some(116909)),
/// Allows the use of `#[ffi_const]` on foreign functions.
(unstable, ffi_const, "1.45.0", Some(58328)),
/// Allows the use of `#[ffi_pure]` on foreign functions.
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2444,7 +2444,7 @@ pub enum PrimTy {

impl PrimTy {
/// All of the primitive types
pub const ALL: [Self; 17] = [
pub const ALL: [Self; 19] = [
// any changes here should also be reflected in `PrimTy::from_name`
Self::Int(IntTy::I8),
Self::Int(IntTy::I16),
Expand All @@ -2458,9 +2458,10 @@ impl PrimTy {
Self::Uint(UintTy::U64),
Self::Uint(UintTy::U128),
Self::Uint(UintTy::Usize),
Self::Float(FloatTy::F16),
Self::Float(FloatTy::F32),
Self::Float(FloatTy::F64),
// FIXME(f16_f128): add these when enabled below
Self::Float(FloatTy::F128),
Self::Bool,
Self::Char,
Self::Str,
Expand Down Expand Up @@ -2508,12 +2509,10 @@ impl PrimTy {
sym::u64 => Self::Uint(UintTy::U64),
sym::u128 => Self::Uint(UintTy::U128),
sym::usize => Self::Uint(UintTy::Usize),
sym::f16 => Self::Float(FloatTy::F16),
sym::f32 => Self::Float(FloatTy::F32),
sym::f64 => Self::Float(FloatTy::F64),
// FIXME(f16_f128): enabling these will open the gates of f16 and f128 being
// understood by rustc.
// sym::f16 => Self::Float(FloatTy::F16),
// sym::f128 => Self::Float(FloatTy::F128),
sym::f128 => Self::Float(FloatTy::F128),
sym::bool => Self::Bool,
sym::char => Self::Char,
sym::str => Self::Str,
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,11 @@ fn lint_literal<'tcx>(
ty::Float(t) => {
let is_infinite = match lit.node {
ast::LitKind::Float(v, _) => match t {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
// FIXME(f16_f128): add this check once we have library support
ty::FloatTy::F16 => Ok(false),
ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
ty::FloatTy::F128 => unimplemented!("f16_f128"),
ty::FloatTy::F128 => Ok(false),
},
_ => bug!(),
};
Expand Down
22 changes: 21 additions & 1 deletion compiler/rustc_middle/src/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fmt;
use either::{Either, Left, Right};

use rustc_apfloat::{
ieee::{Double, Single},
ieee::{Double, Half, Quad, Single},
Float,
};
use rustc_macros::HashStable;
Expand Down Expand Up @@ -201,6 +201,11 @@ impl<Prov> Scalar<Prov> {
Self::from_int(i, cx.data_layout().pointer_size)
}

#[inline]
pub fn from_f16(f: Half) -> Self {
Scalar::Int(f.into())
}

#[inline]
pub fn from_f32(f: Single) -> Self {
Scalar::Int(f.into())
Expand All @@ -211,6 +216,11 @@ impl<Prov> Scalar<Prov> {
Scalar::Int(f.into())
}

#[inline]
pub fn from_f128(f: Quad) -> Self {
Scalar::Int(f.into())
}
RalfJung marked this conversation as resolved.
Show resolved Hide resolved

/// This is almost certainly not the method you want! You should dispatch on the type
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
///
Expand Down Expand Up @@ -422,6 +432,11 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
}

#[inline]
pub fn to_f16(self) -> InterpResult<'tcx, Half> {
self.to_float()
}

#[inline]
pub fn to_f32(self) -> InterpResult<'tcx, Single> {
self.to_float()
Expand All @@ -431,4 +446,9 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
pub fn to_f64(self) -> InterpResult<'tcx, Double> {
self.to_float()
}

#[inline]
pub fn to_f128(self) -> InterpResult<'tcx, Quad> {
self.to_float()
}
}
44 changes: 43 additions & 1 deletion compiler/rustc_middle/src/ty/consts/int.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::Float;
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
Expand Down Expand Up @@ -369,6 +369,11 @@ impl ScalarInt {
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
}

#[inline]
pub fn try_to_f16(self) -> Result<Half, Size> {
self.try_to_float()
}

#[inline]
pub fn try_to_f32(self) -> Result<Single, Size> {
self.try_to_float()
Expand All @@ -378,6 +383,11 @@ impl ScalarInt {
pub fn try_to_f64(self) -> Result<Double, Size> {
self.try_to_float()
}

#[inline]
pub fn try_to_f128(self) -> Result<Quad, Size> {
self.try_to_float()
}
}

macro_rules! from {
Expand Down Expand Up @@ -450,6 +460,22 @@ impl TryFrom<ScalarInt> for char {
}
}

impl From<Half> for ScalarInt {
#[inline]
fn from(f: Half) -> Self {
// We trust apfloat to give us properly truncated data.
Self { data: f.to_bits(), size: NonZero::new((Half::BITS / 8) as u8).unwrap() }
}
}

impl TryFrom<ScalarInt> for Half {
type Error = Size;
#[inline]
fn try_from(int: ScalarInt) -> Result<Self, Size> {
int.to_bits(Size::from_bytes(2)).map(Self::from_bits)
}
}

impl From<Single> for ScalarInt {
#[inline]
fn from(f: Single) -> Self {
Expand Down Expand Up @@ -482,6 +508,22 @@ impl TryFrom<ScalarInt> for Double {
}
}

impl From<Quad> for ScalarInt {
#[inline]
fn from(f: Quad) -> Self {
// We trust apfloat to give us properly truncated data.
Self { data: f.to_bits(), size: NonZero::new((Quad::BITS / 8) as u8).unwrap() }
}
}

impl TryFrom<ScalarInt> for Quad {
type Error = Size;
#[inline]
fn try_from(int: ScalarInt) -> Result<Self, Size> {
int.to_bits(Size::from_bytes(16)).map(Self::from_bits)
}
}

impl fmt::Debug for ScalarInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Dispatch to LowerHex below.
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::scope::DropKind;
use itertools::Itertools;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::Float;
use rustc_ast::attr;
use rustc_data_structures::fx::FxHashMap;
Expand Down Expand Up @@ -1053,7 +1053,8 @@ pub(crate) fn parse_float_into_scalar(
) -> Option<Scalar> {
let num = num.as_str();
match float_ty {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
// FIXME(f16_f128): When available, compare to the library parser as with `f32` and `f64`
ty::FloatTy::F16 => num.parse::<Half>().ok().map(Scalar::from_f16),
ty::FloatTy::F32 => {
let Ok(rust_f) = num.parse::<f32>() else { return None };
let mut f = num
Expand Down Expand Up @@ -1100,7 +1101,8 @@ pub(crate) fn parse_float_into_scalar(

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

Expand Down
32 changes: 31 additions & 1 deletion compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use rustc_middle::bug;
use rustc_middle::ty;
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::feature_err;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
use rustc_span::sym;
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;

Expand Down Expand Up @@ -598,7 +600,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
result
}
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
Some(binding) => Ok((*binding, Flags::empty())),
Some(binding) => {
if matches!(ident.name, sym::f16)
&& !this.tcx.features().f16
&& !ident.span.allows_unstable(sym::f16)
&& finalize.is_some()
{
feature_err(
this.tcx.sess,
sym::f16,
ident.span,
"the type `f16` is unstable",
)
.emit();
}
if matches!(ident.name, sym::f128)
&& !this.tcx.features().f128
&& !ident.span.allows_unstable(sym::f128)
&& finalize.is_some()
{
feature_err(
this.tcx.sess,
sym::f128,
ident.span,
"the type `f128` is unstable",
)
.emit();
}
Ok((*binding, Flags::empty()))
}
None => Err(Determinacy::Determined),
},
};
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext};
Expand Down Expand Up @@ -4129,6 +4130,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
&& PrimTy::from_name(path[0].ident.name).is_some() =>
{
let prim = PrimTy::from_name(path[0].ident.name).unwrap();
let tcx = self.r.tcx();

let gate_err_sym_msg = match prim {
PrimTy::Float(FloatTy::F16) if !tcx.features().f16 => {
Some((sym::f16, "the type `f16` is unstable"))
}
PrimTy::Float(FloatTy::F128) if !tcx.features().f128 => {
Some((sym::f128, "the type `f128` is unstable"))
}
_ => None,
};

if let Some((sym, msg)) = gate_err_sym_msg {
let span = path[0].ident.span;
if !span.allows_unstable(sym) {
feature_err(tcx.sess, sym, span, msg).emit();
}
};

PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
}
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
Expand Down
9 changes: 9 additions & 0 deletions src/doc/unstable-book/src/language-features/f128.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# `f128`

The tracking issue for this feature is: [#116909]

[#116909]: https://github.com/rust-lang/rust/issues/116909

---

Enable the `f128` type for IEEE 128-bit floating numbers (quad precision).
9 changes: 9 additions & 0 deletions src/doc/unstable-book/src/language-features/f16.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# `f16`

The tracking issue for this feature is: [#116909]

[#116909]: https://github.com/rust-lang/rust/issues/116909

---

Enable the `f16` type for IEEE 16-bit floating numbers (half precision).
15 changes: 15 additions & 0 deletions tests/ui/feature-gates/feature-gate-f128.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#![allow(unused)]

const A: f128 = 10.0; //~ ERROR the type `f128` is unstable

pub fn main() {
let a: f128 = 100.0; //~ ERROR the type `f128` is unstable
let b = 0.0f128; //~ ERROR the type `f128` is unstable
foo(1.23);
}

fn foo(a: f128) {} //~ ERROR the type `f128` is unstable

struct Bar {
a: f128, //~ ERROR the type `f128` is unstable
}
Loading
Loading