about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-16 02:02:00 +0000
committerbors <bors@rust-lang.org>2024-03-16 02:02:00 +0000
commitc03ea3dfd907e7dc6305ebf20c94f3a1f1d9fed7 (patch)
tree79407c0172239c031f2658cfd767776e5c7172ea
parent05a2be3def211255dc7640b006ac10f0f02baf5c (diff)
parent2098fec0809521ea8dd489f6cd5f09337a31764f (diff)
downloadrust-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
-rw-r--r--compiler/rustc_ast/src/util/literal.rs2
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs13
-rw-r--r--compiler/rustc_feature/src/unstable.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_lint/src/types.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs22
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs44
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs8
-rw-r--r--compiler/rustc_resolve/src/ident.rs32
-rw-r--r--compiler/rustc_resolve/src/late.rs20
-rw-r--r--src/doc/unstable-book/src/language-features/f128.md9
-rw-r--r--src/doc/unstable-book/src/language-features/f16.md9
-rw-r--r--tests/ui/feature-gates/feature-gate-f128.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-f128.stderr53
-rw-r--r--tests/ui/feature-gates/feature-gate-f16.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-f16.stderr53
-rw-r--r--tests/ui/parser/f16-f128.rs37
-rw-r--r--tests/ui/parser/f16-f128.stderr67
-rw-r--r--tests/ui/resolve/conflicting-primitive-names.rs30
-rw-r--r--tests/ui/resolve/primitive-f16-f128-shadowed.rs31
-rw-r--r--tests/ui/resolve/primitive-usage.rs42
21 files changed, 403 insertions, 119 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)) => {
diff --git a/src/doc/unstable-book/src/language-features/f128.md b/src/doc/unstable-book/src/language-features/f128.md
new file mode 100644
index 00000000000..0cc5f677230
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/f128.md
@@ -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).
diff --git a/src/doc/unstable-book/src/language-features/f16.md b/src/doc/unstable-book/src/language-features/f16.md
new file mode 100644
index 00000000000..efb07a5146d
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/f16.md
@@ -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).
diff --git a/tests/ui/feature-gates/feature-gate-f128.rs b/tests/ui/feature-gates/feature-gate-f128.rs
new file mode 100644
index 00000000000..7f60fb6afa0
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-f128.rs
@@ -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
+}
diff --git a/tests/ui/feature-gates/feature-gate-f128.stderr b/tests/ui/feature-gates/feature-gate-f128.stderr
new file mode 100644
index 00000000000..299375c9aed
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-f128.stderr
@@ -0,0 +1,53 @@
+error[E0658]: the type `f128` is unstable
+  --> $DIR/feature-gate-f128.rs:3:10
+   |
+LL | const A: f128 = 10.0;
+   |          ^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f128` is unstable
+  --> $DIR/feature-gate-f128.rs:6:12
+   |
+LL |     let a: f128 = 100.0;
+   |            ^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f128` is unstable
+  --> $DIR/feature-gate-f128.rs:11:11
+   |
+LL | fn foo(a: f128) {}
+   |           ^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f128` is unstable
+  --> $DIR/feature-gate-f128.rs:14:8
+   |
+LL |     a: f128,
+   |        ^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f128` is unstable
+  --> $DIR/feature-gate-f128.rs:7:13
+   |
+LL |     let b = 0.0f128;
+   |             ^^^^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f128)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-f16.rs b/tests/ui/feature-gates/feature-gate-f16.rs
new file mode 100644
index 00000000000..31d8f87f3ba
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-f16.rs
@@ -0,0 +1,15 @@
+#![allow(unused)]
+
+const A: f16 = 10.0; //~ ERROR the type `f16` is unstable
+
+pub fn main() {
+    let a: f16 = 100.0; //~ ERROR the type `f16` is unstable
+    let b = 0.0f16; //~ ERROR the type `f16` is unstable
+    foo(1.23);
+}
+
+fn foo(a: f16) {} //~ ERROR the type `f16` is unstable
+
+struct Bar {
+    a: f16, //~ ERROR the type `f16` is unstable
+}
diff --git a/tests/ui/feature-gates/feature-gate-f16.stderr b/tests/ui/feature-gates/feature-gate-f16.stderr
new file mode 100644
index 00000000000..e54b54a47bd
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-f16.stderr
@@ -0,0 +1,53 @@
+error[E0658]: the type `f16` is unstable
+  --> $DIR/feature-gate-f16.rs:3:10
+   |
+LL | const A: f16 = 10.0;
+   |          ^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f16)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f16` is unstable
+  --> $DIR/feature-gate-f16.rs:6:12
+   |
+LL |     let a: f16 = 100.0;
+   |            ^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f16)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f16` is unstable
+  --> $DIR/feature-gate-f16.rs:11:11
+   |
+LL | fn foo(a: f16) {}
+   |           ^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f16)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f16` is unstable
+  --> $DIR/feature-gate-f16.rs:14:8
+   |
+LL |     a: f16,
+   |        ^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f16)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: the type `f16` is unstable
+  --> $DIR/feature-gate-f16.rs:7:13
+   |
+LL |     let b = 0.0f16;
+   |             ^^^^^^
+   |
+   = note: see issue #116909 <https://github.com/rust-lang/rust/issues/116909> for more information
+   = help: add `#![feature(f16)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/f16-f128.rs b/tests/ui/parser/f16-f128.rs
deleted file mode 100644
index 4f31dccce3c..00000000000
--- a/tests/ui/parser/f16-f128.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Make sure we don't ICE while incrementally adding f16 and f128 support
-
-mod f16_checks {
-    const A: f16 = 10.0; //~ ERROR cannot find type `f16` in this scope
-
-    pub fn main() {
-        let a: f16 = 100.0; //~ ERROR cannot find type `f16` in this scope
-        let b = 0.0f16; //~ ERROR invalid width `16` for float literal
-
-        foo(1.23);
-    }
-
-    fn foo(a: f16) {} //~ ERROR cannot find type `f16` in this scope
-
-    struct Bar {
-        a: f16, //~ ERROR cannot find type `f16` in this scope
-    }
-}
-
-mod f128_checks {
-    const A: f128 = 10.0; //~ ERROR cannot find type `f128` in this scope
-
-    pub fn main() {
-        let a: f128 = 100.0; //~ ERROR cannot find type `f128` in this scope
-        let b = 0.0f128; //~ ERROR invalid width `128` for float literal
-
-        foo(1.23);
-    }
-
-    fn foo(a: f128) {} //~ ERROR cannot find type `f128` in this scope
-
-    struct Bar {
-        a: f128, //~ ERROR cannot find type `f128` in this scope
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/parser/f16-f128.stderr b/tests/ui/parser/f16-f128.stderr
deleted file mode 100644
index d3f2227acd7..00000000000
--- a/tests/ui/parser/f16-f128.stderr
+++ /dev/null
@@ -1,67 +0,0 @@
-error[E0412]: cannot find type `f16` in this scope
-  --> $DIR/f16-f128.rs:4:14
-   |
-LL |     const A: f16 = 10.0;
-   |              ^^^ help: a builtin type with a similar name exists: `i16`
-
-error[E0412]: cannot find type `f16` in this scope
-  --> $DIR/f16-f128.rs:7:16
-   |
-LL |         let a: f16 = 100.0;
-   |                ^^^ help: a builtin type with a similar name exists: `i16`
-
-error[E0412]: cannot find type `f16` in this scope
-  --> $DIR/f16-f128.rs:13:15
-   |
-LL |     fn foo(a: f16) {}
-   |               ^^^ help: a builtin type with a similar name exists: `i16`
-
-error[E0412]: cannot find type `f16` in this scope
-  --> $DIR/f16-f128.rs:16:12
-   |
-LL |         a: f16,
-   |            ^^^ help: a builtin type with a similar name exists: `i16`
-
-error[E0412]: cannot find type `f128` in this scope
-  --> $DIR/f16-f128.rs:21:14
-   |
-LL |     const A: f128 = 10.0;
-   |              ^^^^ help: a builtin type with a similar name exists: `i128`
-
-error[E0412]: cannot find type `f128` in this scope
-  --> $DIR/f16-f128.rs:24:16
-   |
-LL |         let a: f128 = 100.0;
-   |                ^^^^ help: a builtin type with a similar name exists: `i128`
-
-error[E0412]: cannot find type `f128` in this scope
-  --> $DIR/f16-f128.rs:30:15
-   |
-LL |     fn foo(a: f128) {}
-   |               ^^^^ help: a builtin type with a similar name exists: `i128`
-
-error[E0412]: cannot find type `f128` in this scope
-  --> $DIR/f16-f128.rs:33:12
-   |
-LL |         a: f128,
-   |            ^^^^ help: a builtin type with a similar name exists: `i128`
-
-error: invalid width `16` for float literal
-  --> $DIR/f16-f128.rs:8:17
-   |
-LL |         let b = 0.0f16;
-   |                 ^^^^^^
-   |
-   = help: valid widths are 32 and 64
-
-error: invalid width `128` for float literal
-  --> $DIR/f16-f128.rs:25:17
-   |
-LL |         let b = 0.0f128;
-   |                 ^^^^^^^
-   |
-   = help: valid widths are 32 and 64
-
-error: aborting due to 10 previous errors
-
-For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/resolve/conflicting-primitive-names.rs b/tests/ui/resolve/conflicting-primitive-names.rs
new file mode 100644
index 00000000000..79b6990681d
--- /dev/null
+++ b/tests/ui/resolve/conflicting-primitive-names.rs
@@ -0,0 +1,30 @@
+//@ check-pass
+#![allow(non_camel_case_types)]
+#![allow(unused)]
+
+// Ensure that primitives do not interfere with user types of similar names
+
+macro_rules! make_ty_mod {
+    ($modname:ident, $ty:tt) => {
+        mod $modname {
+            struct $ty {
+                a: i32,
+            }
+
+            fn assignment() {
+                let $ty = ();
+            }
+
+            fn access(a: $ty) -> i32 {
+                a.a
+            }
+        }
+    };
+}
+
+make_ty_mod!(check_f16, f16);
+make_ty_mod!(check_f32, f32);
+make_ty_mod!(check_f64, f64);
+make_ty_mod!(check_f128, f128);
+
+fn main() {}
diff --git a/tests/ui/resolve/primitive-f16-f128-shadowed.rs b/tests/ui/resolve/primitive-f16-f128-shadowed.rs
new file mode 100644
index 00000000000..ed3fb44b256
--- /dev/null
+++ b/tests/ui/resolve/primitive-f16-f128-shadowed.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: --crate-type=lib
+//@ check-pass
+
+// Verify that gates for the `f16` and `f128` features do not apply to user types
+
+mod binary16 {
+    #[allow(non_camel_case_types)]
+    pub struct f16(u16);
+}
+
+mod binary128 {
+    #[allow(non_camel_case_types)]
+    pub struct f128(u128);
+}
+
+pub use binary128::f128;
+pub use binary16::f16;
+
+mod private16 {
+    use crate::f16;
+
+    pub trait SealedHalf {}
+    impl SealedHalf for f16 {}
+}
+
+mod private128 {
+    use crate::f128;
+
+    pub trait SealedQuad {}
+    impl SealedQuad for f128 {}
+}
diff --git a/tests/ui/resolve/primitive-usage.rs b/tests/ui/resolve/primitive-usage.rs
new file mode 100644
index 00000000000..b00d18a4e1e
--- /dev/null
+++ b/tests/ui/resolve/primitive-usage.rs
@@ -0,0 +1,42 @@
+//@ run-pass
+#![allow(unused)]
+#![feature(f128)]
+#![feature(f16)]
+
+// Same as the feature gate tests but ensure we can use the types
+mod check_f128 {
+    const A: f128 = 10.0;
+
+    pub fn foo() {
+        let a: f128 = 100.0;
+        let b = 0.0f128;
+        bar(1.23);
+    }
+
+    fn bar(a: f128) {}
+
+    struct Bar {
+        a: f128,
+    }
+}
+
+mod check_f16 {
+    const A: f16 = 10.0;
+
+    pub fn foo() {
+        let a: f16 = 100.0;
+        let b = 0.0f16;
+        bar(1.23);
+    }
+
+    fn bar(a: f16) {}
+
+    struct Bar {
+        a: f16,
+    }
+}
+
+fn main() {
+    check_f128::foo();
+    check_f16::foo();
+}