Question: /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> StderrLock<'_> { <ins> self.lock_any() } // Locks this handle with any lifetime. This depends on the // implementation detail that the underlying `ReentrantMutex` is // static. fn lock_any<'a>(&self) -> StderrLock<'a> { </ins> StderrLock { inner: self.inner.lock() } } <ins> /// Locks and consumes this handle to the standard error stream, /// returning a writable guard. /// /// The lock is released when the returned guard goes out of scope. The /// returned guard also implements the [`Write`] trait for writing /// data. /// /// # Examples /// /// ``` /// #![feature(stdio_locked)] /// use std::io::{self, Write}; /// /// fn foo() -> io::Result<()> { ///     let stderr = io::stderr(); ///     let mut handle = stderr.into_locked(); /// ///     handle.write_all(b"hello world")?; /// ///     Ok(()) /// } /// ``` #[unstable(feature = "stdio_locked", issue = "none")] pub fn into_locked(self) -> StderrLock<'static> { self.lock_any() } </ins> } #[stable(feature = "std_debug", since = "1.16.0")]

is declared as follows: Because there is only one input lifetime (the elided lifetime of ), it is assigned to the output lifetime , which is why the lock can live at most as long as the temporary.
Thanks. I think this might be a bug in libstd (using instead of as the return type), but I'll file that separately. What I think is a diagnostic inaccuracy is that the error message refers to a borrow, when, by inspection of the library source code, no borrow is taking place in . (Unless I'm missing something?) What I think is happening is that the compiler is enforcing that lives no longer than the temporary produced by , and is misleadingly calling that a borrow in the error message.
As a simplified example: The error message refers to a borrow even when the output type of does not refer to at all!
that's because of the elision rules: on the declaration you're implicitly telling the compiler that the lifetime of the borrow matches the lifetime of the type. .
Thanks. I think the error messages could use a little more detail about how something that the borrow checker sees as a borrow may be an artifact of lifetime constraints in a function signature rather than an actual borrow in the function body. It certainly surprised me the first time I ran into it. (Maybe only in the explanatory text in the compiler error index. It looks like E0597 could also benefit from that detail, because it's a similar case, and an example in E0716 produces E0597.)
Shorter example, probably better suited for an example in the compiler error index:


Question: <ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[allow(unreachable_code)] fn main() { loop { break while continue { //~ ERROR E0590 } } } </ins>

Input: Output: This is on commit .
I've edited that code just recently so would want to work on this
Made PR to fix this
Thanks for fixing this :-) I also reported a couple of other looping-related bugs in in case you also want to have a look at those.
wow those are quite nice bugs :p. Will have a look.


Question: self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu"); self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu"); <del> self.check_toolstate(); </del> self.digest_and_sign(); let manifest = self.build_manifest(); self.write_channel_files(&self.rust_release, &manifest);

Seems like no nightly was released today. That might be related to Unfortunately I don't think I have access to the logs. Cc
Logs are missing on the server, let me start a manual release...
Well that is odd. You wouldn't know what commit is is using? ( file in the tarball, if I recall correctly.)
Is there a way for me to download the "dist" artifacts for better testing? Right now I am manually grabbing a bunch of files from https://s3-us-west- (and we only get dir listing for alt builds there it seems so I am using those). That's not very convenient at all.
Apparently not all commits are pushed to toolstate ( vs ), for example the latest one () is missing in toolstate .
Reverting the cause in the meantime --
Alternatively we could land which will just skip of the toolstate is not found. That installs a toolchain based on these artifacts, but I don't think it gives me access to the tarballs. FTR, for now I did So we are only committing when the toolstate changed? Ouch. That kills my entire approach :(
It should print the URLs it's downloading though, and you can use to avoid it actually downloading stuff.


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

The docs currently claim that the minimum Linux kernel version for is 2.6.18 (released September 20th, 2006). This is because RHEL 5 used that kernel version. However, RHEL 5 entered ELS on March 31, 2017. Should we continue to support RHEL 5 for , or should we increase the minimum Linux Kernel version to 2.6.27 (2nd LTS) or 2.6.32 (RHEL 6, 3rd LTS)? . Even bumping the min-version to 2.6.27 would allow us to remove most of the Linux-specific hacks in . Example: .
Given that RHEL is the only reason we keep comically old kernel versions around, I would propose that Rust only support RHEL until Maintenance Support ends. This is (essentially) what we already did for RHEL 4. Rust never supported RHEL 4, and back when RHEL 5 still had maintenance support. It would be nice to get someone from Red Hat or a RHEL customer to comment. This policy would allow us to increment the minimum kernel from 2.6.18 to 2.6.32 (and remove a lot of Linux-specific hacks). Note that RHEL has a weird (and very long) support system for RHEL 4, 5, and 6 (sources: and ). It has 5 major steps: Full Support Normal support of the OS Maintenance Support 1 Bug/Security fixes Limited hardware refresh Maintenance Support 2 Bug/Security fixes The end of this phase is considered "Product retirement" Extended Life Cycle Support (ELS) Additional paid product from Red Hat Gives updates for a longer period of time No additional releases/images Extended Life Phase (ELP) No more updates Limited Technical Support End date not given by Red Hat Current status of RHEL versions: RHEL 4 Not supported by Rust Currently in ELP (no end date specified) ELS ended March 31, 2017 RHEL 5 Supported by Rust Currently in ELS Maintenance Support ended March 31, 2017 ELS ends November 30, 2020 RHEL 6 Supported by Rust Currently in Maintenance Support 2 Maintenance Support ends November 30, 2020
cc which I think they could be related.


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

It also may be worth to drop support of Windows XP and Vista (especially considering that panics are broken on XP since June 2016, see: ). Previously it was discussed . cc
Besides , which other things would we be able to clean up?
Good question! There are 6 workarounds in for older Linux versions (that I could find). Increasing the minimum version to 2.6.32 (aka 3rd Kernel LTS, aka RHEL 6) would fix 5 of them. Code links are inline: (mentioned above, in 2.6.23) ( in 2.6.24, there is also the mention of a bug occuring on "some linux kernel at some point") to atomically set the flag on the pipe fds ( in 2.6.27) ( in 2.6.27) to permit use of ( in 2.6.28) ( in 4.5, not fixed by this proposal) As you can see, the workarounds fixed by this proposal all have a similar flavor.
I am Red Hat's maintainer for Rust on RHEL -- thanks for the cc. I try to keep an eye on new issues, but this one slipped past me. Red Hat only ships the Rust toolchain to customers for RHEL 7 and RHEL 8. If our customers would like to use Rust on older RHEL, they can do so via , and we'll support them in the same way we would for any other third-party software. Internally we do also build and use on RHEL 6, mostly because it's needed to ship Firefox updates. This is where it gets a little hairy, because each RHEL N is bootstrapped on RHEL N-1 and often kept that way -- meaning a lot of our RHEL 6 builders are still running on a RHEL 5 kernel. I would have to apply local workarounds if upstream Rust loses the ability to run on 2.6.18 kernels. We prefer to keep fixes upstream as much as possible, both for open sharing and to avoid bitrot. Is there much of a benefit to removing the current workarounds? I agree all of that code is annoying and cumbersome, but it's already written, and as far as I know it hasn't been a maintenance burden. Do you see otherwise?


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

If there are any known issues with such Linux compatibility code, I am definitely willing to take assignment for fixing them.
(Not a Rust maintainer, but I'm a Rust user and maintain a lot of other OSS software so I have well-developed feelings around supporting Very Old Software :-)) Do you have any sense of on what timeline Rust would be able to drop support for 2.6.18 kernels without causing you pain? In general I don't think people mind supporting configurations that have users and are painful to work around, but needing to support them for forever is a bitter pill to swallow! Particularly as they get harder and harder to test over time (already I have no idea how to test on really old kernels besides building it myself). So if there was an estimate "we'd like to be able to support this until Q2 2020", even if it's not set in stone, I think that would be very helpful!
The other benefit would be that Rust wouldn't have to use CentOS 5 for CI, which means we don't have to patch LLVM (and Emscripten LLVM) to compile on those systems. Of course that's also fairly limited in scope.
As soon as we stop shipping Firefox and Thunderbird updates on RHEL 6, I won't need Rust there anymore. AFAIK this does correspond to the end of Maintenance Support, November 30, 2020. Then I'll be on to RHEL 7 builders as my minimum, probably still with some RHEL 6 2.6.32 kernels involved. It should be fine for me if we update CI to CentOS 6. This is mostly concerned with how the release binaries are linked to GLIBC symbol versions, which is all in userspace. It's a broader community question whether any other Rust users still care about running on RHEL or CentOS 5. (Small caveat - glibc support for a symbol can still return , .)
I noticed that Red Hat also has Extended Life Cycle Support (ELS) for RHEL 6 until June 30, 2024. Will you need RHEL 5 to work during this time? I don't know how ELS works with Firefox updates. Also, is there any reason RHEL 4 support wasn't an issue prior to March 31, 2017 (while RHEL 5 was still normally supported)?


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

This issue came up for me when dealing with opening files in , see for more info. No single RHEL 5 issue is that bad, it's mainly just the sum of a bunch of tiny issues.
I'm not on that team, but AFAIK we don't ship Firefox updates for ELS. The last build I see for RHEL 5 was . Maybe there could be an exception for a severe security issue, but I really doubt we'd rebase to newer Firefox for that, which means Rust requirements won't change. New Firefox ESR versions do require a newer Rust toolchain too, which is generally why we have to keep up. Otherwise we could just freeze some older compat rustc while upstream moves on. Rust wasn't required until Firefox 52.
that makes perfect sense to me, thanks for clarifying. So the proposed policy would be: Support RHEL until RHEL is retired (i.e. ends normal support). This would mean: Supporting RHEL 5 (v2.6.18) until November 30, 2020 Supporting RHEL 6 (v2.6.32) until June 30, 2024 Supporting RHEL 7 (v3.10) until May, 2029 This is a much longer support tail than any other Linux distros (that I know of), so it would also be the effective minimum kernel version of , , and their dependencies. How does that sound to people? EDIT: The alternative to this would be Support RHEL until it is retired, taking the table above and incrementing the RHEL versions by 1. It would also mean being able to drop RHEL 5 support now.
Sure, that's ideal for me. :smile: As mentioned, is just needed for kernel support, as far as I'm concerned. Userspace concerns like GLIBC symbol versions can stick to currently supported for my needs.
Red Hat should backport the features we need (CLOEXEC and getrandom, in particular) to whatever kernels that it wants Rust to support. I don't know any good reason why they don't do so, other than it's cheaper to convince the whole world to keep supporting older kernel versions than it is to do the backports. We should change that dynamic.


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

The alternative to this would be Support RHEL N until it is retired I think we should not officially support retired OS versions (well, maybe with some grace period), so I prefer this option. Supporting 14 year old kernels seems a bit too much to me. each RHEL N is bootstrapped on RHEL N-1 and often kept that way -- meaning a lot of our RHEL 6 builders are still running on a RHEL 5 kernel Is it possible to apply kernel patches to those builders to add support for functionality like CLOEXEC? Or build Firefox separately on RHEL 6?
I think it won't be fruitful for us to debate the merits of stable enterprise kernels, but no, this is not a possibility. An alternative take is "Red Hat should be responsible for the work in Rust to maintain the support they want" -- here I am, ready and willing. I definitely can't change those kernels. The ones that are stuck on N-1 are precisely to avoid rocking the boat, and backporting features is a big change. Some of our arches do eventually update the builders to their matching N kernel, but some don't, and I don't know all the reasons. If the workarounds are removed, then I will have to reapply them in our own builds. This assumes I keep using only our own binaries -- if I ever have to re-bootstrap from upstream binaries for stage0, I would also have to use some interception (like ) to hack in the workarounds. This is all possible, but much worse than the status quo of maintaining support here.
I think this sounds reasonable. We aren't going to be able to update these kernels, it's just a question of when we would drop support for these OSes. Especially given that we wont need RHEL 5 CI support, I think that leaving things as they are is fine. I opened this issue to verify two things: 1) That we weren't intending on supporting RHEL 5 "forever", and had a clear date when to drop support. 2) That someone from Red Hat actively cared about supporting these older kernels. It looks like both these things are true. We should remove RHEL 5 workarounds after November 30, 2020. This issue can be postponed until then.


Question: cd .. rm -rf gcc-build rm -rf gcc-$GCC <del> yum erase -y gcc gcc-c++ binutils </del>

EDIT: For our use case in , we were able to add compatibility for RHEL 5 .
See for a recent case where supporting such ancient kernels required extra manual work ( to the 2 lines mentioned by above). I am not sure how often that comes up, but probably the hardest part is to even notice that it happens -- and even then those codepaths will likely linger untested.
Yes, but this will still be true in general. If the CI kernel is newer than whatever kernel baseline we choose, it will be possible for newer syscalls to pass undetected. I don't know if we have any control over that -- can we choose a particular VM image? So that leaves us with a stated policy of support. The more that developers are aware of such issues, the better, but I'm the one most likely to notice when my build actually fails. If I come back with a fix, I at least need the project to be receptive. I haven't been in the habit of building nightly on our RHEL6 builders, but maybe I should! Catching this early is better for everyone involved...
That seems reasonable. How quick is the Rust related bootstrapping? Could it be run automatically (or more frequently)? This is an interesting point. If I hadn't made that change, would have kept working on RHEL 5, it just would have leaked an FD. I'm not sure how we would even test for this sort of thing. This isn't a RHEL 5 specific concern, I just don't know how Rust tests these types of resource leak issues in general.
About 2 hours. Automation is harder, since I believe our build system needs my credentials, but I'll look into what is possible here. Yeah, that's a lot more subtle than an !


Question: tp!(r"?A:xy", "/foo", r"?A:foo"); tp!(r"?A:", r"..foo.", r"?A:foo"); tp!(r"?A:xy", r".foo.", r"?A:xyfoo"); <ins> tp!(r"?A:xy", r"", r"?A:xy"); </ins> } }

<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see this happen: Both assertions succeed. Instead, this happened: The second assertion fails, likely due to : Although adding a separator when pushing an empty path is debatable, the behavior should probably be consistent for verbatim and non-verbatim paths. This change caused to . I can add an inefficient workaround, but is this change intentional? <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: 1.56.0-beta.4 <!-- Provide the version you are using that has the regression. --: modify labels: +regression-from-stable-to-nightly -regression-untriaged +O-windows cc
This is an interesting case. The normpath crate has its own path push function to work around the issue of verbatim paths not working with PathBuf::push(), which is exactly the same issue that my PR was trying to solve upstream. The normpath push() function uses pathbuf push function to append a directory separator by calling . Since the pathbuf push now already returns normalized paths (for verbatim paths) this no longer works. I've created a PR on normpath to fix the issue there: So since verbatim paths have special handling to ensure the returned path normalized, yes there are differences. If you call on a verbatim path, then the path will remain unchanged, otherwise it would not be valid any more. We cannot expect push to work the same on verbatim paths as on non-verbatim paths, verbatim paths must be normalized.
Hm, should this not be special cased so that it works the same for all paths? Otherwise the only way to push a trailing separator is to convert to an , push the separator and then convert back to a . IMHO, ideally this would be fixed in so that trailing slashes are never normalized away but I'm uncertain if that change will be accepted.
We could special case it so that is a no-op in all cases.
Would this break existing code though?
on second thought, maybe you are right. Let me see what I can do.


Question: [[package]] name = "phf" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_codegen" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_generator" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_shared" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",

I noticed this scrolling by while "Building stage0 compiler artifacts" today: Optimistically flagging E-easy
I'd like to work on this, how can I fix? make rustc use one version(maybe v0.6.1)?
You will need to look into each dependency that depends on (by searching through ), check if they have a newer version that depends on new , and finally use to upgrade those crates.
Thanks! When I checked, it seems each rand version is used.
Yeah, it's natural that they are all used, and you could try to eliminate those crates using old by upgrading or refactoring. That said, there isn't much drawback with an older , so in that case this issue can be just closed.
Oh, I'm sorry, I misunderstood. Hmmm, I think we don't have to fix this quickly and this may be a catalyst for a newbie like me to contribute, so I leave this, okay?
but one could argue that it will lower the time to compile so it's worth to fix IMHO ;)
Uh, would it be better to fix?
Disclaimer: I'm not a core member, but IMHO this is worth fixing. Also scottmcm who is a core member opened this issue, so I guess you're good to go and fix that issue :)
Okay, I want to try to fix. For instance, depends on , how can I update or refactor this?
That's one thing you can't edit, because rand is a dependency of crossbeam-channel here, so the crate crossbeam-channel needs to update its dependecy (maybe it already did and you just need to update crossbeam-channel itself)?
For future reference, running  from is an easy way to identify the source of all duplicates.
Thanks ! I got this tree(). I updated , but is latest and depends on (). What should I do?
I'm not on compiler (or core), so don't take my word on this one :slightlysmilingface: It looks like upstream rayon needs 0.5, so you could consider making a PR to upgrade it to 0.6. (Maybe .) Also, it seems that , so they'd probably appreciate a PR to upgrade it to newer upstream.
Current rayon only uses rand as a dev-dependency, since rayon-rs/rayon.


Question: [[package]] name = "phf" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_codegen" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_generator" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", </ins> ] [[package]] name = "phf_shared" <del> version = "0.7.22" </del> <ins> version = "0.7.24" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",

That wouldn't show up in here at all, if rustc-rayon follows suit.
So the latest versions are and , but is used in this repository. They come from . Maybe those dependencies should be updated or made optional?
It looks like this was fixed in PR and merged by bors. Should this issue be closed now?
There are still 3 versions of rand in use:
will remove rand 0.5, I can get rid of 0.4 anytime but there are many PRs modifying right now.
Update: is used by , and (via ).
That's with -- only uses as a dev-dependency.
I didn't check now, but at some point was using an old version of a custom fork of .
has rebased since then, so it already reflects that dependency change.
I tried to fix a part of this in , but it didn't come out as planned. There is dependency and license whitelist that needs to be updated. I think just running leaves only one usage of via and (which can be updated). But then there is the licensing story, and it's not very clear to me which dependencies are used by the tools, and which by the compiler.
Last time I checked and were the only thing preventing of , otherwise I'd fix it already. We are working on removing it but it's blocked on releasing new version of .
I think goes away after a , so that one might be easy to fix. I don't know how dependencies are updated across the repository. Is it just that most of them are for the tools, not for and ? Does somebody run from time to time? And why does the license check fail on bors on my PR, but not on Travis or on my computer?
So released new version since. Correct, dependencies of everything that is created by are tracked by single . Dependencies are often updated separately as needed because upgrading everything at once is likely to break something and it's easier to find what is wrong when you change like 5 dependencies instead of 50. I think it should error when you run .
Also you can run the same image that found the error ( in this case) by using these steps


Question: <del> error[E0720]: cannot resolve opaque type --> $DIR/default-body-with-rpit.rs:10:28 | LL |     async fn baz(&self) -> impl Debug { |                            ^^^^^^^^^^ cannot resolve opaque type | = note: these returned values have a concrete "never" type = help: this error will resolve once the item's body returns a concrete type error: aborting due to previous error For more information about this error, try `rustc --explain E0720`. </del>

Here's a MVCE: I expected to see this happen: compilation fails because I'm clearly returning an instead of a Instead, this happened: bad codegen ("async fn resumed after completion") :
This is specifically a bug with default body in traits, this doesn't happen in s. I'll check it out, it's probably a very simple fix.


Question: <ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(rustc_attrs)] enum Abc { A(u8), B(i8), C, D, } #[rustc_mir] fn foo(x: Abc) -> i32 { match x { Abc::C => 3, Abc::D => 4, Abc::B(_) => 2, Abc::A(_) => 1, } } #[rustc_mir] fn foo2(x: Abc) -> bool { match x { Abc::D => true, _ => false } } fn main() { assert_eq!(1, foo(Abc::A(42))); assert_eq!(2, foo(Abc::B(-100))); assert_eq!(3, foo(Abc::C)); assert_eq!(4, foo(Abc::D)); assert_eq!(false, foo2(Abc::A(1))); assert_eq!(false, foo2(Abc::B(2))); assert_eq!(false, foo2(Abc::C)); assert_eq!(true, foo2(Abc::D)); } </ins>

The Switch terminator, which is used in pattern matching, is currently unimplemented in MIR. This terminator should load the discriminant from an lvalue and branch to the appropriate basic block target based on what is found there. It has to integrate with the code.


Question: <del> // Regression test for <https://github.com/rust-lang/rust/issues/100529>. #![no_core] #![feature(no_core)] // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), } </del>

At some point their should also be a for , and probably a way to tell what position each of the non stripped items are, as currently each of these 3 variants are documented with the same inner. but HTML gets a good representation:  The solution is probably to do what we do for structs, and store the , and a , such that each field of a varient gets an to hold the . We also should have a numfields, as even in that schema, you can't tell the difference between This also effects struct AFAIKT. I don't think this needs to be done now. I'll file an issue for it. Originally posted by in modify labels: +A-rustdoc-json +T-rustdoc
Related:


Question: Ok(result.callee) } <ins> pub fn lookup_method_for_diagnostic( &self, self_ty: Ty<'tcx>, segment: &hir::PathSegment<'_>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, ) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> { let pick = self.lookup_probe_for_diagnostic( segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope, None, )?; Ok(self .confirm_method_for_diagnostic(span, self_expr, call_expr, self_ty, &pick, segment) .callee) } </ins> #[instrument(level = "debug", skip(self, call_expr))] pub fn lookup_probe( &self,

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --No user code, just trying to compile my project. The is <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
Do you mind checking if this still ICEs on the most recent nightly?
I just did that now, and it looks like the issue is fixed on the latest nightly. (sorry should have tried that in first place!)
That's weird, because I can repro it (cross-compiling for from linux if it matters).
on the latest nightly?
yep: Also the version of winit from the report () is not the latest . I'm working on bisecting and reducing now
Wait, this actually ICEs on stable too and I didn't notice because rustc emitted a bunch of errors after the ICE (?!)
I've reduced it down to this (which is no longer macOS or aarch64 dependent): (The assignment to was of course something more reasonable in the original code, but now I can't seem to replace it without making the ICE go away) This failed to compile without ICE on 1.69: Regression in () searched nightlies: from nightly-2023-03-06 to nightly-2023-04-19 regressed nightly: nightly-2023-04-15 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.6</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </details label regression-from-stable-to-stable
Whoops, I seemed to have caused it I'll look into it!
WG-prioritization assigning priority (). label -I-prioritize +P-medium


Question: /// uniquely determined by `t` (see RFC 447). If it is true, return the list /// of parameters whose values are needed in order to constrain `ty` - these /// differ, with the latter being a superset, in the presence of projections. <del> pub fn parameters_for<'tcx, T>(t: &T, include_nonconstraining: bool) -> Vec<Parameter> where T: TypeFoldable<'tcx> { </del> <ins> pub fn parameters_for<'tcx>( t: &impl TypeFoldable<'tcx>, include_nonconstraining: bool, ) -> Vec<Parameter> { </ins> let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining,

The second error in this snippet is "nonsense" because it says the type parameter is not constrained, while the real error was already reported — the actual type could not be imported. Found in: rustc 1.13.0-nightly ( 2016-09-26)
.


Question: impl Foo for Bar { // ok! // functions implementation } <ins> fn baz<T: Foo>(t: T) {} // ok! </ins> ``` <del> or: </del> <ins> Alternatively, you could introduce a new trait with your desired restrictions as a super trait: </ins> ``` <del> trait Foo { // some functions } </del> <ins> # trait Foo {} # struct Bar; # impl Foo for Bar {} trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo fn baz<T: Qux>(t: T) {} // also ok! ``` Finally, if you are on nightly and want to use a trait alias instead of a type alias, you should use `#![feature(trait_alias)]`: ``` #![feature(trait_alias)] trait Foo = Iterator<Item=String>; </ins> fn bar<T: Foo>(t: T) {} // ok! ```

I managed to reproduce the problem with this snippet: The compiler yells E0404 at me, but fair enough I always ask it to a bit more about it :) However this time, it only says this: This is confusing because the snippet above doesn't involve the keyword so I didn't understand initially what I was doing wrong, then I read the error message again: I first tried this, and it worked, but having to repeat the whole syntax everywhere wasn't too compelling, hence the alias: The compiler error message makes it very clear that I can't alias a trait, but the E0404 explanation doesn't mention it at all. I hope the description could also include this use case as I've seen sometimes EXXXX explanations go over several facets of the same problem. That won't help me, but maybe others that may trip on the same problem. I would have submitted a pull request for the docs myself, but I have no idea why you can't use type aliases for traits so I can't it ;) I'm using stable Rust 1.19.0 (on Fedora).
One more thing, even though the compiler lets me create an alias for a trait, I don't know when I can use such an alias. Maybe this should be explained too.
Current output (in nightly):
Current output: No structured suggestion for the nightly feature (should be and the feature flag).


Question: name = "build-manifest" version = "0.1.0" dependencies = [ <del> "reqwest", </del> "serde", <del> "serde_json", </del> "toml", ]


Question: } } <ins> // FIXME(#10432) </ins> impl Seek for MemWriter { fn tell(&self) -> u64 { self.pos as u64 } fn seek(&mut self, pos: i64, style: SeekStyle) { <del> match style { SeekSet => { self.pos = pos as uint; } SeekEnd => { self.pos = self.buf.len() + pos as uint; } SeekCur => { self.pos += pos as uint; } } </del> <ins> // compute offset as signed and clamp to prevent overflow let offset = match style { SeekSet => { 0 } SeekEnd => { self.buf.len() } SeekCur => { self.pos } } as i64; self.pos = max(0, offset+pos) as uint; </ins> } }

Currently all of its functions immediately . We need to either remove this or implement it. I vote for implementing it.


Question: pub type SuccessorsMut<'a> = iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>; <del> impl<'tcx> Terminator<'tcx> { pub fn successors(&self) -> Successors<'_> { self.kind.successors() } pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { self.kind.successors_mut() } pub fn unwind(&self) -> Option<&Option<BasicBlock>> { self.kind.unwind() } pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { self.kind.unwind_mut() } } impl<'tcx> TerminatorKind<'tcx> { pub fn if_( tcx: TyCtxt<'tcx>, cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock, ) -> TerminatorKind<'tcx> { static BOOL_SWITCH_FALSE: &[u128] = &[0]; TerminatorKind::SwitchInt { discr: cond, switch_ty: tcx.types.bool, values: From::from(BOOL_SWITCH_FALSE), targets: vec![f, t], } } pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { Resume | Abort | GeneratorDrop | Return | Unreachable | Call { destination: None, cleanup: None, .. } | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), Goto { target: ref t } | Call { destination: None, cleanup: Some(ref t), .. } | Call { destination: Some((_, ref t)), cleanup: None, .. } | Yield { resume: ref t, drop: None, .. } | DropAndReplace { target: ref t, unwind: None, .. } | Drop { target: ref t, unwind: None, .. } | Assert { target: ref t, cleanup: None, .. } | FalseUnwind { real_target: ref t, unwind: None } | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } | Yield { resume: ref t, drop: Some(ref u), .. } | DropAndReplace { target: ref t, unwind: Some(ref u), .. } | Drop { target: ref t, unwind: Some(ref u), .. } | Assert { target: ref t, cleanup: Some(ref u), .. } | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { Some(t).into_iter().chain(slice::from_ref(u)) } SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), FalseEdge { ref real_target, ref imaginary_target } => { Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) } } } pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { use self::TerminatorKind::*; match *self { Resume | Abort | GeneratorDrop | Return | Unreachable | Call { destination: None, cleanup: None, .. } | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), Goto { target: ref mut t } | Call { destination: None, cleanup: Some(ref mut t), .. } | Call { destination: Some((_, ref mut t)), cleanup: None, .. } | Yield { resume: ref mut t, drop: None, .. } | DropAndReplace { target: ref mut t, unwind: None, .. } | Drop { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { Some(t).into_iter().chain(slice::from_mut(u)) } SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), FalseEdge { ref mut real_target, ref mut imaginary_target } => { Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) } } } pub fn unwind(&self) -> Option<&Option<BasicBlock>> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::InlineAsm { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } | TerminatorKind::DropAndReplace { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), } } pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::InlineAsm { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } | TerminatorKind::DropAndReplace { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), } } } </del> impl<'tcx> BasicBlockData<'tcx> { pub fn new(terminator: Option<Terminator<'tcx>>) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator, is_cleanup: false }

moved the file to over 3k LOC, but I didn't fix it there and instead just annotated the file so tidy ignores it. We should probably split the mir types into separate submodules by the way they are used in MIR. I think we can start by pulling out e.g. terminators and all their sub-types to a submodule <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim Will be interested in picking this up


Question: <ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn foo(_s: i16) { } fn bar(_s: u32) { } fn main() { foo(1*(1 as int)); //~^ ERROR: mismatched types: expected `i16`, found `int` (expected `i16`, found `int`) bar(1*(1 as uint)); //~^ ERROR: mismatched types: expected `u32`, found `uint` (expected `u32`, found `uint`) } </ins>

Sorry for not providing smaller case but I hope this is better than nothing: Both versions works (compile and start), but runtime behavior changes. The code that follows the above part: will match no matter what really is, if the value is partially moved (so mouse events are updating my game). If I use the version with , the code works as intended and game is updated only on keyboard presses.
Minimal: This shouldn't compile at all.
Nominating.
Looks like a regression. 0.10 rejects this code.


Question: <ins> fn main() { &{[1, 2, 3][4]}; //~^ ERROR index out of bounds //~| ERROR reaching this expression at runtime will panic or abort //~| ERROR this expression will panic at runtime } </ins>

Originally stumbled upon through the eval IRC bot: Here's the smallest reproduction I could get, Removing either the block or the borrow displays only a normal compiler error (not an ICE) trace
triage: P-high, assigned to ; removing I-nominated label


Question: version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",


Question: version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",


Question: LL | #![deny(dead_code)] |         ^^^^^^^^^ <del> error: aborting due to 1 previous error </del> <ins> error: variant `Variant1` is never constructed --> $DIR/unused-variant.rs:11:5 | LL | enum TupleVariant { |      ------------ variant in this enum LL |     Variant1(i32), |     ^^^^^^^^ | = note: `TupleVariant` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis error: variant `Variant1` is never constructed --> $DIR/unused-variant.rs:17:5 | LL | enum StructVariant { |      ------------- variant in this enum LL |     Variant1 { id: i32 }, |     ^^^^^^^^ | = note: `StructVariant` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis error: aborting due to 3 previous errors </ins>

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: build cleanly Instead, this happened: Running the program shows the field is used: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --Rust version 1.77.0 (tested in playground) </p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Derived code is intentionally ignored for dead code analysis - if you try just You'll get a note explaining this. The note doesn't seem to be attached for warnings, just
Ah, so it's intentional. Interesting. I assume the solution is to mark it with then.
claim
release-assignment so can claim it
Error: Parsing assign command in failed: ...'assignment' ' so Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
claim
Note that while getting a warning if is just derived but never explicitly used may be understandable (as discussed in other issues), you will get a warning if you do use it explicitly (see ) which, in my opinion, should not be the case.
As mentioned above, the fix for this issue is adding a note about how derived traits are intentionally ignored, not to stop ignoring them.


Question: fn visit_lifetime(&mut self, _: &hir::Lifetime) { // Unneeded. } <ins> fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) { let prev = mem::replace(&mut self.inside_body, true); walk_body(self, b); self.inside_body = prev; } </ins> }

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --Consider the following code is local to and inaccessible, and should not be documented. Instead, rustdoc currently documents the module at the same level as . <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: </details
cc does this have to do with those changes you made to item collection?
Very likely. I won't be able to fix it until next week though. EDIT: I suspect it broke from
I just realized that this is broken on stable, too, so I think the cause may be older than that?
Oh. I'm at least happy to realize that I didn't break it recently. Thanks for the report. Will fix it monday.


Question: let const_data = self.encode_rendered_const_for_body(body_id); let qualifs = self.tcx.mir_const_qualif(def_id); <del> record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Const(qualifs, const_data)); </del> <ins> record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst(qualifs, const_data)); </ins> record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public); record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id)); self.encode_item_type(def_id.to_def_id());

Currently with const generics you can create a "specialized" implementation, such as: Which has the following output: (playground link: ) However, when using such a type in another crate this causes a stack overflow in the compiler. For example, with the following code (full example: ): I would expect it to produce the same output as the playground link above, however it produces the following:
A bisect shows this stopped crashing after , marked as needing a test
I was still encountering this in my code with and after trying to minimize it seems that the original example is fixed but the stack overflow still occurs when the const expression in the has braces around it. After experimenting I found some more examples of what works and what doesn't: (see to try it) compiles and runs successfully while and (or ) crash the compiler with the same error as the original: :


Question: version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",


Question: version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ <del> "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", </del> <ins> "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", </ins> "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",


Question: = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` help: try using `=` instead | <del> LL -     B == 2 LL +     B = 2 | </del> <ins> LL |     B = 2 |       ~ </ins> error: expected item, found `==` --> $DIR/issue-101477-enum.rs:6:7

<!-- ICE: Rustc '' 'thread 'rustc' panicked at 'assertion failed: bpos.tou32() = () + as u32'', 'thread 'rustc' panicked at 'assertion failed: bpos.tou32() = () + as u32'' File: --snippet: Version information Command: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongProgram output</strong</summary<p</p</details<!-- query stack: --
cc
I suspect that we don't really need anymore, tbh.
Addressed in Every time I convince myself that "synthesizing a is ok this time", I'm proved wrong.
WG-prioritization assigning priority (). label -I-prioritize +P-medium


Question: <ins> error[E0277]: the size for values of type `[usize]` cannot be known at compilation time --> $DIR/issue-36122-accessing-externed-dst.rs:3:24 | LL |         static symbol: [usize]; |                        ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `[usize]` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. </ins>

Reproduction branch: When applying the change from the last commit I get a panic in my code during the call to . <details<summaryBacktrace</summary</details
Cannot reproduce on my linux. Can you provide a small ? Is that possible? Maybe without all the externals :/
I can reproduce a very similar problem (appears to involve the same origin and failing assertion of ) compiling rust-lang/regex with and compiler flags: For me, setting to 2 or greater is required to present this failure. <details<summarybacktrace</summary<code<preRUSTBACKTRACE=1 cargo build Compiling regex v1.1.2 (/home/kent/rust/regex) thread 'rustc' panicked at 'assertion failed: bpos.tou32() = () + as u32', stack backtrace: 0: std::sys::unix::backtrace::tracing::imp::unwindbacktrace at 1: std::syscommon::backtrace::print at 2: std::panicking::defaulthook::{{closure}} at at 3: std::panicking::defaulthook at 4: rustc::util::common::panichook 5: std::panicking::rustpanicwithhook at 6: std::panicking::beginpanic 7: syntax::sourcemap::SourceMap::bytepostofilecharpos 8: syntax::sourcemap::SourceMap::lookupcharpos 9: <rustccodegenssa::mir::FunctionCx<'a, 'tcx, Bx::scopemetadataforloc 10: <rustccodegenssa::mir::FunctionCx<'a, 'tcx,


Question: <ins> error[E0277]: the size for values of type `[usize]` cannot be known at compilation time --> $DIR/issue-36122-accessing-externed-dst.rs:3:24 | LL |         static symbol: [usize]; |                        ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `[usize]` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. </ins>

Bx::debugloc 11: rustccodegenssa::mir::codegenmir 12: rustccodegenssa::base::codegeninstance 13: rustccodegenssa::monoitem::MonoItemExt::define 14: rustccodegenllvm::base::compilecodegenunit::modulecodegen 15: rustc::depgraph::graph::DepGraph::withtask 16: rustccodegenllvm::base::compilecodegenunit 17: rustccodegenssa::base::codegencrate 18: <rustccodegenllvm::LlvmCodegenBackend as rustccodegenutils::codegenbackend::CodegenBackend::codegencrate 19: rustc::util::common::time 20: rustcdriver::driver::phase4codegen 21: rustcdriver::driver::compileinput::{{closure}} 22: <std::thread::local::LocalKey<T::with 23: rustc::ty::context::TyCtxt::createandenter 24: rustcdriver::driver::compileinput 25: rustcdriver::runcompilerwithpool 26: <scopedtls::ScopedKey<T::set 27: rustcdriver::runcompiler 28: syntax::withglobals 29: rustmaybecatchpanic at 30: <F as alloc::boxed::FnBox<A::callbox 31: std::sys::unix::thread::Thread::new::threadstart at at at 32: <unknown33: clone query stack during panic: end of query stack error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.34.0-nightly ( 2019-02-26) running on x86_64-unknown-linux-gnu note: compiler flags: -Z mir-opt-level=2 -C debuginfo=2 -C incremental --crate-type lib </pre</code</details
With the help of , I've found a tiny test that reproduces this crash on Linux and Mac:
Got another one: <details</detailsHappens when compiling regex tests with and calling on every span found in the mir of the functions needing codegen.
According to glaicer, the ICE from this example has been gone.
can you confirm that your example does not crash on nightly anymore?


Question: <ins> error[E0277]: the size for values of type `[usize]` cannot be known at compilation time --> $DIR/issue-36122-accessing-externed-dst.rs:3:24 | LL |         static symbol: [usize]; |                        ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `[usize]` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. </ins>

Has been fixed in
is likely the part of the rollup fixing it.
Shouldn't a testcase be instead of closing this?
A similar crash that still happens:


Question: <ins> error[E0277]: the size for values of type `[usize]` cannot be known at compilation time --> $DIR/issue-36122-accessing-externed-dst.rs:3:24 | LL |         static symbol: [usize]; |                        ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `[usize]` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. </ins>

I realize it's kinda nonsensical, but here:
Why didn't WF catch this?
That's because only checks statics/constants.
Still reproducible with .
This ought to be a mostly easy fix. The problem is that the well formedness check, which ought to be rejected this code, is ignoring things in an : They fall through to this `` case: We would need to add support for the HIR item: which in turn has a number of items: which are defined here: presumably we want the to check that the types of are well-formed, roughly analogous to how we current check normal static items: (We probably want similar checks on foreign item fns, though?) One tricky part might be compatibility, we may need to turn this into a compatibility lint in case there is lots of broken code in the wild.
I am trying to fix this bug, and need help moving forward. function is modified to accept a and a , yet it doesn't report any additional errors and the ICE prevails. Test file: Commit: Should I create a pull request or is it too early?
Looks like suggestions are incomplete ( does not require ). Also, I left a comment on your commit about how you can avoid adding . I suspect the only reason regular s are required to be is they have an initializer (and that, not the type, requires ), i.e. for we have these errors:
Oddly, the PR that were previously posted to fix this (PR , following on PR ) was subsequently closed as inactive ... but the bug itself seems like it may have been resolved in the meantime?
I'm going to assume this was fixed. Tagging as E-needstest, but if someone wants to take the time, it'd be even better to bisect to where this was fixed, and see if a regression test for this was at that time.
Compiler no longer panics, tested with


Question: LL |     arg.map(|v| &**v) |        ++++++++++++++ <del> error: aborting due to 1 previous error </del> <ins> error[E0308]: mismatched types --> $DIR/transforming-option-ref-issue-127545.rs:9:19 | LL |     arg.unwrap_or(&[]) |         --------- ^^^ expected `&Vec<i32>`, found `&[_; 0]` |         | |         arguments to this method are incorrect | = note: expected reference `&Vec<i32>` found reference `&[_; 0]` help: the return type of this call is `&[_; 0]` due to the type of the argument passed --> $DIR/transforming-option-ref-issue-127545.rs:9:5 | LL |     arg.unwrap_or(&[]) |     ^^^^^^^^^^^^^^---^ |                   | |                   this argument influences the return type of `unwrap_or` note: method defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: use `Option::map_or` to deref inner value of `Option` | LL |     arg.map_or(&[], |v| v) |         ~~~~~~    +++++++ error[E0308]: mismatched types --> $DIR/transforming-option-ref-issue-127545.rs:13:19 | LL |     arg.unwrap_or(v) |         --------- ^ expected `&Vec<i32>`, found `&[i32]` |         | |         arguments to this method are incorrect | = note: expected reference `&Vec<i32>` found reference `&'a [i32]` help: the return type of this call is `&'a [i32]` due to the type of the argument passed --> $DIR/transforming-option-ref-issue-127545.rs:13:5 | LL |     arg.unwrap_or(v) |     ^^^^^^^^^^^^^^-^ |                   | |                   this argument influences the return type of `unwrap_or` note: method defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: use `Option::map_or` to deref inner value of `Option` | LL |     arg.map_or(v, |v| v) |         ~~~~~~  +++++++ error[E0308]: mismatched types --> $DIR/transforming-option-ref-issue-127545.rs:17:19 | LL |     arg.unwrap_or(&[]) |         --------- ^^^ expected `&Vec<i32>`, found `&[_; 0]` |         | |         arguments to this method are incorrect | = note: expected reference `&Vec<i32>` found reference `&[_; 0]` help: the return type of this call is `&[_; 0]` due to the type of the argument passed --> $DIR/transforming-option-ref-issue-127545.rs:17:5 | LL |     arg.unwrap_or(&[]) |     ^^^^^^^^^^^^^^---^ |                   | |                   this argument influences the return type of `unwrap_or` note: method defined here --> $SRC_DIR/core/src/result.rs:LL:COL help: use `Result::map_or` to deref inner value of `Result` | LL |     arg.map_or(&[], |v| v) |         ~~~~~~    +++++++ error: aborting due to 4 previous errors </ins> For more information about this error, try `rustc --explain E0308`.

Given : Current error, for the motivating use case above: It should be possible for rustc to suggest replacing this specific instantiation of with . Maybe similarly for some other common cases: . Originally posted by in label -T-rustdoc T-compiler


Question: <ins> // check-pass // compile-flags: -Z validate-mir #![feature(let_chains)] fn let_chains(entry: std::io::Result<std::fs::DirEntry>) { if let Ok(entry) = entry && let Some(s) = entry.file_name().to_str() && s.contains("") {} } fn main() {} </ins>

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: both compiles successfully Instead, this happened: fails to compile <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
This may have something to do with , as there is something about let_chain drops here as well, but I don't for sure.
The same behaviour happens with an older compiler version. Here goes an example that compiles with . It is not up to me to decide if this behaviour is a blocker that will revert stabilization but in case of such event, I won't have enough free time to investigate and fix stuff in the near future.
Personally and despite the differences, I think that the version is "correct" and the nested version is surprisingly holding a reference of an owned structure () without an explicit bind.
drops the scrutinee after the statement.
cc who have been dealing with dropping stuff related to
Some things that might be helpful to know: The drop order changes for in also had borrow checker impact and made an example compile (see the PR's thread). I'm not a borrow checker expert, so I might be wrong, but this too might be fixed by drop order changes alone. In I'm studying drop order impacts of conditional statements, motivated by let else, but the test that PR adds also includes let chains. There I observed that let chains generally behave drop order wise like when there is a involved, and when it's a bool. I have only studied them regarding the body contained inside though. This table provides a summary of drop orders (disclaimer: it's outdated for let else):
I've locally amended of to add if let chains: And this is the output: Which actually runs counter to what I wrote above, because it predrops.


Question: <ins> // check-pass // compile-flags: -Z validate-mir #![feature(let_chains)] fn let_chains(entry: std::io::Result<std::fs::DirEntry>) { if let Ok(entry) = entry && let Some(s) = entry.file_name().to_str() && s.contains("") {} } fn main() {} </ins>

It seems that it depends on whether the in the chain is preceded by a or not: if you change the line with to , removing the , you get this: So that rule that I wrote above is not correct, but the underlying behaviour is more complicated. Hmmm...
Thanks
claim
pointed this out to me. It may be motivation to revert the stablization of let-chains on beta. Lets try to ensure we talk about this at Thursday triage label I-compiler-nominated
False alarm; pointed out to me that let-chains is already been marked unstable (on beta and nightly). label: -I-compiler-nominated


Question: = help: add `#![feature(derive_smart_pointer)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date <del> error: aborting due to 3 previous errors </del> <ins> error: aborting due to 2 previous errors </ins> For more information about this error, try `rustc --explain E0658`.

https://crater- https://crater- cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
cc
label F-derivesmartpointer
Thread on zulip: https://rust-
claim
WG-prioritization assigning priority (). label -I-prioritize +P-high


Question: [[package]] name = "git2" <del> version = "0.11.0" </del> <ins> version = "0.12.0" </ins> source = "registry+https://github.com/rust-lang/crates.io-index" <del> checksum = "77519ef7c5beee314d0804d4534f01e0f9e8d9acdee2b7a48627e590b27e0ec4" </del> <ins> checksum = "26e07ef27260a78f7e8d218ebac2c72f2c4db50493741b190b6e8eade1da7c68" </ins> dependencies = [ "bitflags", "libc",

Hello, this is your friendly neighborhood mergebot. After merging PR rust-lang/rust, I observed that the tool clippy-driver no longer builds. A follow-up PR to the repository is needed to fix the fallout. cc do you think you would have time to do the follow-up work? If so, that would be great! And nominating for compiler team prioritization.


Question: declare_lint!(OVERFLOWING_LITERALS, Warn, "literal out of range for its type") <ins> declare_lint!(EXCEEDING_BITSHIFTS, Deny, "shift exceeds the type's number of bits") </ins> pub struct TypeLimits { /// Id of the last visited negated expression negated_expr_id: ast::NodeId,

Currently overlong bit shifts are undefined behavior because that's how llvm rolls--. But even when they aren't, we should warn on something like where happens to be , since it's a useless operation that couldn't possibly return anything interesting. There's a and I imagine it'd be a common gotcha since other languages tend to read unadorned integral literals as 32bit s and then promote the in before doing the actual shift.
I think this can be closed, resolved in
Hooray!


Question: <ins> error: `enum` and `struct` are mutually exclusive --> $DIR/issue-99625-enum-struct-mutually-exclusive.rs:3:5 | LL | pub enum struct Range { |     ^^^^^^^^^^^ help: replace `enum struct` with: `enum` error: aborting due to previous error </ins>

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: <!-- Please provide a link to --The current output is: <!-- The following is not always necessary. --Ideally the output should look like: Highlight to the user that the keywords and are mutually exclusive. Replace with . <!-- If the problem is not self-explanatory, please provide a rationale for the change. --<!-- If dramatically different output is caused by small changes, consider also adding them here. If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition. --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: } /// Returns the set of parameters constrained by the impl header. <del> pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>, impl_trait_ref: Option<ty::TraitRef<'tcx>>) -> FxHashSet<Parameter> { </del> <ins> pub fn parameters_for_impl<'tcx>( impl_self_ty: Ty<'tcx>, impl_trait_ref: Option<ty::TraitRef<'tcx>>, ) -> FxHashSet<Parameter> { </ins> let vec = match impl_trait_ref { Some(tr) => parameters_for(&tr, false), None => parameters_for(&impl_self_ty, false),

The second error in this snippet is "nonsense" because it says the type parameter is not constrained, while the real error was already reported — the actual type could not be imported. Found in: rustc 1.13.0-nightly ( 2016-09-26)
.


Question: <ins> error: unexpected closing delimiter: `)` --> $DIR/issue-98601-delimiter-error-unexpected-close.rs:5:17 | LL | fn main() { |           - this opening brace... LL |     todo!(); LL | } | - ...matches this closing brace LL | LL | fn other(_: i32)) {} |                 ^ unexpected closing delimiter error: aborting due to previous error </ins>

See: This code: produces on latest stable (1.61.0).
Maybe we could form a heuristic around tokens that we know should eventually be followed by -- , , , etc. If we see one of those, (then some random other tokens), then we see , then that would be a suspicious rbrace which we could point out later.. e.g. if we see that triggers the heuristic, but not
The problem is that the error happens in the lexer, not the parser. Ideally we'd rework the lexer to have a token stream mode of operation instead of a token tree mode of operation, only for code that is being passed to the parser (i.e., not coming from a macro).
This is particularly confusing when the points to a macro: gives on 1.65.0-nightly (2022-08-31 )
the output now changed to: Do you think the should be removed?
This is changed to: it seems more helpful now.
Let's close this ticket after adding these two cases to the test suite then. I'm sure there are outstanding issues in this area, but we can hope that we'll get tickets for those more specific cases, while the tests keep us from regressing silently (hopefully, lets make sure the tests are fully annotated so its harder to do that by accident).


Question: // Float => does not implement iterator. for i in 0f32..42f32 {} <del> //~^ ERROR `core::iter::Iterator` is not implemented for the type `core::ops::Range<f32>` //~^^ ERROR //~^^^ ERROR // FIXME(#21528) not fulfilled obligation error should be reported once, not thrice </del> <ins> //~^ ERROR the trait `core::num::Int` is not implemented for the type `f32` </ins> // Unsized type. let arr: &[_] = &[1us, 2, 3];

cc
I think you have a PR that improves type inference in some cases where closures are involved (?), do you know if by chance that fixes this as well?
This is not closure specific:
This must be duo to . It seems to enforce the numeric fallback rule a bit too eagerly.
Another example from IRC is that type checked while didn't. Rather interesting.
edwardw, not just that, type inference regressed slightly at the time of the range stabilization PR.
also related
Have a partial fix by deferring numeric fallback, but it seems to hit now.
OK, so I spent some time digging into this. I don't think that deferring numeric fallback is necessarily the solution. sorry if I kept disappearing on IRC, I had to put my head down and study the log to see what was happening. So what seems to happen is that we correctly come up with the constraint: However, we are unable to make the connection between and . The reason is that the new has separate impls for each of the numeric types, whereas the old had only impl for a type . When we process the projections, we first try to resolve (without considering the output type ), and we get ambiguity, because there are many impls that could apply. Unfortunately this all seems a bit right to me. Basically we're trying to infer the type of the range from the output type, which is the reverse direction inference is supposed to go. When we used a blanket impl, we were able to resolve this because there was only one impl for . Probably the best fix is to go back to that, actually, but this is an interesting quandry. I'll have to think about it a bit.
To be clear, the example I was digging into was
Also, to put it another way: having a single blanket impl allows us to draw the connection that when you iterate over , you get . With the current setup of many distinct impls, that is not known to be true.
After some discussion with on RFC, I just wanted to clarify a few things (I myself was a touch confused too). the impl is probably the easiest way to fix this in the short term. , to some extent, this limitation is an artifact of how trait matching is implemented. That is, we intentionally do not take output bindings into account when selecting traits.


Question: // Float => does not implement iterator. for i in 0f32..42f32 {} <del> //~^ ERROR `core::iter::Iterator` is not implemented for the type `core::ops::Range<f32>` //~^^ ERROR //~^^^ ERROR // FIXME(#21528) not fulfilled obligation error should be reported once, not thrice </del> <ins> //~^ ERROR the trait `core::num::Int` is not implemented for the type `f32` </ins> // Unsized type. let arr: &[_] = &[1us, 2, 3];

However, it doesn't have to be this way, but it'd take some work to massage the trait matching infrastructure, since impl selection doesn't presently have access to output binding information, that'd have to be propagated inward. It might be interesting to try and address this in a more wholistic way (i.e., something that accounts for the full set of facts that are registered). particular, the important constraint that we MUST maintain is that, during trans, given the input types, we can derive the output type. But it's permissible for us to use the output type to derive the input type during type checking, since once inference is done, we then have the input types to supply during trans so that we can rederive the output.
The fix is very simple then. Thanks for helping diagnose the problem and pointing to the right direction.


Question: // Float => does not implement iterator. for i in 0f32..42f32 {} <del> //~^ ERROR `core::iter::Iterator` is not implemented for the type `core::ops::Range<f32>` //~^^ ERROR //~^^^ ERROR // FIXME(#21528) not fulfilled obligation error should be reported once, not thrice </del> <ins> //~^ ERROR the trait `core::num::Int` is not implemented for the type `f32` </ins> // Unsized type. let arr: &[_] = &[1us, 2, 3];

This code compiled fine before 1.0.0-nightly ( 2015-01-23 16:08:14 +0000): But with that version, it now gives this error:
changing to should work, I stumbled upon the same thing and the doc seems to be updated: (see at the very bottom) EDIT: Maybe worth noting that these work:
That's just a workaround to a bug (not sure if that was implied). should fall back to being as per the existence of the integer fallback.
I don't necessarily expect this to work. Fallback comes late in the process, once all constraints are known, but (like method dispatch) requires the type being cast to be known immediately.
It's plausible we could make it work since we know that the type is integral (I imagine that's how it ever worked, not sure what would have changed that, though it might have been something I did). It occurs to me though that this is somewhat forward-hostile to the idea of integer literals ever being used for anything other than plain ints (but enabling such a feature may well wind up requiring opt-in anyway).
(Though really it's sort of silly that requires the type to be known immediately, so I guess fixing that would be another way to ease the forward compat fears.)
I thought this was a feature because it's saying that it doesn't know if it's or for example. Would it assume it's signed only if it contains negative numbers in the range? EDIT3: what said makes sense: EDIT2: ignore the following, my bad But I might be missing something because this doesn't output anything from : EDIT: just realized -1u32 is too big so the following makes sense: There's no output from , unless using


Question: /// [`Metadata`]: struct.Metadata.html /// [`fs::metadata`]: fn.metadata.html /// [`fs::symlink_metadata`]: fn.symlink_metadata.html <ins> /// [`is_dir`]: struct.FileType.html#method.is_dir /// [`is_file`]: struct.FileType.html#method.is_file </ins> /// [`is_symlink`]: struct.FileType.html#method.is_symlink /// /// # Examples

should document that , , and are all mutually exclusive. (and that it may also be the case that none of them are true) Why? Because returns true for both files and symlinks to files, and this tends to make me paranoid that a will share similar characteristics and perhaps claim that both and . The only way to convince myself that FileType's behavior is indeed sane is to write a little test program---again. Surely I can't be alone in this.
is calling not (and equivalent on Windows), so if the path is a symlink, then it returns the results based on what the symlink points to, not the symlink itself. So respects the same mutual exclusivity rules as . But yes, this ought to be documented, especially given that the mutually exclusive behavior may be surprising to Windows developers.
Similar goes for , which should document that these are always false for a obtained by calling on a symlink.
Well you can always call on something that is not a symlink, in which case or could be true.


Question: unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } } <del> /// Converts the bytes while the bytes are still ascii. </del> <ins> /// Converts leading ascii bytes in `s` by calling the `convert` function. /// </ins> /// For better average performance, this happens in chunks of `2*size_of::<usize>()`. <del> /// Returns a vec with the converted bytes. </del> <ins> /// /// Returns a tuple of the converted prefix and the remainder starting from /// the first non-ascii character. /// /// This function is only public so that it can be verified in a codegen test, /// see `issue-123712-str-to-lower-autovectorization.rs`. #[unstable(feature = "str_internals", issue = "none")] #[doc(hidden)] </ins> #[inline] #[cfg(not(test))] #[cfg(not(no_global_oom_handling))] <del> fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> { let mut out = Vec::with_capacity(b.len()); </del> <ins> pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { // Process the input in chunks of 16 bytes to enable auto-vectorization. // Previously the chunk size depended on the size of `usize`, // but on 32-bit platforms with sse or neon is also the better choice. // The only downside on other platforms would be a bit more loop-unrolling. const N: usize = 16; let mut slice = s.as_bytes(); let mut out = Vec::with_capacity(slice.len()); let mut out_slice = out.spare_capacity_mut(); let mut ascii_prefix_len = 0_usize; let mut is_ascii = [false; N]; while slice.len() >= N { // SAFETY: checked in loop condition let chunk = unsafe { slice.get_unchecked(..N) }; // SAFETY: out_slice has at least same length as input slice and gets sliced with the same offsets let out_chunk = unsafe { out_slice.get_unchecked_mut(..N) }; for j in 0..N { is_ascii[j] = chunk[j] <= 127; } </ins> <del> const USIZE_SIZE: usize = mem::size_of::<usize>(); const MAGIC_UNROLL: usize = 2; const N: usize = USIZE_SIZE * MAGIC_UNROLL; const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]); </del> <ins> // Auto-vectorization for this check is a bit fragile, sum and comparing against the chunk // size gives the best result, specifically a pmovmsk instruction on x86. // See https://github.com/llvm/llvm-project/issues/96395 for why llvm currently does not // currently recognize other similar idioms. if is_ascii.iter().map(|x| *x as u8).sum::<u8>() as usize != N { break; } </ins> <del> let mut i = 0; unsafe { while i + N <= b.len() { // Safety: we have checks the sizes `b` and `out` to know that our let in_chunk = b.get_unchecked(i..i + N); let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N); let mut bits = 0; for j in 0..MAGIC_UNROLL { // read the bytes 1 usize at a time (unaligned since we haven't checked the alignment) // safety: in_chunk is valid bytes in the range bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned(); } // if our chunks aren't ascii, then return only the prior bytes as init if bits & NONASCII_MASK != 0 { break; } </del> <ins> for j in 0..N { out_chunk[j] = MaybeUninit::new(convert(&chunk[j])); } </ins> <del> // perform the case conversions on N bytes (gets heavily autovec'd) for j in 0..N { // safety: in_chunk and out_chunk is valid bytes in the range let out = out_chunk.get_unchecked_mut(j); out.write(convert(in_chunk.get_unchecked(j))); } </del> <ins> ascii_prefix_len += N; slice = unsafe { slice.get_unchecked(N..) }; out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; } </ins> <del> // mark these bytes as initialised i += N; </del> <ins> // handle the remainder as individual bytes while slice.len() > 0 { let byte = slice[0]; if byte > 127 { break; } // SAFETY: out_slice has at least same length as input slice unsafe { *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); </ins> } <del> out.set_len(i); </del> <ins> ascii_prefix_len += 1; slice = unsafe { slice.get_unchecked(1..) }; out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; </ins> } <del> out </del> <ins> unsafe { // SAFETY: ascii_prefix_len bytes have been initialized above out.set_len(ascii_prefix_len); // SAFETY: We have written only valid ascii to the output vec let ascii_string = String::from_utf8_unchecked(out); // SAFETY: we know this is a valid char boundary // since we only skipped over leading ascii bytes let rest = core::str::from_utf8_unchecked(slice); (ascii_string, rest) } </ins> }

I'm looking into the performance of / on mostly ascii strings, using a small microbenchmark to . Using linux perf tooling I see that the hot part of the code is the following large loop, which despite heavy use of sse2 instructions only seems to process 32 bytes per iteration. I don't see an easy way to improve the autovectorization of this code, but it should be relatively easy to explicitly vectorize it using , and I would like to prepare such a PR if there are no objections. As far as I know, is already in use inside , for example by .
The way the loop ors the bits for the is-ascii check into a single usize doesn't seem ideal for vectorization. keeping the lanes independent should yield better autovectorization results.
Thanks for the suggestion. I already started with a simd implementation, but now checked again if the autovectorization could be improved. With the following main loop The assembly and performance is indeed better, but there is still some weird shuffling and shifting going on: The explicit simd version looks a bit better, mostly because the ascii check directly translates to a : Do you have a preference here between autovectorization and explicit simd?
If the SIMD impl results in reasonable code across architectures, including some without SIMD then that should be fine. I think it would be the first time where we use portable simd unconditionally, so it could use some additional scrutiny. If it's only meant to target x86 with SSE2 then that'd mean having multiple paths and in that case we'd still have to tweak the generic path anyway. At that point we might as well just optimize the latter further. You can probably get rid of those too by keeping multiple bools in a small array. That way the optimizer will more easily see that it can shove them into independent simd lanes. Increasing the unroll count might help too to fit better into simd registers. We do get pretty decent autovectorization in other places in the standard library by massaging things into a state that basically looks like arrays-instead-of-SIMD-types. E.g.
It seems llvm is too "smart" for this trick, on its own that generates the exact same code. The trick does work, although it seems a bit fragile.


Question: unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } } <del> /// Converts the bytes while the bytes are still ascii. </del> <ins> /// Converts leading ascii bytes in `s` by calling the `convert` function. /// </ins> /// For better average performance, this happens in chunks of `2*size_of::<usize>()`. <del> /// Returns a vec with the converted bytes. </del> <ins> /// /// Returns a tuple of the converted prefix and the remainder starting from /// the first non-ascii character. /// /// This function is only public so that it can be verified in a codegen test, /// see `issue-123712-str-to-lower-autovectorization.rs`. #[unstable(feature = "str_internals", issue = "none")] #[doc(hidden)] </ins> #[inline] #[cfg(not(test))] #[cfg(not(no_global_oom_handling))] <del> fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> Vec<u8> { let mut out = Vec::with_capacity(b.len()); </del> <ins> pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { // Process the input in chunks of 16 bytes to enable auto-vectorization. // Previously the chunk size depended on the size of `usize`, // but on 32-bit platforms with sse or neon is also the better choice. // The only downside on other platforms would be a bit more loop-unrolling. const N: usize = 16; let mut slice = s.as_bytes(); let mut out = Vec::with_capacity(slice.len()); let mut out_slice = out.spare_capacity_mut(); let mut ascii_prefix_len = 0_usize; let mut is_ascii = [false; N]; while slice.len() >= N { // SAFETY: checked in loop condition let chunk = unsafe { slice.get_unchecked(..N) }; // SAFETY: out_slice has at least same length as input slice and gets sliced with the same offsets let out_chunk = unsafe { out_slice.get_unchecked_mut(..N) }; for j in 0..N { is_ascii[j] = chunk[j] <= 127; } </ins> <del> const USIZE_SIZE: usize = mem::size_of::<usize>(); const MAGIC_UNROLL: usize = 2; const N: usize = USIZE_SIZE * MAGIC_UNROLL; const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]); </del> <ins> // Auto-vectorization for this check is a bit fragile, sum and comparing against the chunk // size gives the best result, specifically a pmovmsk instruction on x86. // See https://github.com/llvm/llvm-project/issues/96395 for why llvm currently does not // currently recognize other similar idioms. if is_ascii.iter().map(|x| *x as u8).sum::<u8>() as usize != N { break; } </ins> <del> let mut i = 0; unsafe { while i + N <= b.len() { // Safety: we have checks the sizes `b` and `out` to know that our let in_chunk = b.get_unchecked(i..i + N); let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N); let mut bits = 0; for j in 0..MAGIC_UNROLL { // read the bytes 1 usize at a time (unaligned since we haven't checked the alignment) // safety: in_chunk is valid bytes in the range bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned(); } // if our chunks aren't ascii, then return only the prior bytes as init if bits & NONASCII_MASK != 0 { break; } </del> <ins> for j in 0..N { out_chunk[j] = MaybeUninit::new(convert(&chunk[j])); } </ins> <del> // perform the case conversions on N bytes (gets heavily autovec'd) for j in 0..N { // safety: in_chunk and out_chunk is valid bytes in the range let out = out_chunk.get_unchecked_mut(j); out.write(convert(in_chunk.get_unchecked(j))); } </del> <ins> ascii_prefix_len += N; slice = unsafe { slice.get_unchecked(N..) }; out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; } </ins> <del> // mark these bytes as initialised i += N; </del> <ins> // handle the remainder as individual bytes while slice.len() > 0 { let byte = slice[0]; if byte > 127 { break; } // SAFETY: out_slice has at least same length as input slice unsafe { *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); </ins> } <del> out.set_len(i); </del> <ins> ascii_prefix_len += 1; slice = unsafe { slice.get_unchecked(1..) }; out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; </ins> } <del> out </del> <ins> unsafe { // SAFETY: ascii_prefix_len bytes have been initialized above out.set_len(ascii_prefix_len); // SAFETY: We have written only valid ascii to the output vec let ascii_string = String::from_utf8_unchecked(out); // SAFETY: we know this is a valid char boundary // since we only skipped over leading ascii bytes let rest = core::str::from_utf8_unchecked(slice); (ascii_string, rest) } </ins> }

The following creates a instruction just like the simd version, but a slightly different alternative with a array and comparing against 0 does not. It only needs to be better than the autovectorized version on those platforms ;) My initial idea was to gate the simd code on either SSE2 or Neon (possibly also Altivec and RiscV). I'd also add a scalar loop for the non-multiple-of-N remainder, so all-ascii strings are fully handled by specialized code. Currently this remainder goes through the generic and code path. On other platforms, only the scalar loop would be used, since I assume the autovectorization would also generate suboptimal code. But I agree that if similar code quality can be achieved with autovectorization, that would be preferable. I'll open a PR after a little bit more polishing the code.


Question: let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| { panic!("nnfailed to specify `dist.upload-addr` in `config.toml`nn") }); <del> let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() { let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { panic!("nnfailed to specify `dist.gpg-password-file` in `config.toml`nn") }); t!(fs::read_to_string(&file)) } else { String::new() }; </del> <ins> let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| { panic!("nnfailed to specify `dist.gpg-password-file` in `config.toml`nn") }); let pass = t!(fs::read_to_string(&file)); </ins> let today = output(Command::new("date").arg("+%Y-%m-%d"));

Seems like no nightly was released today. That might be related to Unfortunately I don't think I have access to the logs. Cc
Logs are missing on the server, let me start a manual release...
Well that is odd. You wouldn't know what commit is is using? ( file in the tarball, if I recall correctly.)
Is there a way for me to download the "dist" artifacts for better testing? Right now I am manually grabbing a bunch of files from https://s3-us-west- (and we only get dir listing for alt builds there it seems so I am using those). That's not very convenient at all.
Apparently not all commits are pushed to toolstate ( vs ), for example the latest one () is missing in toolstate .
Reverting the cause in the meantime --
Alternatively we could land which will just skip of the toolstate is not found. That installs a toolchain based on these artifacts, but I don't think it gives me access to the tarballs. FTR, for now I did So we are only committing when the toolstate changed? Ouch. That kills my entire approach :(
It should print the URLs it's downloading though, and you can use to avoid it actually downloading stuff.