jiebi/CodeConvo huggingface dataset:
Code change:
if trait_.def_id() == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } <ins> // Return if the trait itself or any types of the generic parameters are doc(hidden). let mut stack: Vec<&Type> = trait_.iter().collect(); stack.push(&for_); while let Some(ty) = stack.pop() { if let Some(did) = ty.def_id() { if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { return; } } if let Some(generics) = ty.generics() { stack.extend(generics); } } </ins> if let Some(trait_did) = trait_.def_id() { record_extern_trait(cx, trait_did); }

Related discussion:
text: Last line yields several occurrences of in the generated file. ## Expected behavior No occurrences of anywhere since it was label C-bug T-rustdoc cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I expect the fix is to check for just after
claim
cc I checked for doc(hidden) like this: But it doesn't seem to work, as my test would fail. I also tried using the same way to check for but it also failed. I noticed that the issue involves so I might need to iterate over generic parameters, I cannot find any function that does that in , so can someone point me in the right direction? Thanks :)
You can look at how the pass works:
am I right in understanding this only happens for cross-crate traits, and impls for hidden traits in the same crate are still hidden? In other words, just makes the cross-crate case consistent?
I believe so, yes: the pass was already taking care of such cases for local types. FWIW, the thing that motivated this discussion was noticing a leaking on the docs for , but not on the ones for
Code change:
}, }; let mut prev = eraser.fold_ty(ty); <del> let mut prev_span = None; </del> <ins> let mut prev_span: Option<Span> = None; </ins> for binding in expr_finder.uses { // In every expression where the binding is referenced, we will look at that

Related discussion:
text: I tried this code on nightly: I expected to see this happen: compiler does not panic. Instead, this happened: compiler panics and suggests I open a bug report. I initially posted to , but says this is a different issue, despite panicking on the same line in . (Though I'm realizing now that might be the proximal cause but not very related to the root cause.) : <details<summaryPanic message</summary<p</p</detailsThanks all for maintaining Rust, by the way.
Thanks!
searched nightlies: from nightly-2022-12-01 to nightly-2023-01-21 regressed nightly: nightly-2023-01-07 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.5</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </details
It's , i'll fix it unless someone beats me to it since I'm busy this weekend
Hi it's Justin from Commure :wave:. I found a compiler panic you made :grinning:
sorry for causing you trouble
Code change:
sp } fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool { <del> let src = self.file_loader.read_file(Path::new(&file_map.name)).ok(); return file_map.add_external_src(src) </del> <ins> file_map.add_external_src( || self.file_loader.read_file(Path::new(&file_map.name)).ok() ) </ins> } }

Related discussion:
text: In investigating I was generating some source code, and using the shell script listed in we can see: That's a lot of time to expand a crate that doesn't have any macros in it!
cc you may be interested in this!
A looks like almost all the time is spent in In which case, cc
Apparently most time is spent
called ~38k times
Since we need to build the module graph and resolve imports during expansion for macros 2.0, we must construct node ids and def ids throughout expansion (i.e. interleaved arbitrarily many times until we hit fix-point). Ideally we'd keep running totals of the time spent assigning node ids, assigning def ids, etc. for more accurate profiling information within the expansion step.
in theory though isn't the fixed point for this crate the crate itself? (e.g. there's no macros here). Or are the def ids persisted for the rest of compilation, so "blaming" expansion isn't quite correct here?
Yeah, the def ids are persisted for the rest of compilation. We could move the "first round" of def id collection (in which we collect the raw, unexpanded source) outside of expansion, but that would introduce more code complexity and wouldn't count the time we spend collecting def ids for AST that comes from macro expansions.
Ah ok, nah it seems fine! I think there's a number of cases where is attributing time in the wrong place nowadays... Still it seems odd that 30-50k invocations of this function would take so long to execute?
Do I understand this correctly that all DefIds generated are actually used, right? There are no "temporary" DefIds? Each of these invocations creates a Blake2 hasher. I'd be interested how the performance looks with other hashing algorithms. I'd like to switch to something faster anyway:
Are you sure this isn't the other quadratic case fixed in ?
It may very well be! Feel free to close this w/ that PR landing, I'll verify to be sure but I'd imagine you're correct in that it's fixed by
er, didn't mean to close just yet
Code change:
sp } fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool { <del> let src = self.file_loader.read_file(Path::new(&file_map.name)).ok(); return file_map.add_external_src(src) </del> <ins> file_map.add_external_src( || self.file_loader.read_file(Path::new(&file_map.name)).ok() ) </ins> } }

Related discussion:
text: A of Servo's crate shows a huge amount of time (46 seconds!) in name resolution. It turns out that is calling , specifically . That's a lot of unused imports! Sure enough if we create a synthetic file locally with this script: we find: That's a lot of time spent processing unused imports! The slowdown here isn't quite the same as the style crate, unfortunately. The style crate only has ~7k unused imports, which apparently takes it 48s in that profile. In any case the intent here is clear, lots of unused imports seem to slow down compilation, and the crate looks to have a lot of unused imports!
cc
We could address this quickly by just emitting the first 10 unused imports warnings and then warning that there are more unused imports not shown.
I can never deal with more than 10 lints at a time anyway myself, so seems like a reasonable solution to me!
Dumping out a ton of warnings is useful when you're hooked into an IDE and you can see them as e.g. green squiggles under the offending text as opposed to 10k lines on a terminal.
I think the reason is slow is because it calls , which does this: I don't think we want to read source files multiple times like that.
Thank you for looking into Servo compile times Alex, and great find here! Could you CC me or someone from the Servo team for Servo-related issues? Thanks.
Can do!
In general I've always wanted the lint system to avoid even running in blocks. Currently the lint system runs all lints in parallel on the tree. This is great since it means we only traverse it once, and the cost of the traversal is consolidated. We don't need to reduce that cost itself (which is nice because then we don't have to worry about inside ). Most lints do not maintain state. The lint framework has the capability to do so, and we use this a couple times in Clippy, but most lints are , so they won't notice if or whatever isn't called in a region of . The "allowness" of a lint is tied to where in the tree the lint traversal is, not the span emitted by the lint.
Code change:
sp } fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool { <del> let src = self.file_loader.read_file(Path::new(&file_map.name)).ok(); return file_map.add_external_src(src) </del> <ins> file_map.add_external_src( || self.file_loader.read_file(Path::new(&file_map.name)).ok() ) </ins> } }

Related discussion:
text: It's perfectly possible to a block of code and have the lint still be emit there because a different block of code (where it is ) hit the lint but emitted a span it got from elsewhere. We've had trouble with this before in clipyp iirc. All of this enables this proposal: If we had a specialized trait for this, then when we have an we can turn off calling lint methods entirely, and when there's a turn it on again. It doesn't even have to be a trait, really, it could just be a defaulted fake-static method (until happens) on LateLintPass. I suspect this will get significant speedups for crates like Style. I may_ be able to take a crack at this if y'all think this is a good approach.
It occurs to me that a boolean check per lint each tree node might actually end up being more expensive? I'll have look at this code closer. Might be possible to make this fast by having a second array of trait objects which only contains the active lint passes.
It seems like we do a large enough amount of work that the whole "vector of active lints" stuff won't really be necessary. However, I just realized that this bug is not during the lint pass but during the resolution phase (which defers linting to the actual lint pass). This won't be able to help, though we can fix it by doing the spantosnippet in the actual lint and then making this optimization. So in that case I suspect this optimization is unnecessary. In general we've rarely had performance issues with lints in clippy (which has way more lints than rustc), and we've been pretty careful to measure impact there. Still, if folks think this optimization can help, let me know.
Code change:
<ins> error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants --> $DIR/unstable-const-fn-in-libcore.rs:24:26 | LL |             Opt::None => f(), |                          ^^^ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:53 | LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T { |                                                     ^ constant functions cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:47 | LL |     const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T { |                                               ^^^^ constant functions cannot evaluate destructors error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0493. For more information about an error, try `rustc --explain E0015`. </ins>

Related discussion:
text: As shown in const-qualification can ignore some s, in the context of libcore / rustc crates: This should not compile without "miri unleashed"; const-qualification does not see this function as const since the unstable feature is not enabled, and thus does not check it. It outside of libcore, nor . cc More discussion is also available . I have a fix and will post a PR shortly. There are a couple of existing cases in where this matters (for and ), and I'll fix those at the same time.
Code change:
return noop_visit_attribute(at, self); } <del> let filename = self.cx.resolve_path(&*file.as_str(), it.span()); </del> <ins> let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) { Ok(filename) => filename, Err(mut err) => { err.emit(); continue; } }; </ins> match self.cx.source_map().load_file(&filename) { Ok(source_file) => { let src = source_file.src.as_ref()

Related discussion:
text: to reproduce the fault this can be used: will result in this ICE: thread 'rustc' panicked at 'cannot resolve relative path in non-file source ', note: Run with RUSTBACKTRACE=1 environment variable to display a backtrace. 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.36.0 ( 2019-07-03) running on x86_64-unknown-linux-gnu the question is what is the path that shall be used when the code is from stdin maybe some temp file name in the currrent working dir.
This ICE also occurs when using and , which makes sense as they use the same mechanism under the hood (, , meaning it also .
While poking at this I also noticed that items are silently ignored, and filed .
Code change:
14 |     println!("Hello, World!"); |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ | <del> = note: expands to `println! { "Hello, World!" }` = note: expands to `print! { concat ! ( "Hello, World!" , "/n" ) }` </del> <ins> = note: expanding `println! { "Hello, World!" }` = note: to `print ! ( concat ! ( "Hello, World!" , "/n" ) )` = note: expanding `print! { concat ! ( "Hello, World!" , "/n" ) }` = note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, World!" , "/n" ) ) )` </ins>

Related discussion:
text: Output is: The first message here is inaccurate. The macro-use does not expand to that macro-use. shows the input to macros, not the output. So instead of "expands to:", it should say "expanding:". But changing the behavior to match what the message says would be even better. ;) This is a regression because the error messages are new. used to just dump token streams to stdout (lol).
Introduced in .
Closing -- I believe fixed this.
Code change:
ulimit -c unlimited fi <ins> # There was a bad interaction between "old" 32-bit binaries on current 64-bit # kernels with selinux enabled, where ASLR mmap would sometimes choose a low # address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. # This is probably a kernel bug, but setting `ulimit -Hs` works around it. # See also `dist-i686-linux` where this setting is enabled. if [ "$SET_HARD_RLIMIT_STACK" = "1" ]; then rlimit_stack=$(ulimit -Ss) if [ "$rlimit_stack" != "" ]; then ulimit -Hs "$rlimit_stack" fi fi </ins> ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh"

Related discussion:
text: 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.
Code change:
ulimit -c unlimited fi <ins> # There was a bad interaction between "old" 32-bit binaries on current 64-bit # kernels with selinux enabled, where ASLR mmap would sometimes choose a low # address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. # This is probably a kernel bug, but setting `ulimit -Hs` works around it. # See also `dist-i686-linux` where this setting is enabled. if [ "$SET_HARD_RLIMIT_STACK" = "1" ]; then rlimit_stack=$(ulimit -Ss) if [ "$rlimit_stack" != "" ]; then ulimit -Hs "$rlimit_stack" fi fi </ins> ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh"

Related discussion:
text: 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?
Code change:
ulimit -c unlimited fi <ins> # There was a bad interaction between "old" 32-bit binaries on current 64-bit # kernels with selinux enabled, where ASLR mmap would sometimes choose a low # address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. # This is probably a kernel bug, but setting `ulimit -Hs` works around it. # See also `dist-i686-linux` where this setting is enabled. if [ "$SET_HARD_RLIMIT_STACK" = "1" ]; then rlimit_stack=$(ulimit -Ss) if [ "$rlimit_stack" != "" ]; then ulimit -Hs "$rlimit_stack" fi fi </ins> ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh"

Related discussion:
text: 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)?
Code change:
ulimit -c unlimited fi <ins> # There was a bad interaction between "old" 32-bit binaries on current 64-bit # kernels with selinux enabled, where ASLR mmap would sometimes choose a low # address and then block it for being below `vm.mmap_min_addr` -> `EACCES`. # This is probably a kernel bug, but setting `ulimit -Hs` works around it. # See also `dist-i686-linux` where this setting is enabled. if [ "$SET_HARD_RLIMIT_STACK" = "1" ]; then rlimit_stack=$(ulimit -Ss) if [ "$rlimit_stack" != "" ]; then ulimit -Hs "$rlimit_stack" fi fi </ins> ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh"

Related discussion:
text: 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.