Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

The following code fails on stable: When compiled in release mode, the assert is optimized out by LLVM even though it checks the exact same condition as the other assert, as can be verified by testing in debug mode. Note that it's theoretically possible for the stack to be aligned correctly such that the bug is suppressed, but that's not likely. The 256's can be replaced with larger alignments if that happens. The bug is caused by the impl of copying to the stack with the default alignment of 16. ()
and seem related
This is a soundness hole.
So... I guess the problem is that the that rustc emits for the unsized local doesn't use ? That's... kind of bad, because it doesn't look like even supports dynamically setting the alignment: If this is correct, the issue should be renamed to something like "unsized locals do not respect alignment".
A way to fix this would be to change the ABI for dynamic trait calls that take by value to always pass by address. When the trait object is created is where the trampoline function would be generated, so there is no additional cost for static calls.
This can also be fixed by not allowing dynamically-sized local variables with an alignment more than some maximum value and having all dynamically-sized locals use that maximum alignment unless optimizations can prove that a smaller alignment suffices.
Messing with the ABI wouldn't help with unsized locals in general (assuming is correct), since e.g. will also need an alloca with dynamic alignment in general. Given only a value, there is no static way to say anything about its alignment, so how would you distinguish whether calling a method on it is OK?
Can we call and then align the pointer for the local ourselves as a workaround until we come up with a good solution?
In clang there's a function which might or might not be useful in this case.
requires a constant alignment. Non constant alignments are . This matches semantics of LLVM instruction, so it's not helping, as alignment of value in is unknown at compile time when moving from .
I think that overallocating for unsized locals of unknown alignment may make sense. You can and then make use of to compute the offset. Sure, it increases stack requirements, but it seems acceptable for , and in most cases you end up with extra 7 bytes on stack or less. 256 alignment seems like an edge case where wasting 255 bytes doesn't matter.


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

if we keep setting as the default alignment we can skip the overallocating and offset dance for types with an alignment below that.
My idea was that rustc would prohibit coercing overaligned types to a dyn trait that takes by value. So:
The alignment is dynamically determined though, not sure if saving 15 bytes of stack space is worth the conditional branch?
Oh right. Yea that's probably not helpful.
Since , this would be backwards incompatible (at latest) once trait object upcasting is finally implemented: and trait objects would have to have the same alignment restriction (because you can upcast to ), but today you can freely create such objects with any alignment.
I was under the impression that calling didn't require dynamic , is that related to missing MIR optimizations, meaning we have unnecessary moves which end up duplicating the data on the stack using a dynamic ?
Correctness shouldn't rely on optimizations to fire...
Sure, I was just hoping we weren't relying on "unsized locals", only unsized parameters (i.e. ), for what we're exposing as stable. And I was hoping an optimization wouldn't need to be involved to get there. I wonder if it would even be possible to restrict "unsized locals" to the subset where we can handle it entirely through ABI, and not actually have dynamic s anywhere, since that would make me far more comfortable with 's implementation or even stabilization. Ironically, if that works, it's also the subset we could've implemented years earlier than we did, since most of the complexity, unknowns (and apparently bugs) are around dynamic s, not calling trait object methods on a dereference of .
That should be possible. I think everything that is necessary is performing the deref of the box as argument () instead of moving the box contents to a local first () That would also make it possible to call in cg_clif. Cranelift doesn't have alloca support, so the current MIR is untranslatable.
Hmm, but that's not trivially sound because it could lead to MIR calls where argument and return places overlap, which is UB. We'd potentially have to special-case it to derefs, but even then what's to stop someone from doing ? Maybe we could introduce a temporary for the return value instead, for these kinds of virtual calls? That should remove any potential overlap while allowing the call.


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

(Unrelatedly, I just realize we use a copying-out shim for vtable entries that take by value, even when would be passed as at the call ABI level. We would probably have to make computing the call ABI a query for this microopt to not be expensive)
That would result in being moved to a temp first before dropping and calling the boxed closure. If it wasn't moved first before the drop of , then borrowck would give an error. (I meant for this change to be done at mir construction level, not as an optimization pass, so borrowck should catch any soundness issues)
We can try it, I guess, but right now a lot relies on many redundant copies/moves being created by MIR building and may not catch edge cases like this. But also I don't think moving out of a moves the itself today. Me too, but I was going with the "correct by construction" approach of creating a redundant copy/move, just on the return side, instead of the argument side, of the call.
After revisiting on triage, removing nomination.
pre-triage: nominated for discussion in the next weekly meeting.
I just checked and, a function call roughly this (touched up for clarity): Some of my previous comments assumed the wasn't there and the call would use the destination directly, but given that there is a move, that simplifies my suggestion. <hr/For virtual by-value calls, we can skip one move when building the MIR, specifically the move out of the dereference of a for the argument. Given that we already move the result of the call, there should be no aliasing caused by this, but if we decide to change anything about how we build MIR calls, we'd need to be extra careful. We can also make this pattern be gated by a separate feature-gate (rather than ), and make sure the standard library only uses that feature-gate and not . This should solve any alignment issues might have, because we'd not be using dynamic unless the broader feature is used.
OK, if I understand what's being proposed here, it is to excerpt a subset of the "original unsized-locals plan" -- specifically, to permit locals with unsized types, but only in contexts where we can be guaranteed that we can point to the original storage and don't actually have to move any value (and hence we don't require variable size stack frames).


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

I'm in favor of this proposal, but I do think we want to be slightly careful to ensure we're not violating soundness. The main concern would be if there is some way to access or re-use the variable that was moved. I attempted to do so with this example () but it fails to compile: The error here arises because the closure would need to capture a to do anything, which prevents a later move. But maybe there is some kind of tricky example that can arise where we re-assign the value during argument evaluation?
compiles and does before , where is the result of .
Borrowck should prevent that, right?
borrowck may rely on MIR building creating extraneous copies, so we can't just assume it helps us. IMO we should limit it to functions taking unsized parameters and function calls passing such parameters or dereferences of es (any other pointer/reference doesn't support moving out of).
Well, I think is right that borrowck would catch violations of soundness in some strict sense, but I guess what I meant is that we might be breaking backwards compatibility.
The example that feels pretty relevant. If I understood your proposal, it would no longer compile. If I recall (thinking back), I had a plan to handle this by save the to an alternate location in the actual call, we pass ownership of and then do a shallow free of the This still seems like it would work, though I'm not sure how easy/elegant it is to formulate. In a sense we'd be rewriting to .
Isn't example dependent on doing a direct virtual call? My understanding is that you can't do this on stable with because the virtual call exists in one place, in libstd, and it doesn't do anything weird, so it would work with a restricted ruleset. EDIT: if it can work on stable, it's because calling 's will move the whole before the assignment is evaluated, which is fine, because the shallow drop is actually inside that , not its caller.
I agree that this code doesn't compile on stable today, but I'm not sure if that's the point. I guess you're saying it's ok for it to stop compiling? I think what I would like is that our overall behavior is as consistent as possible between Sized and Unsized parameters. I think we could actually do a more general change that doesn't special case Sized vs Unsized or anything else.


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

I think I am basically proposing the same thing as earlier, but with a twist: Today, when building the parameters, we introduce a temporary for each parameter. So if we had we might do: What I am saying is that we could say: If the argument is moved (not copied), and the "place" has outer derefs (e.g., we are passing where is some place), then we assign the place to a temporary and we make the argument to the function be : I don't believe this is observable to end-users, except potentially for when the destructor on runs. I believe that it accepts all the same code we used to accept. It also has nothing specific to or types at all. Does that make sense? I'm very curious to know if anyone sees any problems with it. (One obvious thing: if we ever add , its design would have to accommodate this requirement, but I think that's fine, in fact the complications around getting moves right for precisely this case are one of the reasons we've held off on thus far.)
Can you not reinitialize today? If you move the whole , it is indeed more conservative (and should let us skip unnecessary moves even in cases). But also, do you want to move the locals check from typeck to borrowck? I don't have an intuition for when your approach wouldn't create unsized MIR locals, from the perspective of typeck. However, this is only relevant if we want a stricter feature-gate. At the very least it seems like it would be easier to implement a change only to MIR building, and it should fix problems with for the time being, even without a separate feature-gate.
Hmm, that's a good point, I think do that. Sigh. I knew that seemed too easy. I remember we used to try and prevent that, but we never did it fully, and in the move to NLL we loosened those rules back up, so this compiles: Still, you could do my proposal for unsized types, though it would introduce an incongruity. UPDATE: Oh, wait, I remember now. For unsized types, reinitialization is not possible, because you can't do with an unsized rvalue (we wouldn't know how many bytes to move). So in fact there isn't really the same incongruity.


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

To be clear, I wasn't proposing changing anything apart from MIR building either, I don't think. IIUC, what you proposed is that would be compiled to: whereas under my proposal (limited to apply to unsized parameters, instead of moved parameters) would yield: I think I mis-stated the problem earlier. It's not so much that your proposal will introduce compilation errors, it's that I think it changes the semantics of code like this in what I see as a surprising way: I believe that this code would compile to the following under your proposal: which means that would be invoked with the new value of , right? Under my proposal, the code would still compile, but it would behave in what I see as the expected fashion. Specifically, it would generate:
Isn't there a way to "lock" that value through the borrow-checker, so further accesses would be disallowed, until the call returns? I'd rather be stricter here. <hr/My point was that if your proposal affects sized moves, you're breaking stable reinitialization. If it doesn't affect sized moves, I don't see how this applies anymore:
Let me just chime in here and say that this is a pain in Miri. Unsized locals are pretty different from sized locals, I had to introduce a bunch of special hacks to make them work. MIR locals even needed a new state just for them: Lazily allocating locals seems odd to me, but at least we can consistently do that for all locals. Elsewhere however to make this lazy initialization actually work out and catch mistakes where an unsized local is "overwritten" with a value of different size: This all feels really unprincipled, and it would be great if at some point we could come up with a coherent semantics for unsized locals in MIR. The worst part is that the size of a local is implicitly determined on the first write to it. It would be much better to be explicit about that, e.g. at time.
I don't think we have anything like this today, but presumably we could add such a thing, but I'm not quite sure what you have in mind. When does this prohibition on further accesses take effect?


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

In particular, the IR for under your proposal, if I understood, would be But the access to that (I believe) we wish to prevent takes place in the "evaluate remaining arguments" part of things. So I think we'd have to add some sort of "pseudo-move" that tells borrowck that should not be assignable from that point forward, right? Well, it depends on your perspective. It's true that, given the need to permit reinitialization, the check is now specific to unsized values -- i.e., MIR construction will be different depending on whether we know the type to be sized or not. That's unfortunate. However, I think we still maintain a degree of congruence, from an end-user perspective. In particular, users could not have reinitialized a anyhow. However, under my proposal, users can write things like and the code works as expected (versus either having an unexpected result or getting an error). In any case, it seems like we're sort of "narrowing in" on a proposal here: when we see a function call with a parameter that is , and the value being passed is a deref, we want to modify the IR to not introduce a temporary and instead pass that parameter directly from its location, either we do some sort of "no more assignments" lock, or we move the pointer and introduce a temporary (and then pass in a deref of that temporary) Does that sound right so far?
If it's easier to do the more flexible approach (by moving the pointer) than the "locking" approach (which is a bit like borrowing the pointer until all arguments are evaluated, then releasing the borrow and doing a move instead), I don't mind it, I was only arguing with the "uniformity" aspect. Something important here: your approach is stabilizable, while mine is meant more for that one in the standard library, and not much else.
Yes, I was kind of shooting for something that we could conceivably stabilize.
Removing nomination, this was already discussed in triage meeting and it's under control.
So should we maybe try out the approach I proposed and see how well it works?
yes, going to try that out.
For the record, the "new plan" is this.


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

When generating the arguments to a call, we ordinarily will make a temporary containing the value of each argument: But we will modify this such that, for arguments that meet the following conditions: The argument is moved (not copied), and its type is not known to be , and the "place" has outer derefs (e.g., we are passing P where P is some place), then we assign the place P (instead of ) to a temporary and we make the argument to the function be (instead of ). This means that given where , we used to generate but now we generate We are now moving the box itself, which is slightly different than the semantics for values known to be sized. In particular, it does not permit of the box after having moved its contents. But that is not supported for unsized types anyway. The change does permit modifications to the callee during argument evaluation and they will work in an analogous way to how they would work with sized values. So given something like: we will find that we (a) save the old value of to a temporary and then (b) overwrite while evaluating the arguments and then (c) invoke the with the old value of .
Update: There is also
is a perfectly normal operand, I don't know what you mean. It's the same kind of as we currently have in (on the RHS)
Oh sorry, somehow I thought operands could only refer directly to locals, not also dereference them. I think I am beginning to see the pieces here -- together with function argument handling, this entirely avoids having to dynamically determine the size of a local. I have to agree that is quite elegant, even though baking "pass-by-reference" into MIR semantics still seems like a heavy hammer to me. On the other hand this places a severe restriction on now unsized locals may be used, basically taking back large parts of Is there some long-term plan to bring that back (probably requires with dynamic alignment in LLVM)? Or should we amend the RFC or at least the tracking issue with the extra restrictions?
I would keep the more general feature but use two different feature-gates (if we can). And just like with a few other feature-gates () we could warn that (the general one) is incomplete and could lead to misaligned variables (or something along those lines).


Question: /// Returns an operand suitable for use until the end of the current /// scope expression. /// <del> /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. </del> <ins> /// The operand returned from this function will *not be valid* /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. </ins> crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>> where M: Mirror<'tcx, Output = Expr<'tcx>>,

We could also add runtime asserts that the (dynamic) alignment is respected, once we know could never trigger them (e.g. from stable code).
I was wondering about that too. It seems like it'd be good to review the more general feature in any case. This is partly why I brought up the idea of wanting a guaranteed "no alloca" path -- this was something I remember us discussing long ago, and so in some sense I feel like the work we're doing here isn't just working around LLVM's lack of dynamic alignment support (though it is doing that, too) but also working to complete the feature as originally envisioned.
I two notes to the tracking issue so we don't overlook this in the future.
This is probably expected, but the fix failed to actually make sound:


Question: // killed, rather than having an error bubble up and cause a panic. cargo.rustflag("-Zon-broken-pipe=kill"); <ins> if builder.config.llvm_enzyme { cargo.rustflag("-l").rustflag("Enzyme-19"); } </ins> // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary // and may just be a time sink. if compiler.stage != 0 {

A while ago we merged the first backend pr to enable automatic differentiation in Rust: This was good enough to add and enable the config in and run . We would now like to improve the integration to also successfully run (to use Rust in our autodiff compiler explorer). and I looked into it for a while and while it seems like a simple linker issue, we didn't fully understood where it comes from and what's the best way to fix it. This commit has a few more changes (not yet upstreamed) that might help for understanding how enzyme is used We also have documentation here: Back to the issue. We first build Enzyme (a git submodule) and then try to link it. To copy Jed's observations: The code to add is in inside fn cargo. Note that linking works correctly when building normal crates. Also, I find it odd that this one line of code yields so many repeat arguments (as in, Is there a better way to link Enzyme? Should we prefer to elide Enzyme linking when it isn't needed or be more explicit with paths so it is always found? A potentially related linking error only happens under MacOS: Related Zulip issue: https://rust- Tracking:
It's not just about dist builds; this happens on any build that triggers tool builds (e.g., running would fail too). This happens because enzyme linking flags are set in the general-purpose cargo function and used in every build even when they aren't needed. changes this so that the flags are set only for the rustc build as they aren't required for other builds.
Thank you for the quick fix!


Question: ); err } <del> infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); let mut err = struct_span_err!( self.tcx.sess, span, E0313, "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", var_name ); note_and_explain_region( self.tcx, &mut err, "...the borrowed pointer is valid for ", sub, "...", None, ); note_and_explain_region( self.tcx, &mut err, &format!("...but `{}` is only valid for ", var_name), sup, "", None, ); err } </del> infer::RelateObjectBound(span) => { let mut err = struct_span_err!( self.tcx.sess,

This issue is a proposal for the deprecation of error code . I opened a PR () as part of an effort to add long error explanations for error codes that didn't have one (). I chose and for my erroneous code example, I used the example from . I quickly realized, through running the example and other code that would also raise and through the CI failure message, that was not being raised. I went back to consult the issue I received the original code example from and noticed comments about not occurring anymore with . The issue was eventually labeled with . But, looking at the current contents of the file, can still be emitted even while it isn't: also doesn't have any UI tests as it is part of the error codes in . Since , is no longer actually emitted (although it is in code that it could) thanks to , I believe it should be deprecated. I would be happy to help deprecate the error code, if it is decided that it should happen. I would just need to know the proper steps to take to deprecate an error code. If there are reasons for why it is still an error code, I would love to be enlightened. claim <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
If is not emitted anymore then it can be removed immediately. A crater run can also be done to ensure that this is the case. I'm also happy to do this if you want.
Sure, that sounds good.
Sorry just for clarification, do you want me to do the PR or you?


Question: self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span)); } let ext = self.parse_extern()?; <del> self.bump(); // `fn` </del> <ins> self.expect_keyword(kw::Fn)?; </ins> let header = FnHeader { unsafety,

The following program compiles, and prints :
As pointed out by on discord , this also works on stable:
Regression introduced in 1.40.0, specifically this line:
I have a fix in


Question: fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { if self.in_root && item.vis.node.is_pub() { <del> self.attr_macros.push(ProcMacroDef { </del> <ins> self.macros.push(ProcMacro::Def(ProcMacroDef { </ins> span: item.span, function_name: item.ident, <del> }); </del> <ins> def_type: ProcMacroDefType::Attr })); </ins> } else { let msg = if !self.in_root { "functions tagged with `#[proc_macro_attribute]` must

The PR improved the situation about documenting proc macros. Thanks for that! However, I noticed a bug with it. I'm using . Running results in this: ! Looks like a simple typo or off-by-one or something like that bug. When using only and not s, everything looks good to me. CC
Oh, and also, running prints: Not sure if this warning is expected there. And not sure if related to this bug.
This is a consequence of the fact that has not yet been merged. Once it gets merged, and rust updates its Cargo submodule, this issue should go away.
It turns out that this issue was unrelated. I've opened a PR to fix it.
I see. Thanks for your work on this :)


Question: <ins> error: generic parameters may not be used in const operations --> $DIR/size-of-t.rs:7:30 | LL |     let _arr: [u8; size_of::<T>()]; |                              ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions error: aborting due to previous error </ins>

Example: Results in the following error: of course, is by default unless you say , so the error and the suggestion are clearly wrong. And if you do say explicitly, you get Note being suggested, which is ~not even valid syntax~ apparently valid syntax, but not something you would write. I expected to see this happen: Either this compiles cleanly Or the compiler emits a different error that makes sense <!-- 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. --: (Seems to happen on nightly too.) </details
Duplicate of
Reopening to track the error message, which is not tracked by . is just wrong.


Question: RelateParamBound(a, ..) => a, RelateRegionParamBound(a) => a, Reborrow(a) => a, <del> ReborrowUpvar(a, _) => a, </del> DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span,


Question: } } <ins> // This is required by the compiler to exist (e.g., it's a lang item), but it's // never actually called by the compiler.  Emscripten EH doesn't use a // personality function at all, it instead uses __cxa_find_matching_catch. // Wasm error handling would use __gxx_personality_wasm0. </ins> #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( <del> version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, </del> <ins> _version: c_int, _actions: uw::_Unwind_Action, _exception_class: uw::_Unwind_Exception_Class, _exception_object: *mut uw::_Unwind_Exception, _context: *mut uw::_Unwind_Context, </ins> ) -> uw::_Unwind_Reason_Code { <del> __gxx_personality_v0(version, actions, exception_class, exception_object, context) </del> <ins> core::intrinsics::abort() </ins> } extern "C" {

<!-- 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: Compiling with , after the emsdk is activated and emcc works, to compile properly Instead, this happened: Prints this error: I've tried adding to no avail <!-- 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. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
runs successfully
Also is broken on ubuntu with the same error message (at least windows subsystem for linux)
rustc 1.53.0-nightly ( 2021-04-24) emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.12 () Here's some info I gathered: Rust tries to . I think Rust is assuming that this symbol comes from emscripten. emscripten has a : libc++abi.a: emscripten exceptions: this is what rustc is trying to use; libc++abi-noexcept.a: no exceptions: does not compile libc++abi-except.a: wasm exceptions: experimental; in emscripten's repo shows that was never compiled into libc++abi.a by This commit looks suspicious: Prior to emscripten SDK version 2.0.10, I think has been and never did anything. Rust probably shouldn't be calling a stubbed function. seems untested if you ask me because I don't know how it could ever have worked. I successfully compiled hello world with emscripten SDK version 2.0.9. That version still has the stub.
label I-prioritize T-compiler O-wasm
thanks for the analysis. Assigning priority as discussed in the of the Prioritization Working Group. Let's find someone who can have a look at this. label -I-prioritize +P-high +I-nominated
I recall with the LLVM 11 upgrade, the compat notes mentioned which version of Emscripten to use when compiling with the target.


Question: } } <ins> // This is required by the compiler to exist (e.g., it's a lang item), but it's // never actually called by the compiler.  Emscripten EH doesn't use a // personality function at all, it instead uses __cxa_find_matching_catch. // Wasm error handling would use __gxx_personality_wasm0. </ins> #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( <del> version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, </del> <ins> _version: c_int, _actions: uw::_Unwind_Action, _exception_class: uw::_Unwind_Exception_Class, _exception_object: *mut uw::_Unwind_Exception, _context: *mut uw::_Unwind_Context, </ins> ) -> uw::_Unwind_Reason_Code { <del> __gxx_personality_v0(version, actions, exception_class, exception_object, context) </del> <ins> core::intrinsics::abort() </ins> } extern "C" {

Once this bug is resolved, can we add a similar note for the releases that upgrade Rust to LLVM 12?
As mentioned the panic=unwind strategy is broken on wasm32-unknown-emscripten. I recommend to switch default to panic=abort. Note that also rust std lib has to be rebuilt with panic=abort to fix the undefined symbol errors. Testing on my side showed that the problem could be fixed by changing TargetOptions on line 38 to "panicstrategy: PanicStrategy::Abort," in file. Unfortunatelly I do not have experience in preparing pull request and have no capacity to get into it now.
This issue can be solved by setting the env var which will override any flags passed to emcc. See this comment - Passing these flags using the won't work, as they are not passed to the linker. I received this error in two places, one for symbol and one for , hence the flag.
Reported this on Emscripten:


Question: scope 1 { debug self => _4;                // in scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL let mut _5: &mut T;              // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 <ins> let mut _6: &mut T;              // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 </ins> } bb0: {

Since InstCombine can now introduce where there was none before, without checking that the value is in fact not used afterwards. This may cause a value to be marked as uninitialized by the dataflow, but still be used in that uninitialized state. If InstCombine ran before the generator transform this would be acutely unsound and could probably be exploited directly, but other than that transform I don't think we rely on this property yet. This impacts , which does run after InstCombine and relies on the dataflow. I've observed this on , where it produces this diff: The second use of occurs despite the first move deinitializing the local. cc
Maybe we should stop making instcombine convert to ? This could be done in the pre-codegen cleanups, but for MIR it is wrong to use or on such values in general. Alternatively instcombine needs to start using dataflow to only insert moves when the site is the last use of the local.


Question: <ins> error[E0425]: cannot find value `a` in this scope --> $DIR/issue-92100.rs:5:10 | LL |         [a.., a] => {} |          ^ not found in this scope error: aborting due to previous error For more information about this error, try `rustc --explain E0425`. </ins>

<!-- 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. --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.57.0 ( 2021-11-29) running on x8664-unknown-linux-gnu note: compiler flags: -C embed-bitcode=no -C debuginfo=2 -C incremental --crate-type bin note: some of the compiler flags provided by cargo are hidden query stack during panic: end of query stack <!-- 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. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
reduced:
Minimized this a tiny bit further, and I have a detailed explanation why this occurs: So this bug first starts going wrong in late resolution. Specifically, , we define the as a binding when we see the second element (ident subpattern) of the slice pattern, and then bind it later when we walk thru the (expression!) in the first slice pattern element. Essentially, since we treat as being defined here: and then resolve that as the path for we reach a situation where we expect a variable to have been defined before it has been lowered in HIR, which leads to the ICE later on, since we expect to have lowered that path element.
Wonder how difficult it would be to make have subpatterns instead of subexpressions... edit: wouldn't help, see below..
Actually, I don't think fixing this just for ranges is sufficient. I can reproduce this same issue with this: Maybe I can just delay this panic as a span bug, since we're always gonna error out anyways. I think I would ideally like to fix this by making sure we separate bindings in patterns from affecting resolution for expressions in patterns. edit: Ended up fixing it the right way.
claim


Question: let mut param_env = obligation.param_env; fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { <del> param_env = param_env.with_constness(pred.constness.and(param_env.constness())); </del> <ins> pred.remap_constness(self.tcx(), &mut param_env); </ins> pred });

<!-- 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: print (from Debug impl) Instead, this happened: E0277, trait impl not found This was found by CI in the Ruffle Project: The issue is caused by the effective anti-bound of Drop, introduced by the manual impl of the trait, as well as the PR which introduced bounds for a number of functions in . It most recently worked on: rustc 1.59.0-nightly ( 2021-12-18) : modify labels: +regression-from-stable-to-nightly -regression-untriaged
cc


Question: // the `type_of` of the trait's associated item. If we're using the old lowering // strategy, then just reinterpret the associated type like an opaque :^) let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() { <del> self .tcx .type_of(alias_ty.def_id) .subst(self.tcx, alias_ty.substs) </del> <ins> self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs) </ins> } else { <del> self.tcx.mk_alias(ty::Opaque, alias_ty) </del> <ins> self.tcx.mk_alias(ty::Opaque, shifted_alias_ty) </ins> }; self.predicates.push( ty::Binder::bind_with_vars( <del> ty::ProjectionPredicate { projection_ty: alias_ty, term: default_ty.into(), }, </del> <ins> ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, </ins> self.bound_vars, ) .to_predicate(self.tcx), ); <del> for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs) </del> <ins> // We walk the *un-shifted* alias ty, because we're tracking the de bruijn // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd // have to reset `self.depth` back to `ty::INNERMOST` or something. It's // easier to just do this. for bound in self .tcx .item_bounds(unshifted_alias_ty.def_id) .subst_iter(self.tcx, unshifted_alias_ty.substs) </ins> { bound.visit_with(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. --<!-- 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. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
probably Regression in searched nightlies: from nightly-2023-02-15 to nightly-2023-03-16 regressed nightly: nightly-2023-02-20 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 actually
Or at least, the logic broke because of , so the ICE message probably changed in that PR from some other message, to this one in the title.
label +S-bug-has-mcve


Question: pub struct Context<'a> { waker: &'a Waker, local_waker: &'a LocalWaker, <del> ext: ExtData<'a>, </del> <ins> ext: AssertUnwindSafe<ExtData<'a>>, </ins> // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes // are contravariant while return-position lifetimes are

https://crater-
I'll need to re-check later but this seems to bisect to somehow.
The UI test changes from that PR appear to back this up, as confusing as it is.
I'm not sure what's going on in that crate, if it built successfully by mistake, or how that PR interacts with it, so let's cc the PR author and reviewer for validation.
After , no longer implements and , because the context now contains a which doesn't implement those traits. So this is an issue with the standard library and not the crate being built. Repro: label -T-compiler +T-libs +S-has-mcve
WG-prioritization assigning priority (). Noticing this on which says that was meant to be confined on nightly. Unsure about the fallout of this regression but for now marking as critical for tracking purposes. label -I-prioritize +P-critical
Revert up:
Isn't not unwind safe?
That line was by your PR, so while what you say is technically true, talking about what "already happened" when we are traveling back and forth through time via version control may be more confusing than helpful.
That line was already there. I the line below it though. Original PR:
Apologies, I guess I can't count numbers today? Hm, so, the full error of the regression is this: Note that it's trying to make a pointer implement . And for what it's worth, stable does indeed document is . Thus unfortunately that line you pointed to, as opposed to the one I thought you were referring to, is effectively just documenting that all are , and that will include regardless of whether it is is . And confusingly, , unlike .
I have opened as an alternative.


Question: <ins> // Test that async fn works when nested inside of // impls with lifetime parameters. // // check-pass // edition:2018 #![feature(async_await)] struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { fn test() { async fn test() {} } } fn main() { } </ins>

The diagnostics ("use of undeclared lifetime name") are bad, but this indeed must be an error because the inner is an illegal use of the outer rather than an implicitly defined fresh lifetime.
Hm, I don't think that's quite what I'd expect: previously using in that context would be fine because there is no shadowing so to speak, that is, this compiles:
From Similarly, if a fn definition is nested inside another fn definition, it is an error to mention lifetimes from that outer definition (without binding them explicitly). This is again intended for future-proofing and clarity, and is an edge case. (In the second example there's an explicit definition that shadows the previous definition for following uses, in the first example there's no second definition, only use)
I see that this is in the RFC, but I think I more or less disagree with the reasoning given. Disallowing the use of inband lifetimes when nesting function seems arbitrary and not entirely helpful; it also makes a mechanical change from "old" to "new" more difficult because shadowing is visible only based on indent levels.
IMO it should be an error, with a helpful note like the one you get when writing . Let's not make in-band lifetimes any more confusing than they already are.
The distinction is that inband lifetime's selling point is that you don't need to declare lifetimes. If we say that, and then clarify it with "except" then I think the feature feels incomplete. Inband lifetimes confusion does not increase with permitting this, IMO.
The problem is if it's allowed, then has a different meaning than This seems unfortunate and confusing. Even unergonomic if I may say so. There's no way that the distinction between and won't be missed in a quick scan of the second one. But, like, the RFC process did decide that isn't important, so whatever.
Well, somewhat, but not really. Nothing outside of imports/definitions inherits into the inner function, unlike the impl where there is a history and multiple things which inherit (, lifetimes, generics).


Question: <ins> #![feature(const_raw_ptr_to_usize_cast)] const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut (); pub const FOO: usize = unsafe { BAR as usize }; //~^ ERROR it is undefined behavior to use this value fn main() {} </ins>

Some people were of the opinion that this shouldn't work, but it currently does. : cc
cc
it's just super scary. EDIT: it should not and does not work. If we allowed this, various surprising things can happen, especially around implicit promotion. If you want to store pointers and integers, you can use a raw pointer.
For my own education, can you elaborate on why function pointers are ok? I'd thought that the runtime addresses of things -- including functions -- shouldn't be accessible at const-time since we don't know where they'll live at runtime. Could I make a const array that usize long?
When compiling to LLVM, the real function handle or pointer address is obtained. If you try doing anything weird with pointers at compile time, you will quickly notice that you are not at runtime. For example, you cannot divide such a usize by anything. You can add or subtract integers, because that's just pointer offsetting, but you can't inspect the address in any way. This also means that no, you cannot use this usize for array lengths or enum discriminants. This is due to the fact that miri pointers are not just addresses, but abstract pointers that are in a separate layer from the bytes of normal memory like the one of integers.
Thanks for the explanation. I guess that means that such a couldn't be passed to a const generic either?
The thing is const generics don't know where the usize comes from, so they could try to do something with it that is not allowed if it is just a pointer address. Until monomorphization we can't know if there is an issue. Note that converting a pointer to an usize and back just to be able to put it in const, statics, or use it with const generics, is a real pain. We would be better off in this case with an type, such that I can write and avoid the conversion to usize. For const generics, C++ accepts function pointers at the type level and that works just fine with clang, so I expect to work fine as well.
How would work? is disallowed but and work? that seems very weird and special cased (especially for fn types that involve higher rank lifetimes, as in my example) or is ~= ?


Question: <ins> #![feature(const_raw_ptr_to_usize_cast)] const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut (); pub const FOO: usize = unsafe { BAR as usize }; //~^ ERROR it is undefined behavior to use this value fn main() {} </ins>

then is a double indirection and to use it you need to worry about managing the memory it points to (which contains the )
I haven't thought this through beyond having used the atomic pointers in the C++ standard library: One way to implement this could be where we provide blanket impls for , , , , , , , ... or use some compiler magic to achieve a similar effect...
This is a bit offtopic, but regarding , mentioned at least once the possibility of introducing some new type, to make sugar for . I guess it can't entirely be "sugar", because of existing impls, but at least both could work the same.
Hehe, this is cute. :) And I agree it is working as intended. (Nice that the translation to LLVM actually gets this right, should there be a testcase to make sure it stays that way? :D )
So... other than testing this, all we need is a PR that adds -casts in constants under a feature gate (and makes those casts unsafe in constants and )
I've opened to brainstorm how to either add an type or retrofit to support items.
These kind of operations are now unsafe in contexts (impl PR: )
So do we have a test that you cannot use such usize as array length? :D
hmm... apparently not... Test-instructions: (via the feature gate) to turn various kinds of references and function pointers into these expressions in array length, repeat lengths and enum discriminant initializers (e.g. ) Note: Do not use items, everything needs to be inline in the use site to be properly tested
this is no longer allowed by any means:
Yes that is intended. This issue is for adding a regression test testing what happens when you use a pointer casted to a usize in an array length.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

I'm opening this up to serve as a tracking issue for enabling multiple codegen units in release mode by default. I've written up a before but the tl;dr; is that multiple codegen units enables us to run optimization/code generation in parallel, making use of all available computing resources often speeding up compilations by more than 2x. Historically this has not been done due to claims of a loss in performance, but the is intended to assuage such concerns. The most viable route forward seems to be to enable multiple CGUs and ThinLTO at the same time in release mode. Blocking issues: [x] Enable for libstd on all platforms - - - - Potential blockers/bugs: - -
cc
Presumably this will remain a stable compiler flag, but what else will change by default? Is the plan to make this only affect , or is the plan to also make this affect ? Do we want to make continue to use only a single CGU, to hedge against regressions for people who are already willing to trade off compiler time for runtime?
I would specifically propose that any opt level greater than 1 uses 16 codegen units and ThinLTO enabled by default for those 16 codegen units.
This is very interesting. One would think that ThinLTO-driven inlining should always have to do less work when our much more conservative pre-LLVM inlining. But that doesn't always seem to be the case, as in the . Most tests on the seem to profit though. Overall it's still not a clear picture to me.
was that comment meant for a different thread? I forget which one as well though, so I'll respond here! As a "quick benchmark" I compiled the regex test suite with 16 CGUs + ThinLTO and then toggled inlining in all CGUs on/off. Surprisingly inlining in all CGUs was 5s faster to compile, and additionally . In those timings is where inlining is only in one CGU, where is inlining in all CGUs. One benchmark, , got twice as slow!
Yeah, the comment was in response to (rust-doom) but since that was closed already, I put it here.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

Regarding the compilation time difference between pre- and post-trans inlining, my hypothesis would be that sometimes pre-trans inlining will lead to more code being eliminated early on (as in the case of regex apparently) and sometimes it will have the opposite effect. I suspect that there's room for improvement by tuning which LLVM passes we run specifically for ThinLTO. Or do we do that already?
Heh it's true yeah, I'd imagine that there's always room for improvement in pass tuning in Rust :). Right now we perform (afaik) 0 customization of any pass manager in LLVM. All of the normal optimization passes, LTO optimization passes, and ThinLTO optimization passes are all the same as what's in LLVM itself.
I wanted to also take the time and tabulate all the results from the to make sure it's all visibile in one place. Note that all the timings below are comparing a release build to a release build with 16 CGUs and ThinLTO enabled Improvements All of the following compile times improved, sorted by most improved to least improved Regressions The following crates regressed in compile times, sorted from smallest regression to largest alexcrichton's attempt to reproduce the regressions Here I attempt to reproduce the regressions on my own machine with Unfortunately the only regression I was able to reproduce was the rust-belt regression. I'll be looking more into that.
Looking into , one interesting thing I've found is that the crate takes longer to compile with ThinLTO than it would otherwise. Looking at it appears that one codegen unit in this crate takes 99% of the time in LLVM. This codegen unit appears to be basically entirely dominated by . Almost all of the benefit of multiple codegen units is spreading out the work across all CPUs. Enabling ThinLTO to avoid losing any perf is fundamentally doing more work than what's already happening at , but we get speedups across the board in most cases. If we have one huge CGU, split it in two, and work on those in parallel then we've got 50% of the original time to run ThinLTO (in a perfect world). If ThinLTO takes more than 50% of the time then we'd have a build time regression, but that's almost never happening.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

What's happening here is that we have one huge CGU, but when we split it up we still have one huge CGU. This means that the CGU which may take ~1% less time in LLVM only gives us a tiny sliver of a window to run ThinLTO passes. In the case of the crate this means that adding ThinLTO passes is an overall build time regression. So generalizing even further, I think that enabling ThinLTO and multiple CGUs by default is going to regress compile time performance in any crate where our paritioning implementation doesn't actually partition very well. In the case of we've got one huge function which hogs almost all the optimization time (I think) and the entire crate is basically dominated by that one function. I would be willing to conclude, however, that such a situation is likely quite rare. Almost all other crates in the ecosystem will benefit from the partitioning which should basically evenly split up a crate. maybe you have thoughts on this though?
Thank you so much for collecting and analyzing such a large amount of data, Your conclusions make sense to me. Unevenly distributed CGU sizes are also a problem for incremental compilation; e.g. the test sees 90% CGU re-use, yet compile time is almost the same as from-scratch. In the non-incremental case it might be an option to detect the problematic case right after partitioning and then switch to non-LTO mode? I'm not sure it's worth the extra complexity though. For cases where there is one big CGU but that CGU contains multiple functions, we should be able to rather easily redistribute functions to other CGUs. We'd only need a metric for the size of a . The number of MIR instructions might be a sufficient heuristic here. That would not help for but it might help for other crates. In conclusion, judging from the table above, I think we should make the default sooner rather than later. Open questions I see: What to do about ? I would have thought that it would always be a clear win to disable this when ThinLTO is enabled but that doesn't seem to be the case. Are there hardware configurations where this never is a win? E.g. should we default to traditional compilation if ?


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

FWIW, as the author of , which is a made-for-fun Piston game, I am more than happy to take a small compile regression when it seems like vast majority of crates get huge real-time improvements!
This seems like a good thing to have in our back pocket, but I'm also wary of trying to do this by default. For example the case is one where we may wish to disable ThinLTO but the one massive function could also critically rely on a function in a different CGU being inlined? That sort of case would be difficult for us to determine... In any case though I agree that we probably don't need the complexity just yet so I think we can defer this for later. Agreed! So far all the crate's I've seen the O(instructions) has been quite a good metric for "how long this takes in all LLVM-related passes", so counting MIR sounds reasonable to me as well. Again though I also feel like this is ok to have in our back pocket. I'd want dig more into the minor change example, I'm curious how awry the CGU distribution is there and whether a heuristic like this would help. Quite surprisingly I've yet to see any data that it's beneficial to compile time in release mode or doesn't hurt runtime. (all data is that it hurts both compile time and runtime performance!) That being said we're seeing such big wins from ThinLTO on big projects today that we can probably just save this as a possible optimization for the future. On the topic of inline functions I recently dug up again (later closed in favor of , but the latter may no longer be true today). I suspect that may "fix" quite a bit of the compile time issue here without coming at a loss of performance? In any case possibly lots of interesting things we could do there. Also a good question! I find this to be a difficult one, however, because the CGU number will affect the output artifact, which means that if we do this sort of probing it'll be beneficial for performance but come at the cost of more difficult deterministic builds. You'd have to specify the CGUs manually or build on the same-ish hardware to get a deterministic build I think? I think though that if you have 1 CPU then this is universaly a huge regression.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

With one CPU we'd split the preexisting one huge CGU into N different ones, probably take roughly the same amount of time to opimize those, and then tack on ThinLTO and more optimization passes. My guess is that with one CPU we'd easily see 50% regressions. With 2+ CPUs however I'd probably expect to see benefits to compile time. Anything giving us twice the resources to churn the cgus more quickly should quickly start seeing wins in theory I think. For now though the deterministic builds wins me over in terms of leaving this as-is for all hardware configurations. That and I doubt anyone's compiling Rust on single-core machines nowadays!
One thing I think that's also worth pointing out is that up to this point we've mostly been measuring the runtime of an entire . That's actually, I believe, the absolute worst case scenario for where ThinLTO will provide benefit. Despite this, it's showing huge improvements for lots of projects! The benefit of ThinLTO and multiple CGUs is leveraging otherwise idle parallelism on the build machine. It's overall increasing the amount of work the compiler does. For a from scratch, though, you typically already have tons of crates compiling for the first half of the build in parallel. In that sense there's not actually any idle parallelism. Put another way, ThinLTO and multiple CGUs should only be beneficial for builds which dont have many crates compiling in parallel for long parts of the build. If a build is 100% parallel for the entire time then ThinLTO will likely regress compile time performance. Now you might realize, however, that one very common case where you're only building one crate is in an incremental build! Typically if you do an incremental build you're only building a handful of crates, often serially. In that sense I think that there's some massive wins of ThinLTO + multiple CGUs in incremental builds rather than entire crate builds. Although improving both is of course great as well :)
For deterministic builds you have to do some extra configuration anyway (e.g. path remapping) so I would not consider that a blocker. And I guess there are single core VMs around somewhere.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

But all of this is such a niche case that I don't really care MIR-only RLIBs should put us into a pretty good spot regarding this, so I'm quite confident that we're on the right path overall.
That's really interesting. For incremental compilation enabled the situation might be different (because pre-trans inlining hurts re-use) but for the non-incremental case it sounds like it's pretty clear what to do.
Yeah, maybe we should revisit this at some point. Although I have to say the current solution of only and symbols and nothing in between is really nice and simple.
Hm yeah that's a good point about needing configuration anyway for deterministic builds. It now seems like a more plausible route to take! Also that's a very interesting apoint about incremental and inlining on our own end... Maybe we should dig more into those ThinLTO runtime regressions at some point! Also yeah I don't really want to change how we trans inline functions just yet, I do like the simplicity too :)
out of curiosity how did you figure out this and which function it was. I've wanted to look into why the webrender build is so slow and would welcome tips.
oh sure I'd love to explain! So I originally found as a problematic crate when compiling rust-belt as it just took awhile and I decided to dig deeper. I checked out the crate and ran: That drops in the current directory, and opening that up I see: ! The graph here isn't always the easiest to read, but we've clearly got two huge bars, both of which correspond to taking a huge amount of time for that one CGU (first is optimization, second is ThinLTO + codegen). Next I ran: and that command dumps a bunch of IR files into . Our interesting CGU is so I opened up (we sure do love our long filenames). Inside that file it was 70k lines and some poking around showed that one function was 66k lines of IR. I sort of forget now how at this point I went from that IR to determining there was a huge function in there though...
I don't know if this is the right place, but I think it should be considered whether the symbol issues reported in the Nightly section here: should be considered a blocker or not.


Question: MD->addOperand(Unit); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { Module *M = unwrap(Mod); for (Function &F : M->functions()) { if (F.hasAvailableExternallyLinkage()) F.deleteBody(); } } </ins> #else extern "C" bool

The tl;dr is that certain versions of llvm, (i've seen this on 3.8, and whatever llvm rustc nightly uses) appends seemingly random garbage to the end of some names, e.g. we get: instead of: This knocks the debuginfo out of sync (it doesn't have the garbage appended). I've been able to repro this with clang3.8 for c++ files as well (haven't tested on other llvm), and switching to 5.0 seems to have fixed the issue. I don't know if its within reach, but perhaps we should attempt upgrading to llvm 5.0 before releasing this on stable? Note I understand this is for release mode, but i see this in debug mode on rustc nightly right now as well...


Question: // Otherwise it's a span with wrong macro expansion info, which // we don't want to track anyway, since it's probably macro-internal `use` <del> if let Some(sub_span) = self.span.sub_span_of_token(item.span, token::BinOp(token::Star)) { </del> <ins> if let Some(sub_span) = self.span.sub_span_of_star(item.span) { </ins> if !self.span.filter_generated(item.span) { let access = access_from!(self.save_ctxt, item, item.hir_id); let span = self.span_from_span(sub_span);

contains a function, which allows to to, well, retokenize existing span: There's only caller of this function: And there's only one caller of that caller: In other words, the only reason why we need is to get the span of hir::Usewhich happens to be a glob import. ( rls needs to know the span of use foo:: with explicit list of imported items" code action. This was the first demoed code action and is still that is implemented ) I'd like to remove the function, as it is one of the few remaining things that requires to be public, and as it is very much a hack anyway. Additionally, I believe I've broken this function accidently a while ago: Rather than retokenizing a span, it retokenized file from the begining until the end of the span (whcih, as uses are usually on top, worked correctly most of the times by accident). What would be the best way to fix this? Add hir::Use-- this seem to be the "proper" solution here Move hack's implementation to where it belongs: in , just fetch the text of the file and look for ('') Remove the deglog functionlity from RLS? I don't like this option as it handicaps the RLS before we formally decided to deprecated it. But I don't completely disregard it either, as, as a whole, it seems to be a full-stack one off hack penetrating every layer of abstraction. WDYT?
I'd suggest the second alternative (move hack's implementation to in librutcsaveanalysis), save analysis is a home of many hacks already and one more until save analysis is deprecated in its entirety won't hurt. Adding span for would be ok if it were useful for anything else at least.


Question: linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { <del> features: "+v6,+vfp2".to_string(), </del> <ins> features: "+v6,+vfp2,-d32".to_string(), </ins> abi_blacklist: super::arm_base::abi_blacklist(), target_mcount: "__mcount".to_string(), .. base

The support for ARMv6 architecture was broken somewhere between ...: compiles file while produces binary that crashes with . More specifically, this is a binary cross-compiled from for arch, linked with a . The hardware is part of Raspberry Pi Zero rev. 1.1, the processor information is as follows:
Presumably due to LLVM update. Can you determine what the illegal instruction is? (E.g. via gdb and .)
did you try compiling code on your raspberry pi 0 ? this might be issue with gcc cross compiler (code generator part)l/linker rather than Rust
Looks like even compilation directly on RPi0 is broken as the compiler/cargo crashes: Running under gdb: I'm not sure if this helpful at all, I can send (e-mail) you the coredump or do anything else you need, unfortunately I have basically no experience debugging low-level ASM issues.
The problematic instruction is , which vfp2 and dpvfp. The target builds with . There were some in LLVM 9 around the sp/dp handling on ARM ( became ), possibly we flipped a default there...
According to the ARM1176JZF-S Technical Reference Manual (which is the CPU used in Raspberry Pi Zero) it contains a VFP11 coprocessor (VFP2 implementation with full support for single-precision and double-precision math operations). Maybe VFP11 is somehow slightly different from what LLVM assumes? ARM refs: VFP11 VectorFloating-point Coprocessor Technical Reference Manual for ARM1136JF-S
Thanks for the references. So both vfp2 and fp64 should be supported. Something I missed before is that the instruction uses the register, while the VFP11 coprocessor only has 16 double-precision registers. To target this CPU needs to be to the target features. It looks like the corresponding does disable . Possibly the default flipped here, in which case we should just add to all the older ARM targets.
This issue might be related to this one - libc's CI is broken since the LLVM upgrade.
This is probably caused by EDIT: Ah nevermind, someone found this already
Reopening until there is confirmation that this is fixed...
Hi with the recent 1.38.0-nightly ( 2019-07-26) both local toolchain / cargo and the cross-compiled binary seem to work. Thanks.
Great, closing as fixed


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. use std::env; use std::fs::{self, TempDir}; fn main() { let td = TempDir::new("create-dir-all-bare").unwrap(); env::set_current_dir(td.path()).unwrap(); fs::create_dir_all("create-dir-all-bare").unwrap(); } </ins>

The following panics: The following works: Apologies in advance if this is intended behavior.
I have found that it also works when using:
This will be fixed by


Question: ")?; for implementor in foreign { <del> // need to get from a clean::Impl to a clean::Item so i can use render_impl if let Some(t_did) = implementor.impl_.for_.def_id() { if let Some(impl_item) = cache.impls.get(&t_did).and_then(|i| i.iter() .find(|i| i.impl_item.def_id == implementor.def_id)) { let i = &impl_item.impl_item; let impl_ = Impl { impl_item: i.clone() }; let assoc_link = AssocItemLink::GotoSource( i.def_id, &implementor.impl_.provided_trait_methods ); render_impl(w, cx, &impl_, assoc_link, RenderMode::Normal, i.stable_since(), false)?; } </del> <ins> if let Some(i) = implementor2item(&cache, implementor) { let impl_ = Impl { impl_item: i.clone() }; let assoc_link = AssocItemLink::GotoSource( i.def_id, &implementor.impl_.provided_trait_methods ); render_impl(w, cx, &impl_, assoc_link, RenderMode::Normal, i.stable_since(), false)?; </ins> } } }

It should work a bit like IDE's feature that finds everything that implements a given interface.
This should be a fairly small change (the most annoying part has already been done) so i'll open this up as a mentored issue. The bit that writes out the "Implementors" section is in . This is where the known implementors for a given trait are pulled out of the global context and listed out onto the rendered page. The bit that's responsible for creating links is , implemented on a local type. This kind of Item is easily made from the kind of Item that's otherwise worked on in , but there's a catch: The entries in the Implementors list aren't s. They're s, which are only a subset of the things you get on an Item. This is the "most annoying part" i mentioned earlier. Fortunately, i ran into this when creating the "Implementations on Foreign Types" section, so if you scroll up a little in , you can see so i could render the full impl block for them. The task for anyone who wants to take this on is to pull that up a little so that it's used for all the implementors, not just the foreign ones. With a in hand, combine it with the Context to create a and call to generate the link. ( This also helpfully includes the extra HTML bits that will flush the link to the right edge, which is really the final step.) And... that's it! The link should probably go between the and the where clause underneath it, so that it's aligned with the impl line and not the where clause. You may need to also close/open the that's wrapping the whole line to make sure the link itself isn't monospace. If you have any questions, let me know! Either comment here, or hop onto IRC in , or the impl period Gitter under .


Question: <ins> error[E0070]: invalid left-hand side of assignment --> $DIR/issue-93486.rs:3:36 | LL |         vec![].last_mut().unwrap() = 3_u8; |         -------------------------- ^ |         | |         cannot assign to this expression error: aborting due to previous error For more information about this error, try `rustc --explain E0070`. </ins>

I was attempting to assign directly to the result of a vector's , which caused this error to fire. That is when I discovered that the help section was telling me to do add an extra let to my while statement, which is not syntactically correct. I tried this code: I expected to see this happen: The code would fail to compile and the help message would tell me to dereference the left side, or at the least give me code that was syntactically correct. Instead, this happened: The could failed to compile, and the help message gave syntactically incorrect code as seen in the backtrace section. <!-- 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. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
This minifies to which reports and are related I think, since this example produces the ICE mentioned there on stable
label +A-diagnostics +D-invalid-suggestion +T-compiler
claim


Question: <ins> //@ edition:2024 //@ compile-flags: -Zunstable-options #![feature(gen_blocks)] const gen fn a() {} //~^ ERROR functions cannot be both `const` and `gen` const async gen fn b() {} //~^ ERROR functions cannot be both `const` and `async gen` fn main() {} </ins>

() Reproduces on the playground using . label +D-incorrect +F-gen_blocks +requires-nightly


Question: <ins> error[E0567]: auto traits cannot have generic parameters --> $DIR/issue-117789.rs:3:17 | LL | auto trait Trait<P> {} |            -----^^^ help: remove the parameters |            | |            auto trait cannot have generic parameters error[E0658]: auto traits are experimental and possibly buggy --> $DIR/issue-117789.rs:3:1 | LL | auto trait Trait<P> {} | ^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information = help: add `#![feature(auto_traits)]` to the crate attributes to enable error: aborting due to 2 previous errors Some errors have detailed explanations: E0567, E0658. For more information about an error, try `rustc --explain E0567`. </ins>

<!-- ICE: Rustc '' 'thread 'rustc' panicked at 'assertion failed'', 'thread 'rustc' panicked at 'assertion failed'' File: --auto-reduced (treereduce-rust): <details<summary<strongoriginal code</strong</summary<poriginal: </p</detailsVersion 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
Regression in nightly-2022-02-02 found 9 bors merge commits in the specified range commit[0] 2022-01-31: Auto merge of - spastorino:fix-perf-overlap-mode2, r=nikomatsakis commit[1] 2022-01-31: Auto merge of - tmiasko:is-self-recursive, r=ecstatic-morse commit[2] 2022-02-01: Auto merge of - WaffleLapkin:rustcmustimplementoneofchecktarget, r=nagisa commit[3] 2022-02-01: Auto merge of - eddyb:diagbld-scalar-pair, r=jackh726 commit[4] 2022-02-01: Auto merge of - ehuss:rollup-9ecozo9, r=ehuss commit[5] 2022-02-01: Auto merge of - thomcc:chunky-splitz-says-no-checking, r=the8472 commit[6] 2022-02-01: Auto merge of - eholk:disable-drop-range-analysis, r=pnkfelix commit[7] 2022-02-01: Auto merge of - matthiaskrgr:rollup-f7dkn3p, r=matthiaskrgr commit[8] 2022-02-01: Auto merge of - yaahc:Termination-abstraction, r=Mark-Simulacrum ERROR: no CI builds available between and within last 167 days
Actually reduced
Might have been caused by
Ah yes, the assert was there ping :)


Question: LL | fn d<'a, const C: S<'a>>() {} |      +++           ++++ <ins> error[E0771]: use of non-static lifetime `'a` in const generic --> $DIR/unusual-rib-combinations.rs:29:22 | LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>; |                      ^^ | = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052> </ins> error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/unusual-rib-combinations.rs:7:16 |

This is a fuzzed test case, found with and minimized with . I wasn't able to find any similar issues: : <details<summary<strongBacktrace</strong</summary<p</p</details
This is related to , do we need to keep this ICE or we cover it at here:
The assert was in If you have a reproducer, then it can be to and the assert can be removed.
label +S-bug-has-mcve


Question: <ins> // run-pass // edition:2021 struct Props { field_1: u32, //~ WARNING: field is never read: `field_1` field_2: u32, //~ WARNING: field is never read: `field_2` } fn main() { // Test 1 let props_2 = Props { //~ WARNING: unused variable: `props_2` field_1: 1, field_2: 1, }; let _ = || { let _: Props = props_2; }; // Test 2 let mut arr = [1, 3, 4, 5]; let mref = &mut arr; let _c = || match arr { [_, _, _, _] => println!("A") }; println!("{:#?}", mref); } </ins>

Encountered an ICE when building  0.18.0 on edition 2021. I have roughly narrowed it down to the following (can probably be reduced further). Seems to be an issue with closure captures. <!-- 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. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</detailscc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
The code can be further simplified to: The issue seems to be around using type annotation. If a type annotation is included, the right hand side of the let statement should always be read.
Is there a runtime check/ is MIR generated for checking if is valid? Because if that's the case then we need props2 to be caputred.
claim I should have a fix later tonight
We found another instance of this ICE that still fails with included: Found trying to migrate . Let me know if you need any more information.


Question: <ins> // edition:2021 #![feature(type_alias_impl_trait)] struct CallMe; type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a; type FnType = impl Fn(&u32) -> ReturnType; impl std::ops::Deref for CallMe { type Target = FnType; fn deref(&self) -> &Self::Target { fn inner(val: &u32) -> ReturnType { async move { *val * 2 } } &inner //~ ERROR: expected generic lifetime parameter, found `'_` } } fn main() {} </ins>

<!-- 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. --Explicitly giving lifetimes to with and doing the same on does not fix the ICE either. Version
label +S-bug-has-mcve
Triage: Fixed on the latest nightly, labels: +E-needs-test


Question: <ins> // Regression test for issue #124935 // Tests that we do not erroneously emit an error about // missing main function when the mod starts with a `;` ; //~ ERROR expected item, found `;` fn main() { } </ins>

Tested on nightly and stable. The second diagnostic is strange. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-diagnostics S-has-mvce
claim
any idea why rustbot ignored me?
Just guessing, the missing + for S-has-mcve maybe?
Oops, this should'nt've been closed.


Question: <ins> error: invalid label name `'static` --> $DIR/issue-52437.rs:2:13 | LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize] |             ^^^^^^^ error[E0282]: type annotations needed --> $DIR/issue-52437.rs:2:30 | LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize] |                              ^ consider giving this closure parameter a type error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0282`. </ins>

Binder(<[type error] as ToBytes) This only happens if there are two erroneous functions, if I take out it works fine. It seems like I was trying to do this wrong in the first place since the first function gives an error . Not sure what the right way to do this is. <details<summaryTraceback</summary</details
Tried to reduce it and found a similar case with the same ICE:
Compiler triage: Seems likely to be caused by the need for lazy norm. Marking as p-medium for now.
The ICE doesn't appear on the latest nightly, marked as E-needstest