profile
viewpoint
Jubilee workingjubilee Rainbow bridge builder.

labs12-rxid/ds-deploy 1

Containing deployment code for the DS API.

workingjubilee/APIzza 1

Continuous deployment of pizza

gabada/groundchair 0

airtable clone

workingjubilee/Algorithms 0

An introduction to algorithmic problem-solving and algorithmic paradigms.

Pull request review commentrust-lang/rust

Switchable buffering for Stdout

+use crate::fmt::Arguments;+use crate::io::{self, buffered::LineWriterShim, BufWriter, IoSlice, Write};+/// Different buffering modes a writer can use+#[unstable(feature = "stdout_switchable_buffering", issue = "78515")]+#[derive(Debug, Copy, Clone, PartialEq, Eq)]+pub enum BufferMode {+    /// Unbuffered: forward writes directly to the underlying writer. In some+    /// cases, a writer may buffer temporarily (for instance, when processing+    /// a formatted write), but even in this case it will always immediately+    /// flush.+    None,++    /// Block buffering: buffer writes until the buffer is full, then forward+    /// to the underlying writer+    Block,

Why would line buffering take a value?

Lucretiel

comment created time in 4 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Switchable buffering for Stdout

+use crate::fmt::Arguments;+use crate::io::{self, buffered::LineWriterShim, BufWriter, IoSlice, Write};+/// Different buffering modes a writer can use+#[unstable(feature = "stdout_switchable_buffering", issue = "78515")]+#[derive(Debug, Copy, Clone, PartialEq, Eq)]+pub enum BufferMode {+    /// Unbuffered: forward writes directly to the underlying writer. In some+    /// cases, a writer may buffer temporarily (for instance, when processing+    /// a formatted write), but even in this case it will always immediately+    /// flush.+    None,++    /// Block buffering: buffer writes until the buffer is full, then forward+    /// to the underlying writer+    Block,

stdio.h's setvbuf is fallible (though it is not clear from the standard when a non-zero value actually comes back, it only says "if an invalid value is given for mode or the request cannot be honored"), and it is UB to invoke it after a write. Hmm...

If stream is NULL, or if mode or size is not within a valid change, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, this function returns -1 and sets errno to EINVAL.

Ah, I see. Yes, "if the stream you are trying to adjust the buffering to does not exist anymore" is one good reason.

Lucretiel

comment created time in 6 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Switchable buffering for Stdout

+use crate::fmt::Arguments;+use crate::io::{self, buffered::LineWriterShim, BufWriter, IoSlice, Write};+/// Different buffering modes a writer can use+#[unstable(feature = "stdout_switchable_buffering", issue = "78515")]+#[derive(Debug, Copy, Clone, PartialEq, Eq)]+pub enum BufferMode {

I'm not saying it's not a problem, but I am saying that C hasn't really invented an addition to this scheme since it became accepted amongst various OS in ~1983.

Lucretiel

comment created time in 7 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Switchable buffering for Stdout

+use crate::fmt::Arguments;+use crate::io::{self, buffered::LineWriterShim, BufWriter, IoSlice, Write};+/// Different buffering modes a writer can use+#[unstable(feature = "stdout_switchable_buffering", issue = "78515")]+#[derive(Debug, Copy, Clone, PartialEq, Eq)]+pub enum BufferMode {

I think it might make more sense to just expose it with #[non_exhaustive], since it's meant to be an input like https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html which means it mostly serves to give a parsimonious interface and resembles the C interfaces here (but in a Rust-y way, since those use a fixed set of macros).

Lucretiel

comment created time in 10 hours

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Switchable buffering for Stdout

+use crate::fmt::Arguments;+use crate::io::{self, buffered::LineWriterShim, BufWriter, IoSlice, Write};+/// Different buffering modes a writer can use+#[unstable(feature = "stdout_switchable_buffering", issue = "78515")]+#[derive(Debug, Copy, Clone, PartialEq, Eq)]+pub enum BufferMode {+    /// Unbuffered: forward writes directly to the underlying writer. In some+    /// cases, a writer may buffer temporarily (for instance, when processing+    /// a formatted write), but even in this case it will always immediately+    /// flush.+    None,

I am guessing the reasoning here is that we want to let write_fmt not have to allocate for each call to write_fmt, so it can still do multiple tiny writes and then our SwitchWriter can dump the result even if it doesn't happen to end with a newline? Is there a reason we should not try to fix that on the other end of the writing and formatting infrastructure, instead of here?

Lucretiel

comment created time in 10 hours

PullRequestReviewEvent

pull request commentrust-lang/rust

Switchable buffering for Stdout

A lot can happen with streams. A pipe can be opened, redirected, closed, et cetera. The ability to respond to such a dynamic environment is a must. We should offer an interface morally equivalent to https://linux.die.net/man/3/setvbuf (which is a C standard, so it should apply cross-OS), while also being mindful that an author may want to manage their interactions in response to user-space commands like https://www.gnu.org/software/coreutils/manual/html_node/stdbuf-invocation.html or similar.

And if possible we would like to write to terminals using line buffering by default and write to non-terminals using block buffering by default, following the convention of most environments. That doesn't have to go in this PR, but we may wish to open a follow up issue.

I am given to understand that Microsoft Windows has interesting nuances to be aware of that don't mesh with a Unix-dominant view of how things should go, in particular in its cmd.exe prompt and its NTFS and ReFS file systems, so it would be a good idea to eventually collect input from someone who was well-versed in those before stabilizing this, presuming it lands. Though I am also given to understand the recent Windows Terminal more closely reflects interfaces in other OS: https://github.com/Microsoft/Terminal

Lucretiel

comment created time in 10 hours

issue commentrust-lang/rfcs

-0.0 should format with a minus sign by default

Swift does. But I don't believe that reasoning based on the idea that there should be a strong divide between Debug and Display here is very applicable here even if we were to presume such was a good place to start. That intended divide is why Rust does not provide derivable implementations for Display, forcing the programmer to think carefully about choosing a presentation. Thus people will write println!("{}", val); to output data, and either impl Display or fix it to "{:?}" when a type error occurs. Except in this case they won't because floats do in fact Display. If anything is being "abused", it's our Display formatting abused as Debug formatting.

Having done that, we're patting ourselves on the back a bit much if we are drawing a bright line between "write different format chars in Rust" from "write different format chars in C". And in C they are consistently conformant in this regard to IEEE754.

But as nagisa stated earlier, the question for std implementations of Display are whether it has "an obvious, widely accepted string representation" and we've established strongly that there is a widely accepted convention here: a technical standard and majority compliance with it. And I did go back further and found that IEEE854-1987 is explicit about "-0 should print as -0" and IEEE754-1985 is suggestive of it, so this is not a recent change in 2019 or even 2008.

rprichard

comment created time in 14 hours

push eventworkingjubilee/rustc

Jubilee Young

commit sha 0e88db7db4c09c63ba8a0036d34e72bd48719bd1

Dogfood {exclusive,half-open} ranges in compiler (nfc) In particular, this allows us to write more explicit matches that avoid the pitfalls of using a fully general fall-through case, yet remain fairly ergonomic. Less logic is in guard cases, more is in the actual exhaustive case analysis. No functional changes.

view details

push time in a day

issue commentrust-lang/rfcs

-0.0 should format with a minus sign by default

And the log file is exactly the concern. IEEE754 makes it pretty clear that 0.0 and -0.0 are not to be treated interchangeably as data points and should round-trip with sign, and so a logged value by default should be capable of being turned into its source float pattern. It is also confounding that we say that the negative sign is printed by default when here it is not: https://doc.rust-lang.org/stable/std/fmt/index.html

Though it also mentions the Signed trait which... doesn't exist in Rust at the moment, I believe? So that's clearly in dire need of updating either way.

Display should certainly output formatted data in a way that is presentable to an ordinary human being instead of a cybernetically attached headcrab, but I do not think it should unnecessarily assume a presence or absence of technical (or mathematical!) capability in doing so. std in particular does not have enough information to assume users are not mathematicians (which are not programmers by default, nor are programmers necessarily mathematicians), who might be quite conversant with at least some of the technical nuances here. At worst, someone with a fairly basic knowledge of integer arithmetic i.e. below the natural numbers will see a -0 and know that it would also be normatively equal to 0, regardless of the sign on it. To assume less knowledge is to seriously open the question that maybe they don't know what a decimal number is, and then we have to seriously ask whether or not we should format floats at all.

Either way, std's Displays should likely err in the direction of being used in log and error formats, since that is often where they wind up: useful to both the Rust programmer, who is likely to see such in a paste from an error log, and adequately legible to the non-programmer.

rprichard

comment created time in a day

issue commentrust-lang/rust

Tracking issue for `X..`, `..X`, and `..=X` (`#![feature(half_open_range_patterns)]`)

I would be happy to draft the PR to stabilize this but first I want to know if https://github.com/rust-lang/rust/issues/48501 is something that needs action on it still.

Centril

comment created time in a day

issue commentrust-lang/rust

Tracking issue for `X..`, `..X`, and `..=X` (`#![feature(half_open_range_patterns)]`)

While I am normally Down On Lints, there's definitely considerable support for aggressively linting here because it's a clear correctness concern, also see adjoining discussion in https://github.com/rust-lang/rust/issues/37854#issuecomment-718036042

Centril

comment created time in a day

pull request commentrust-lang/rust

Dogfood {exclusive,half-open} ranges in compiler (nfc)

Updated to put the Some(0) | None first. These are at least appreciated by some, even if it's still subject to debate, see: https://github.com/rust-lang/rust/issues/37854#issuecomment-718036042 Also there is a motion to stabilize this specific pattern, which is a faster result than I expected. :^) https://github.com/rust-lang/rust/issues/67264#issuecomment-716798691

workingjubilee

comment created time in a day

push eventworkingjubilee/rustc

Jubilee Young

commit sha f637d333d00de1dd3bc7562b23642dc80be8d335

Match Some(0) | None first && exhaustively

view details

push time in a day

issue commentrust-lang/rust

Tracking issue for exclusive range patterns

That seems like a good idea, and I would actually say this almost shouldn't be a Clippy lint because it's fundamental to Rust's exhaustiveness capabilities, but it could be at least tested in Clippy.

oli-obk

comment created time in 2 days

issue commentrust-lang/rust

Tracking issue for duration_constants

In #78216 I introduced Duration::ZERO, which resolves that for Duration::MIN by being a logical constant and not a repr-sensitive constant, and accordingly removed Duration::MIN. That is one way to simplify an API and its concerns, I suppose.

I do not believe Duration::MAX should be under this feature flag because while it is a constant it has a very different purpose and that is a reasonable concern that is directly related to its intention (saturating ops) and is completely different from most of the concerns here. I also do not have a good answer for what to do with it aside from that reshuffling, however.

frewsxcv

comment created time in 2 days

push eventworkingjubilee/rustc

Jubilee Young

commit sha 82f3a236cdb80f65cd5b89a1cb015f95184bf66a

Remove Duration::MIN entirely Duration::ZERO supercedes it in effect.

view details

push time in 2 days

issue commentrust-lang/rust

Tracking Issue for `Duration::{zero, is_zero}` (`#![feature(duration_zero)]`)

As of #78216, Nightly Rust moves to the constant for a variety of reasons stated here, in addition to the fact that a const does not require a const evaluation context in order to be used in places where consts but not dynamic values are accepted... this matters a lot for match contexts and the many sugared versions of match.

LukasKalbertodt

comment created time in 2 days

push eventworkingjubilee/rustc

Jubilee Young

commit sha c986af5ff1e583ac1e76c990a64adf3acecd3ba3

Remove Duration::MIN entirely

view details

push time in 2 days

pull request commentrust-lang/rust

Duration::zero() -> Duration::ZERO

Duration::MIN is exactly why I figured I didn't want to open a stabilization PR for this just yet, because whether or not one should override or the two should alias was uncertain to me and I felt that should be an open question, and I felt the community should get half a second to respond to this change arriving in nightly. If you are in favor of removing Duration::MIN in favor of Duration::ZERO, then I will include that in this PR as another commit so it can be reverted individually.

workingjubilee

comment created time in 2 days

Pull request review commentrust-lang/rust

Duration::zero() -> Duration::ZERO

 fn duration_const() {     const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();     assert_eq!(SUB_SEC_NANOS, 123_456_789); -    const ZERO: Duration = Duration::zero();-    assert_eq!(ZERO, Duration::new(0, 0));--    const IS_ZERO: bool = ZERO.is_zero();+    const IS_ZERO: bool = Duration::ZERO.is_zero();     assert!(IS_ZERO); -    const ONE: Duration = Duration::new(1, 0);--    const SECONDS: u64 = ONE.as_secs();+    const SECONDS: u64 = Duration::SECOND.as_secs();     assert_eq!(SECONDS, 1);      const FROM_SECONDS: Duration = Duration::from_secs(1);-    assert_eq!(FROM_SECONDS, ONE);+    assert_eq!(FROM_SECONDS, Duration::SECOND); -    const SECONDS_F32: f32 = ONE.as_secs_f32();+    const SECONDS_F32: f32 = Duration::SECOND.as_secs_f32();     assert_eq!(SECONDS_F32, 1.0);      const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);-    assert_eq!(FROM_SECONDS_F32, ONE);+    assert_eq!(FROM_SECONDS_F32, Duration::SECOND); -    const SECONDS_F64: f64 = ONE.as_secs_f64();+    const SECONDS_F64: f64 = Duration::SECOND.as_secs_f64();     assert_eq!(SECONDS_F64, 1.0);      const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);-    assert_eq!(FROM_SECONDS_F64, ONE);+    assert_eq!(FROM_SECONDS_F64, Duration::SECOND); -    const MILLIS: u128 = ONE.as_millis();+    const MILLIS: u128 = Duration::SECOND.as_millis();     assert_eq!(MILLIS, 1_000);      const FROM_MILLIS: Duration = Duration::from_millis(1_000);-    assert_eq!(FROM_MILLIS, ONE);+    assert_eq!(FROM_MILLIS, Duration::SECOND); -    const MICROS: u128 = ONE.as_micros();+    const MICROS: u128 = Duration::SECOND.as_micros();     assert_eq!(MICROS, 1_000_000);      const FROM_MICROS: Duration = Duration::from_micros(1_000_000);-    assert_eq!(FROM_MICROS, ONE);+    assert_eq!(FROM_MICROS, Duration::SECOND); -    const NANOS: u128 = ONE.as_nanos();+    const NANOS: u128 = Duration::SECOND.as_nanos();     assert_eq!(NANOS, 1_000_000_000);      const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);-    assert_eq!(FROM_NANOS, ONE);+    assert_eq!(FROM_NANOS, Duration::SECOND);      const MAX: Duration = Duration::new(u64::MAX, 999_999_999); -    const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);+    const CHECKED_ADD: Option<Duration> = MAX.checked_add(Duration::SECOND);     assert_eq!(CHECKED_ADD, None); -    const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);+    const CHECKED_SUB: Option<Duration> = (Duration::ZERO).checked_sub(Duration::SECOND);

...? I thought I was running into a compiler error here, but I changed it to no effect. I am just going to assume I and rustc had a misunderstanding between us.

workingjubilee

comment created time in 2 days

PullRequestReviewEvent

push eventworkingjubilee/rustc

Jubilee Young

commit sha af4d1786e70e441e0998a80d5db0f2f197ea2cf1

Fixup tests: Duration::MIN -> ::ZERO

view details

push time in 2 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

IEEE754-2019 has some recommendations for reproducible floating point results and one of them is that you work with an "arithmetic" float that is also an "interchange" float. That means working with binary{16,32,64,128}, which means no abstract floats. Given that we already have a tough row to hoe with const flops, I think we should take IEEE754 seriously about that, and I don't think that would get better if we used a different format for our reals, either.

oli-obk

comment created time in 2 days

Pull request review commentrust-lang/rust

Updated the list of white-listed target features for x86

 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[     ("aes", None),     ("avx", None),     ("avx2", None),+    ("avx512bf16", Some(sym::avx512_target_feature)),+    ("avx512bitalg", Some(sym::avx512_target_feature)),     ("avx512bw", Some(sym::avx512_target_feature)),     ("avx512cd", Some(sym::avx512_target_feature)),     ("avx512dq", Some(sym::avx512_target_feature)),     ("avx512er", Some(sym::avx512_target_feature)),     ("avx512f", Some(sym::avx512_target_feature)),+    ("avx512gfni", Some(sym::avx512_target_feature)),     ("avx512ifma", Some(sym::avx512_target_feature)),     ("avx512pf", Some(sym::avx512_target_feature)),+    ("avx512vaes", Some(sym::avx512_target_feature)),     ("avx512vbmi", Some(sym::avx512_target_feature)),+    ("avx512vbmi2", Some(sym::avx512_target_feature)),     ("avx512vl", Some(sym::avx512_target_feature)),+    ("avx512vnni", Some(sym::avx512_target_feature)),+    ("avx512vp2intersect", Some(sym::avx512_target_feature)),

Ditto.

DevJPM

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentrust-lang/rust

Updated the list of white-listed target features for x86

 fn powerpc64_linux() { #[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn x86_all() {+    // the below is in alphabetical order and matches+    // the order of X86_ALLOWED_FEATURES in rustc_codegen_ssa's target_features.rs++    println!("adx: {:?}", is_x86_feature_detected!("adx"));     println!("aes: {:?}", is_x86_feature_detected!("aes"));-    println!("pcmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq"));+    println!("avx: {:?}", is_x86_feature_detected!("avx"));+    println!("avx2: {:?}", is_x86_feature_detected!("avx2"));+    println!("avx512bf16: {:?}", is_x86_feature_detected!("avx512bf16"));+    println!("avx512bitalg: {:?}", is_x86_feature_detected!("avx512bitalg"));+    println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw"));+    println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd"));+    println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq"));+    println!("avx512er: {:?}", is_x86_feature_detected!("avx512er"));+    println!("avx512f: {:?}", is_x86_feature_detected!("avx512f"));+    println!("avx512gfni: {:?}", is_x86_feature_detected!("avx512gfni"));+    println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma"));+    println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf"));+    println!("avx512vaes: {:?}", is_x86_feature_detected!("avx512vaes"));+    println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi"));+    println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2"));+    println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl"));+    println!("avx512vnni: {:?}", is_x86_feature_detected!("avx512vnni"));+    println!("avx512vp2intersect: {:?}", is_x86_feature_detected!("avx512vp2intersect"));+    println!("avx512vpclmulqdq: {:?}", is_x86_feature_detected!("avx512vpclmulqdq"));+    println!("avx512vpopcntdq: {:?}", is_x86_feature_detected!("avx512vpopcntdq"));+    println!("bmi1: {:?}", is_x86_feature_detected!("bmi1"));+    println!("bmi2: {:?}", is_x86_feature_detected!("bmi2"));+    println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b"));+    println!("f16c: {:?}", is_x86_feature_detected!("f16c"));+    println!("fma: {:?}", is_x86_feature_detected!("fma"));+    println!("fxsr: {:?}", is_x86_feature_detected!("fxsr"));+    println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt"));+    //println!("movbe: {:?}", is_x86_feature_detected!("movbe")); // movbe is unsupported as a target feature+    println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq"));+    println!("popcnt: {:?}", is_x86_feature_detected!("popcnt"));     println!("rdrand: {:?}", is_x86_feature_detected!("rdrand"));     println!("rdseed: {:?}", is_x86_feature_detected!("rdseed"));-    println!("tsc: {:?}", is_x86_feature_detected!("tsc"));-    println!("mmx: {:?}", is_x86_feature_detected!("mmx"));

It is not intended that MMX feature detection be removed from Rust, in spite of the fact we don't do anything with it. The detection of capabilities and emission of such code are two entirely different concerns. Likewise it is not clear why tsc is being removed here.

DevJPM

comment created time in 4 days

Pull request review commentrust-lang/rust

Updated the list of white-listed target features for x86

 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[     ("aes", None),     ("avx", None),     ("avx2", None),+    ("avx512bf16", Some(sym::avx512_target_feature)),+    ("avx512bitalg", Some(sym::avx512_target_feature)),     ("avx512bw", Some(sym::avx512_target_feature)),     ("avx512cd", Some(sym::avx512_target_feature)),     ("avx512dq", Some(sym::avx512_target_feature)),     ("avx512er", Some(sym::avx512_target_feature)),     ("avx512f", Some(sym::avx512_target_feature)),+    ("avx512gfni", Some(sym::avx512_target_feature)),     ("avx512ifma", Some(sym::avx512_target_feature)),     ("avx512pf", Some(sym::avx512_target_feature)),+    ("avx512vaes", Some(sym::avx512_target_feature)),     ("avx512vbmi", Some(sym::avx512_target_feature)),+    ("avx512vbmi2", Some(sym::avx512_target_feature)),     ("avx512vl", Some(sym::avx512_target_feature)),+    ("avx512vnni", Some(sym::avx512_target_feature)),+    ("avx512vp2intersect", Some(sym::avx512_target_feature)),

Ditto.

DevJPM

comment created time in 4 days

Pull request review commentrust-lang/rust

Updated the list of white-listed target features for x86

 pub fn time_trace_profiler_finish(file_name: &str) { // WARNING: the features after applying `to_llvm_feature` must be known // to LLVM or the feature detection code will walk past the end of the feature // array, leading to crashes.+// To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def+// where the * matches the architecture's name

You should remind people to check out the submodule in our repo and its current commit, e.g. currently https://github.com/rust-lang/llvm-project/tree/ee1617457899ef2eb55dcf7ee2758b4340b6533f

DevJPM

comment created time in 4 days

Pull request review commentrust-lang/rust

Updated the list of white-listed target features for x86

 const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[     ("aes", None),     ("avx", None),     ("avx2", None),+    ("avx512bf16", Some(sym::avx512_target_feature)),

The tests are going absolutely bonkers over the absence of this feature.

DevJPM

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent

startedlifthrasiir/rust-strconv

started time in 4 days

issue commentrust-lang/rfcs

Suggestions for additional floating-point types

f16 has uses in neural networks as well.

There are actually many problems with using f80, especially if we do not ship a soft float to cover it... it would not be a type defined by an abstraction, frankly, it would be a type defined by Intel's hardware quirks, and we would only be adding more on top of it. One of the nice things about Rust is that it is highly portable right now, so I do not think it makes sense to add such a non-portable type to the language and limit portability that much, though a language extension that makes it simpler to define and use such a non-portable type would make sense.

aaronfranke

comment created time in 4 days

issue commentbytecodealliance/wasmtime

Modules built from Rust only work on Windows when built in release mode

If gdb can debug wasm, then rustc should continue adding the section for wasm targets. If gdb cannot debug wasm, then rustc should not add the section. I don't know gdb's limits here.

itowlson

comment created time in 5 days

issue commentrust-lang/rfcs

-0.0 should format with a minus sign by default

IEEE754-2019 states that transformations from a floating point to an external decimal character sequence and back shall (are required to) preserve signs for infinites and zeros, and this was likely specified also in previous versions (2008) but I have not extensively diffed it. But as a result, I do not really see a reason to debate here.

rprichard

comment created time in 5 days

issue openeddiku-dk/futhark

Consider WebAssembly support

It is considered fashionable nowadays to provide a high level of WebAssembly (wasm) support. Futhark already compiles to C, and from C it can be compiled to wasm, though this would probably be relatively crude. However, more important for Futhark's particular goals, WebAssembly offers a generic SIMD API nowadays that can be implemented by a runtime and would allow Futhark to make maximal usage of parallelization. Also, a lot of VMs seem to be integrating with wasm support so it would provide an easy way for people to import Futhark code into their language of choice while minimizing additional maintenance overhead.

created time in 5 days

issue commentrust-lang/polonius

Experiment with Lobster-like memory management

Yes. Specifically, this is an interesting idea, but to the extent that this idea is useful and interesting, this is already what NLL is.

Otherwise, it relies on certain assumptions (e.g. presence of a memory management unit) that would not be appropriate on a language level and it relies on certain rules in terms of lifetimes that would make usage of this unpredictable. Namely, lifetime rules are encoded in type signatures in Rust. This means changes purely interior to a function should not alter calling the function in Rust. Lobster's description here contains no such limitation. So it may be very appropriate for Lobster but not necessarily appropriate for Rust.

LifeIsStrange

comment created time in 7 days

Pull request review commentrust-lang/rust

Dogfood {exclusive,half-open} ranges in compiler (nfc)

 impl<'tcx> LateLintPass<'tcx> for UnusedResults {                 }                 ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {                     // If the array is definitely non-empty, we can do `#[must_use]` checking.-                    Some(n) if n != 0 => {+                    Some(n @ 1..) => {

My overall hypothesis was that this pattern is neither significantly more or less legible to humans, but significantly more legible to the compiler, which allows it to better reason around and assist the programmer, so in the spirit of meeting the machine halfway...

I will note my initial inclination was to move the simple "negative" ( Some(0) | None ) condition first, which might make more sense. Happy to hear what others think, though.

workingjubilee

comment created time in 7 days

PullRequestReviewEvent

issue commentrust-lang/rust-clippy

`bool_comparison` should not fire when testing for false

I came here to add to the lamentations because it is my experience that very often Clippy recommends the ! on expressions like ident.is_cond_true() which is directly against the flow of the overall reading, and in general negative reasoning is harder for me.

svmnotn

comment created time in 7 days

PR opened rust-lang/rust

Dogfood {exclusive,half-open} ranges in compiler (nfc)

In particular, this allows us to write more explicit matches that avoid the pitfalls of using a fully general fall-through case, yet remain fairly ergonomic. Less logic is in guard cases, more is in the actual exhaustive case analysis.

No functional changes.

+12 -8

0 comment

6 changed files

pr created time in 8 days

create barnchworkingjubilee/rustc

branch : dogfood-fancy-ranges

created branch time in 8 days

issue commentrust-lang/rust

ICE when attempting to use const_evaluatable_checked without the feature enabled

@rustbot modify labels: +const-generics-fixed-by-min-const-generics, +const-generics-fixed-by-const-generics, +A-const-generics, +F-const_evaluatable_checked

DrMeepster

comment created time in 8 days

issue commentrust-lang/rust

ICE when attempting to use const_evaluatable_checked without the feature enabled

@rustbot modify-labels: +const-generics-fixed-by-min-const-generics, +const-generics-fixed-by-const-generics, +A-const-generics, +F-const_evaluatable_checked

DrMeepster

comment created time in 8 days

pull request commentrust-lang/rust

[Performance run] Switch rustc_hash -> ahash

This was previously tried in https://github.com/rust-lang/rust/pull/59592

jyn514

comment created time in 8 days

PR opened rust-lang/rust

Duration::zero() -> Duration::ZERO

In review for #72790, whether or not a constant or a function should be favored for #![feature(duration_zero)] was seen as an open question. In https://github.com/rust-lang/rust/issues/73544#issuecomment-691701670 an invitation was opened to either stabilize the methods or propose a switch to the constant value, supplemented with reasoning. Followup comments suggested community preference leans towards the const ZERO, which would be reason enough.

ZERO also "makes sense" beside existing associated consts for Duration. It is ever so slightly awkward to have a series of constants specifying 1 of various units but leave 0 as a method, especially when they are side-by-side in code. It seems unintuitive for the one non-dynamic value (that isn't from Default) to be not-a-const, which could hurt discoverability of the associated constants overall. Elsewhere in std, methods for obtaining a constant value were even deprecated, as seen with std::u32::min_value.

Most importantly, ZERO costs less to use. A match supports a const pattern, but const fn can only be used if evaluated through a const context such as an inline const { const_fn() } or a const NAME: T = const_fn() declaration elsewhere. Likewise, while https://github.com/rust-lang/rust/issues/73544#issuecomment-691949373 notes Duration::zero() can optimize to a constant value, "can" is not "will". Only const contexts have a strong promise of such. Even without that in mind, the comment in question still leans in favor of the constant for simplicity. As it costs less for a developer to use, may cost less to optimize, and seems to have more of a community consensus for it, the associated const seems best.

r? @LukasKalbertodt

+79 -86

0 comment

4 changed files

pr created time in 8 days

push eventworkingjubilee/rustc

Jubilee Young

commit sha ef027a1eed4cc8d34d1a4bf9222369e7fef48e93

Duration::zero() -> Duration::ZERO Duration::ZERO composes better with match and various other things, at the cost of an occasional parens, and results in less work for the optimizer, so let's use that instead.

view details

push time in 8 days

issue commentrust-lang/rust

rust missing features like powerful text formatting

fn main() {
    let ch = 'd';
    println!("{}", ch as u32);
}

Try it on the Playground.

anshul-birajdar

comment created time in 8 days

create barnchworkingjubilee/rustc

branch : duration-zero

created branch time in 8 days

issue commentrust-lang/rust

Tracking issue for exclusive range patterns

It is not clear that

0..=9
10..=99
100..=999
1000..=9999

is less desirable.

However I would like to voice that I prefer having the option to have an exclusive range pattern for the sole case of the "half-open range" that goes from a certain value unto the natural end of that range.

oli-obk

comment created time in 8 days

pull request commentrust-lang/rust

Specialize format! for simple "{}" case

I can't believe that worked.

workingjubilee

comment created time in 8 days

push eventworkingjubilee/rustc

Jubilee Young

commit sha 1ee0392606bb53a70ed082acb551e30dd6ee21c7

Simplify to invoking Trait on ident

view details

push time in 8 days

push eventworkingjubilee/rustc

Jubilee Young

commit sha ceee28df098fd8ea0a091c7f74ced2d6d1abf597

Simplify to literal

view details

push time in 9 days

issue commentrust-lang/rust

Consider limiting #[rustc_args_required_const(...)] to intrinsics.

given https://github.com/rust-lang/stdarch/pull/876#issuecomment-660523891

IMO we should panic on out-of-range immediates, with the intention of turning those into compile-time errors once we have enough support for const generics (and #[rustc_args_required_const] becomes syntax sugar for const generics).

cc @Amanieu

eddyb

comment created time in 9 days

issue commentrust-lang/rust

Consider limiting #[rustc_args_required_const(...)] to intrinsics.

So the only reason to make it require constness is to force users to use constants there, even though it's not necessary at all.

So, my understanding, partly informed by @Lokathor's explanation at https://github.com/rust-lang/rust/issues/73542#issuecomment-646989795, is that this is because it is matching the design of Intel's API. The input to that intrinsic function must be a value that can be compiled as an x86 asm immediate (expressed in the intrinsic function in Intel's guide as const int index, ). Then Intel's design for the intrinsic will only look at the lower bits. The & operation there, I believe, is done to make sure it actually only provides those lower bits. I don't know for sure, since I did not write these, but I don't think it's supposed to be a runtime check at all... I think it's done with the intent that the entire thing is const folded.

eddyb

comment created time in 9 days

issue commentrust-lang/rust

Package gdb with Rust

ping! It's 2020, do you know where your civilization is?

This issue was opened with the assertion that "gdb has first-class support for Rust now, and two active maintainers (@tromey @Manishearth). Let's package it with Rust."

Is this still true?

Per https://github.com/rust-lang/rustup/issues/2532, it seems we currently ship a rust-gdb wrapper in Rustup, but it needs documentation. This is especially confusing to me because unlike most optional pieces of Rust, it isn't in rustup's component list, and I actually don't have gdb installed so it errors to invoke it.

brson

comment created time in 9 days

issue commentrust-lang/rustc-dev-guide

Add context to "may be out of date" sections

It's probably worth lifting this caveat from the "high-level overview of the compiler" into "About this guide": https://rustc-dev-guide.rust-lang.org/overview.html#constant-change

That way we clearly assert the base case of change initially. Places we can update that assert the contents are possibly dated or that themselves might need an update due to time passing:

This is a good example to reference: Specialization - Additional Resources. Something might have been dated, and is out of the guide's bounds, so it is unlikely to update, but it is given a time it dates to in the guide, so the reader can choose whether or not to click at all.

workingjubilee

comment created time in 9 days

issue commentrust-lang/rust

Consider limiting #[rustc_args_required_const(...)] to intrinsics.

That is correct, as seen in the code you quoted, these were stabilized in #49664 in 1.27 i.e. Rust 2018 with const generic stabilization not in sight and after passing a final comment period in #48556. They had their rustc_args_required_const adornment added at the same time as they were added,

That means these APIs have parameters that ask for const values that can be turned into immediates in a form that conforms well with the expected API of the Intel intrinsic functions in C and C++ compilers, as we can see here: https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_extract_epi64

So I imagine it's a very "drop in" experience for someone who is used to Intel intrinsics, but is... Admittedly Kinda Awkward in Rust terms.

eddyb

comment created time in 9 days

issue commentrust-lang/rust

Create a benchmark suite for uncovering runtime regressions

Hello! What are things looking like for this nowadays?

Our plan for core::simd is likely to include some bench-testing on some reasonably realistic workloads, and it would be nice to integrate with something like this. It seems like lolbench got some mileage but then encountered hosting limits? https://github.com/anp/lolbench/issues/68

nikomatsakis

comment created time in 10 days

issue commentrust-lang/rust

Neon SIMD intrinsics not found when compiling on ARM v7l

I had a moment to review this issue today in closer detail.

vreinterpretq_u32_u16 is not present. vreinterpretq_u32_u8 is. vgetq_lane_u8 is not present. vget_lane_u8 is.

In other words, this is not a compiler error, or at least, not the compiler error it is suggested to be. This is merely the absence of very common intrinsics for the ARM platform.

Nufflee

comment created time in 10 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

Are there any problems with const fn foo<T: Add>(a: T, b: T) -> T::Output { a + b } implying T: const Add that would prevent making that a blocker? Ergonomics, I suppose?

oli-obk

comment created time in 10 days

issue commentrust-lang/rust

Consider limiting #[rustc_args_required_const(...)] to intrinsics.

From the perspective of users of the relevant Intel and ARM APIs here, these are expected to be intrinsic functions, even though they are effectively provided as a library. So, parsing this request is a bit challenging. What is the desired outcome here?

eddyb

comment created time in 11 days

issue commentrust-lang/rust

There are too many entries in the test suite directories

Also see #76268: many of these are run pass tests that do not particularly need to be UI tests.

pnkfelix

comment created time in 11 days

issue commentrust-lang/rust

Audit for binary IEEE 754-2008 compliance on relevant platforms

Also: We definitely cannot obtain binary compliance currently on many platforms, even those that are not "embedded", without extensively patching our operations there, because there are platforms that have nonstandard behavior, even if it's just for the sole reason of "their silicon literally predates the standard of IEEE754-2008". So LLVM's problems are not necessarily the only gateway to pass.

For aarch64, x86-64, ppc64le, and a few other targets, this is comparatively minor as a concern.

auroranockert

comment created time in 11 days

startedhopv/rust-horn

started time in 11 days

issue openedrust-lang/rustc-dev-guide

Add context to "may be out of date" sections

Many places in the guide mention "this section may be out of date", such as in the parser. This is unfortunately quite ambiguous because the writer usually has not contextualized it with a "when" or "why", and so the reader does not know how much to trust or mistrust the information. Such comments should be marked with enough data to provide actual context, such as

  1. a reason for why the data may be out of date other than "change"... change is a constant across the project
  2. a time the comment was added (visible in git blame but not on the website)
  3. a link to a relevant WG, tracking issue, or similar, that may provide further explanation for the change process

created time in 11 days

push eventrust-lang/stdsimd

Jubilee Young

commit sha a5bdb8b1ff7ec99e25d8dd195b142b1ab7058e30

Document size/align of SIMD types

view details

Jubilee

commit sha 3aec4a2d00fab81b0372e3e98ea34d8305233f29

Merge pull request #43 from rust-lang/docs/layout Document size/align of SIMD types

view details

push time in 12 days

PR merged rust-lang/stdsimd

Reviewers
Document size/align of SIMD types

Docs introduced per conversation here.

We might want to change the rules of Rust regarding these later on, but we can at least inform people of the current state of things.

+11 -0

0 comment

1 changed file

workingjubilee

pr closed time in 12 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

Can we vary a given Trait impl for two types based on constness? I think I saw an RFC for that, but I do not believe it had achieved acceptance.

oli-obk

comment created time in 12 days

issue commentidris-lang/Idris2

Feature requests and proposals

This is possible in Rust because char is defined as a Unicode Scalar Value, which definitionally is up to 4 bytes. This may prove unfortunately Entertaining to implement across multiple backends if certain backends disagree on encoding of Char. Judging by other issues, I see that there is at least some usage of a JavaScript backend. As JS Strings must be indiced base on UTF-16, the codegen may have to be adjusted. However, I did enough meandering to at least recover some evidence that it uses ECMAScript 2015 fromCodePoint and codePointAt functions, so it probably is indeed expressible as a u32.

https://github.com/idris-lang/Idris2/blob/f64163de1f65b959c95053bb8d295d1522b58537/src/Compiler/ES/ES.idr#L261-L264

edwinb

comment created time in 12 days

PR opened rust-lang/stdsimd

Reviewers
Document size/align of SIMD types

Docs introduced per conversation here.

We might want to change the rules of Rust regarding these later on, but we can at least inform people of the current state of things.

+11 -0

0 comment

1 changed file

pr created time in 13 days

push eventrust-lang/stdsimd

Jubilee Young

commit sha a5bdb8b1ff7ec99e25d8dd195b142b1ab7058e30

Document size/align of SIMD types

view details

push time in 13 days

push eventrust-lang/stdsimd

Jubilee Young

commit sha b69965767098666ee91b0235921aff9209de8b20

Document size/align of SIMD types

view details

push time in 13 days

create barnchrust-lang/stdsimd

branch : docs/layout

created branch time in 13 days

issue commentrust-lang/rust

Diagnostic: no EMMS instruction before call

Agreed. It is no longer possible to invoke the relevant intrinsics on nightly, so Rust cannot cause the relevant interaction directly, and in particular the reproducer just results in a compiler error. This issue can be closed.

gnzlbg

comment created time in 14 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

@RalfJung Yeah, we absolutely need a totally ludicrous amount of tests for floating point assumptions. I am going to be trying to develop such as part of developing portable SIMD.

@tavianator Hmm. Once we agree that we're OK with const fn explicitly const-compiling to a form that may not perfectly match runtime, but does match IEEE754, and has minimal unexpected deviation, we are essentially agreeing that we're theoretically OK with const evaluation working that way to handle NaN issues, and it's mostly hashing out the details. It does seem potentially soluble, and that NaN canonicalization is in fact likely the way to go here.

However, I think we're still best off with erroring/linting against const ops on NaNs as our "step 0", and gradually unwinding such a restriction as we go along, on the same thesis that we want to get some experience with having a reliable behavior in a well-known space first, and then move it forward into other spaces.

And yeah, I doubt transcendentals will ever be const for us. It feels like the prerequisites for doing so in a way that make sense across multiple platforms is really "unlock a new revolution in mathematics and computer science right here in rust-lang". Which, you know, I like that we're ambituous as a language, but that might be expecting a bit much of ourselves.

oli-obk

comment created time in 14 days

issue commentrust-lang/stdsimd

Some floating point test failures on Raspberry Pi 4 with Neon

Hum, I thought thumbv7neon was for "T32" code and armv7 +neon would be the logical choice for "A32" code, so I feel I am missing some nuance here. Nonetheless, if it is really that bad in perf and unsuitable for deployment, we should seriously consider raising a rustc issue to lint against using that target in that way.

KodrAus

comment created time in 14 days

issue commentrust-lang/rust

Compile constant SIMD initialiser to a constant vector expression

According to Godbolt rustc +nightly --emit=llvm-ir -Copt-level=0 now gives

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @_ZN7example3foo17h2ac4b13db8a0abecE
  (<2 x double>* noalias nocapture sret dereferenceable(16) %0, double %x, double %y)
  unnamed_addr #0 !dbg !6 {
    %1 = bitcast <2 x double>* %0 to double*, !dbg !10
    store double 0.000000e+00, double* %1, align 16, !dbg !10
    %2 = getelementptr inbounds <2 x double>, <2 x double>* %0, i32 0, i32 1, !dbg !10
    store double 1.000000e+00, double* %2, align 8, !dbg !10
    ret void, !dbg !11
}

attributes #0 = { nonlazybind uwtable "probe-stack"="__rust_probestack" "target-cpu"="x86-64" }

!llvm.module.flags = !{!0, !1, !2}
!llvm.dbg.cu = !{!3}

and -Copt-level=3 now gives

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @_ZN7example3foo17h2ac4b13db8a0abecE
  (<2 x double>* noalias nocapture sret dereferenceable(16) %0, double %x, double %y)
  unnamed_addr #0 !dbg !6 {
    store <2 x double> <double 0.000000e+00, double 1.000000e+00>, <2 x double>* %0, align 16, !dbg !10
    ret void, !dbg !11
}

attributes #0 = { nofree norecurse nounwind nonlazybind uwtable writeonly
"probe-stack"="__rust_probestack" "target-cpu"="x86-64" }
huonw

comment created time in 15 days

issue commentrust-lang/rust

repr(simd) struct with one i64 element incorrectly emits x86_mmx

Rust no longer supports using MMX intrinsics or emitting MMX instructions (except possibly via inline assembly). The reproducer now generates

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @foo(<1 x i64>* noalias nocapture sret dereferenceable(8) %0, <1 x i64>* noalias nocapture readonly dereferenceable(8) %x) unnamed_addr #0 {
  %1 = getelementptr inbounds <1 x i64>, <1 x i64>* %x, i64 0, i64 0
  %2 = load i64, i64* %1, align 8
  %3 = getelementptr inbounds <1 x i64>, <1 x i64>* %0, i64 0, i64 0
  store i64 %2, i64* %3, align 8
  ret void
}

attributes #0 = { nofree norecurse nounwind nonlazybind uwtable "probe-stack"="__rust_probestack""target-cpu"="x86-64" }

!llvm.module.flags = !{!0, !1}

!0 = !{i32 7, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}

This issue can be closed.

gnzlbg

comment created time in 15 days

issue commentrust-lang/rust-clippy

Lint request: deny_mmx_target_feature

Rust no longer supports using MMX intrinsics or emitting MMX instructions (except possibly via inline assembly). This issue can be closed.

gnzlbg

comment created time in 15 days

issue commentrust-lang/stdsimd

Get Cranelifted

Total redesign of the backend only, yes.

Though I should note that if our public API makes certain promises about how it lowers that it can't keep, then we effectively are breaking our public API anyways, just in a way that is harder to discern.

workingjubilee

comment created time in 15 days

issue openedrust-lang/stdsimd

Get Cranelifted

Per the conversation on Zulip in t-compiler and project-portable-simd, we are going to find Cranelift landing a direct challenge to our landing in std, because the last one in is a rotten egg has to support the other... but while we could "race" them, it seems addition might require a total redesign anyways. So we need to

  1. Figure out what Cranelift needs from us
  2. Figure out what we need from Cranelift
  3. Figure out what additional consequences landing std::simd has for Cranelift support
  4. Figure out what additional consequences landing Cranelift support has for std::simd
  5. Solve all that

@_bjorn3|133247 said:

I hope most if not all of the operations used by portable simd could use (newly introduced) `simd_*` platform intrinsics that are architecture and vector size independent. This would allow easy emulation of them implemented once per operation.

This has led to some immediate questions, 0. What exactly are "platform-intrinsics" supposed to be? Our current understanding is that their LLVM ops... but Cranelift isn't LLVM, obviously. So...

  1. What changes about them when moving from LLVM to Cranelift?
  2. What does this do for SIMD FFI?
  3. Can we find a way around the SIMD FFI question?

created time in 15 days

issue commentrust-lang/stdsimd

Floats are problematic

Ah. Those are on tier 3 support under the mipsisa{32,64}{,el} names, and it's not even clear we can build std for them, so it seems all the MIPS targets we should be keeping an eye on do not incorporate the IEEE754-2008 behavior and are thus not in our field of concern.

workingjubilee

comment created time in 15 days

issue commentrust-lang/stdsimd

Floats are problematic

@programmerjake Ah, thank you, I kept hearing the detail of swapped qNaN and sNaNs but for some reason "it's the most significant bit in the mantissa" kept sliding from my mind while writing from this up. This makes sense.

MIPS doesn't seem to have a lot of usage, but it is on our Platform Support list and we do build hosts on it. Anyways, for this reason we might run into troubles exploiting its vector ISAs, like we might with Neon v1, but this difference at least seems more soluble and I would prefer if we could at least get basic functionality together (i.e. scalar fallbacks). And really it was IEEE754-1985's fault for needlessly avoiding specifying which way around it should go.

It doesn't seem like there's a clear target division between the different eras of MIPS targets in rustc's targets list, and MIPS64 is older than 2008. I suppose we have to assume all MIPS FPUs are Like That, then?

workingjubilee

comment created time in 15 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

What I would personally prefer to do would be to by-default disable implicit const folding floats on all platforms and then gradually reenable it for all verified platforms. This would give us a moment of certainty that we are behaving Correctly, and then from that point forward we can at least hope that if we make an optimization, the test suite says it's OK, and no one screams? We've probably not busted anyone.

oli-obk

comment created time in 16 days

issue openedrust-lang/stdsimd

Floats are problematic

It is well known that floating point code often merits extra caution due to the details of rounding math, but the fact that floating point numbers are more interesting to handle applies not just to software interacting with floating point numbers and the floating point environment (all of which can affect our API significantly), but also applies to hardware implementations of both vector and scalar floating point units, so to both our SIMD code and our scalar fallbacks. These aren't bugs per se because it's not a bug, it's a feature, but they are features requiring enhanced attention to detail. This is related to https://github.com/rust-lang/unsafe-code-guidelines/issues/237 and https://github.com/rust-lang/rust/issues/73328 as well.

Most domains involving SIMD code use floats extensively, so this library has a "front-row seat" to problems with floating point operations. Thus, in order for SIMD code to be reasonably portable, we should try to discover where these... unique... implementations lie and decide how to work around them, or at least inform our users of the Fun Facts we learn.

Arch-specific concerns remain for:

  • [ ] 32-bit x86
  • [ ] 32-bit ARM
  • [ ] MIPS
  • [ ] Wasm

32-bit x86

The x87 80-bit "long double" float registers can do interesting things to NaN, and in general if a floating point value ends up in them and experiences an operation, this can introduce extra precision that may lead to incorrect mathematical conclusions later on. Further, Rust no longer supports MMX code at all because their interaction with the x87 registers were just entirely too much trouble. Altogether, this is probably why the x86-64 System V ABI specifies usage of the XMM registers for handling floating point values, which do not have these problems.

32-bit ARM

There are so many different floating point implementations on 32-bit ARM that armclang includes a compiler flag for FPU architecture and another one for float ABI.

  • VFP AKA Vector Floating Point: VFP units that appear on ARMv7 seem to default to flushing denormals to zero unless the appropriate control register has the "FZ bit" set appropriately.
  • Neon AKA Advanced SIMD: Vector registers flush denormals to zero always. This is not true of aarch64's Enhanced Neon AKA Advanced SIMD v2.
  • Aarch32: Lest we imagine that ARMv8-A is completely free of problems, the "aarch32" execution mode has an unspecified default value for the FZ bit even if Neon v2 is available.

MIPS

NaNs sometimes do weird things on this platform, resulting in some of the packed_simd tests getting the very interesting number -3.0.

Wasm

Technically Wasm is IEEE754 compliant but it is very "...technically!" here because it specifies a canonicalizing behavior on NaNs that constitutes an interesting choice amongst architectures and may not be expected by a programmer that is used to e.g. being able to rely on NaN bitfields being fairly stable, so we will want to watch out for it when implementing our initial floating point test suite.

The Good News

We have reasonable confidence in float behavior in x86's XMM-and-later registers (so from SSE2 onwards), aarch64's Neon v2 registers, PowerPC, and z/Architecture (s390x). As far as we know, on these architectures ordinary binary32 and binary64s are what they say they are, support basic operations in a reasonably consistent fashion, and nothing particularly weird occurs even with NaNs. So we are actually in a pretty good position for actually using most vector ISAs! It's just all the edge cases that pile up.

Main Takeaway

We want to extensively test even "simple" scalar operations on floating point numbers, especially casts and bitwhacking, or anything else that might possibly be affected by denormal numbers or NaN, so as to surface known and unknown quirks in floating point architectures and how LLVM handles them.

created time in 16 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

I am not entirely sure, honestly. I would be inclined to say that we would want implicit folding of floating point operations to be as invisible as possible to the programmer, and that given that many arches explicitly support executing code compiled for different targets, we should reasonably question our assumptions about what the target "really is".

oli-obk

comment created time in 16 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

There is also an option of choosing to only const eval floats using subnormal number support, on the thesis that reading the resulting number at zero at runtime is of minimal consequence. This produces a slight compilation vs. runtime deviation, unfortunately, but also is actually pretty simple. —@workingjubilee

accept that the result will be different, and compute it using proper IEEE754 semantics. (This is also arguably the closest to the spirit of IEEE754 which is that operations compute things at infinite precision and you get the rounded result). [..] In a case like that, I'd prefer number 3. —@thomcc

If the spec says "unpredictably get non-IEEE754-conforming results", i.e. some operations are conforming and some or not, then const fn can just use IEEE754. Basically what this would boil down to is that on these platforms, the affected operations are non-deterministic. This is not sound of course if the optimizer at the same time assumes them to be deterministic. But well, I'd be willing to note that down as a platform bug and move on... that's what everyone else seems to do and it seems to work for them^^ —@RalfJung

So it seems like there is at least some perceived wisdom in something like this (including myself, granted), regarding subnormal handling.

If I were making all the decisions re: const fn and floats, I would say we should 0. specify CTFE as using IEEE754 floats with default rounding mode 0. only const-eval floats in explicit const contexts, so no implicit const folding of floats 0. specify that we accept weirdness in older platforms' float behavior 0. introduce lints and diagnostics as needed to steer people correctly around this

This means that if the platform has what I might call a "cursed" implementation of floating point (contra "buggy", because really, it's not a bug, it's a feature), then Rust currently makes no effort to change that, but avoids introducing unintended deviance that isn't specified by the programmer... or the LLVM optimizer, which is a barrier but which we can, at least to some extent, say "that's LLVM's problem, we're trying our best!"

I believe this is the least work for the most correctness and the least limitations on future choices in Rust. Also, while setting FZ during runtime might invite programmer meddling, we can at least confidently set floating point environment flags to enable subnormal handling during compilation without worrying if they might be changed at runtime, so that barring other bugs we can even try to compile correctly on armv7 hosts.

oli-obk

comment created time in 16 days

issue commentrust-lang/rust

Audit for binary IEEE 754-2008 compliance on relevant platforms

The current version, IEEE 754-2019, was published in July 2019.[1] It is a minor revision of the previous version, incorporating mainly clarifications, defect fixes and new recommended operations.

Should this be updated to audit against the new spec?

auroranockert

comment created time in 17 days

issue commentrust-lang/rust

Must a `const fn` behave exactly the same at runtime as at compile-time?

My understanding is that on "subnormals are zero, flush to zero" hardware, the subnormal will effectively zero when interacted with. So if Rust produces a subnormal from const compilation, then at runtime the value would be read as zero. The problem is then if an operation that behaves differently if it would see a non-zero subnormal or zero interacts with that number. Even then, if it is an arithmetic op and the result would also be a subnormal then it actually is of no consequence to continue to const eval float operations.

So there is an option of implementing a similar set of rules around NaN.

There is also an option of choosing to only const eval floats using subnormal number support, on the thesis that reading the resulting number at zero at runtime is of minimal consequence. This produces a slight compilation vs. runtime deviation, unfortunately. It would also imply never advancing hosts which cannot support it (if there are any) to tier 1.

oli-obk

comment created time in 17 days

PR opened rust-lang/stdsimd

Reviewers
Add cross-links to Zulip, etc.
+10 -1

0 comment

1 changed file

pr created time in 17 days

create barnchrust-lang/stdsimd

branch : link-more

created branch time in 17 days

PullRequestReviewEvent

pull request commentrust-lang/stdsimd

Feature/round

Alright. This seems inevitable but it's not like it's tier 1 and this is fixable.

calebzulawski

comment created time in 17 days

pull request commentrust-lang/stdsimd

Feature/round

If this affects almost everything going forward for riscv64gc then, isn't dropping the test effectively tantamount to dropping our support for that architecture? We can put that on the table as an option, but I want to be sure we're all aware of what we're putting on the table.

calebzulawski

comment created time in 18 days

more