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