jiebi/CodeConvo huggingface dataset:
Code change:
} // At this point, we are calling a function, `callee`, whose `DefId` is known... if is_lang_panic_fn(tcx, callee) { self.check_op(ops::Panic); <ins> // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if ty.is_str() => (), _ => self.check_op(ops::PanicNonStr), } } </ins> return; }

Related discussion:
text: The panic payload of the macro (as passed on to ) is generic, but the CTFE panic support assumes it will always be an . This leads to ICEs: Cc
I guess we could support this, but we'd have to find some way to render the errors. Maybe we need to wait for const traits so we can require const Debug?
Alternatively constck could require the argument to have type .
also requires a
Yeah, the libcore panic machinery does not support non-format-string panics.
Aye, left out the latter of my message. is likely the most common argument to , and it's not unusual with e.g. ; so I agree that waiting for const traits before supporting any other arguments is reasonable.
Im hitting this ICE on stable without feature flag:
Hm indeed, that is interesting: any idea why we go on here after seeing an error? Does this kind of behavior mean any part of CTFE is reachable on stable somehow?
yes. We're not gating CTFE on whether there were stability (or any other static checks) failing. I've been abusing this since 1.0 to demo things on the stable compiler and never got around to fixing it. I don't even know if we have a tracking issue for it.
:rofl: So what would be a possible approach here? Replace such consts by early enough that their MIR never actually gets evaluated? We might as well use this issue, IMO...
That would require us to mutate all MIR and potentially even HIR. Other possible solutions: poison the mir Body if const checks fail (by adding a field like or by just nuking the body by replacing it with ) and thus make allow const evaluation to check if the mir Body failed the checks and bail out before doing anything make the have an field similar to
On second thought, let's leave this issue for the ICE, and make a new one for "we can trigger nightly-only const code on stable because we don't abort compilation early enough":
Given that this ICE is pre-existing, as shown by , can we un-block ? I'd really like to see const_panic stabilized, and this seems like a minor issue to be blocking on.
That comment is an example of accidentally partially exposing an unstable feature on stable -- a separate bug tracked in I don't see how that's an argument for shipping that feature on stable when it is broken.
Code change:
} // At this point, we are calling a function, `callee`, whose `DefId` is known... if is_lang_panic_fn(tcx, callee) { self.check_op(ops::Panic); <ins> // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if ty.is_str() => (), _ => self.check_op(ops::PanicNonStr), } } </ins> return; }

Related discussion:
text: In particular, applies to all unstable const features. Fixing this bug here is not even that hard I think: somewhere around here there needs to be a check that the argument has type . Re: , AFAIK that one is also blocked on figuring out how the diagnostics should look like, and a further concern (though maybe not blocking) is .
I guess that might make this a non-issue, where it is proposed also would require as first argument.
For reference: , which was recently merged. The plan is to fix the behaviour of in the Rust 2021 edition. Given that this ICE is listed as a blocker for , does this mean that stabilizing that will have to wait for the next edition?
No, because breaking changes are allowed to be made to unstable features without moving to a new edition; that's kinda the whole idea. The 2021 edition will effectively just extend the same restriction to all invocations, const context or not.
I'd like to tackle this but I'm not very experienced with the CTFE code. I get that we need to check from the that we've matched on in this branch and we need to match on the enum, but: For the first question, I see and that we probably want to check that the type of the tuple and that there's variants of that are , but do we stop the iteration when we get one that is a type? Is the projection list always guaranteed to terminate in a variant of that has a ? And once we have an instance of , do we just check that there's any_ projection in the list that has a ?
you can use to get the type of the . Then you can test its to be .
Code change:
let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![ proc_macro, bridge, client, proc_macro_ty, method, ])); <del> custom_derives.iter().map(|cd| { cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ cx.expr_str(cd.span, cd.trait_name), cx.expr_vec_slice( span, cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>() ), local_path(cd.span, cd.function_name), ]) }).chain(custom_attrs.iter().map(|ca| { cx.expr_call(span, proc_macro_ty_method_path(attr), vec![ cx.expr_str(ca.span, ca.function_name.name), local_path(ca.span, ca.function_name), ]) })).chain(custom_macros.iter().map(|cm| { cx.expr_call(span, proc_macro_ty_method_path(bang), vec![ cx.expr_str(cm.span, cm.function_name.name), local_path(cm.span, cm.function_name), ]) })).collect() </del> <ins> macros.iter().map(|m| { match m { ProcMacro::Derive(cd) => { cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ cx.expr_str(cd.span, cd.trait_name), cx.expr_vec_slice( span, cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>() ), local_path(cd.span, cd.function_name), ]) }, ProcMacro::Def(ca) => { let ident = match ca.def_type { ProcMacroDefType::Attr => attr, ProcMacroDefType::Bang => bang }; cx.expr_call(span, proc_macro_ty_method_path(ident), vec![ cx.expr_str(ca.span, ca.function_name.name), local_path(ca.span, ca.function_name), ]) } } }).collect() </ins> }; let decls_static = cx.item_static(

Related discussion:
text: The PR improved the situation about documenting proc macros. Thanks for that! However, I noticed a bug with it. I'm using . Running results in this: ! Looks like a simple typo or off-by-one or something like that bug. When using only and not s, everything looks good to me. CC
Oh, and also, running prints: Not sure if this warning is expected there. And not sure if related to this bug.
This is a consequence of the fact that has not yet been merged. Once it gets merged, and rust updates its Cargo submodule, this issue should go away.
It turns out that this issue was unrelated. I've opened a PR to fix it.
I see. Thanks for your work on this :)
Code change:
} } <ins> fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] { vec::map(libs, |a| get_absolute_rpath(a) ) } pub fn get_absolute_rpath(lib: &Path) -> Path { os::make_absolute(lib).dir_path() } </ins> #[cfg(stage0)] pub fn get_install_prefix_rpath(target_triple: &str) -> Path { let install_prefix = env!("CFG_PREFIX");

Related discussion:
text: These are configured something like
I am not sure why this happens off hand, but when bootstrapping the non-build-triple compilers artifacts are copied from e.g. to .
Code change:
let attrs = self.parse_inner_attributes()?; let post_attr_lo = self.token.span; <del> let mut items = ThinVec::new(); while let Some(item) = self.parse_item(ForceCollect::No)? { self.maybe_consume_incorrect_semicolon(Some(&item)); </del> <ins> let mut items: ThinVec<P<_>> = ThinVec::new(); // There shouldn't be any stray semicolons before or after items. // `parse_item` consumes the appropriate semicolons so any leftover is an error. loop { while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons let Some(item) = self.parse_item(ForceCollect::No)? else { break; }; </ins> items.push(item); }

Related discussion:
text: Tested on nightly and stable. The second diagnostic is strange. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-diagnostics S-has-mvce
claim
any idea why rustbot ignored me?
Just guessing, the missing + for S-has-mcve maybe?
Oops, this should'nt've been closed.
Code change:
# use this rustfmt binary instead as the stage0 snapshot rustfmt. #rustfmt = "/path/to/rustfmt" <ins> # Instead of downloading the src/stage0 version of cargo-clippy specified, # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. # # Note that this option should be used with the same toolchain as the `rustc` option above. # Otherwise, clippy is likely to fail due to a toolchain conflict. #cargo-clippy = "/path/to/cargo-clippy" </ins> # Whether to build documentation by default. If false, rustdoc and # friends will still be compiled but they will not be used to generate any # documentation.

Related discussion:
text: I'm pretty sure it is possible to set custom paths for , & in but not for clippy.
label +T-bootstrap
Code change:
LL |         y.foo(); |         ^ value used here after move <del> error[E0382]: use of moved value: `*x` </del> <ins> error[E0382]: use of moved value: `x` </ins> --> $DIR/double-move.rs:45:9 | LL |         let _y = *x; |                  -- value moved here LL |         x.foo(); <del> |         ^ value used here after move </del> <ins> |         ^ value used here after partial move </ins> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 | <ins> LL |         let x = "hello".to_owned().into_boxed_str(); |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait </ins> LL |         x.foo(); |         - value moved here LL |         let _y = *x; |                  ^^ value used here after move <del> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait </del> error: aborting due to 6 previous errors

Related discussion:
text: 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.
Code change:
LL |         y.foo(); |         ^ value used here after move <del> error[E0382]: use of moved value: `*x` </del> <ins> error[E0382]: use of moved value: `x` </ins> --> $DIR/double-move.rs:45:9 | LL |         let _y = *x; |                  -- value moved here LL |         x.foo(); <del> |         ^ value used here after move </del> <ins> |         ^ value used here after partial move </ins> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 | <ins> LL |         let x = "hello".to_owned().into_boxed_str(); |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait </ins> LL |         x.foo(); |         - value moved here LL |         let _y = *x; |                  ^^ value used here after move <del> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait </del> error: aborting due to 6 previous errors

Related discussion:
text: 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?
Code change:
LL |         y.foo(); |         ^ value used here after move <del> error[E0382]: use of moved value: `*x` </del> <ins> error[E0382]: use of moved value: `x` </ins> --> $DIR/double-move.rs:45:9 | LL |         let _y = *x; |                  -- value moved here LL |         x.foo(); <del> |         ^ value used here after move </del> <ins> |         ^ value used here after partial move </ins> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 | <ins> LL |         let x = "hello".to_owned().into_boxed_str(); |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait </ins> LL |         x.foo(); |         - value moved here LL |         let _y = *x; |                  ^^ value used here after move <del> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait </del> error: aborting due to 6 previous errors

Related discussion:
text: 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.
Code change:
LL |         y.foo(); |         ^ value used here after move <del> error[E0382]: use of moved value: `*x` </del> <ins> error[E0382]: use of moved value: `x` </ins> --> $DIR/double-move.rs:45:9 | LL |         let _y = *x; |                  -- value moved here LL |         x.foo(); <del> |         ^ value used here after move </del> <ins> |         ^ value used here after partial move </ins> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 | <ins> LL |         let x = "hello".to_owned().into_boxed_str(); |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait </ins> LL |         x.foo(); |         - value moved here LL |         let _y = *x; |                  ^^ value used here after move <del> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait </del> error: aborting due to 6 previous errors

Related discussion:
text: 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:
Code change:
# Complete! <del> At this point, you have successfully built the Guessing Game! Congratulations! </del> <ins> This project showed you a lot: `let`, `match`, methods, associated functions, using external crates, and more. </ins> <del> This first project showed you a lot: `let`, `match`, methods, associated functions, using external crates, and more. Our next project will show off even more. </del> <ins> At this point, you have successfully built the Guessing Game! Congratulations! </ins>

Related discussion:
text: I am learning rust and reading the book for the first time The section mentions a "Next Project" at the very end We can add a link to that project ?
It's referring to the next project showed in the book (so next section if I remember well). If confirms, this issue can be closed.
Actually, this sentence is vestigial from when we had the Dining Philosophers chapter. I would actually prefer to remove this sentence. Want to submit another PR? :D
absolutely :-) on it
was interested in looking at the old . pasted here for future people was removed in
sent PR
Code change:
LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod) { report_fatal_error("ThinLTO not available"); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { report_fatal_error("ThinLTO not available"); } </ins> #endif // LLVM_VERSION_GE(4, 0)

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