jiebi/CodeConvo huggingface dataset:
Code change:
use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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:
use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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:
use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

Related discussion:
text: 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).
Code change:
use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; <del> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </del> use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; <ins> use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; </ins> use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi;

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:
<ins> // The problem in #66357 was that the call trace: // // - parse_fn_block_decl // - expect_or // - unexpected // - expect_one_of // - expected_one_of_not_found // - recover_closing_delimiter // // ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`. fn f() { |[](* } //~^ ERROR expected one of `,` or `:`, found `(` //~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` </ins>

Related discussion:
text: When compiling a personal project, I got an error that the compiler panicked and entered unreachable code. I've dumped the output: And I committed my code which caused the bug here: It might be because I had only written half of an anonymous function at at line 92. This is not that urgent as I only saw it with half-written code, but since the compiler suggested I file a bug I did. :
Good call! Reducing it to is enough to trigger the ICE. <details<summarybacktrace </summary
modify labels: I-ICE T-compiler C-bug A-frontend
I've traced the problem down to this call:
triage: P-high, removing nomination label.
Code change:
<ins> const QUERY = 'MyForeignType::my_method'; const EXPECTED = { 'others': [ // Test case for https://github.com/rust-lang/rust/pull/96887#pullrequestreview-967154358 // Validates that the parent path for a foreign type method is correct. { 'path': 'foreign_type_path::aaaaaaa::MyForeignType', 'name': 'my_method' }, ], }; </ins>

Related discussion:
text: 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
Code change:
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred) })); <del> if ocx.select_all_or_error().is_empty() { </del> <ins> if ocx.select_all_or_error().is_empty() && count > 0 { </ins> diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), "dereference the return value",

Related discussion:
text: <!-- [31mICE[0m: Rustc '' 'thread 'rustc' panicked at 'expected region for ('a//0) but found Type(&'{erased} mut FooImpl<'{erased}, '{erased}, T/) when instantiating args=[&'{erased} mut FooImpl<'{erased}, '{erased}, T/, '?27, ?2t, Closure(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), ['{erased}, '{erased}, T/, i32, Binder(fn((&ReLateParam(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), BrAnon) mut FooImpl<'{erased}, '{erased}, T/,)), []), ()])]'', 'thread 'rustc' panicked at 'expected region for ('a//0) but found Type(&'{erased} mut FooImpl<'{erased}, '{erased}, T/) when instantiating args=[&'{erased} mut FooImpl<'{erased}, '{erased}, T/, '?27, ?2t, Closure(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), ['{erased}, '{erased}, T/, i32, Binder(fn((&ReLateParam(DefId(0:22 ~ a[a197]::{impl}::foo::{closure}), BrAnon) mut FooImpl<'{erased}, '{erased}, T/,)), []), ()])]'' File: --auto-reduced (treereduce-rust): original: Version 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: [mirborrowck] borrow-checking [mirborrowck] borrow-checking --
ICEs on nightly and beta, but not on stable. Minimized further: <details<summaryProgram output</summary</details
The ICE is another one from , cc
Still reproduces on 1.81.0-nightly (2024-06-13 ) -E-needs-test
I'll look into it later today.
Code change:
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred) })); <del> if ocx.select_all_or_error().is_empty() { </del> <ins> if ocx.select_all_or_error().is_empty() && count > 0 { </ins> diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), "dereference the return value",

Related discussion:
text: : <details<summary<strongBacktrace</strong</summary<p</p</details
This looks to be a recent regression from cc and is on beta 1.79, but is just in diagnostics.
Code change:
#![forbid(dead_code)] #[derive(Debug)] <del> pub struct Whatever { //~ ERROR struct `Whatever` is never constructed </del> <ins> pub struct Whatever { </ins> pub field0: (), <del> field1: (), </del> <ins> field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read </ins> field2: (), field3: (), field4: (),

Related discussion:
text: The struct is meant to not be constructible. Also the behavior is incoherent between tuple structs (correct behavior) and named structs (incorrect behavior). Also, this is a regression, this didn't use to be the case. No response No response
label +F-never_Type +D-inconsistent
We will also get such warnings for private structs with fields of never type (): The struct is never constructed although it is not constructible. This behavior is expected and is not a regression. Did you meet any cases using this way in real world? For the incoherent behavior, we also have: This because we only skip positional ZST (PhantomData and generics), this policy is also applied for never read fields:
Can you elaborate in which sense it is expected? I can understand that it is expected given the current implementation of Rust. It seems between stable and nightly a new lint was implemented. This lint is expected for inhabited types. However it has false positives on inhabited types, i.e. types that are only meant for type-level usage (for example to implement a trait). I agree we should probably categorize this issue as a false positive of a new lint rather than a regression (technically). Thanks, I can see the idea behind it. I'm not convinced about it though, but it doesn't bother me either. So let's just keep this issue focused on the false positive rather than the inconsistent behavior.
How do you think about private structs with fields of never type?
I would consider it the same as public structs, because they can still be "constructed" at the type-level. So they are dynamic dead--code but not dead-code since they are used statically. It would be dead-code though if the type is never used (both in dynamic code and static code, i.e. types).
Actually, thinking about this issue, I don't think this is a false positive only for the never type. I think the whole lint is wrong. The fact that the type is empty is just a proof that constructing it at term-level is not necessary for the type to be "alive" (aka usable). This could also be the case with non-empty types. A lot of people just use unit types for type-level usage only (instead of empty types).
Code change:
#![forbid(dead_code)] #[derive(Debug)] <del> pub struct Whatever { //~ ERROR struct `Whatever` is never constructed </del> <ins> pub struct Whatever { </ins> pub field0: (), <del> field1: (), </del> <ins> field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read </ins> field2: (), field3: (), field4: (),

Related discussion:
text: So my conclusion would be that linting a type to be dead-code because it is never constructed is brittle as it can't be sure that the type is not meant to be constructed at term-level (and thus only used at type-level). Adding is not a solution because if the type is actually not used at all (including in types) then we actually want the warning. Here is an example: The same thing with a private struct: And now actual dead code:
I think a better way is: is usually used to do such things like just a proof. Maybe we can add a help for this case.
But I agree that we shouldn't emit warnings for pub structs with any fields of never type (and also unit type), this is an intentional behavior.
Oh yes good point. So all good to proceed with adding never type to the list of special types.
Thanks a lot for the quick fix! Once it hits nightly, I'll give it a try. I'm a bit afraid though that this won't fix the underlying problem of understanding which types are not meant to exist at runtime. For example, sometimes instead of using the never type, I also use empty enums such that I can give a name and separate identity to that type. Let's see if it's an issue. If yes, I guess ultimately there would be 2 options: Just use in those cases. Introduce a trait (or better name) for types that are not meant to exist at runtime like unit, never, and phantom types, but could be extended with user types like empty enums. I'll ping this thread again if I actually hit this issue.
I could test it (using nightly-2024-08-01) and . I just had to change a to in a crate where I didn't have already. Ultimately, is going to be a type alias for so maybe it's not worth supporting it. And thinking about empty enums, this should never be an issue for my particular usage, which is to build empty types. Because either the type takes no parameters in which case I use an empty enum directly. Or it takes parameters and I have to use a struct with fields, and to make the struct empty I also have to add a never field. So my concern in the previous message is not an issue for me.
Code change:
issue_url = gh_url() + '/{}/comments'.format(number) response = urllib2.urlopen(urllib2.Request( issue_url, <del> json.dumps({'body': maybe_delink(message)}), </del> <ins> json.dumps({'body': maybe_delink(message)}).encode(), </ins> { 'Authorization': 'token ' + github_token, 'Content-Type': 'application/json', } )) response.read() <del> except urllib2.HTTPError as e: print("HTTPError: %sn%s" % (e, e.read())) </del> <ins> except HTTPError as e: print("HTTPError: %sn%r" % (e, e.read())) </ins> raise

Related discussion:
text: 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
Code change:
// + span: $DIR/nrvo-simple.rs:3:20: 3:21 // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } StorageLive(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19 <ins> StorageLive(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18 StorageLive(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18 </ins> -         _6 = &mut _2;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18 +         _6 = &mut _0;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18 <del> _3 = move _1(move _6) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19 </del> <ins> _5 = &mut (*_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18 _3 = move _1(move _5) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19 </ins> } bb1: { <ins> StorageDead(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:18: 4:19 StorageDead(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20 </ins> StorageDead(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20 -         _0 = _2;                         // scope 1 at $DIR/nrvo-simple.rs:5:5: 5:8 -         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:6:1: 6:2

Related discussion:
text: 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.
Code change:
this.visit_ty(&ty); } } <del> GenericParamKind::Const { ref ty, .. } => { </del> <ins> GenericParamKind::Const { ref ty, default } => { </ins> let was_in_const_generic = this.is_in_const_generic; this.is_in_const_generic = true; walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); <ins> if let Some(default) = default { this.visit_body(this.tcx.hir().body(default.body)); } </ins> this.is_in_const_generic = was_in_const_generic; } }

Related discussion:
text: Const generic defaults are being stabilized, <!-- 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<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Seems to also happen with closures:
I got a fix for this one I think. claim
even worse, this compiles on beta but shouldn't
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-critical
I think this needs to remain open until the fix is beta-backported :thinking: not 100% sure on procedure here
You might be correct. At least that's what happened last time one of my PRs was backport nominated (), though I'm not sure if that was due to that being a regression on stable. Regardless, thanks for reopening this.
that's my understading, too. I /think/ issues that are pending a beta/stable backport (like this one) will stay open until the corresponding backport PR has landed. The {stable,beta}-backport procedure is detailed but this detail is not explicited (I'll see if I can fix that to be more clear). For completeness, backports are discussed every Thursday during the compiler team weekly meeting (). Anyway, thanks a lot for fixing this issue and also to + for reporting and debugging :)
Copied from Zulip: Question/thought: Is this a case where tracking bound vars got in the way? Or did it actually help uncover a potential bug?
Not sure what you mean. The bug was that we were just not doing lifetime name resolution at all on const generic defaults. Like this code compiles on beta: edit: ohhh, you mean ?