mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Add f16
and f128
support
This commit is contained in:
parent
da27b89ca5
commit
d5db933f9d
28 changed files with 384 additions and 73 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -167,9 +167,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
|||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.97.0"
|
||||
version = "0.98.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92a0aedc4ac2adc5c0b7dc9ec38c5c816284ad28da6d4ecd01873b9683f54972"
|
||||
checksum = "9426c8fd0fe61c3da880b801d3b510524df17843a8f9ec1f5b9cec24fb7412df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -179,9 +179,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.97.0"
|
||||
version = "0.98.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db18493569b190f7266a04901e520fc3a5c00564475154287906f8a27302c119"
|
||||
checksum = "d5f2eb1cd6054da221bd1ac0197fb2fe5e2caf3dcb93619398fc1433f8f09093"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"chalk-derive",
|
||||
|
@ -189,9 +189,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-recursive"
|
||||
version = "0.97.0"
|
||||
version = "0.98.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae4ba8ce5bd2e1b59f1f79495bc8704db09a8285e51cc5ddf01d9baee1bf447d"
|
||||
checksum = "129dc03458f71cfb9c3cd621c9c68166a94e87b85b16ccd29af015d7ff9a1c61"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
|
@ -202,9 +202,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.97.0"
|
||||
version = "0.98.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ec1b3b7f7b1ec38f099ef39c2bc3ea29335be1b8316d114baff46d96d131e9"
|
||||
checksum = "d7e8a8c1e928f98cdf227b868416ef21dcd8cc3c61b347576d783713444d41c8"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
|
@ -546,6 +546,7 @@ dependencies = [
|
|||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_parse_format",
|
||||
"rustc-hash",
|
||||
"rustc_apfloat",
|
||||
"smallvec",
|
||||
"span",
|
||||
"stdx",
|
||||
|
@ -613,6 +614,7 @@ dependencies = [
|
|||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_pattern_analysis",
|
||||
"rustc-hash",
|
||||
"rustc_apfloat",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"span",
|
||||
|
@ -658,6 +660,7 @@ dependencies = [
|
|||
"profile",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark-to-cmark",
|
||||
"rustc_apfloat",
|
||||
"smallvec",
|
||||
"span",
|
||||
"stdx",
|
||||
|
@ -1939,6 +1942,7 @@ dependencies = [
|
|||
"rayon",
|
||||
"rowan",
|
||||
"rustc-hash",
|
||||
"rustc_apfloat",
|
||||
"smol_str",
|
||||
"stdx",
|
||||
"test-utils",
|
||||
|
|
|
@ -104,10 +104,10 @@ arrayvec = "0.7.4"
|
|||
bitflags = "2.4.1"
|
||||
cargo_metadata = "0.18.1"
|
||||
camino = "1.1.6"
|
||||
chalk-solve = { version = "0.97.0", default-features = false }
|
||||
chalk-ir = "0.97.0"
|
||||
chalk-recursive = { version = "0.97.0", default-features = false }
|
||||
chalk-derive = "0.97.0"
|
||||
chalk-solve = { version = "0.98.0", default-features = false }
|
||||
chalk-ir = "0.98.0"
|
||||
chalk-recursive = { version = "0.98.0", default-features = false }
|
||||
chalk-derive = "0.98.0"
|
||||
crossbeam-channel = "0.5.8"
|
||||
dissimilar = "1.0.7"
|
||||
dot = "0.1.4"
|
||||
|
|
|
@ -28,6 +28,7 @@ tracing.workspace = true
|
|||
smallvec.workspace = true
|
||||
hashbrown.workspace = true
|
||||
triomphe.workspace = true
|
||||
rustc_apfloat = "0.2.0"
|
||||
|
||||
ra-ap-rustc_parse_format.workspace = true
|
||||
ra-ap-rustc_abi.workspace = true
|
||||
|
|
|
@ -30,8 +30,10 @@ pub enum BuiltinUint {
|
|||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum BuiltinFloat {
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F128,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -65,8 +67,10 @@ impl BuiltinType {
|
|||
(name![u64], BuiltinType::Uint(BuiltinUint::U64)),
|
||||
(name![u128], BuiltinType::Uint(BuiltinUint::U128)),
|
||||
|
||||
(name![f16], BuiltinType::Float(BuiltinFloat::F16)),
|
||||
(name![f32], BuiltinType::Float(BuiltinFloat::F32)),
|
||||
(name![f64], BuiltinType::Float(BuiltinFloat::F64)),
|
||||
(name![f128], BuiltinType::Float(BuiltinFloat::F128)),
|
||||
];
|
||||
|
||||
pub fn by_name(name: &Name) -> Option<Self> {
|
||||
|
@ -97,8 +101,10 @@ impl AsName for BuiltinType {
|
|||
BuiltinUint::U128 => name![u128],
|
||||
},
|
||||
BuiltinType::Float(it) => match it {
|
||||
BuiltinFloat::F16 => name![f16],
|
||||
BuiltinFloat::F32 => name![f32],
|
||||
BuiltinFloat::F64 => name![f64],
|
||||
BuiltinFloat::F128 => name![f128],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -155,8 +161,10 @@ impl BuiltinUint {
|
|||
impl BuiltinFloat {
|
||||
pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> {
|
||||
let res = match suffix {
|
||||
"f16" => BuiltinFloat::F16,
|
||||
"f32" => BuiltinFloat::F32,
|
||||
"f64" => BuiltinFloat::F64,
|
||||
"f128" => BuiltinFloat::F128,
|
||||
_ => return None,
|
||||
};
|
||||
Some(res)
|
||||
|
@ -192,8 +200,10 @@ impl fmt::Display for BuiltinUint {
|
|||
impl fmt::Display for BuiltinFloat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
BuiltinFloat::F16 => "f16",
|
||||
BuiltinFloat::F32 => "f32",
|
||||
BuiltinFloat::F64 => "f64",
|
||||
BuiltinFloat::F128 => "f128",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ use std::fmt;
|
|||
use hir_expand::name::Name;
|
||||
use intern::Interned;
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use rustc_apfloat::ieee::{Half as f16, Quad as f128};
|
||||
use smallvec::SmallVec;
|
||||
use syntax::ast;
|
||||
|
||||
|
@ -62,11 +63,16 @@ pub type LabelId = Idx<Label>;
|
|||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct FloatTypeWrapper(Box<str>);
|
||||
|
||||
// FIXME(#17451): Use builtin types once stabilised.
|
||||
impl FloatTypeWrapper {
|
||||
pub fn new(value: String) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
|
||||
pub fn to_f128(&self) -> f128 {
|
||||
self.0.parse().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn to_f64(&self) -> f64 {
|
||||
self.0.parse().unwrap_or_default()
|
||||
}
|
||||
|
@ -74,6 +80,10 @@ impl FloatTypeWrapper {
|
|||
pub fn to_f32(&self) -> f32 {
|
||||
self.0.parse().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn to_f16(&self) -> f16 {
|
||||
self.0.parse().unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FloatTypeWrapper {
|
||||
|
@ -91,7 +101,7 @@ pub enum Literal {
|
|||
Bool(bool),
|
||||
Int(i128, Option<BuiltinInt>),
|
||||
Uint(u128, Option<BuiltinUint>),
|
||||
// Here we are using a wrapper around float because f32 and f64 do not implement Eq, so they
|
||||
// Here we are using a wrapper around float because float primitives do not implement Eq, so they
|
||||
// could not be used directly here, to understand how the wrapper works go to definition of
|
||||
// FloatTypeWrapper
|
||||
Float(FloatTypeWrapper, Option<BuiltinFloat>),
|
||||
|
|
|
@ -36,6 +36,7 @@ macro_rules! m {
|
|||
let _ = 'c';
|
||||
let _ = 1000;
|
||||
let _ = 12E+99_f64;
|
||||
let _ = 45E+1234_f128;
|
||||
let _ = "rust1";
|
||||
let _ = -92;
|
||||
}
|
||||
|
@ -50,6 +51,7 @@ macro_rules! m {
|
|||
let _ = 'c';
|
||||
let _ = 1000;
|
||||
let _ = 12E+99_f64;
|
||||
let _ = 45E+1234_f128;
|
||||
let _ = "rust1";
|
||||
let _ = -92;
|
||||
}
|
||||
|
@ -58,6 +60,7 @@ fn f() {
|
|||
let _ = 'c';
|
||||
let _ = 1000;
|
||||
let _ = 12E+99_f64;
|
||||
let _ = 45E+1234_f128;
|
||||
let _ = "rust1";
|
||||
let _ = -92;
|
||||
}
|
||||
|
|
|
@ -275,8 +275,10 @@ pub mod known {
|
|||
u32,
|
||||
u64,
|
||||
u128,
|
||||
f16,
|
||||
f32,
|
||||
f64,
|
||||
f128,
|
||||
bool,
|
||||
char,
|
||||
str,
|
||||
|
|
|
@ -33,6 +33,7 @@ triomphe.workspace = true
|
|||
nohash-hasher.workspace = true
|
||||
typed-arena = "2.0.1"
|
||||
indexmap.workspace = true
|
||||
rustc_apfloat = "0.2.0"
|
||||
|
||||
ra-ap-rustc_abi.workspace = true
|
||||
ra-ap-rustc_index.workspace = true
|
||||
|
|
|
@ -119,8 +119,10 @@ impl TyExt for Ty {
|
|||
TyKind::Scalar(Scalar::Bool) => Some(BuiltinType::Bool),
|
||||
TyKind::Scalar(Scalar::Char) => Some(BuiltinType::Char),
|
||||
TyKind::Scalar(Scalar::Float(fty)) => Some(BuiltinType::Float(match fty {
|
||||
FloatTy::F128 => BuiltinFloat::F128,
|
||||
FloatTy::F64 => BuiltinFloat::F64,
|
||||
FloatTy::F32 => BuiltinFloat::F32,
|
||||
FloatTy::F16 => BuiltinFloat::F16,
|
||||
})),
|
||||
TyKind::Scalar(Scalar::Int(ity)) => Some(BuiltinType::Int(match ity {
|
||||
IntTy::Isize => BuiltinInt::Isize,
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use base_db::FileId;
|
||||
use chalk_ir::Substitution;
|
||||
use hir_def::db::DefDatabase;
|
||||
use rustc_apfloat::{
|
||||
ieee::{Half as f16, Quad as f128},
|
||||
Float,
|
||||
};
|
||||
use test_fixture::WithFixture;
|
||||
use test_utils::skip_slow_tests;
|
||||
|
||||
|
@ -140,6 +144,14 @@ fn bit_op() {
|
|||
|
||||
#[test]
|
||||
fn floating_point() {
|
||||
check_number(
|
||||
r#"const GOAL: f128 = 2.0 + 3.0 * 5.5 - 8.;"#,
|
||||
"10.5".parse::<f128>().unwrap().to_bits() as i128,
|
||||
);
|
||||
check_number(
|
||||
r#"const GOAL: f128 = -90.0 + 36.0;"#,
|
||||
"-54.0".parse::<f128>().unwrap().to_bits() as i128,
|
||||
);
|
||||
check_number(
|
||||
r#"const GOAL: f64 = 2.0 + 3.0 * 5.5 - 8.;"#,
|
||||
i128::from_le_bytes(pad16(&f64::to_le_bytes(10.5), true)),
|
||||
|
@ -152,6 +164,20 @@ fn floating_point() {
|
|||
r#"const GOAL: f32 = -90.0 + 36.0;"#,
|
||||
i128::from_le_bytes(pad16(&f32::to_le_bytes(-54.0), true)),
|
||||
);
|
||||
check_number(
|
||||
r#"const GOAL: f16 = 2.0 + 3.0 * 5.5 - 8.;"#,
|
||||
i128::from_le_bytes(pad16(
|
||||
&u16::try_from("10.5".parse::<f16>().unwrap().to_bits()).unwrap().to_le_bytes(),
|
||||
true,
|
||||
)),
|
||||
);
|
||||
check_number(
|
||||
r#"const GOAL: f16 = -90.0 + 36.0;"#,
|
||||
i128::from_le_bytes(pad16(
|
||||
&u16::try_from("-54.0".parse::<f16>().unwrap().to_bits()).unwrap().to_le_bytes(),
|
||||
true,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -411,6 +411,7 @@ fn likely() {
|
|||
|
||||
#[test]
|
||||
fn floating_point() {
|
||||
// FIXME(#17451): Add `f16` and `f128` tests once intrinsics are added.
|
||||
check_number(
|
||||
r#"
|
||||
extern "rust-intrinsic" {
|
||||
|
|
|
@ -28,6 +28,10 @@ use hir_expand::name::Name;
|
|||
use intern::{Internable, Interned};
|
||||
use itertools::Itertools;
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_apfloat::{
|
||||
ieee::{Half as f16, Quad as f128},
|
||||
Float,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use stdx::{never, IsNoneOr};
|
||||
use triomphe::Arc;
|
||||
|
@ -545,6 +549,17 @@ fn render_const_scalar(
|
|||
write!(f, "{it}")
|
||||
}
|
||||
Scalar::Float(fl) => match fl {
|
||||
chalk_ir::FloatTy::F16 => {
|
||||
// FIXME(#17451): Replace with builtins once they are stabilised.
|
||||
let it = f16::from_bits(u16::from_le_bytes(b.try_into().unwrap()).into());
|
||||
let s = it.to_string();
|
||||
if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
|
||||
// Match Rust debug formatting
|
||||
write!(f, "{s}.0")
|
||||
} else {
|
||||
write!(f, "{s}")
|
||||
}
|
||||
}
|
||||
chalk_ir::FloatTy::F32 => {
|
||||
let it = f32::from_le_bytes(b.try_into().unwrap());
|
||||
write!(f, "{it:?}")
|
||||
|
@ -553,6 +568,17 @@ fn render_const_scalar(
|
|||
let it = f64::from_le_bytes(b.try_into().unwrap());
|
||||
write!(f, "{it:?}")
|
||||
}
|
||||
chalk_ir::FloatTy::F128 => {
|
||||
// FIXME(#17451): Replace with builtins once they are stabilised.
|
||||
let it = f128::from_bits(u128::from_le_bytes(b.try_into().unwrap()));
|
||||
let s = it.to_string();
|
||||
if s.strip_prefix('-').unwrap_or(&s).chars().all(|c| c.is_ascii_digit()) {
|
||||
// Match Rust debug formatting
|
||||
write!(f, "{s}.0")
|
||||
} else {
|
||||
write!(f, "{s}")
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
TyKind::Ref(_, _, t) => match t.kind(Interner) {
|
||||
|
|
|
@ -265,8 +265,10 @@ pub fn layout_of_ty_query(
|
|||
chalk_ir::Scalar::Float(f) => scalar(
|
||||
dl,
|
||||
Primitive::Float(match f {
|
||||
FloatTy::F16 => Float::F16,
|
||||
FloatTy::F32 => Float::F32,
|
||||
FloatTy::F64 => Float::F64,
|
||||
FloatTy::F128 => Float::F128,
|
||||
}),
|
||||
),
|
||||
},
|
||||
|
|
|
@ -426,6 +426,7 @@ fn enums() {
|
|||
|
||||
#[test]
|
||||
fn primitives() {
|
||||
// FIXME(#17451): Add `f16` and `f128` once they are stabilised.
|
||||
size_and_align! {
|
||||
struct Goal(i32, i128, isize, usize, f32, f64, bool, char);
|
||||
}
|
||||
|
|
|
@ -127,9 +127,11 @@ pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
|
|||
TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
|
||||
];
|
||||
|
||||
pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
|
||||
pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 4] = [
|
||||
TyFingerprint::Scalar(Scalar::Float(FloatTy::F16)),
|
||||
TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
|
||||
TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
|
||||
TyFingerprint::Scalar(Scalar::Float(FloatTy::F128)),
|
||||
];
|
||||
|
||||
type TraitFpMap = FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Box<[ImplId]>>>;
|
||||
|
|
|
@ -18,6 +18,10 @@ use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile};
|
|||
use intern::Interned;
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_abi::TargetDataLayout;
|
||||
use rustc_apfloat::{
|
||||
ieee::{Half as f16, Quad as f128},
|
||||
Float,
|
||||
};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use stdx::never;
|
||||
use syntax::{SyntaxNodePtr, TextRange};
|
||||
|
@ -55,6 +59,13 @@ macro_rules! from_bytes {
|
|||
Err(_) => return Err(MirEvalError::InternalError(stringify!(mismatched size in constructing $ty).into())),
|
||||
}))
|
||||
};
|
||||
($apfloat:tt, $bits:tt, $value:expr) => {
|
||||
// FIXME(#17451): Switch to builtin `f16` and `f128` once they are stable.
|
||||
$apfloat::from_bits($bits::from_le_bytes(match ($value).try_into() {
|
||||
Ok(it) => it,
|
||||
Err(_) => return Err(MirEvalError::InternalError(stringify!(mismatched size in constructing $apfloat).into())),
|
||||
}).into())
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! not_supported {
|
||||
|
@ -1110,6 +1121,10 @@ impl Evaluator<'_> {
|
|||
}
|
||||
if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
|
||||
match f {
|
||||
chalk_ir::FloatTy::F16 => {
|
||||
let c = -from_bytes!(f16, u16, c);
|
||||
Owned(u16::try_from(c.to_bits()).unwrap().to_le_bytes().into())
|
||||
}
|
||||
chalk_ir::FloatTy::F32 => {
|
||||
let c = -from_bytes!(f32, c);
|
||||
Owned(c.to_le_bytes().into())
|
||||
|
@ -1118,6 +1133,10 @@ impl Evaluator<'_> {
|
|||
let c = -from_bytes!(f64, c);
|
||||
Owned(c.to_le_bytes().into())
|
||||
}
|
||||
chalk_ir::FloatTy::F128 => {
|
||||
let c = -from_bytes!(f128, u128, c);
|
||||
Owned(c.to_bits().to_le_bytes().into())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut c = c.to_vec();
|
||||
|
@ -1169,6 +1188,39 @@ impl Evaluator<'_> {
|
|||
}
|
||||
if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
|
||||
match f {
|
||||
chalk_ir::FloatTy::F16 => {
|
||||
let l = from_bytes!(f16, u16, lc);
|
||||
let r = from_bytes!(f16, u16, rc);
|
||||
match op {
|
||||
BinOp::Ge
|
||||
| BinOp::Gt
|
||||
| BinOp::Le
|
||||
| BinOp::Lt
|
||||
| BinOp::Eq
|
||||
| BinOp::Ne => {
|
||||
let r = op.run_compare(l, r) as u8;
|
||||
Owned(vec![r])
|
||||
}
|
||||
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
|
||||
let r = match op {
|
||||
BinOp::Add => l + r,
|
||||
BinOp::Sub => l - r,
|
||||
BinOp::Mul => l * r,
|
||||
BinOp::Div => l / r,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Owned(
|
||||
u16::try_from(r.value.to_bits())
|
||||
.unwrap()
|
||||
.to_le_bytes()
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
it => not_supported!(
|
||||
"invalid binop {it:?} on floating point operators"
|
||||
),
|
||||
}
|
||||
}
|
||||
chalk_ir::FloatTy::F32 => {
|
||||
let l = from_bytes!(f32, lc);
|
||||
let r = from_bytes!(f32, rc);
|
||||
|
@ -1225,6 +1277,34 @@ impl Evaluator<'_> {
|
|||
),
|
||||
}
|
||||
}
|
||||
chalk_ir::FloatTy::F128 => {
|
||||
let l = from_bytes!(f128, u128, lc);
|
||||
let r = from_bytes!(f128, u128, rc);
|
||||
match op {
|
||||
BinOp::Ge
|
||||
| BinOp::Gt
|
||||
| BinOp::Le
|
||||
| BinOp::Lt
|
||||
| BinOp::Eq
|
||||
| BinOp::Ne => {
|
||||
let r = op.run_compare(l, r) as u8;
|
||||
Owned(vec![r])
|
||||
}
|
||||
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
|
||||
let r = match op {
|
||||
BinOp::Add => l + r,
|
||||
BinOp::Sub => l - r,
|
||||
BinOp::Mul => l * r,
|
||||
BinOp::Div => l / r,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Owned(r.value.to_bits().to_le_bytes().into())
|
||||
}
|
||||
it => not_supported!(
|
||||
"invalid binop {it:?} on floating point operators"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));
|
||||
|
|
|
@ -627,6 +627,7 @@ impl Evaluator<'_> {
|
|||
if let Some(name) = name.strip_prefix("atomic_") {
|
||||
return self.exec_atomic_intrinsic(name, args, generic_args, destination, locals, span);
|
||||
}
|
||||
// FIXME(#17451): Add `f16` and `f128` intrinsics.
|
||||
if let Some(name) = name.strip_suffix("f64") {
|
||||
let result = match name {
|
||||
"sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs"
|
||||
|
|
|
@ -19,6 +19,7 @@ use hir_def::{
|
|||
};
|
||||
use hir_expand::name::Name;
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_hash::FxHashMap;
|
||||
use syntax::TextRange;
|
||||
use triomphe::Arc;
|
||||
|
@ -1432,10 +1433,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
hir_def::hir::Literal::Int(it, _) => Box::from(&it.to_le_bytes()[0..size()?]),
|
||||
hir_def::hir::Literal::Uint(it, _) => Box::from(&it.to_le_bytes()[0..size()?]),
|
||||
hir_def::hir::Literal::Float(f, _) => match size()? {
|
||||
16 => Box::new(f.to_f128().to_bits().to_le_bytes()),
|
||||
8 => Box::new(f.to_f64().to_le_bytes()),
|
||||
4 => Box::new(f.to_f32().to_le_bytes()),
|
||||
2 => Box::new(u16::try_from(f.to_f16().to_bits()).unwrap().to_le_bytes()),
|
||||
_ => {
|
||||
return Err(MirLowerError::TypeError("float with size other than 4 or 8 bytes"))
|
||||
return Err(MirLowerError::TypeError(
|
||||
"float with size other than 2, 4, 8 or 16 bytes",
|
||||
))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -27,8 +27,10 @@ pub fn uint_ty_to_string(ty: UintTy) -> &'static str {
|
|||
|
||||
pub fn float_ty_to_string(ty: FloatTy) -> &'static str {
|
||||
match ty {
|
||||
FloatTy::F16 => "f16",
|
||||
FloatTy::F32 => "f32",
|
||||
FloatTy::F64 => "f64",
|
||||
FloatTy::F128 => "f128",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +58,9 @@ pub(super) fn uint_ty_from_builtin(t: BuiltinUint) -> UintTy {
|
|||
|
||||
pub(super) fn float_ty_from_builtin(t: BuiltinFloat) -> FloatTy {
|
||||
match t {
|
||||
BuiltinFloat::F16 => FloatTy::F16,
|
||||
BuiltinFloat::F32 => FloatTy::F32,
|
||||
BuiltinFloat::F64 => FloatTy::F64,
|
||||
BuiltinFloat::F128 => FloatTy::F128,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,8 +111,10 @@ fn infer_literal_pattern() {
|
|||
if let "foo" = any() {}
|
||||
if let 1 = any() {}
|
||||
if let 1u32 = any() {}
|
||||
if let 1f16 = any() {}
|
||||
if let 1f32 = any() {}
|
||||
if let 1.0 = any() {}
|
||||
if let 1f128 = any() {}
|
||||
if let true = any() {}
|
||||
}
|
||||
"#,
|
||||
|
@ -121,7 +123,7 @@ fn infer_literal_pattern() {
|
|||
19..26 'loop {}': !
|
||||
24..26 '{}': ()
|
||||
37..38 'x': &'? i32
|
||||
46..208 '{ ...) {} }': ()
|
||||
46..263 '{ ...) {} }': ()
|
||||
52..75 'if let...y() {}': ()
|
||||
55..72 'let "f... any()': bool
|
||||
59..64 '"foo"': &'static str
|
||||
|
@ -145,25 +147,39 @@ fn infer_literal_pattern() {
|
|||
124..126 '{}': ()
|
||||
131..153 'if let...y() {}': ()
|
||||
134..150 'let 1f... any()': bool
|
||||
138..142 '1f32': f32
|
||||
138..142 '1f32': f32
|
||||
145..148 'any': fn any<f32>() -> f32
|
||||
145..150 'any()': f32
|
||||
138..142 '1f16': f16
|
||||
138..142 '1f16': f16
|
||||
145..148 'any': fn any<f16>() -> f16
|
||||
145..150 'any()': f16
|
||||
151..153 '{}': ()
|
||||
158..179 'if let...y() {}': ()
|
||||
161..176 'let 1.0 = any()': bool
|
||||
165..168 '1.0': f64
|
||||
165..168 '1.0': f64
|
||||
171..174 'any': fn any<f64>() -> f64
|
||||
171..176 'any()': f64
|
||||
177..179 '{}': ()
|
||||
184..206 'if let...y() {}': ()
|
||||
187..203 'let tr... any()': bool
|
||||
191..195 'true': bool
|
||||
191..195 'true': bool
|
||||
198..201 'any': fn any<bool>() -> bool
|
||||
198..203 'any()': bool
|
||||
158..180 'if let...y() {}': ()
|
||||
161..177 'let 1f... any()': bool
|
||||
165..169 '1f32': f32
|
||||
165..169 '1f32': f32
|
||||
172..175 'any': fn any<f32>() -> f32
|
||||
172..177 'any()': f32
|
||||
178..180 '{}': ()
|
||||
185..206 'if let...y() {}': ()
|
||||
188..203 'let 1.0 = any()': bool
|
||||
192..195 '1.0': f64
|
||||
192..195 '1.0': f64
|
||||
198..201 'any': fn any<f64>() -> f64
|
||||
198..203 'any()': f64
|
||||
204..206 '{}': ()
|
||||
211..234 'if let...y() {}': ()
|
||||
214..231 'let 1f... any()': bool
|
||||
218..223 '1f128': f128
|
||||
218..223 '1f128': f128
|
||||
226..229 'any': fn any<f128>() -> f128
|
||||
226..231 'any()': f128
|
||||
232..234 '{}': ()
|
||||
239..261 'if let...y() {}': ()
|
||||
242..258 'let tr... any()': bool
|
||||
246..250 'true': bool
|
||||
246..250 'true': bool
|
||||
253..256 'any': fn any<bool>() -> bool
|
||||
253..258 'any()': bool
|
||||
259..261 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -397,8 +397,10 @@ fn infer_literals() {
|
|||
r##"
|
||||
fn test() {
|
||||
5i32;
|
||||
5f16;
|
||||
5f32;
|
||||
5f64;
|
||||
5f128;
|
||||
"hello";
|
||||
b"bytes";
|
||||
'c';
|
||||
|
@ -421,26 +423,28 @@ h";
|
|||
}
|
||||
"##,
|
||||
expect![[r##"
|
||||
18..478 '{ ... }': ()
|
||||
18..515 '{ ... }': ()
|
||||
32..36 '5i32': i32
|
||||
50..54 '5f32': f32
|
||||
68..72 '5f64': f64
|
||||
86..93 '"hello"': &'static str
|
||||
107..115 'b"bytes"': &'static [u8; 5]
|
||||
129..132 ''c'': char
|
||||
146..150 'b'b'': u8
|
||||
164..168 '3.14': f64
|
||||
182..186 '5000': i32
|
||||
200..205 'false': bool
|
||||
219..223 'true': bool
|
||||
237..333 'r#" ... "#': &'static str
|
||||
347..357 'br#"yolo"#': &'static [u8; 4]
|
||||
375..376 'a': &'static [u8; 4]
|
||||
379..403 'b"a\x2... c"': &'static [u8; 4]
|
||||
421..422 'b': &'static [u8; 4]
|
||||
425..433 'br"g\ h"': &'static [u8; 4]
|
||||
451..452 'c': &'static [u8; 6]
|
||||
455..467 'br#"x"\"yb"#': &'static [u8; 6]
|
||||
50..54 '5f16': f16
|
||||
68..72 '5f32': f32
|
||||
86..90 '5f64': f64
|
||||
104..109 '5f128': f128
|
||||
123..130 '"hello"': &'static str
|
||||
144..152 'b"bytes"': &'static [u8; 5]
|
||||
166..169 ''c'': char
|
||||
183..187 'b'b'': u8
|
||||
201..205 '3.14': f64
|
||||
219..223 '5000': i32
|
||||
237..242 'false': bool
|
||||
256..260 'true': bool
|
||||
274..370 'r#" ... "#': &'static str
|
||||
384..394 'br#"yolo"#': &'static [u8; 4]
|
||||
412..413 'a': &'static [u8; 4]
|
||||
416..440 'b"a\x2... c"': &'static [u8; 4]
|
||||
458..459 'b': &'static [u8; 4]
|
||||
462..470 'br"g\ h"': &'static [u8; 4]
|
||||
488..489 'c': &'static [u8; 6]
|
||||
492..504 'br#"x"\"yb"#': &'static [u8; 6]
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2622,6 +2622,13 @@ impl BuiltinType {
|
|||
matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
|
||||
}
|
||||
|
||||
pub fn is_f16(&self) -> bool {
|
||||
matches!(
|
||||
self.inner,
|
||||
hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F16)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_f32(&self) -> bool {
|
||||
matches!(
|
||||
self.inner,
|
||||
|
@ -2636,6 +2643,13 @@ impl BuiltinType {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn is_f128(&self) -> bool {
|
||||
matches!(
|
||||
self.inner,
|
||||
hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F128)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_char(&self) -> bool {
|
||||
matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ dot.workspace = true
|
|||
smallvec.workspace = true
|
||||
triomphe.workspace = true
|
||||
nohash-hasher.workspace = true
|
||||
rustc_apfloat = "0.2.0"
|
||||
|
||||
# local deps
|
||||
cfg.workspace = true
|
||||
|
|
|
@ -16,6 +16,10 @@ use ide_db::{
|
|||
RootDatabase,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rustc_apfloat::{
|
||||
ieee::{Half as f16, Quad as f128},
|
||||
Float,
|
||||
};
|
||||
use stdx::format_to;
|
||||
use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T};
|
||||
|
||||
|
@ -540,13 +544,22 @@ pub(super) fn literal(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) ->
|
|||
ast::Char(char) => char .value().as_ref().map_err(|e| format!("{e:?}")).map(ToString::to_string),
|
||||
ast::Byte(byte) => byte .value().as_ref().map_err(|e| format!("{e:?}")).map(|it| format!("0x{it:X}")),
|
||||
ast::FloatNumber(num) => {
|
||||
let (text, _) = num.split_into_parts();
|
||||
let text = text.replace('_', "");
|
||||
if ty.as_builtin().map(|it| it.is_f32()).unwrap_or(false) {
|
||||
let text = num.value_string();
|
||||
if ty.as_builtin().map(|it| it.is_f16()).unwrap_or(false) {
|
||||
match text.parse::<f16>() {
|
||||
Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
|
||||
Err(e) => Err(e.0.to_owned()),
|
||||
}
|
||||
} else if ty.as_builtin().map(|it| it.is_f32()).unwrap_or(false) {
|
||||
match text.parse::<f32>() {
|
||||
Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
} else if ty.as_builtin().map(|it| it.is_f128()).unwrap_or(false) {
|
||||
match text.parse::<f128>() {
|
||||
Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
|
||||
Err(e) => Err(e.0.to_owned()),
|
||||
}
|
||||
} else {
|
||||
match text.parse::<f64>() {
|
||||
Ok(num) => Ok(format!("{num} (bits: 0x{:X})", num.to_bits())),
|
||||
|
|
|
@ -5329,6 +5329,49 @@ const FOO$0: f32 = 1.9999999403953552_f32;
|
|||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
// Check `f16` and `f128`
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: f16 = -1.0f16;
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: f16 = -1.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: f128 = -1.0f128;
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: f128 = -1.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
|
@ -8045,6 +8088,22 @@ fn main() {
|
|||
);
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
$01.0f16;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*1.0f16*
|
||||
```rust
|
||||
f16
|
||||
```
|
||||
___
|
||||
|
||||
value of literal: 1 (bits: 0x3C00)
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
$01.0f32;
|
||||
}
|
||||
|
@ -8061,6 +8120,22 @@ fn main() {
|
|||
);
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
$01.0f128;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*1.0f128*
|
||||
```rust
|
||||
f128
|
||||
```
|
||||
___
|
||||
|
||||
value of literal: 1 (bits: 0x3FFF0000000000000000000000000000)
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
fn main() {
|
||||
$0134e12;
|
||||
}
|
||||
|
@ -8390,8 +8465,8 @@ impl Iterator for S {
|
|||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 7791..7999,
|
||||
focus_range: 7856..7862,
|
||||
full_range: 7800..8008,
|
||||
focus_range: 7865..7871,
|
||||
name: "Future",
|
||||
kind: Trait,
|
||||
container_name: "future",
|
||||
|
@ -8404,8 +8479,8 @@ impl Iterator for S {
|
|||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 8629..9095,
|
||||
focus_range: 8673..8681,
|
||||
full_range: 8638..9104,
|
||||
focus_range: 8682..8690,
|
||||
name: "Iterator",
|
||||
kind: Trait,
|
||||
container_name: "iterator",
|
||||
|
|
|
@ -33,6 +33,7 @@ text-edit.workspace = true
|
|||
[dev-dependencies]
|
||||
rayon.workspace = true
|
||||
expect-test = "1.4.0"
|
||||
rustc_apfloat = "0.2.0"
|
||||
|
||||
test-utils.workspace = true
|
||||
|
||||
|
|
|
@ -489,6 +489,8 @@ impl ast::Byte {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustc_apfloat::ieee::Quad as f128;
|
||||
|
||||
use crate::ast::{self, make, FloatNumber, IntNumber};
|
||||
|
||||
fn check_float_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
|
||||
|
@ -499,14 +501,16 @@ mod tests {
|
|||
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into());
|
||||
}
|
||||
|
||||
fn check_float_value(lit: &str, expected: impl Into<Option<f64>> + Copy) {
|
||||
// FIXME(#17451) Use `expected: f128` once `f128` is stabilised.
|
||||
fn check_float_value(lit: &str, expected: &str) {
|
||||
let expected = Some(expected.parse::<f128>().unwrap());
|
||||
assert_eq!(
|
||||
FloatNumber { syntax: make::tokens::literal(lit) }.value_string().parse::<f64>().ok(),
|
||||
expected.into()
|
||||
FloatNumber { syntax: make::tokens::literal(lit) }.value_string().parse::<f128>().ok(),
|
||||
expected
|
||||
);
|
||||
assert_eq!(
|
||||
IntNumber { syntax: make::tokens::literal(lit) }.value_string().parse::<f64>().ok(),
|
||||
expected.into()
|
||||
IntNumber { syntax: make::tokens::literal(lit) }.value_string().parse::<f128>().ok(),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -520,9 +524,9 @@ mod tests {
|
|||
check_float_suffix("123f32", "f32");
|
||||
check_float_suffix("123.0e", None);
|
||||
check_float_suffix("123.0e4", None);
|
||||
check_float_suffix("123.0ef32", "f32");
|
||||
check_float_suffix("123.0ef16", "f16");
|
||||
check_float_suffix("123.0E4f32", "f32");
|
||||
check_float_suffix("1_2_3.0_f32", "f32");
|
||||
check_float_suffix("1_2_3.0_f128", "f128");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -589,8 +593,10 @@ bcde", b"abcde",
|
|||
|
||||
#[test]
|
||||
fn test_value_underscores() {
|
||||
check_float_value("1.234567891011121_f64", 1.234567891011121_f64);
|
||||
check_float_value("1__0.__0__f32", 10.0);
|
||||
check_float_value("1.3_4665449586950493453___6_f128", "1.346654495869504934536");
|
||||
check_float_value("1.234567891011121_f64", "1.234567891011121");
|
||||
check_float_value("1__0.__0__f32", "10.0");
|
||||
check_float_value("3._0_f16", "3.0");
|
||||
check_int_value("0b__1_0_", 2);
|
||||
check_int_value("1_1_1_1_1_1", 111111);
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ pub mod marker {
|
|||
impl_copy! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
f16 f32 f64 f128
|
||||
bool char
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ pub mod default {
|
|||
0; usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128
|
||||
}
|
||||
impl_default! {
|
||||
0.0; f32 f64
|
||||
0.0; f16 f32 f64 f128
|
||||
}
|
||||
// endregion:builtin_impls
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ pub mod clone {
|
|||
impl_clone! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
f16 f32 f64 f128
|
||||
bool char
|
||||
}
|
||||
|
||||
|
@ -796,7 +796,7 @@ pub mod ops {
|
|||
)*)
|
||||
}
|
||||
|
||||
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
|
||||
add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 }
|
||||
// endregion:builtin_impls
|
||||
// endregion:add
|
||||
|
||||
|
@ -1043,7 +1043,7 @@ pub mod fmt {
|
|||
impl_debug! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
f16 f32 f64 f128
|
||||
bool char
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue