Question: /// } /// ``` #[must_use] <del> #[unstable(feature = "panic_info_message", issue = "66745")] </del> <ins> #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } }

was closed when stabilized the corresponding language feature, but we didn’t realize that it was also the tracking issue for this standard library feature: History: [x] Original tracking issue: [x] Discussion of payload vs message [x] Making .message() infallible: [x] Split core/std PanicInfo into two types: This made core::panic::PanicInfo::message() infallible. [x] Use opaque return type: [x] FCP [x] Stablization PR: Unresolved questions: [x] Should it be infallible? Yes, by making std::panic::PanicHookInfo a different type. [x] What should the return type be? or an opaque ? The first is simpler, but the latter allows a bit more flexibility for future changes.
Instead of making a PR go through the queue to fix the tracking issue, should we stabilize this method? fcp merge The doc-comment is slightly wrong or out of date. Its second line shoudl be removed. always creates a where is , regardless of the number of arguments given. In the single-argument case, that argument is required to have type . At first returning seemed unusual to me and I considered that we could make the method return instead, on the basis that calling its impl is almost the only useful thing to do with a . But has been stable and documented as the return type of since 1.0.0, so maybe it’s fine.
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [x] [ ] [ ] [x] [x] [ ] [ ] [ ] Concerns: single-arg core::panic () Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
The module also links to that closed tracking issue. Let’s consider the pFCP above to also include stabilizing it. ( is stable.)
concern single-arg core::panic Should we change libcore’s macro so that its single-argument form creates a with a instead of one with a ?


Question: /// } /// ``` #[must_use] <del> #[unstable(feature = "panic_info_message", issue = "66745")] </del> <ins> #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } }

CC Pushing this idea further, it’s tempting to maybe remove entirely and instead have a whose dynamic type can be . But that doesn’t work because is a method of and is not .
I thought the point of the message field was that core can't make a payload since it can't allocate?
The struct is: Both the and fields involve borrowing. As far as is concerned, they could both be borrowing form a stack frame. (And as far as I understand they are, in practice today.) It’s in the case of unwinding that there’s an owned that can return, which requires allocating.
Based on the timing of it looks like you may have thoughts on this :)
Ah, goes into how and why the panic handler in libstd (which is called by if libstd is linked) ignores the it receives. We could probably change this but it gets tricky: while most implementations of for environments would be fine with receiving a borrowed payload, libstd wants to potentially take ownership and box it for unwinding.
I have zero recollection for why this is the way it is, and I'm not really particularly interested in doing all the archaeology to dig up why it is the way it is. I'm not a huge fan of just stabilizing things because they happen to be there, but I don't really see why we wouldn't want to stabilize this. If there were a reason to not stabilize this though an investigation would presumably turn that up, but I'm not up to do that investigation myself.
That’s totally fair. I’m confident that this was more likely forgotten than deliberately left unstable. If deliberate we would have kept the tracking issue open or made a new one for the remaining bits. This is what lead me to propose stabilization. Having dug a little more, and thanks to Ralf’s blog post, I think we may want at some point to revisit what data we expect to contain or not in various situation. In particular it could be interesting to extend to support payloads other than and make it closer to . Given those possibly-desirable changes, it may not be the time to add more constraints: fcp cancel
proposal cancelled.
Lol, I had no idea. ;) So, indeed, I was wondering if we could do something about the duality of the and fields in . I assume we cannot change the fact that the same type is used both of panic handlers and panic hooks.


Question: /// } /// ``` #[must_use] <del> #[unstable(feature = "panic_info_message", issue = "66745")] </del> <ins> #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } }

Concretely, I was thinking of adjusting somewhat like this: That would at least remove the need for the hack in . (The hack would likely move to instead, but that is a smaller hack IMO: the hack is now not encoded in the state of any more, just in its dynamic API.) I think this would retain all current functionality while clarifying the invariant of wrt. the payload (and explicitly calling the message a "payload"; right now it seems to be something that sits next to the payload which is inaccruate). But there are enough subtleties here that we'll only really know once someone implements this. With this change, the panic hook would always get a . We should likely provide a method somewhere in libstd to factor out this code: I was imagining something like an extension trait on with a type like . However, the panic hook is not the only place where that conversion is useful; another situation is code that caught a panic and wants to extract the message. I expect most instances of that to just handle payloads, not knowing that payloads are also common (that is certainly what happened when I wrote such code). So ideally we'd have a method that takes and returns , but I do not have a good idea where to put that. This is the hard part, as we cannot use . I wonder if we can use a take-based approach, similar to ? Conceptually, would put the panic into an , and somehow pass an to the panic handler, and the implementation of said handler could then the payload if it needs full ownership (like for unwinding). Except the panic handler cannot be generic, so it would have to be , which is not a thing. But with enough unsafe code we could re-implement something that behaves like that. I don't see any way to do this entirely safely; the panic handler that wants to take out the payload and put it somewhere needs to dynamically determine the size of the payload and arrange for there to be enough space. In liballoc, we could provide a safe wrapper for this that puts things into a , but in libcore, I don't think there is a safe API that we could provide to grab ownership.


Question: /// } /// ``` #[must_use] <del> #[unstable(feature = "panic_info_message", issue = "66745")] </del> <ins> #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } }

But maybe it is enough for the public API to expose ways to borrow the payload (should work for all non-unwinding handlers); if only libstd needs to take the payload (for unwinding) we could keep the unsafe part of the API internal. Also, we certainly do not want a panic hook to the payload out of its . At this point it seems to be quite a problem that panic hook and panic handler both use the same type. In fact, a panic handler likely wants a to be able to things without interior mutability. Is there any way we could make the attribute support both signatures, and then (based on the types of the methods) only -based implementations will actually be able to or the payload?
I agree, but it’s can easily be an inherent method of nor of because those are in libcore which doesn’t have access to . It feels slightly unfortunate that we’d need an extension trait just for this. I considered this yesterday and come to pretty much the same conclusions. To take ownership of a payload of unknown size through a non-generic API we pretty much heap allocation, which for libcore means something like receiving an , unsafely using , and returning that is to be passed to . It’s not pretty, but if only libcore and libstd deal with this internally maybe that’s ok? Is there a use case for a other than libstd’s to take ownership of the payload?
I was thinking of a slightly different API actually: Here, does to put the payload into caller-allocated storage; that storage must have (at least) size and align as given by . What I did not consider is how to get out the vtable, so maybe that higher-order approach is better.
We discussed this in the libs-api meeting today. We concluded that before stabilizing this, we need to make sure it works (doesn't return ) for std::panic!() as well. That is already the case with Rust 2021's std::panic!() (since it's identical to core::panic!() in this edition), but not for Rust 2015/2018's std::panic!(). Once that is fixed, we feel okay with returning a placeholder message for non-string panics (panics from or Rust 2015/2018's ), at which point the function can return an unconditionally, rather than an .


Question: /// } /// ``` #[must_use] <del> #[unstable(feature = "panic_info_message", issue = "66745")] </del> <ins> #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn message(&self) -> PanicMessage<'_> { PanicMessage { message: self.message } }

(And also, should be returned by value, not by reference.)
Any progress on stabilization?
It would great to have this little feature.
Still nothing? What's missing?
can this be stabilized after was resolved in the pull request ?
Yes, soon, hopefully! I've updated the overview at the top of this tracking issue. The main question left before stabilization is the return type of the method. Should this return (as the unstable method does today), or should it return an opaque type that wraps that fmt::Arguments, so we can still change in the future? (In case we want to support different types of no_std panic, such as panicking with an Error or something.)
Can it return or so?
I would vote for an opaque type that would also implement .
Did that in this PR:
merge
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [ ] [x] [x] [x] [x] No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon.


Question: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

(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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: error[E0508]: cannot move out of type `[u8]`, a non-copy slice <del> --> $DIR/unsized-exprs2.rs:22:19 </del> <ins> --> $DIR/unsized-exprs2.rs:22:5 </ins> | LL |     udrop::<[u8]>(foo()[..]); <del> |                   ^^^^^^^^^ |                   | |                   cannot move out of here |                   move occurs because value has type `[u8]`, which does not implement the `Copy` trait </del> <ins> |     ^^^^^^^^^^^^^^^^^^^^^^^^ |     | |     cannot move out of here |     move occurs because value has type `[u8]`, which does not implement the `Copy` trait </ins> error: aborting due to previous error

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: rm $(TMPDIR)/bar $(RUSTC) foo.rs --emit=asm,ir,bc,obj,link --crate-type=staticlib rm $(TMPDIR)/bar.ll <del> rm $(TMPDIR)/bar.bc </del> rm $(TMPDIR)/bar.s rm $(TMPDIR)/bar.o rm $(TMPDIR)/$(call STATICLIB_GLOB,bar)

Passing rustc the flag and passing may produce different files (that is, outputs). This is true of rust-core (see below), though was not the case for a simpler ("Hello, world!") test file. Test script: Diff output indicates binary files differ. Tested with , rust-core on . rustc compiled from master on Arch Linux. If this is, in fact, expected behavior- sorry for the trouble, unexpected to me.
Can you provide a diff between the outputs? This is likely a known issue, but I would like to be sure.
.bc is a binary format, so just gives "Binary files and differ" as its output. On my machine, is 19K and is 62K. I'm not familiar enough with the format to extract much more data.
I note the difference persists when the second line is (two separate flags), though both produce both artifacts.
Can you pass and diff those outputs?
With emit flags as and respectively, there is no difference in and (according to diff.)
It seems that every bytecode is invalid only when a rlib is produced. It stopped working between rust-git-0.9.1301 and 1362 (shortly before 2014-02-23 15:37:05 -0800). Going back thorugh the log, I found I believe that creates deflated bytecode. Perhaps should be stored with extension or .


Question: [1.8h]: https://github.com/rust-lang/rust/pull/31460 [1.8l]: https://github.com/rust-lang/rust/pull/31668 [1.8m]: https://github.com/rust-lang/rust/pull/31020 <del> [1.8m]: https://github.com/rust-lang/rust/pull/31534 </del> <ins> [1.8mf]: https://github.com/rust-lang/rust/pull/31534 </ins> [1.8mp]: https://github.com/rust-lang/rust/pull/30894 [1.8mr]: https://users.rust-lang.org/t/multirust-0-8-with-cross-std-installation/4901 [1.8ms]: https://github.com/rust-lang/rust/pull/30448

These are all legal, and somewhat strange, since they're not really following the file-system analogy that modules are typically explained with. I expect this behaviour is just whatever happens to fall out of the current implementation strategy, so let's make a more explicit decision one way or another. As one might expect, each of these is a distinct instance of (which can be verified by placing in : the compiler will greet you 3 times). Noticed in .
This seems weird to me. I think the intention is that the out-of-line syntax () should only work at the top-level.
I'd vote for allowing non-inline modules only at the top-level, to retain a clear mapping to the file system.
(Or nested inside modules.)
triage: P-medium Backwards incompatible, but ... kind of a curiousity.
Found one more mod aliasing scenario. It involves several files, and is semi officially allowed by the reference. The layout The files The copy module will be aliased. The problem is that although and are not directory owners, their inner modules are.
Upon reflecting more about this, I think that there are two questions here. should non inline modules be allowed (syntactically) inside items? should module aliasing (the same file representing two modules in the crate) be allowed? The questions are independent because you can use attribute to create module aliasing manually. I would prefer if the answer to the second question is not. I'm contributing to the Rust plugin for IntelliJ IDEA, and one of the tasks there is mapping files to modules (for example, to go to the parent module). I would much prefer just to highlight module aliasing as an error, rather then to deal with non one-to-one mapping between files and modules. As a side note, if a user does want aliasing for some reason, she can always use symbolic link for the same effect.
I tend to believe it is fine to have aliasing if you write the yourself (you asked for it...), and that it would be ok to put a non-inline module inside an non-module, if you specify the path yourself, but that we should error out otherwise. However, there has definitely been confusion in the past about the role of as a declaration and not a , and disallowing aliasing would prevent that confusion from leading to incorrect trees.


Question: [1.8h]: https://github.com/rust-lang/rust/pull/31460 [1.8l]: https://github.com/rust-lang/rust/pull/31668 [1.8m]: https://github.com/rust-lang/rust/pull/31020 <del> [1.8m]: https://github.com/rust-lang/rust/pull/31534 </del> <ins> [1.8mf]: https://github.com/rust-lang/rust/pull/31534 </ins> [1.8mp]: https://github.com/rust-lang/rust/pull/30894 [1.8mr]: https://users.rust-lang.org/t/multirust-0-8-with-cross-std-installation/4901 [1.8ms]: https://github.com/rust-lang/rust/pull/30448

however is disconcerting, and suggests that perhaps the code has a slightly different model in mind than I do in my head. :) That is, I strongly expect to (by default) be found at . What happens if you don't have the , but just place in ?
It is forbidden because is not a directory owner.
Just in case here is a repository with the example: I don't see a reason to allow user to shoot himself in the leg. What if you accidentelly have identical attributes (copy paste problem)? My main concern though is that non injective file to module mapping may complicate the implementation of some rust tools. Here is another hypothetical example of this. Suppose you implement incremental compilation for rustc. You will need a mapping from files to modules. If mod aliasing is alowed, then you will need a multimapping. So you end up with more complex code which is used only in a tiny fraction of projects and because of this probably contains some bugs.
Ah, I see. So it seems to me that the problem is that should not be allowed in contexts where would be illegal. In other words, an inline module should only be considered a "directory owner" if it is located within a directory owner. A compromise might be Yet Another Lint Warning. ;) I agree with you about preventing people from shooting themselves in the leg, but I guess I think people don't use lightly or frequently, so this seems unlikely to be a major source of confusion.
I totally agree that this curiosity is insignificant for users. But I still worry more about the implementation side of the issue, and a lint warning does not help here.


Question: pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_err(span, explain); <ins> // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; } </ins> diag.fileline_help(span, &format!("add #![feature({})] to the  crate attributes to enable", feature));

Steps to reproduce: The output of is: does as suggested by the message, but that fails too (as expected): Proposed fix: in the beta and stable channels (i.e. whenever is forbidden), the message that suggests adding should not be shown. (Clean up the test case with .) CC
Gonna milestone this real quick, as it seems quite important.
I might be able to whip up a quick fix, though I'm not 100% sure about testing it properly ... (I've never actually tried building something for a non-dev release channel before...)
after chatting with it seems like I have a patch, building it now
gonna leave to it
Hello good Rust folks :smile: Before the beta, I used which is in . Is there any way to use this trait during the beta ? I'm not sure how I can get the code to compile. Thanks for any tip / hints you can offer :+1:
Hi Commenting on random unrelated issues is usually not the right thing to do. You should rather open a new issue, or ask on . But to answer your question anyway, that trait only has : … and is stable and can be used on beta. So I’d recommend you copy/paste the trait into your code, or make a function.
Thanks for taking the time to answer. I appreciate it. I don't see how this is unrelated. This is related, since the code I'm talking about used to compile with and the compiler suggests to do that, during the beta period. Thanks for your tip on copying the function :+1: I guess I'll just do that if nothing better is available and change this again when the trait is stable.
This specific issue is about fixing one of the compiler’s error message, not about fixing code that triggers that error. It really helps everyone to keep discussions on topic.
Alright. I understand. I'll make sure to open a new issue or go on StackOverflow next time if appropriate. Thanks again :+1:
This doesn't seem to be properly fixed in the beta channel. I'm still being recommended to add in the errors, and then told it's not available in the beta channel. Rust version: The code I used (snappy example in the docs with the extra addition on the first line:
This happened after Beta release.


Question: pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_err(span, explain); <ins> // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; } </ins> diag.fileline_help(span, &format!("add #![feature({})] to the  crate attributes to enable", feature));

We'll see the effect of this patch in 1.0 and afterwards Beta, etc.
Whoops, I thought this made it in before beta. Thanks!
are there plans to release updates to the beta channel within a given 6 weeks cycle? Either this one or in the future.
I'm certain there will be updates; see discussion from last night here:
So how does one fix this error? I'm a new user of the rust library and I can't seem to use the collections library during the beta due to this problem. Given this git issue is a top google result, it would be nice if there were a solution here. Edit: Looks like the solution is to switch to the rust nightly. Is the entire collections library off-limits in the beta?
by design, you have access to the parts of that are re-exported from (and are stable).


Question: <ins> // Copyright 2017 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. // // no-system-llvm // compile-flags: -O #![crate_type="lib"] #[no_mangle] pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} // CHECK-NEXT: ret i32 6 vec![1, 2, 3].iter().sum::<i32>() } </ins>

Rustc used to be able to replace with a constant when optimizing, not at the moment. It simply looks like a Layout method that is not inlinable. (This is a regression strictly speaking — stable & beta can do this optimization, but not nightly.) Code to reproduce:
Are there any ways to write automated tests to check for "regressions" like this? Assertions against LLVM bitcode?
Yes can be used for this, e.g. Assuming this is run against the bitcode after optimization, that is.
cc -- seems LLVM related
Nope. Just () that is not marked as inline.
cc
I didn't confirm that making Layout::repeat as inline fixes this, so please confirm that/add a test before closing.


Question: // In theory, any zero-sized value could be borrowed // mutably without consequences. However, only &mut [] // is allowed right now, and only in functions. <del> if self.const_kind == Some(hir::ConstContext::Static(hir::Mutability::Mut)) { // Inside a `static mut`, &mut [...] is also allowed. match ty.kind() { ty::Array(..) | ty::Slice(_) => {} _ => return Err(Unpromotable), } } else if let ty::Array(_, len) = ty.kind() { </del> <ins> if let ty::Array(_, len) = ty.kind() { </ins> // FIXME(eddyb) the `self.is_non_const_fn` condition // seems unnecessary, given that this is merely a ZST. match len.try_eval_usize(self.tcx, self.param_env) {

Consider the following code: This should just work. But instead it throws an error: The reason for this is that gets lifetime extended via promotion, so this reference now points to a separate mutable static -- but mutable statics cannot be mutated during CTFE. I see no way to fix this, other than stopping to promote mutable references -- which we should IMO do anyway, they are a very strange and unprincipled special case. Just imagine doing this in a loop, suddenly all these different and mutable allocations share the same address... Cc
Ugh, that's an ancient rule (believe it or not, it's a workaround for not being able to write and have the length be inferred!) and it was never meant to get this far, I guess I didn't think it through properly when adding the "outermost scope" rule, which is the only position where allowing it makes sense. In the current implementation, it should've never been promoted, only allowed, my bad!


Question: // for where the type was defined. On the other // hand, `paths` always has the right // information if present. <del> Some(&( ref fqp, ItemType::Trait | ItemType::Struct | ItemType::Union | ItemType::Enum, )) => Some(&fqp[..fqp.len() - 1]), Some(..) => Some(&*self.cache.stack), </del> <ins> Some(&(ref fqp, _)) => Some(&fqp[..fqp.len() - 1]), </ins> None => None, }; ((Some(*last), path), true)

There are bad (404) links in search results with nightly rustdoc. E.g. go to and then click the result. This leads to which does not exist. Cc
Actually, this issue seems to exist even on stable -- somehow it went unnoticed for quite a while, it seems.
I think it's because we are badly handling a reexport/type alias.
I think this is a duplicate of


Question: <ins> // Assuming that the hidden type in these tests is `&'_#15r u8`, // we have a member constraint: `'_#15r member ['static, 'a, 'b, 'c]`. // // Make sure we pick up the minimum non-ambiguous region among them. // We will have to exclude `['b, 'c]` because they're incomparable, // and then we should pick `'a` because we know `'static: 'a`. // check-pass trait Cap<'a> {} impl<T> Cap<'_> for T {} fn type_test<'a, T: 'a>() -> &'a u8 { &0 } // Basic test: make sure we don't bail out because 'b and 'c are incomparable. fn basic<'a, 'b, 'c>() -> impl Cap<'a> + Cap<'b> + Cap<'c> where 'a: 'b, 'a: 'c, { &0 } // Make sure we don't pick `'static`. fn test_static<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c> where 'a: 'b, 'a: 'c, T: 'a, { type_test::<'_, T>() // This will fail if we pick 'static } fn main() {} </ins>

The following code should pass regardless of the declaration order of lifetimes: This is related to but it's different in that we do have a lower bound region, , but we fail to recognize that because , which is responsible for calculating from , assumes that the outlive relation is a total order, which is not true. Here is the graph of : ! So we need an efficient algorithm that works for partial order relations, but the one that comes to mind is . The perf may not be really important here but I'm curious to see the alternatives. label C-bug T-compiler A-borrow-checker E-mentor E-help-wanted <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
Here is the code of concern The code should calculate the from a set of universal regions (). The relations are encoded in and are guaranteed to be transitive and reflexive. The relation graph may have cycles and can be sparse. The goal here is to find a unique minimum choice that is known to be outlived by all other regions. If none can be found, the function returns . Regions that have cycles between them are considered equivalent so we can pick either one of them as a unique choice. e.g. , we can pick either one of as a minimum choice.


Question: #![cfg_attr(const_fn, feature(const_fn))] <del> #![feature(const_constructor)] </del> // Ctor(..) is transformed to Ctor { 0: ... } in HAIR lowering, so directly // calling constructors doesn't require them to be const.

The feature allows calling any expression of a tuple-like constructor in a : cc
Implemented on 2019-06-07 by in which was reviewed by
Is there anything else needs to be done to resolve this issue?
FCP and stabilization pull request.
Do you think you have time to write a report (e.g. in the style of ) and amend the reference after?
I propose that we stabilize . Tracking issue: Version target: 1.40 (2019-11-05 =beta, 2019-12-19 =stable). Tuple struct and tuple variant constructors are now considered to be constant functions. As such a call expression where the callee has a tuple struct or variant constructor "function item" type can be called : Consistency with other . This should also ensure that constructors implement traits and can be coerced to function pointers, if they are introduced. - Tests various syntactic forms, use in both and items, and constructors in both the current and extern crates. The case in should also get a test.
Thanks! Could you embed this report in a PR with the aforementioned test there as well? I'll FCP that PR.


Question: #![cfg_attr(const_fn, feature(const_fn))] <del> #![feature(const_constructor)] </del> // Ctor(..) is transformed to Ctor { 0: ... } in HAIR lowering, so directly // calling constructors doesn't require them to be const.

When using to create an enum variant in Rust 1.37+, we get an error: results in: but if the enum is constructed explicitly, the compilation succeeds: Looking at , it looks like should be considered a with . Playground links for both variants: ,
Duplicate of (will close in a bit). It seems like folks open this issue because on stable, the error message does not point to the tracking issue, e.g. you don't see: can we fix this?
I think we should just stabilize it
Is this diagnostics problem specific to this feature gate? I meant a more general fix to const-fn related gates.
Not sure. I thought we're using the normal feature gate infra
Reopening this to make sure we add a test per


Question: <ins> enum e{A((?'a a+?+l))} //~^ ERROR `?` may only modify trait bounds, not lifetime bounds //~| ERROR expected one of `)`, `+`, or `,` //~| ERROR expected trait bound, not lifetime bound </ins>

I'm seeing an internal compiler error on the following input (found by ): The error happens on and but not on .
triage : P-medium, removing nomination, adding needs-bisect.
(the bisection here would be entirely automatable if were addressed.)
Bisected roughly: ICE occurred from but not panicked, panicked from
in particular looks suspicious. cc
Pre-, we return early with an error here: Post-, in the corresponding code happens in a call to : and the parser "recovers" from the error encountered in , allowing this line to be reached:
I opened , which takes the stance that is no longer appropriate here. It's possible that there's a better fix that changes the way works, but that would require a deeper expertise of how these things are supposed to work than I currently have.


Question: /// /// Note that the arguments are not passed through a shell, but given /// literally to the program. This means that shell syntax like quotes, <del> /// escaped characters, word splitting, glob patterns, substitution, etc. </del> <ins> /// escaped characters, word splitting, glob patterns, variable substitution, etc. </ins> /// have no effect. /// /// # Examples

I tried this code: I expected to see this happen: Print the content of the $123 environment variable Instead, this happened: It literally prints $123 : <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
It is the shell that resolves environment variables. You're not using a shell here, just directly executing a command. This is behaving as expected.
Indeed, this is the expected behavior. This can be circumvented by actually using a shell, e.g. on POSIX:
I did a quick check on the doc for Note that the argument is not passed through a shell, but given literally to the program. This means that shell syntax like quotes, escaped characters, word splitting, glob patterns, substitution, etc. have no effect. I guess we can expand "substitution" into "variable substitution" to make it more clear.
so is this just a documentation change? claim


Question: StorageLive(_4);                 // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 _4 = &mut (*_1);                 // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 StorageLive(_5);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL <del> _5 = &mut (*(*_4));              // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL _3 = move _5;                    // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL </del> <ins> StorageLive(_6);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL _6 = &mut (*(*_4));              // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL _5 = &mut (*_6);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL _3 = &mut (*_5);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL StorageDead(_6);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL </ins> StorageDead(_5);                 // scope 1 at $SRC_DIR/liballoc/boxed.rs:LL:COL _2 = &mut (*_3);                 // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 StorageDead(_4);                 // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:14: 8:15

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: 35 |     #[stable = "1300"] impl S { } |     ^^^^^^^^^^^^^^^^^^ <del> error: aborting due to 9 previous errors </del> <ins> error: aborting due to 8 previous errors </ins>

Minimal example: Error message (ran in playground): Tested on nightly as well ()
Related:
twice without checking the return value. Modify it to return and check where it is being called ether both calls have returned an (cancel one, emit the other, return ), wether only one was created (emit it, return ) or none has (return ).
I'll fix this, thanks for the instruction!
I would happily have a go at this, if that's ok with
Sure go for it!
have you had time to work on this? If not could I give it a go? :)
I totally thought I was going to have time, but I had a crazy week at work this week. Go ahead and give it a go :) I'll find another bug to work on when I definitely have time
It looks like the PR to fix this was merged but has a few dangling threads. There seems to be some confusion about short-circuiting functionality and the necessity of the patch and also the error count still reads 2 rather than 1. Should a new issue be opened with those issues and this issue closed?


Question: } _ if sp == expr.span && !is_macro => { if let Some(steps) = self.deref_steps(checked_ty, expected) { <ins> let expr = expr.peel_blocks(); </ins> if steps == 1 { <del> // For a suggestion to make sense, the type would need to be `Copy`. if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) { if let Ok(code) = sm.span_to_snippet(sp) { </del> <ins> if let hir::ExprKind::AddrOf(_, mutbl, inner) = expr.kind { // If the expression has `&`, removing it would fix the error let prefix_span = expr.span.with_hi(inner.span.lo()); let message = match mutbl { hir::Mutability::Not => "consider removing the `&`", hir::Mutability::Mut => "consider removing the `&mut`", }; let suggestion = String::new(); return Some(( prefix_span, message, suggestion, Applicability::MachineApplicable, )); } else if self.infcx.type_is_copy_modulo_regions( self.param_env, expected, sp, ) { // For this suggestion to make sense, the type would need to be `Copy`. if let Ok(code) = sm.span_to_snippet(expr.span) { </ins> let message = if checked_ty.is_region_ptr() { "consider dereferencing the borrow" } else {

<!-- 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: I expected that the help text would give syntactically correct code, or that there would be no help text. Instead, this happened: The provided code snippet is not valid - it tries to deference the else-block, which is impossible. Better would be to put the inside the else-block. <!-- 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. --: Also occurs on stable, 1.50.0. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim I have a fix for this bug + an improvement. Gotta got for now but will submit the PR later today.


Question: -include ../../run-make-fulldeps/tools.mk <del> # only-thumbv7m-none-eabi # only-thumbv6m-none-eabi </del> <ins> # only-thumb </ins> # How to run this # $ ./x.py clean

I was working on making a run-make test today for a particular thumb target. While looking over how we do this elsewhere, I found this bit of code: From my local testing, it seems like having multiple lines of this form has the net effect of making the test a no-op that does not test anything: since a target matching line 13 will not match line 14, and vice versa, there are no targets that can run on this test. We should either revert the portion of the commit that did this: or figure out some other way to express the desired property here (or change the semantics of when multiple targets are provided to make it gather all such targets up in a set before doing the check for membership... but I am wary of making such a change since doing it right would require differentiating e.g. processor target vs OS target, for example...)
Also, It looks like there may be other instances of the same mistake elsewhere in the test suite, such as in:
Oof, not good. It shouldn't be hard to make rustbuild outright reject this scenario though.
Further effort on has led me to conclude that these lines do not work at all, at least not for cross-compilation.


Question: <ins> error[E0261]: use of undeclared lifetime name `'a` --> $DIR/erase-error-in-mir-drop-tracking.rs:11:46 | LL |     fn connect(&'_ self) -> Self::Connecting<'a>; |                                              ^^ undeclared lifetime | help: consider introducing lifetime `'a` here | LL |     fn connect<'a>(&'_ self) -> Self::Connecting<'a>; |               ++++ help: consider introducing lifetime `'a` here | LL | trait Client<'a> { |             ++++ error: `C` does not live long enough --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5 | LL |     async move { c.connect().await } |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`. </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. --<!-- 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
Another regression of cc
Before I create a fix: is an expected/reasonable value in this ? I.e. is the right fix here just to allow ?
I don't think so. Actually just looked, think it's because we're not erasing properly. Let me put up a quick fix.


Question: // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), <del> // Allows use of the :literal macro fragment specifier (RFC 1576) (active, macro_literal_matcher, "1.27.0", Some(35625), None), </del> // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None),

Tracking issue for rust-lang/rfcs.
Is anyone working on implementation already? If not I can take a crack at it.
I'll probably do it.
Huh oh, we have an issue already: do we mean to include potentially minus-prefixed literals? If yes, we have a problem because 1. it means we have to return an Expr instead of a Lit, which means I'm not sure one will be able to use the bound fragment in a non-expr context (for example in a static array type?) and 2. it's no longer always a single-TT, so the benefits in terms of future-proofing are a bit less good. If we don't... well, we loose expressivity. I have no idea what is more intuitive though... Would you, as a Rust user, expect to parse ? I certainly can think of use cases for this...
good point. I think I would have expected it, I also agree with the complications.
Can't we upgrade Lit to support negative literals?
I'd expect "literal" (or a future integer-literal specifier) to include (negative 5), but not (the negation of positive 5). Perhaps that expectation doesn't match reality, though. For instance, based on parsing rules for non-literals, I'd expect to act like . So, if handling both and as literals makes this easier, that works. But "literal" definitely needs to include negative numbers, or we'd have a weird user trap to explain.
I'd expect "literal" (or a future integer-literal specifier) to include -5 (negative 5), but not - 5 (the negation of positive 5). Unary operators, including minus, are processed purely by the parser at the moment, no lexer involved. So their treatment is whitespace agnostic. (I personally think this is a good thing.)
I agree with is not syntactically different from and has no reason to be. But I also agree with the fact that the user will probably expect negative numbers to work as literals (even it – syntactically – they're not).
is also supported in literal patterns while arbitrary expressions are not. It'd be reasonable to support it in fragments as well.
Another thing that won't match is a macro call, like , or any of the other macros that I think of as expanding to a literal (, ...).


Question: // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), <del> // Allows use of the :literal macro fragment specifier (RFC 1576) (active, macro_literal_matcher, "1.27.0", Some(35625), None), </del> // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None),

I dunno, maybe this is not such a good idea after all. Re-reading the RFC in a more skeptical light, I felt like the "Motivation" section could use some more concrete use cases. Maybe this is just failure of imagination on my part, though! I think the likelihood of this feature attracting people who really want constant expressions should be acknowledged as a drawback, too.
That's fine IMO. Personally I'd like it to match only explicit literals in code to distinguish, for example, between literal and identifier and produce different code for them. Right now this is not possible because all of , , are too broad and conflict with each other.
Hi All, I have implemented this feature in my fork of Rust over 1.25.0, under this branch: Following a quick review by a rustc mentor I may have the free time to provide a full pull request for this.
BTW label has the tooltip "implemented in nightly and unstable" but I did not see it there, i.e. commits & pull requests referencing this. Did I miss it?
The implementation that I worked on was merged, yay!
Is there anything stopping an FCP for this?
It's currently merged in unstable; do you mean an FCP to declare it stable?
Yes, an FCP to stabilise. Should have clarified.
Currently, it is not possible to pass a literal from a macro to another macro. . I think this is a bug.
Interesting! That is a bug. I opened to track it.
Agreed, this should be allowed just like passing any other node types.
Is there anything else preventing this from being stabilized? The issue above has been fixed.
This has baked for some time now and I believe it should be ready for stabilization. So let's start the review. merge The feature gate test is here: Unstable book: Tests defined here:
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!


Question: // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), <del> // Allows use of the :literal macro fragment specifier (RFC 1576) (active, macro_literal_matcher, "1.27.0", Some(35625), None), </del> // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None),

See for info about what commands tagged team members can give me.
Reading through the tests, I see that is a literal. While that makes sense to me, I remember hearing that it wasn't, but was instead a negation operator and a literal. Am I misremembering?
cc on
I agree that it makes sense. I would say that even if is interpreted as negation + a literal, I would probably still want the macro matcher to accept since that behavior seems more intuitive. In other words, I would see being more as an implementation detail than what a literal is in the mental model.
I think that the nuance with causes a bit of a problem, because I don't think it should be treated as a literal, but I also don't think that the current implementation of would allow detecting it either. You could naïvely allow but that would allow which is clearly wrong.
there are tests currently implemented that verify that is detected as a literal.
I worded that wrong; I meant that only having a matcher and not being able to distinguish strings and numbers means that you can't easily make not a literal.
for procedural macros the input as lexed by the compiler is (two tokens) but procedural macros can create tokens that are negatives (like ). In that sense matching for makes sense to me.
Are literals generated by the compiler counted as true literals? A quick example would be something like: This fails to match, as the expansion, I guess, happens after the selection. I just naively assumed that would have worked.
is not a literal generated by the compiler, it is an identifier followed by an exclamation mark followed by a set of parentheses containing some tokens. See for example: If you were to use it in expression position, it would be interpreted as an invocation of which expands to a string literal. In this case and in your macro though, it is never in a syntactic position where it would be treated as an expression.
I can understand semantically why it doesn't make sense, I just thought it would have, but that being said, I already changed it to , so there's no issue. It just made more sense to me as a literal, because according to the compiler, it could generate a literal from it. I guess it was more a question than an actual issue.
This is true, but there's more to it!


Question: // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), <del> // Allows use of the :literal macro fragment specifier (RFC 1576) (active, macro_literal_matcher, "1.27.0", Some(35625), None), </del> // inconsistent bounds in where clauses (active, trivial_bounds, "1.28.0", Some(48214), None),

A few built-in macros can expand their arguments eagerly through ~m a g i c~, so they accept and likes even if they expect string literals: Fortunately (or not), this currently cannot be done in user-defined macros.
I actually just realised that I can't change it to , as it's used in . So, I've just had to manually unroll the macro. ! It doesn't look pretty. :( Ninja edit: I just tested what actually happens if you try to pass in a non-literal with . It rejects it the exact same way. Does the already make use of this feature? If not, the seems to propagate the required token. Oh, unless the compiler steps in... That's actually probably the case... I've reverted it back to the type.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.
Since you implemented this, would you be willing to write up the stabilization PR?
sure
This appears to be missing from the Rust reference


Question: // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g., `<*mut T>::null`). <del> match impl_self_ty.kind() { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { Some(type_di_node(cx, impl_self_ty)) } else { Some(namespace::item_namespace(cx, def.did())) } </del> <ins> if let ty::Adt(def, ..) = impl_self_ty.kind() && !def.is_box() { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { return (type_di_node(cx, impl_self_ty), true); } else { return (namespace::item_namespace(cx, def.did()), false); </ins> } <del> _ => None, </del> } } else { // For trait method impls we still use the "parallel namespace" // strategy <del> None </del> } <del> }); </del> <ins> } </ins> <del> self_type.unwrap_or_else(|| { namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ) }) </del> <ins> let scope = namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ); (scope, false) </ins> } }

If you combine LTO, anything that uses alloc and debug compilation mode, the compiler fails. The minimum example to reproduce is this : With this : To reproduce, run (or just use ): You should see this error: The above error does not reproduce for other compiler versions or options, all of the below work: I found reporting something similar, but for them is throwing the error, so I opened a new issue instead. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Initial reduction for :
Filed
In , dblaikie suggests that ought to separate the type-method declaration from the function definition, and I think I have that working. It passes the reproducer here, at least... claim


Question: // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g., `<*mut T>::null`). <del> match impl_self_ty.kind() { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { Some(type_di_node(cx, impl_self_ty)) } else { Some(namespace::item_namespace(cx, def.did())) } </del> <ins> if let ty::Adt(def, ..) = impl_self_ty.kind() && !def.is_box() { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { return (type_di_node(cx, impl_self_ty), true); } else { return (namespace::item_namespace(cx, def.did()), false); </ins> } <del> _ => None, </del> } } else { // For trait method impls we still use the "parallel namespace" // strategy <del> None </del> } <del> }); </del> <ins> } </ins> <del> self_type.unwrap_or_else(|| { namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ) }) </del> <ins> let scope = namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ); (scope, false) </ins> } }

<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Since nightly release , we've had build failures for () with message when lto is enabled. If I disable LTO, the build succeeds and the test passes. There are many similar tests which do currently build and run successfully with this version, it is only one specific test we have which is causing the issue. You can reproduce the issue if you build the test in release mode: I haven't been able to work out what actually causes this, and it seems to require a reasonable amount of code before the issue gets triggered. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust nightly 2023-03-23 <!-- Provide the version you are using that has the regression. --: The error message isn't particularly helpful here, but here is the full output from our github action: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
here probably more info on how to reproduce could help. If I read the , the test alone compiles but it fails when enabling the flag, thus the label. label E-needs-mcve
WG-prioritization assigning priority (). label -I-prioritize +P-medium
Probably related to the LLVM upgrade, but I was unable to reduce this to a pure LLVM reproducer.
We just got this error building Firefox on Fedora 38, with Rust 1.69.0 and LLVM 16.0.1:
See /
I'll try a build with that patch. One thing to note though, regarding: The Firefox build got this message on aarch64, ppc64le, and x86_64. (Only s390x succeeded.)
D147620 worked locally for me, building LLVM 16 with that patch and then Firefox built fine. But it looks like that review is not settled yet.


Question: // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g., `<*mut T>::null`). <del> match impl_self_ty.kind() { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { Some(type_di_node(cx, impl_self_ty)) } else { Some(namespace::item_namespace(cx, def.did())) } </del> <ins> if let ty::Adt(def, ..) = impl_self_ty.kind() && !def.is_box() { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { return (type_di_node(cx, impl_self_ty), true); } else { return (namespace::item_namespace(cx, def.did()), false); </ins> } <del> _ => None, </del> } } else { // For trait method impls we still use the "parallel namespace" // strategy <del> None </del> } <del> }); </del> <ins> } </ins> <del> self_type.unwrap_or_else(|| { namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ) }) </del> <ins> let scope = namespace::item_namespace( cx, DefId { krate: instance.def_id().krate, index: cx .tcx .def_key(instance.def_id()) .parent .expect("get_containing_scope: missing parent?"), }, ); (scope, false) </ins> } }

Whether the ultimate fix is in LLVM or rustc, I hope we can get that into beta for the 1.70.0 release.
I have a patch for rustc that passes the test case in -- I'll try with Firefox later today. claim


Question: // declared as public (due to pruning, we don't explore // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { <del> candidates.push(ImportSuggestion { path }); </del> <ins> let did = match def { Def::StructCtor(did, _) | Def::VariantCtor(did, _) => self.parent(did), _ => def.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); </ins> } } }

For this code: You get the following error message: The suggestion may be excused to be not 100% perfect, but here it suggests to add an use statement despite that same item being imported already. What I want is this exactly: that it removes stuff from the suggestion list that is already being imported. Note that changing the glob import to a non glob one doesn't change anything.
cc
Why is that even an error?
tuple structs have private fields by default, you can't construct instances of B outside of the foo module.
oh ^^ maybe we should simply modify this error message then to say that the "function" is private?
It already says "constructor is not visible here due to private fields". That's okay, but maybe you might have meant another B from another module or something. However, the candidate offered is not any better as its the same one you are attempting to use.
Reopening to track "removal of suggestion" work for pub tuple structs with private fields.


Question: write!(f, "{}", hi) } IntRange(range) => write!(f, "{:?}", range), // Best-effort, will render e.g. `false` as `0..=0` <del> Wildcard | Missing { .. } | NonExhaustive => write!(f, "_"), </del> <ins> Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty), </ins> Or => { for pat in self.iter_fields() { write!(f, "{}{:?}", start_or_continue(" | "), pat)?;

<!-- 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. --When compiling on an Apple M1 processor: <!-- 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
Can also reproduce this when compiling on an Intel Macbook
I've encountered the same error on a different platform (x8664) when compiling . The project doesn't use cargo so repro is nontrivial, but from I can see that the ICE started occurring at which is a rollup of . <details<summary<strongBacktrace</strong</summary<p</p</details
Also seems to be hitting starlark-rust, , as per
Somewhat minimized standalone testcase: Builds on stable, fails on nightly. cc
Thanks for the minimization! Seems like we've hit again, but through a different code path. I'm investigating.
I think might be another duplicate of this, triggered when compiling the crate.


Question: relevant_pr_url, relevant_pr_user, pr_reviewer, <del> cur_datetime </del> <ins> cur_datetime, github_token, </ins> ) if not message: print('<Nothing changed>')

Updated the toolstate repository at https://rust-lang- currently does not seem to work, see e.g. To "tool failed to build"-issues are being created, either. remarked that the error . Cc


Question: } } else { debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); <del> // If the receiver already has errors reported due to it, consider it valid to avoid // unnecessary errors (#58712). return receiver_ty.references_error(); </del> <ins> return false; </ins> } }

<!-- ICE: Rustc '' 'thread 'rustc' panicked at 'coerceborrowedpointer had no error'', 'thread 'rustc' panicked at 'coerceborrowedpointer had no error'' 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<!-- query stack: [typeck] type-checking [analysis] running analysis passes on this crate --
Regression in there are no individual builds of the commits yet tho :sweat_smile:
I would guess cc


Question: <ins> // check-pass // incremental struct Struct<T>(T); impl<T> std::ops::Deref for Struct<T> { type Target = dyn Fn(T); fn deref(&self) -> &Self::Target { unimplemented!() } } fn main() { let f = Struct(Default::default()); f(0); f(0); } </ins>

The following code works in 1.56.0 but crashes 1.57.0 as well as the most recent nightly — . <details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
According to cargo-bisect-rustc the regression is from — FYI regressed nightly: nightly-2021-09-06 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.1</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </details
Seems that this is duplicate of and ; only triggers with incremental compilation enabled. Unfortunately although I authored the original PR, I don't know a lot about incr-comp or the query system to diagnostic the issue. label: +A-incr-comp
Found the bug, I'll put up a PR in a sec. claim
reopening as this is a stable-to-stable regression, and (I think) we keep those open until a fix lands on stable or we explicitly decline to fix.
was this backported / can we close the issue? :)
The fix was backported and released in 1.58.0
Perfect, thanks for checking !


Question: let tcx = self.tcx; let def_id = instance.def_id(); <del> let containing_scope = get_containing_scope(self, instance); </del> <ins> let (containing_scope, is_method) = get_containing_scope(self, instance); </ins> let span = tcx.def_span(def_id); let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file);


Question: let tcx = self.tcx; let def_id = instance.def_id(); <del> let containing_scope = get_containing_scope(self, instance); </del> <ins> let (containing_scope, is_method) = get_containing_scope(self, instance); </ins> let span = tcx.def_span(def_id); let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file);


Question: let tcx = self.tcx; let def_id = instance.def_id(); <del> let containing_scope = get_containing_scope(self, instance); </del> <ins> let (containing_scope, is_method) = get_containing_scope(self, instance); </ins> let span = tcx.def_span(def_id); let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file);


Question: <del> // #![feature(stdsimd)] </del> #![no_main] #![no_std] use core::fmt::Write;


Question: //~^ ERROR missing lifetime specifier //~| ERROR `S<'_>` is forbidden as the type of a const generic parameter <ins> trait Foo<'a> {} struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>; //~^ ERROR use of non-static lifetime `'a` in const generic //~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter </ins> fn main() {}

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: 20 |     m!(MyTrait<>); //~ ERROR generic arguments in macro path |               ^^ <del> error: aborting due to 5 previous errors </del> <ins> error: aborting due to 4 previous errors </ins>

Minimal example: Error message (ran in playground): Tested on nightly as well ()
Related:
twice without checking the return value. Modify it to return and check where it is being called ether both calls have returned an (cancel one, emit the other, return ), wether only one was created (emit it, return ) or none has (return ).
I'll fix this, thanks for the instruction!
I would happily have a go at this, if that's ok with
Sure go for it!
have you had time to work on this? If not could I give it a go? :)
I totally thought I was going to have time, but I had a crazy week at work this week. Go ahead and give it a go :) I'll find another bug to work on when I definitely have time
It looks like the PR to fix this was merged but has a few dangling threads. There seems to be some confusion about short-circuiting functionality and the necessity of the patch and also the error count still reads 2 rather than 1. Should a new issue be opened with those issues and this issue closed?


Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

The man page for says And yet Miri found libstd calling this function with an alignment of 4 on a 64bit-platform. This happens when size=2, align=4. The fact that size<align makes it enter the code path for .
The only reason I can imagine for to exist there is a buggy implementation of . This check is only meaningful if a buggy implementation returns not an allocation suitably aligned for any built-in type (on x86_4 – 16-bytes) but rather an allocation aligned for the particular request?
A lack of comment is disturbing here. If git history does not reveal any such issue, then we should just remove that check entirely.
That extra check was introduced by to fix
I have opened in jemalloc to get clarification from them about their alignment guarantees. It would be nice if someone with more knowledge could chime in, in particular knowledge about where exactly that value of 16 for on x86-64 comes from. Cc
Possibly from here:
C has types with an alignment smaller than are supported in all contexts. AFAICT this includes the memory returned by any memory allocation function - not only , but also . The largest scalar type of C implementations needs to be supported in all contexts. On most platforms, this type is often which the requires it to have an alignment of 16, so on these particular platforms, will have an alignment requirement of 16 bytes. On these platforms, all memory allocation functions need to return memory aligned to a 16 byte boundary when called with a to be able to support the largest scalar type provided by the C implementation. Otherwise would return memory not suitable for storing a scalar type. However, if the memory allocation is smaller than the size of the largest scalar type, then it would be illegal to store it there, so the memory returned needs to only be properly aligned to be able to store the largest scalar type that would fit in that particular size. In practice, this means that for sizes up to , the alignment of the returned memory equals the size of the allocation rounded to the previous power of two (e.g. in a 5 byte allocation, you can at most fit a 32-bit scalar, so the allocation only needs 4 byte of alignment). And for sizes larger than , the alignment is at least (this allows storing, e.g., an array of s).


Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

In practice, the fastest thing you can do, is calling malloc if , because if malloc will return an alignment of at least rounded to the previous power of two, which is always satisfied (remember that must be a power of two, so if its smaller than size, it is at least the previous one). will do this without having to branch on any user provided alignment argument. That's precisely what that code is doing. The else branch is calling a "generic" which should be able to handle any user-specified alignment. The implementation of based on : appears to have the bug you mention, and should probably call or similar. I suspect that the implementation of provided by jemalloc, which we use here: doesn't have this issue, because it probably just forwards the call to , which supports alignment smaller than .
So basically on the C side, one assumes that is not used with types that use the C equivalent of ? With that assumption, I agree it is enough for to guarantee an alignment of rounded down to the next power of two. (I think your post originally said "up", but now it says "down" so I guess we agree.) That's what I and our implementation indeed handles that case just fine. The bug in the way we call is fixed by Still, it would be nice not to be able to reason about "in practice", but get some commitment from jemalloc -- see And finally, this only concerns on Unixes. Does anyone know what the situation looks like with on Windows? libstd currently assumes even small allocations to be aligned there, and agrees with that (Ctrl-F "on 64-bit platforms").
EDIT: C11 to C, but yes, malloc doesn't know anything about the alignment of a type. It still can be used, but the user needs to check whether the allocation is properly aligned. The docs are quite clear IMO: Anything more concrete than that will be target specific, and those details are outside jemalloc's control - if jemalloc wants to replace the system allocator in a target, it needs to comply with the ABI there. If it were to guarantee more, e.g., all allocations are 16byte aligned, it wouldn't work on platforms using the SysV i386 ABI.
Well, with that statement from the jemalloc docs is wrong, isn't it?


Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

And for users to manually do the alignment, getting something more concrete would be useful. And also for Rust! Currently you are deducing a whole lot of things from a few words in the spec. I have zero confidence that this is the only way to read the spec. So something like: "for we guarantee an alignment of ; for smaller sizes we guarantee an alignment of the size rounded down to the next power of two." would IMO be prudent to ask from the jemalloc devs. Or else we'll find ourselves with more bugs when someone interprets all this slightly differently.
I don't know how useful would that be: malloc only needs to comply with the C standard. Parts of it are implementation-defined, and what those are defined to is often specified by the system ABI. That's the only thing the global allocator can rely on. On most platforms, the system allocator - which is the default global allocator for Rust programs - is not jemalloc - it is the one from glibc, musl, microsoft, apple, google, mozilla, etc. In some platforms, like FreeBSD, the system allocator is jemalloc, but even there we can't exploit that knowledge because users can just and now the global allocator is a different one. That's an use case we support. So even if jemalloc were to offer extra guarantees here, Rust's system allocator cannot make use of them. The only places were we can can exploit jemalloc's specific guarantees, is when using crates like jemallocator, to explicitly hardcode the allocator to a particular one. As in, if that allocator is not linked, you get a linker error or similar. But even there, it makes sense to stick to what C and the platform ABI guarantees, because jemalloc is free to break anything else in the next version.
Well it would save us this entire discussion. If that doesn't demonstrate its usefulness I don't know what does.^^ I don't know what the "system allocator" is for Linux, but the one in glibc actually guarantees a 16-byte alignment on 64bit systems for all allocations. So by that standard jemalloc would just be incorrect.
The platform ABI guarantees that. What the malloc implementations guarantee is irrelevant.


Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

If glibc were to guarantee that all addresses are 32-byte aligned, there is no way in which we could exploit that information in the implementation of the system allocator, because the platform only requires 16-byte alignment, and it is valid to pick any allocator at run-time that satisfies that.
So there a document somewhere saying "for x86-64 bit, 16-byte alignment is guaranteed"? But that document contains an exception for small sizes, making s behavior legal?
Yes, there are documents containing the rules of what's legal, at least for Linux x8664. Those document allow an exception for small sizes. One API that uses those is , which requires the alignment to be at least , which is 8 on x86_64, and which allows you to allocate bytes, with a smaller alignment. I still have no idea what jemalloc has to do with any of this - your original question is about , and that has nothing to do with jemalloc. But yes, jemalloc exploits this behavior, to be able to satisfy 1 byte request, and return addresses that are 1 byte aligned. Otherwise each 1 byte request would consume 16 bytes of memory within a memory page.
A document that could be relevant is the C standard. Unfortunately, as mentioned in the commit message for , it is rather tautological on this topic: The standard does not give any numeric value. Like many other aspects of C, it looks like the actual value of is implementation-defined.
When using jemalloc, becomes jemalloc. That's how happened. Do you have a reference for something that concretely calls out an exception for small types? The C standard only does this very indirectly, as you showed.
That was a bug in our implementation of system that applies to pretty much all allocators, not only jemalloc. says (emphasis mine): Since the alignment of an object is a power of two that is always smaller than or equal to the object size, rounding down the alignment of an allocation to the previous power of two always produces an allocation properly aligned for every type that can fit it. That holds for all allocations, so there is no exception for that. That's the rule. Since that would mean that large allocations must be unreasonably aligned, the standard does provide an exception for allocations of size larger than than .