diff options
| author | bors <bors@rust-lang.org> | 2024-03-16 02:02:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-16 02:02:00 +0000 |
| commit | c03ea3dfd907e7dc6305ebf20c94f3a1f1d9fed7 (patch) | |
| tree | 79407c0172239c031f2658cfd767776e5c7172ea /compiler | |
| parent | 05a2be3def211255dc7640b006ac10f0f02baf5c (diff) | |
| parent | 2098fec0809521ea8dd489f6cd5f09337a31764f (diff) | |
| download | rust-c03ea3dfd907e7dc6305ebf20c94f3a1f1d9fed7.tar.gz rust-c03ea3dfd907e7dc6305ebf20c94f3a1f1d9fed7.zip | |
Auto merge of #121926 - tgross35:f16-f128-step3-feature-gate, r=compiler-errors,petrochenkov
`f16` and `f128` step 3: compiler support & feature gate Continuation of https://github.com/rust-lang/rust/pull/121841, another portion of https://github.com/rust-lang/rust/pull/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: https://github.com/rust-lang/rust/issues/116909 r? `@compiler-errors` cc `@Nilstrieb` `@rustbot` label +F-f16_and_f128
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/util/literal.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/unstable.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/types.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/value.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/consts/int.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 20 |
10 files changed, 146 insertions, 15 deletions
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 5ed2762b726..a17c7708e4a 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -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)), }), ), diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 2e14238f950..4db8ffd3e54 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -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; @@ -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) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 52421fce867..c3f216936df 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -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. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bb468b2e056..e21d31238e0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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), @@ -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, @@ -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, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 5d36a8b3d0e..51fe08d4af1 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -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!(), }; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e937c17c8ac..24d4a79c7d7 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -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; @@ -202,6 +202,11 @@ impl<Prov> Scalar<Prov> { } #[inline] + pub fn from_f16(f: Half) -> Self { + Scalar::Int(f.into()) + } + + #[inline] pub fn from_f32(f: Single) -> Self { Scalar::Int(f.into()) } @@ -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. /// @@ -423,6 +433,11 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> { } #[inline] + pub fn to_f16(self) -> InterpResult<'tcx, Half> { + self.to_float() + } + + #[inline] pub fn to_f32(self) -> InterpResult<'tcx, Single> { self.to_float() } @@ -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() + } } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index a70e01645f4..71d7dfd8b01 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -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}; @@ -370,6 +370,11 @@ impl ScalarInt { } #[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() } @@ -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 { @@ -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 { @@ -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. diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 2fe5d3fb5e0..411119b521b 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -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; @@ -1060,7 +1060,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 @@ -1107,7 +1108,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), } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 6518d9735ae..b24ed573ff9 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -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; @@ -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), }, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c9b5c659f0f..837c069b599 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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}; @@ -4138,6 +4139,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)) => { |
