Skip to content

Commit

Permalink
Rollup merge of rust-lang#121926 - tgross35:f16-f128-step3-feature-ga…
Browse files Browse the repository at this point in the history
…te, 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
  • Loading branch information
matthiaskrgr authored Mar 6, 2024
2 parents 5cef608 + b8f45a3 commit a128563
Show file tree
Hide file tree
Showing 20 changed files with 373 additions and 119 deletions.
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 @@ -375,6 +375,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 @@ -461,6 +461,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())
}

/// 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, IntoDiagnosticArg};
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
33 changes: 32 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,36 @@ 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) => {
match ident.name {
sym::f16
if !this.tcx.features().f16
&& !ident.span.allows_unstable(sym::f16) =>
{
feature_err(
this.tcx.sess,
sym::f16,
ident.span,
"the type `f16` is unstable",
)
.emit();
}
sym::f128
if !this.tcx.features().f128
&& !ident.span.allows_unstable(sym::f128) =>
{
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 @@ -4118,6 +4119,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

0 comments on commit a128563

Please sign in to comment.