jiebi/CodeConvo huggingface dataset:
Sorry, this is not necessarily the smallest possible example. Please let me know if this is unhelpful and I'll come up with something more concise. Given the following code: The output in current stable (1.63.0) is: (Please note the "expected closure with ... found closure with ..." hint.) From 1.64 onwards, the expected/found hint is omitted: To me the 1.63 behaviour is preferable to that from 1.64+ as it can often be non-obvious where the differences lie.
searched nightlies: from nightly-2022-06-01 to nightly-2022-08-11 regressed nightly: nightly-2022-07-23 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.4</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </details
Looks like it was caused by , which is pretty big diagnostics PR in that rollup. cc
Of course I caused it.
label -E-needs-bisection
WG-prioritization assigning priority (). label -I-prioritize +P-medium
<!-- 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. ---rs has been updated with a workaround, so the reproduction described below will need adapting (e.g. check out that repo from around or earlier, since that will not include the workaround in ) problem exhibits itself only with certain numbers of codegen-units. The default setting for codegen-units is host dependent (the default is chosen, in part, as a function of the number of cores the host has available, in order to parallelize the code-generation performed by LLVM). In my own experiments, the problem is masked (does not arise) for codegen-units={1,2,4,8}, and the problem does arise for codegen-units={16,32,64,128,256}. You are best off passing explicit when investigating this, just to ward against that being an invisible factor in the experiments. (bug report follows below) I tried this code: I expected to see this happen: succeeds in debug mode. Instead, this happened: fails in debug mode. *isn't immediately obvious why would cause the problem searched nightlies: from nightly-2023-03-27 to nightly-2023-04-02 regressed nightly: nightly-2023-04-01 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.6</summaryHost triple: x8664-unknown-linux-gnu Reproduce with: </details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-nightly-to-nightly -regression-untriaged --
I forked and minimized the reproducible example down to simply having a type (but not a value) with in a crate (and then adding that proc macro crate as a dependency of another crate). You can find it here: (just run in ) Here is a workaround for the crate:
WG-prioritization assigning priority ().
label -I-prioritize +P-high +T-compiler
TBH it's not clear to me how alignment checks would end up causing linker errors, but since this seems bisected to , let's at the very least notify the PR's author
I already looked over this and was also mystified. I suppose I could take another look? I know almost completely nothing about wasm so I'm not hopeful.
Builds fine: Same linker error: As a mitigation for the linker error, users may put this in their (for the workspace!) That only helps with the alignment checks, is still not going to work.
I can build the reproducer, unmodified, if I use LLD. Or suggests this might be a link order issue. That would explain why LLD is fine with the link, but GNU's linker isn't. Actually, that doesn't make much sense because our standard library is already at the end of the link. I'm out of ideas :shrug: I think this is somehow dependent on linker details that I don't know and I'm struggling to educate myself on.
reported this same linker error from . It can be reproduced by creating an empty Cargo project, then running then . I have not managed to minimize this reproducer. The errant symbol is which is defined as: This has the same sort of shape as the non-unwinding panics from the alignment checks and from the standard library UB-detecting assertions. searched nightlies: from nightly-2023-01-01 to nightly-2023-06-09 regressed nightly: nightly-2023-03-12 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.6</summaryHost triple: x8664-unknown-linux-gnu Reproduce with: </detailsSo this bisects to a rollup then can't find the unrolled perf builds. Manual trials identifies as the source of the regression.
A tiny update: it seems like this problem goes away if you use  (and for me, it also didn't reproduce for many other values for number-of-codegen-units; I won't bother enumerating those here). This was somewhat of a surprise. I need to investigate more to figure out what relevance the codegen unit partitioning has to do with this issue.
If nothing else, it is a halfway decent fallback measure while we continue to investigate the problem.
Wanted to add, that I also ran into this issue. For me, it also occurred while compiling a macro crate. I originally thought it was an issue with , as it happened after I ran a , and the issue was fixed by pinning to a slightly older version: There was a bunch of weird behavior I encountered when trying to uncover the issue. The issue was one. When I made other library upgrade changes, it would cause or fix the breakage. I didn't dive too deeply, but it seems like I was still encountering this issue even when I set the compiler to 1.67. (See this Github Actions build and associated commit: ) So it's possible that going to an old version simply hid the issue, but didn't actually pinpoint where the issue was introduced. Let me know if there's any other information I can provide to help isolate the issue. I've seemingly been able to work around the issue by using , as described earlier: I didn't try the other solution about codegen-units.
One MCVE for the stylist-macros build issue looks like this: Just a stylist-macros crate, with this and : So now I'm switching gears to see if I reduce wasm_bindgen to something smaller, so that we can have a small set of crates to talk about on their own here.
Okay got a pretty impressively tiny MCVE for wasm-bindgen too: In case its not clear, this seems like a pretty simple example that should easily work out of the box. (The use of from the mcve-stylist part of the story seems like an important part of the reproduction.) Still looking. Update: Wow, is it somehow of all things that is causing the problem here? That is ... bizarre, to say the least.
may be relevant. That issue is about not mentioning symbols in the version script such that they don't get exported. Also when applying to the rlib containing the symbols the linker error is fixed, so it seems like the linker doesn't pull in archive members even when the version script mentions it. Edit: For regular dylibs we mention all these symbols in , but for proc macros we only list a couple of internal symbols.
Edit2: There is a special case for proc macros with the handling to not mention any symbols beyond those required to handle circular dependencies. Fixing should fix this issue too by making the version script a subset of again (apart from a couple of symbols defined outside of archives).
: As an addendum to this: (which was in a rollup, as mentioned) the future-proofing safe-guard of adding to the linker invocation. We can add that same link-arg ourselves as part of further bisection that acts prior to PR . In my own MCVE, when I add that link-arg, I find that the code did compile circa 1.63 even with that flag. The flag stopped working sometime between nightly-2022-08-01 and nightly-2022-08-02. (I have not yet tracked down further than that, since its too old to have per-commit prebuilds archived.) Update: oh, of course, it is almost certainly PR that injected the change in behavior mentioned in the previous paragraph.
See related discussion in https://rust- (I have a branch with a commit that seems to fix this here: ; I hope to have a PR up today, once I get a regression test into place.)
<!-- 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.
Some types ( and in particular) implement and on . If one of these types are wrapped in an (or ), there is no real reason why one shouldn't be able to call or methods on it. For example, this code should compile: I think this can be implemented pretty straightforwardly by adding the following impls to and : Are there good reasons for why impls like these shouldn't be ?
Closing because generic impls like proposed won't behave correctly, as described in .
<!-- 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: The current output is: <!-- The following is not always necessary. --Ideally the output should suggest to the user that they need to initialize the enum variant's value in order to use the . <!-- 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 --
Can you give the output of what it should look like?
It should probably look similar to the suggestion given for and So I guess sth. like: Edit: Or instead of saying “to instantiate this tuple variant” we could say “to call this function” like it's done for the erroneous snippet (where is a ).
claim
commit the fix
I tried this code: I expected to see this happen: Compiles successfully. Instead, this happened: Fails with this error: nightly-2024-06-26 and earlier. nightly-2024-06-27 and later, starting with . See for a discussion of the issue. : cc
To elaborate, the difference is in symbols.o. Here's a dump of symbols.o before the change: And here's after: Spot the difference. Spoiler: is now present.
So is that right or wrong? The static is "used" so marking it exported to ensure it does not get optimized away seems to make sense? I don't understand why this is a problem only on Windows.
Well that's not a problem per se but if we want to do that then we have to do it properly. is defined as a in (on my machine). This is linked directly and not in a lib file. So it's already being included. There's no reason for to include it. The only issue is that is being emitted as a comdat, meaning the linker is still allowed to remove it. We could just not do that (or add a linker directive). But that's a pre-existing issue.
I don't understand any part of that.^^ Should my PR get reverted or is there a better way to fix this regression? If there is a better way, I am afraid I lack the knowledge to implement and test it. I don't understand symbol handling on Linux, let alone on Windows.
I don't know enough about the Rust compiler to say. My complete guess would be that was silently broken before but now it's nosily broken.
Hm, who would understand our Windows linking story? ?
After CGU partitioning, we try to internalize symbols when possible. What is surprising to me is that this process only looks at export level, ignoring used attribute (in the contrast to say the internalization during fat LTO). Consequently we have a situation where synthetic object file references a symbol that is no longer exported (on Linux that does not result in a linking error, even though reference is unresolved). Anyway, if the consequence of would be to export those symbols for no reason, that seems rather counter productive to me.
Ah, the behaviour was working to spec before: So I think I'd agree that is the wrong approach and should be reverted because this currently ends up conflating different things. Maybe changes elsewhere would fix this but I don't want to speculate.
the separate issue you pointed out earlier in is presumably still relevant for ?
Could this explain recent CI flakiness? The failure at and a couple other failed merges (linked on that thread, also the retries) have been msvc linker errors.
That's unfortunate. :/ Our reachable symbol code is such a spaghetti mess... I guess I'll just have to copy-paste more things into Miri then. :shrug: I am traveling right now, I'd appreciate if someone else could do the revert.
The following patch should fix the incorrect internalization I mentioned earlier: As for the question whether those symbols should be exported in the first place, it might be necessary for COFF and . The following code suggests that would not have the desired effect otherwise I don't have access to windows environment at the moment to verify that, so I don't plan to work on this myself.
Ooh this is also the stuff that also broke several ci-runs already ...
Looks like this did not fully fix the ci failures :melting_face:
Makes sense: some CI failures look non-deterministic, while we'd expect this error not to be.
Alternative approach for Miri:
The and targets force panic=abort. said : This looks related to , which points at these now-merged LLVM changes: It's possible that we do not need to force panic=abort anymore for arm64 Windows as a result. What's the best way to determine if this is still required?
Theoretically the way to fix this issue is: First Next, run the build Finally, run the tests If that all passes, then the change can land! The tests may be able to be skipped, and some tests may fail, so it may be possible to switch the defaults and we can fixup bugs later. I don't personally have hardware to test these changes on myself, though.
I occasionally have access to a Windows arm64 laptop, so I'll try and get a rustc build going on it at some point.
<!-- 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. --minimal project with full compiler output can be found here cargo 1.77.0-nightly ( 2024-01-09) : <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Inlined from Another issue. If a struct has two different custom derives on it and the second one panics, the error span will point to the first one, not the one which panicked. Reproduction Script
was "Reproduction Script" supposed to be a link? I'm spinning this off from as I don't think it's going to block stabilization and/or closing that issue.
Reproduction script there is a summary tag
<details<summaryReproduction Script</summaryIn a crate called In another crate The error will highlight even though panicked. </details
This seems to be fixed now, so this issue can be closed.
I ran this as a test, and got the following output:
I was using std::io::copy from an SSD to memory using , which reported an eye-raising 30 MB/s. Wrapping it in a BufReader (either as the outer or middle layer) made no real difference. So I googled around a bit and found the recommended size was 64KB according to some random Microsoft article, so I decided to copy-paste the std::io::copy implementation and increase the buffer size. This got up to 600 MB/s at about 256KB which sounded a lot more it continued going upwards from there past the point of believability (unless the files were being pulled from RAM as a consequence of my repeated accesses). With a 10MB Vec, I got 228.36 GB/s . Unrealistic values aside, has anybody checked the buffer value to make sure there isn't some huge low-hanging fruit for std::io::copy speeds?
You mention windows. This may be platform-specific behavior. On unix systems I would fadvise on the input file for copying. Googling tells me that the windows equivalent is . Have you tried that?
After a coarse overview, my intuition is that there is some funny business going on with the length determined by and the subsequent calls on the , that could explain the unrealistic results.
It’s possible. The actual times did increase dramatically from the std::io::copy default though - my suspicion is that there is probably some caching to RAM going on or something as cold runs were generally slower than hot runs. This was for some work code that I’m no longer actively developing. I’ll leave this email marked as unread for awhile in case I have some spare time to write a benchmark. I don’t think the other flag that was mentioned is accessible with the default open file api, but in any case it at least appears there’s some low hanging fruit wrt to std::io::copy perf
I tried benchmarking on Windoze before and after changing to (instead of the original ) and the results were slightly worse (up to ~3%) with the modified setup, both on HDD and SSD. However, I'm not sure if my benchmarks were good enough - I was having a hard time tweaking them so that I could see any difference between results for different file sizes.
FWIW, I'm providing the benchmark code below; it can easily be expanded to different file sizes:
4MB isn’t a whole lot. That’s well within the size of hard drive caches or possibly an OS memory-based cache. I was noticing the difference with files several gigabytes in size. As a sanity check, maybe look to see what the actual time is, not just the % difference between timings with different buffer sizes. The actual time may be wildly different than the actual steady state performance of the disk if it’s reading the data from a cache. It may also be possible at a low level to pass a flag to encourage the OS to disable or flush the cache, but I don’t know if there’s any way to instruct the hard drive to do the same.
I only pasted the benchmark for 4MB as a reference - I tested files from 4KB up to 16MB. I'm not an expert with low-level hard drive stuff, just hoping my attempt can help someone else.
Ideally you would test with a file approximately twice as big as you have RAM, so if you have 8GB of RAM you would want to test with a 16GB file.
extended open flags are accessible via FWIW lots of bennchmarks exist showing synchronous IO calls improve when matching IO operations to the underlying block size (e.g. 4MB for modern SSD's) across multiple OS's, so its very likely that there are improvements to gain here. However, 4MB is stack-breaking size by default, and heap allocations will destroy potential improvements (and further, if we're optimising, we probably want overlapped IO and a ring of buffers rather than just one buffer which will always leave one device idle).... so its complex;)
heap allocations will destroy potential improvements How come? would allocate once at the beginning. Heap memory isn't inherently slower and one memory allocation is basically free compared to the heavy IO that's happening afterwards.
But we also don't want to be allocating 4MB every time we do as someone might be doing a bunch of small copies.
possible approaches: thread local buffers or a buffer pool stat the input before deciding on the buffer size (this is what gnu cp does I think) heap-allocate a bigger buffer after a few iterations of the copy loop with an on-stack buffer specialize copy operations from file to memory to directly into the already allocated target, thus skipping the need for a buffer
specialize copy operations from file to memory to directly into the already allocated target, thus skipping the need for a buffer I think some kind of specialization for sources would be ideal. Because in this case, should not buffer at all and simply use the reader's buffer. Effectively this also gives you a customizable buffer size by wrapping your in a with whatever size you want. As of today, if your source is then is always the wrong answer. I got a substantial performance improvement using a simple loop instead:
a single heap allocation is entirely reasonable for a single invocation of copy of a lot of data. For many copies of a small amount of data, one ends up with a lot of allocations again (consider for instance copying data out of a tar, where we have views on the data and there's no actual synchronous IO etc happening. I like some of the suggested possibilities with specialisation.
It's a nice general optimization, but not necesarily ideal if you use a as . Adding a on the reader size does let you control the buffer size but it still introduces an unnecessary memcopy compared to . Perhaps a writer-side optimization would be more flexible. Then you can specialize either for or
That sounds rather uncommon to me though. After all, is provided by the trait so it's always available. The only case I can see where you would invoke with a as destination is some generic interfaces that takes any . But IMO such interfaces are ill-designed, as they could simply implement instead and offer a much more flexible API.
yes, generic code taking a write was the concern. E.g. tar-rs has a tar archive which takes a and is fed with items. I'm not saying that creating an in-memory archive would be a good idea, just pointing out that these patterns do exist.
I had same kind of issue but with different library (). The copy rate was around 70 MB/s (inside single NVMe SSD). The problem was actually with running the debug version of my program.