Question: raise RuntimeError("failed to find config line for {}".format(key)) <del> for section_key in config: section_config = config[section_key] if section_key not in sections: raise RuntimeError("config key {} not in sections".format(section_key)) </del> <ins> def configure_top_level_key(lines, top_level_key, value): for i, line in enumerate(lines): if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '): lines[i] = "{} = {}".format(top_level_key, value) return </ins> <del> if section_key == 'target': </del> <ins> raise RuntimeError("failed to find config line for {}".format(top_level_key)) for section_key, section_config in config.items(): if section_key not in sections and section_key not in top_level_keys: raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key)) if section_key in top_level_keys: configure_top_level_key(sections[None], section_key, section_config) elif  section_key == 'target': </ins> for target in section_config: configure_section(targets[target], section_config[target]) else:

The problem is that the configure script assumes that all keys are in a section and there are no top-level keys. This forces people to use instead: We should make it possible to set top-level keys through , both and . We should also update the line in the readme linked above to suggest instead of printf. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Mentoring instructions: look around I think the fix would be something like .
In the , from where exactly do we get the top-level keys? from the set function?
I'm not sure off the top of my head. How could you find out that information?
Hi are you still working on this?
do you think it's okay to unassign ? This issue is blocking as well.
Since there's no response from the assignee, I think you can take the issue. Are you still keen on working on this issue?
Yup I am interested! claim
Hi and thanks for mentoring! Assuming I run , I think will be 2. So I am not sure if this path would work. It seems like the first blocker is that does not contain or as keys. Should the approach be to expand with those keys? Or should we just allow / as special cases? I am guessing it's closer to the latter, since that might affect the definition of which searches for . Finally, I am a little confused what top-level keys mean - do they exclusively refer to [, ] ? Are there more?
I am able to expand when parsing to include and but I realise I may either have to make changes to or write a new method. Before I do that, I would like to understand how the configure script is commonly used. Could you give me some sample commands, say if I want to modify the field of llvm?
Shall we refactor the 2 top level keys under a section? this makes the parsing logic more consistent and unwieldy lol
you can take a look at for a complete example of what a configuration could look like. I think that would resolve most, if not all of your queries(: Hope this helps!
try running
Got it, thanks I put up a PR. This is kinda my first PR so would appreciate all the tips and advice!


Question: unsafe { self.__iterator_get_unchecked(index) } } } <ins> trait SpecFold: Iterator { fn spec_fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B; } impl<A: Iterator, B: Iterator> SpecFold for Zip<A, B> { // Adapted from default impl from the Iterator trait #[inline] default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; while let Some(x) = ZipImpl::next(&mut self) { accum = f(accum, x); } accum } } impl<A: TrustedLen, B: TrustedLen> SpecFold for Zip<A, B> { #[inline] fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; loop { let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 { (upper, false) } else { // Per TrustedLen contract a None upper bound means more than usize::MAX items (usize::MAX, true) }; for _ in 0..upper { let pair = // SAFETY: TrustedLen guarantees that at least `upper` many items are available // therefore we know they can't be None unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) }; accum = f(accum, pair); } if !more { break; } } accum } } </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. --I tried this code: I expected to see this happen: same codegen or similar in performance Instead, this happened: array has way worse codegen <details<summaryAssembly</summary<p</p</details<!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: 1.64 <!-- Provide the version you are using that has the regression. --65 till now. Regressed in nightly-2022-08-13, maybe LLVM 15 ?: : <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. -- modify labels: +regression-from-stable-to-stable -regression-untriaged <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
WG-prioritization assigning priority (). cc since this regressed in the LLVM 15 update label -I-prioritize +P-medium +T-compiler
I've seen llvm doing these strange 1-byte-at-a-time "vectorizations" in other places too. This might be a more general problem. In this case we can probably paper over it by implementing TrustedRandomAccess for the array iter.
Unfortunately, the array iterator is fundamentally worse right now, because indexing into it -- a fundamental part of being a by-value array iterator -- keeps it from SRoAing and thus doesn't optimize well. This is why when I was making better I ended up making to not have to use . Sadly, for the foreseeable future you're better off using the "weaker" slice iterator when you can.
My guess is that the SROA is missing something in the opaque pointer mode.


Question: unsafe { self.__iterator_get_unchecked(index) } } } <ins> trait SpecFold: Iterator { fn spec_fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B; } impl<A: Iterator, B: Iterator> SpecFold for Zip<A, B> { // Adapted from default impl from the Iterator trait #[inline] default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; while let Some(x) = ZipImpl::next(&mut self) { accum = f(accum, x); } accum } } impl<A: TrustedLen, B: TrustedLen> SpecFold for Zip<A, B> { #[inline] fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { let mut accum = init; loop { let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 { (upper, false) } else { // Per TrustedLen contract a None upper bound means more than usize::MAX items (usize::MAX, true) }; for _ in 0..upper { let pair = // SAFETY: TrustedLen guarantees that at least `upper` many items are available // therefore we know they can't be None unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) }; accum = f(accum, pair); } if !more { break; } } accum } } </ins>

claim
It's not about vectorization. This optimization can be restored by using . But highly unrecommended. Upstream issue:
The upstream issue is closed. claim


Question: Some(field) => (field.ident.span, field.span), None => (base.span, base.span), }; <del> self.check_field(use_ctxt, span, adt, variant_field); </del> <ins> self.check_field(use_ctxt, span, adt, variant_field, true); </ins> } } else { for field in fields { let use_ctxt = field.ident.span; let index = self.tcx.field_index(field.hir_id, self.tables); <del> self.check_field(use_ctxt, field.span, adt, &variant.fields[index]); </del> <ins> self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); </ins> } } }

In a recent PR I made a change to unify the wording of multiple privacy errors, but : used to be This one change needs to be reversed while keeping the rest.
Hi! Could I give this issue a shot?
I am sorry I forgot to claim the issue
No worries :-)


Question: }).collect::<Result<Vec<_>, _>>()?; let offset = st[i].fields.offset(field_index) + offset; <del> let LayoutDetails { size, mut align, .. } = st[i]; </del> <ins> let LayoutDetails { mut size, mut align, .. } = st[i]; </ins> let mut niche_align = niche.value.align(dl); let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {

<details<summaryBacktrace</summary</detailsWindows 10 (64-bit)
Which code had caused this assertion? Caused by this assertion: Which was introduced in , which is beta-nominated. cc
I'm glad I that assertion! What it likely means is that isn't a multiple of . I'd be quite surprised if and/or weren't involved.
In my case this error is caused by the crate. Simply including it in your and compiling crashes rustc. <details<summaryBacktrace</summary</detailsI'm on Arch running the latest nightly rustc.
Looks like triggers the assertion, and it has alignment but size (which is illegal), IIRC, includes some types that are ( this is indeed which has a packed ) and has caused issues in the past as well. EDIT: minimal repro:


Question: <del> Subproject commit 3abdd2f1ced4cf3a44c7de88c5e39b3bb5037c4d </del> <ins> Subproject commit 86b8643586aa39f36fb7a02e98c8d64d31415e70 </ins>

Hello, this is your friendly neighborhood mergebot. After merging PR rust-lang/rust, I observed that the tool clippy-driver no longer builds. A follow-up PR to the repository is needed to fix the fallout. cc do you think you would have time to do the follow-up work? If so, that would be great! cc the PR reviewer, and nominating for compiler team prioritization.


Question: self.register_unsize_obligations(span, &**u) } ty::UnsizeVtable(ref ty_trait, self_ty) => { <ins> // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` implements `Foo`: </ins> vtable2::register_object_cast_obligations(self, span, ty_trait, self_ty); <ins> // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: let origin = infer::RelateObjectBound(span); self.register_region_obligation(origin, self_ty, ty_trait.bounds.region_bound); </ins> } } }

This should not compile, since is for some non- and thus will contain as well. It compiles fine however and results in the varying output depending on the optimization level (which shows that this is an UB out of the "safe" code). Tested with and playpen.
A more self-contained example that shouldn't type-check:
It seems that this has been possible since generalized lifetime bounds went in.
Huh. This was supposed to be fixed. I'll take a look.
P-backcompat-lang, 1.0
OK, simple oversight. PR coming soon. Amazing we have no test for this. It occurs only with coercions. (In general, this code path could be cleaned up, and will be as part of implementing generalized where clauses, making these kinds of oversights harder to do.)


Question: } pub fn create_sysroot(build: &Build, compiler: &Compiler) { <del> // nothing to do in stage0 if compiler.stage == 0 { return } </del> let sysroot = build.sysroot(compiler); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot));

These two errors, which I believe are related, have started happening with rustbuild recently. I think the second is sometimes caused by the first after trying to avoid cleaning out everything; but since this is all nondeterministic from what I can tell I've included it in case it helps diagnose the problem. cc
A few more lines of potentially helpful information:


Question: } pub fn create_sysroot(build: &Build, compiler: &Compiler) { <del> // nothing to do in stage0 if compiler.stage == 0 { return } </del> let sysroot = build.sysroot(compiler); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot));

Before the recent changes to rustbuild, when changing , it has rebuilt the entire stage0 artifacts and thus the entire compiler. Now its only doing: Later on, you are getting an error like "found possibly newer version of crate which depends on".
cc note, I'm not using any --keep-stage stuff or anything.
workaround is to do manually
I think this is the same as (or that's the same as this), haven't had a chance to investigate yet. My guess is that this is a regression from
yes I think its the same issue. If you are closing dupes, then please close the one that was filed later :)


Question: if (!innerToggle) { return; } <del> let sectionIsCollapsed = false; </del> if (hasClass(innerToggle, "will-expand")) { <del> removeClass(innerToggle, "will-expand"); onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { if (!hasClass(e, "type-contents-toggle")) { e.open = true; } }); innerToggle.title = "collapse all docs"; </del> <ins> expandAllDocs(); </ins> } else { <del> addClass(innerToggle, "will-expand"); onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle")) ) { e.open = false; } }); sectionIsCollapsed = true; innerToggle.title = "expand all docs"; </del> <ins> collapseAllDocs(); </ins> } <del> innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed); </del> } (function() {

Take any page in the Rust docs, for example . When you press the or keyboard shortcuts on your keyboard, they are supposed to either collapse or expand all items on the page, but not both (according to the instructions that you can find by clicking on your keyboard (or on the screen). Please make the + and - keyboard shortcuts idempotent, otherwise it would be redundant to have two buttons that do the same thing.
What do you think about this ?
Yeah we should do this.
I'll send a patch in the next days then.


Question: <ins> // Copyright 2014 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. // ignore-tidy-linelength #![deny(deprecated)] extern crate url; fn main() { let _ = url::Url::parse("http://example.com"); //~^ ERROR use of deprecated item: This is being removed. Use rust-url instead. http://servo.github.io/rust-url/ } </ins>

Users should use the cargo-ified Deprecate for a release or two then delete. cc
:+1:
Related:
I tried this: Hoping to deprecate the whole crate, but then building this program does not emit any warning: I expected a deprecation warning on the line. Is there another way to achieve this, or do I need to annotate individual items in the crate?
That should have worked, but you may need to remove the annotation above (they may be conflicting). I would also personally find it very helpful to annotate methods in particular what the path forward is (or just a general post about how to migrate).
Removing worked, thanks. Should this deprecation go through the RFC process, or can I assume that the team wants it since filed this issue? The documentation at explains how to use rust-url, and in particular the concept of relative v.s. non-relative URL schemes (e.g. vs ) which is a bit unusual. I believe this sufficient to make migration straightforward, but I’m obviously biased. Any feedback on the documentation is welcome. (I’ll make the deprecation message include the documentation’s URL, it seems more useful landing page than the github repo.)
Having an issue is sometimes considered a "todo item" rather than "everyone has approved this", you'll find both styles of issues on the issue tracker. We don't have much precedent for deprecating an in-tree crate, so we're forging new territory here. I'd like to start moving crates out of the repo, however, so I hope to have some more on this topic soon.


Question: <ins> // This is a separate test from `issue-66693.rs` because array lengths are evaluated // in a separate stage before `const`s and `statics` and so the error below is hit and // the compiler exits before generating errors for the others. #![feature(const_panic)] fn main() { let _ = [0i32; panic!(2f32)]; //~^ ERROR: argument to `panic!()` in a const context must have type `&str` // ensure that conforming panics are handled correctly let _ = [false; panic!()]; //~^ ERROR: evaluation of constant value failed // typechecking halts before getting to this one let _ = ['a', panic!("panic in array len")]; } </ins>

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.


Question: <ins> // This is a separate test from `issue-66693.rs` because array lengths are evaluated // in a separate stage before `const`s and `statics` and so the error below is hit and // the compiler exits before generating errors for the others. #![feature(const_panic)] fn main() { let _ = [0i32; panic!(2f32)]; //~^ ERROR: argument to `panic!()` in a const context must have type `&str` // ensure that conforming panics are handled correctly let _ = [false; panic!()]; //~^ ERROR: evaluation of constant value failed // typechecking halts before getting to this one let _ = ['a', panic!("panic in array len")]; } </ins>

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 .


Question: mod remove_unneeded_drops; mod remove_zsts; mod required_consts; <ins> mod reveal_all; </ins> mod separate_const_switch; mod shim; mod simplify;

Previously: Now: <!-- 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
Inlining exposes a use of unnormalized local in a call terminator (not sure if this is more of an issue with inlining or a validator): Note: revision annotation doesn't work in an auxiliary file (so it isn't tested on CI with mir-opt-level=2). modify labels: +A-mir-opt-inlining
This ICEs again because the fix was reverted Can someone reopen please?
Due to this new requires to trigger. <details<summaryICE:</summary</details
(FWIW can also trigger this: )
fixes this for and , but it still ICEs with on its own or with mir-opt-level 1/2 cc


Question: //~^ ERROR any use of this value will cause an error //~| WARN this was previously accepted by the compiler but is being phased out <ins> // capture fault with zero value const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) }; //~^ ERROR any use of this value will cause an error //~| WARN this was previously accepted by the compiler but is being phased out const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) }; //~^ ERROR any use of this value will cause an error //~| WARN this was previously accepted by the compiler but is being phased out </ins> fn main() {}

Tracking issue for trailingzeros and leadingzeros for non zero types as introduced by . The feature gate for the issue is . On many architectures, this functions can perform better than trailingzeros/leading_zeros on the underlying integer type, as special handling of zero can be avoided.
It seems on my (common) architecture it doesn't give an advantage: : : So the question is: is this NonZero method worth keeping? Are the architectures where it gives a performance advantage common enough?
but as you show in your example if you want to make a distributable binary and due to this not set the target-cpu there is a big difference
The architecture I'm using is quite standard. A distributable binary could probably use it as "universal target". I don't know much common is going to be an instruction like tzcnt in the future. If you think a similar instruction will be sufficiently uncommon then please ignore my comments here :-)
merge cc
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [ ] [x] [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. The RFC will be merged soon.
started to make the stabilization PR but hit a problem I think that constcttz needs to be stabilized for this to be stabilized from //! If an intrinsic is supposed to be used from a with a attribute, //! the intrinsic's attribute must be , too. Such a change should not be done //! without T-lang consulation, because it bakes a feature into the language that cannot be //! replicated in user code without compiler support.


Question: <ins> error: `?` may only modify trait bounds, not lifetime bounds --> $DIR/issue-68890.rs:1:11 | LL | enum e{A((?'a a+?+l))} |           ^ error: expected one of `)`, `+`, or `,`, found `a` --> $DIR/issue-68890.rs:1:15 | LL | enum e{A((?'a a+?+l))} |               ^ expected one of `)`, `+`, or `,` error: expected trait bound, not lifetime bound --> $DIR/issue-68890.rs:1:11 | LL | enum e{A((?'a a+?+l))} |           ^^^ error: aborting due to 3 previous errors </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: <ins> // Regression test for #65553 // // `D::Error:` is lowered to `D::Error: ReEmpty` - check that we don't ICE in // NLL for the unexpected region. // check-pass trait Deserializer { type Error; } fn d1<D: Deserializer>() where D::Error: {} fn d2<D: Deserializer>() { d1::<D>(); } fn main() {} </ins>

The following code () panics the compiler in stable 1.38.0, beta 1.39.0-beta.6, and nightly 2019-10-17: Removing the bound or filling it with makes it compile just fine. Error + backtrace:
cc
Hmm, I didn't know that adding a "syntactically trivial bound" could cause something like this. Is there some implicit bound that gets in cases like this?
minimized test case ():
The minimized test worked in previous stable Rust versions (at least in 1.33 under 2015 edition; though 2018 edition breaks there, which indicates this is with 99.999% certainty injected by MIR-borrowck...)
triage: P-high. Adding self to assignee list; removing I-nominated.


Question: let _ = StableTupleStruct (1); let _ = FrozenTupleStruct (1); let _ = LockedTupleStruct (1); <ins> // At the moment, the following just checks that the stability // level of expanded code does not trigger the // lint. Eventually, we will want to lint the contents of the // macro in the module *defining* it. Also, stability levels // on macros themselves are not yet linted. macro_test!(); </ins> } fn test_method_param<F: Trait>(foo: F) {

The expansion of and both currently cause code to fail the stability check because they expand to reveal unstable implementation details. A seemingly reasonable solution to this would be to just not run the analysis on any code that has been macro-expanded. cc
I definitely agree with this approach: we should be able to annotate a macro with a stability level, and that's what should count for its users. Do we have a way of telling what part of an AST was generated via macro expansion by the time we get to linting?
Mostly; there's the field of a : for normal code, for macro generated code (basically containing the backtrace of macro invocations that led to that point).
OK, that makes this sound like a pretty easy fix. I'll take a quick look at it tomorrow (unless wants to?)
Hm, this seems slightly subtle, since the contents of a macro would then never be checked for stability. This differs to a conventional function, e.g. given , won't warn, but the contents of is still checked, while where is just never checked. (Of course, macros and phasing are both feature gated so you have to opt-in to instability to use non-standard macros anyway.)
Good point. Also, it looks tricky with the current infrastructure to even lint on the macro invocation -- the backtrace of macro expansion does not appear to link to the def_id of the macro (or give any other way of getting at the macro's stability). Nevertheless, I think we should bail out of the lint when we hit the results of expansion; those should be checked, if anywhere, at the site of macro definition. One other question: do syntax extensions also produce the span information you mentioned above? I ask because original problematic cases are written syntax extensions. If not, is there some other way of telling that an expansion happened?
I have a patch ready that bails of out the lint on expanded code. This also seems to mask uses of . If y'all are ok with this strategy for now, I'll file a PR.
Sounds good to me. Thanks!
cc


Question: pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>, ) { <ins> // We walk the pattern before declaring the pattern's inner bindings, // so that we avoid resolving a literal expression to a binding defined // by the pattern. visit::walk_pat(self, pat); </ins> self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: self.check_consistent_bindings_top(pat); <del> visit::walk_pat(self, pat); </del> } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --error: internal compiler error: unexpected panic note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: note: rustc 1.57.0 ( 2021-11-29) running on x8664-unknown-linux-gnu note: compiler flags: -C embed-bitcode=no -C debuginfo=2 -C incremental --crate-type bin note: some of the compiler flags provided by cargo are hidden query stack during panic: end of query stack <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
reduced:
Minimized this a tiny bit further, and I have a detailed explanation why this occurs: So this bug first starts going wrong in late resolution. Specifically, , we define the as a binding when we see the second element (ident subpattern) of the slice pattern, and then bind it later when we walk thru the (expression!) in the first slice pattern element. Essentially, since we treat as being defined here: and then resolve that as the path for we reach a situation where we expect a variable to have been defined before it has been lowered in HIR, which leads to the ICE later on, since we expect to have lowered that path element.
Wonder how difficult it would be to make have subpatterns instead of subexpressions... edit: wouldn't help, see below..
Actually, I don't think fixing this just for ranges is sufficient. I can reproduce this same issue with this: Maybe I can just delay this panic as a span bug, since we're always gonna error out anyways. I think I would ideally like to fix this by making sure we separate bindings in patterns from affecting resolution for expressions in patterns. edit: Ended up fixing it the right way.
claim


Question: } fn main() { <del> print_x(X);  //~error this function takes 2 parameters but 1 parameter was supplied //~^ NOTE the following parameter types were expected: &Foo<Item=bool>, &str </del> <ins> print_x(X); //~^ ERROR this function takes 2 parameters but 1 parameter was supplied //~| NOTE the following parameter types were expected: &Foo<Item=bool>, &str //~| NOTE expected 2 parameters </ins> }

From: src/test/compile- Error E0061 needs a span_label, updating it from: To: Bonus: the types could be incorporated into the label rather than a note (though we may want to avoid types with long names in the label)
Planning on tackling the bonus here. Is there a prefered max length for output on the console. In the case it would exceed this should i truncate the typename or just not include?
- great point. If you want to work on truncation, feel free to add it, too. I'm not sure if the term crate will tell you the current terminal size, but it may.
I'm fixing and I noticed that it and this issue currently share the same code for generating this error, and adding code to add a to the message in would fix both.
Did you do the bonus as well? I can tackle that if you haven't.
I haven't yet - I can fix the issue (currently testing/fixing unit tests) and you can take on the bonus part of the issue.
Sounds great to me! Thanks.
- I opened up issue to track the bonus portion of the work for you.


Question: }; let last_type_ascription_set = self.last_type_ascription.is_some(); <del> match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { self.last_type_ascription = None; // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } (false, _) => {} // continue parsing the expression // An exhaustive check is done in the following block, but these are checked first // because they *are* ambiguous but also reasonable looking incorrect syntax, so we // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) (true, Some(AssocOp::Add)) // `{ 42 } + 42 // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { self.last_type_ascription = None; // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { self.last_type_ascription = None; return Ok(lhs); } (true, Some(_)) => { // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. // For example: `if let Some(x) = x { x } else { 0 } / 2` let mut err = self.struct_span_err(self.token.span, &format!( "expected expression, found `{}`", pprust::token_to_string(&self.token), )); err.span_label(self.token.span, "expected expression"); self.sess.expr_parentheses_needed( &mut err, lhs.span, Some(pprust::expr_to_string(&lhs), )); err.emit(); } </del> <ins> if !self.should_continue_as_assoc_expr(&lhs) { self.last_type_ascription = None; return Ok(lhs); </ins> } <del> self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { </del> <ins> self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { </ins> // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what // it refers to. Interpolated identifiers are unwrapped early and never show up here // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process

The idea of shortening to has been discussed many times before, and the general consensus always ends up being that it is not a good idea. I would like to propose something a bit different, so please hear me out. I propose that instead of aliasing to , we instead just make expand into when in the context of a variable declaration. For example: This solves the problems (readability, more concise) that people have with , whilst not causing the issues that people have (pattern matching and consistancy). The most common issue people have with aliasing to is that it doesn't fit well with patterns, like . However, gets rid of this problem, because you wouldn't write if you were trying to pattern match, so why would someone want to write ? You wouldn't do that, and it wouldn't compile. This would be optional, of course. would still work fine, and people would just have to option of removing the to let it be implied. There are a lot of other abbreviations used in rust (, , ) that all serve the purpose of writing less. It just doesn't feel right that one of the most commonly used keywords is so long. :heart::crab: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Rust wants to make to make you think when you try and use mutation, even if only a little bit, because mutation can be difficult to reason about. Shortening to doesn't fit this philosophy. Also, this makes mutation just as easy as no mutation. This will lead people to choose mutation because it will give them less compiler errors in the short term, and in doing so open themselves up to some weird bugs that could have been prevented with the syntactic salt that is . tldr: wasn't rejected because of the name , but because it allowed easy mutation, which runs counter to Rust's philosophy.
I politely disagree. In fact, it is actually the other way around. Using unnecessarily will cause compiler warnings, discouraging the use of unneeded mutability. The compiler doesn't warn when the use of is actually needed.
The fact that people will choose in the face of compiler warnings has been shown in practice, across many projects.


Question: }; let last_type_ascription_set = self.last_type_ascription.is_some(); <del> match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { self.last_type_ascription = None; // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } (false, _) => {} // continue parsing the expression // An exhaustive check is done in the following block, but these are checked first // because they *are* ambiguous but also reasonable looking incorrect syntax, so we // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) (true, Some(AssocOp::Add)) // `{ 42 } + 42 // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { self.last_type_ascription = None; // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { self.last_type_ascription = None; return Ok(lhs); } (true, Some(_)) => { // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. // For example: `if let Some(x) = x { x } else { 0 } / 2` let mut err = self.struct_span_err(self.token.span, &format!( "expected expression, found `{}`", pprust::token_to_string(&self.token), )); err.span_label(self.token.span, "expected expression"); self.sess.expr_parentheses_needed( &mut err, lhs.span, Some(pprust::expr_to_string(&lhs), )); err.emit(); } </del> <ins> if !self.should_continue_as_assoc_expr(&lhs) { self.last_type_ascription = None; return Ok(lhs); </ins> } <del> self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { </del> <ins> self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { </ins> // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what // it refers to. Interpolated identifiers are unwrapped early and never show up here // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process

Also, the problem isn't that people may choose to put just for the heck of it, but that they will unintentionally mutate something that was supposed to be immutable. And because it is being mutated, there is no warning, and they used because it is their default, it is their default because it gets rid of compiler errors that say they were trying to mutate things that are immutable even though they weren't supposed to mutate them in the first place. They will use because it is just as easy as making it immutable. So the problem is a bit more subtle than you seem to think.
Incorrect. Extreme brevity harms readability. See Perl. lol Readers would ignore the vs distinction far more often that vs , partially due to length difference, but works even better than say . It's true boilerplate often harms readability, but boilerplate requires some complexity be repeated, not merely the in . It harms readability even further if also works for , especially when you consider code readers need not actually know Rust. Rust syntax was designed largely to reduce cognitive load, not to reduce typing. We use , , and , not any shorter alternatives. And delegation RFCs have kinda given up the short syntaxes. I think Rust's omission of is now considered a mistake, but presumably helps C programmers. Rust has short keywords only really for fundamental "items" used repeatedly by basically every module. It's similar cognitive load if you write , , or , but actually just writing the shorter bare increases cognitive load. I think invokes the minor linguistic subtlety that variable means mutable binding, while acts like a common term for binding, which makes very slightly clearer.
The statement would be orthogonal to the current language in some sense though. is not a special syntax, but is composed of statement + pattern. It is in line with other places expects a pattern, where you can write , , or .
It seems unlikely to me that we would support as a short-hand. I'm personally opposed to it both because it adds unnecessary compiler complexity, stylistic schisms, and for the reasons outlined by However, I've taken the liberty of reusing this issue towards improved diagnostics: The idea here is to check . The idea here is to check: The relevant code is here: cc
claim
Error: Parsing assign command in failed: claim :)... Please let know if you're having trouble with this bot.


Question: }; let last_type_ascription_set = self.last_type_ascription.is_some(); <del> match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { self.last_type_ascription = None; // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } (false, _) => {} // continue parsing the expression // An exhaustive check is done in the following block, but these are checked first // because they *are* ambiguous but also reasonable looking incorrect syntax, so we // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) (true, Some(AssocOp::Add)) // `{ 42 } + 42 // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { self.last_type_ascription = None; // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { self.last_type_ascription = None; return Ok(lhs); } (true, Some(_)) => { // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. // For example: `if let Some(x) = x { x } else { 0 } / 2` let mut err = self.struct_span_err(self.token.span, &format!( "expected expression, found `{}`", pprust::token_to_string(&self.token), )); err.span_label(self.token.span, "expected expression"); self.sess.expr_parentheses_needed( &mut err, lhs.span, Some(pprust::expr_to_string(&lhs), )); err.emit(); } </del> <ins> if !self.should_continue_as_assoc_expr(&lhs) { self.last_type_ascription = None; return Ok(lhs); </ins> } <del> self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { </del> <ins> self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { </ins> // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what // it refers to. Interpolated identifiers are unwrapped early and never show up here // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process

Although I would also guess that the initial idea is very unlikely to end up accepted, it feels premature to unilaterally hijack the thread in your very first comment and make it have a different (and in a way opposite) purpose. Teams of the Rust project are designed to make decisions collectively. Improving diagnostics sounds good, but issue numbers are cheap.
Implementing something as a diagnostic actually brings you closer to a working implementation -- I think more proposals should start out as diagnostics. I will not bother the other language team members with not-fully-formed proposals that we will not accept in either case. I converted the issue into the most actionable and productive thing it could be. The place for ephemeral discussions is either on Discord or on internals. If you want to discuss this further, I'm available at Discord (but will not respond to it further here). wasting everyone's time with things that will go nowhere (because it won't be accepted and because it is not important enough to be raised at the team) is not.
IMHO, the original thing this issue was opened for should be an RFC, not an issue. I'd have closed this, pointed the OP to the RFCs repo, and opened a new issue for the diagnostic issue.
This issue was literally in the RFCs repo initially, transferred it from there.
Language bashing is not welcome here
Wait, so should I unassign here, and assign to the new issue?
Nah, just use this one.
Yeah, thats fine. You can just change this issue to be for diagnostics instead.
I'm sorry, I've been pretty busy with coursework, and I'm still fighting my Python installation to even build the compiler, let alone make progress on this. Sorry :(
I'll assign this to myself to work on when I have time. If you want to work on it however, feel free to work-steal it from me!
I would like to help with this
Sorry; should have updated this issue...! There's a PR at the moment. Feel free to leave suggestions on it if you like. :)


Question: }; let last_type_ascription_set = self.last_type_ascription.is_some(); <del> match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { self.last_type_ascription = None; // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } (false, _) => {} // continue parsing the expression // An exhaustive check is done in the following block, but these are checked first // because they *are* ambiguous but also reasonable looking incorrect syntax, so we // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) (true, Some(AssocOp::Add)) // `{ 42 } + 42 // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { self.last_type_ascription = None; // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { self.last_type_ascription = None; return Ok(lhs); } (true, Some(_)) => { // We've found an expression that would be parsed as a statement, but the next // token implies this should be parsed as an expression. // For example: `if let Some(x) = x { x } else { 0 } / 2` let mut err = self.struct_span_err(self.token.span, &format!( "expected expression, found `{}`", pprust::token_to_string(&self.token), )); err.span_label(self.token.span, "expected expression"); self.sess.expr_parentheses_needed( &mut err, lhs.span, Some(pprust::expr_to_string(&lhs), )); err.emit(); } </del> <ins> if !self.should_continue_as_assoc_expr(&lhs) { self.last_type_ascription = None; return Ok(lhs); </ins> } <del> self.expected_tokens.push(TokenType::Operator); while let Some(op) = AssocOp::from_token(&self.token) { </del> <ins> self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { </ins> // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what // it refers to. Interpolated identifiers are unwrapped early and never show up here // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process

From The following code should be using the common list parsing utilities: CC
What/where are the common list parsing utilties? Edit: never mind, I've got it. , , etc. for anyone who's wondering.


Question: <ins> // run-rustfix use std::any::Any; fn foo<T: Any>(value: &T) -> Box<dyn Any + '_> { Box::new(value) as Box<dyn Any> //~^ ERROR lifetime may not live long enough } fn main() { let _ = foo(&5); } </ins>

we currently output The suggestion is incomplete and will not result in compilable code. Because the lifetime is coming from an argument of type , which is an unconstrained type parameter, itself will not have the needed lifetime and causes the obligation that we're trying to reverse by suggesting . The appropriate changes to the code would be either or , depending on whether appears in any other argument or not.
The suggested code .


Question: <ins> // check-pass #![deny(unused_lifetimes)] trait Trait2 { type As; } // we should not warn about an unused lifetime about code generated from this proc macro here #[derive(Clone)] struct ShimMethod4<T: Trait2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::As)); pub fn main() {} </ins>

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --code from requires debug assertions <!-- 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 --
lol, nightly emits this:D : another one from
any updates? :upsidedownface:
claim I think I got a fix :slightlysmilingface:
Error: Parsing assign command in failed: ...' claim' ' I think I'... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
claim


Question: <ins> error: expected trait bound, found `impl Trait` type --> $DIR/issue-102182-impl-trait-recover.rs:1:11 | LL | fn foo<T: impl Trait>() {} |           ^^^^^^^^^^ not a trait | help: use the trait bounds directly | LL - fn foo<T: impl Trait>() {} LL + fn foo<T: Trait>() {} | error: aborting due to previous error </ins>

When writing the current error is "expected one of these tokens", without any attempt to recover the parse. It should instead be closer to: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
What do you expect the suggestion from this code? here is a valid identifier, "expected one of these tokens" comes when the second identifier comes.
I think this case should remain as is. in particular is a shame because it is a valid type for the parser, but not a valid trait, and newcomers might not yet have a mental model for the distinction. I would say, when parsing a trait, if it can't be parsed, then try to parse a type in a snapshot (like we do in other parts of the parser), and if successful, emit a targeted error (trait expected but found type).
claim


Question: /// # Examples /// /// ```no_run <del> /// #![feature(buffered_io_capacity)] </del> /// use std::io::{BufReader, BufRead}; /// use std::fs::File; ///

adds methods to and . Unresolved questions:
Can I nominate this for stabilization? It's a straightforward API with no real alternatives possible, and I had a real-world use case for it recently.
CC --^?
fcp merge
Team member has proposed to merge this. The next step is review by the rest of the tagged team members: [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. The RFC will be merged soon.


Question: - it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T where T: AnotherTrait<AssocType=U>` <ins> Any unconstrained lifetime parameter of an `impl` is not supported if the lifetime parameter is used by an associated type. </ins> ### Error example 1 Suppose we have a struct `Foo` and we would like to define some methods for it.

As it is currently written, E0207 talks entirely about type parameters. Now that const parameters also need to constrain implementations (under the same rules described for types), they also need to be mentioned in the error explanation. Since other items don't require const parameters to be used at all, we might also want to specifically call out this difference here. Furthermore, E0207 triggers if you use an unconstrained lifetime in an associated type, and this is completely unspecified by the error as well. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature <ins> help: consider borrowing here | LL |     let _foo: &[u8] = *foo; |               + </ins> error: aborting due to 3 previous errors

I tried compiling this code: which resulted in the following output of rustc: So the compiler says So I tried adding a borrow and recompiling the code: which resulted in: so the compiler says and so I'm stuck in a loop. The compiler can't decide whether I should borrow or not. As a newbie to Rust, this is very frustrating and the opposite of helpful, it just confuses me further. Please fix this indecisiveness :) :
For reference, what you likely want to do is one of the following which means they cannot be the type of a local binding. You can give a binding a slice type (), because that's morally equivalent to a pointer (with sizing info), which has a compile time determined size, as all borrows are .
Current output: After :


Question: element_ty } None => { <ins> // Attempt to *shallowly* search for an impl which matches, // but has nested obligations which are unsatisfied. for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() { if let Some((_, index_ty, element_ty)) = self.find_and_report_unsatisfied_index_impl(expr.hir_id, base, base_t) { self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); return element_ty; } } </ins> let mut err = type_error_struct!( self.tcx.sess, expr.span,

I tried this code (): I expected to see this happen: rustc outputs an error saying that I need to add the and traits on . Instead, this happened: which is jarring to see, and unhelpful, because HashMap does support Index, but only with particular trait bounds on . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
The reduced case: works as expected, perhaps it is caused when the implementer is not from the local crate?
claim


Question: .map(|param| tcx.type_of(param.def_id)) // This is no generic parameter associated with the arg. This is // probably from an extra arg where one is not needed. <del> .unwrap_or(tcx.types.err) </del> <ins> .unwrap_or_else(|| { tcx.sess.delay_span_bug( DUMMY_SP, &format!( "missing generic parameter for `AnonConst`, parent {:?}", parent_node ), ); tcx.types.err }) </ins> } else { tcx.sess.delay_span_bug( DUMMY_SP,

results in an ICE (): <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: LL | use V; |     ^ ambiguous name | <del> = note: ambiguous because of multiple potential import sources </del> <ins> = note: ambiguous because of multiple glob imports of a name in the same module </ins> note: `V` could refer to the variant imported here --> $DIR/issue-105069.rs:1:5 | LL | use self::A::*; |     ^^^^^^^^^^ <ins> = help: consider adding an explicit import of `V` to disambiguate </ins> note: `V` could also refer to the variant imported here --> $DIR/issue-105069.rs:3:5 | LL | use self::B::*; |     ^^^^^^^^^^ <ins> = help: consider adding an explicit import of `V` to disambiguate </ins> error: aborting due to previous error

<!-- 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
`
label +S-bug-has-mcve
What is the expected output here? Can this actually compile, and if so, what does refer to?


Question: // (We do this separately from the above so that when the setup actually // happens we get some output.) // We re-use the `cargo` from above. <del> cargo.arg("--env"); </del> <ins> cargo.arg("--print-sysroot"); </ins> // FIXME: Is there a way in which we can re-use the usual `run` helpers? let miri_sysroot = if builder.config.dry_run {

Hello, this is your friendly neighborhood mergebot. After merging PR rust-lang/rust, I observed that the tool miri no longer builds. A follow-up PR to the repository is needed to fix the fallout. cc do you think you would have time to do the follow-up work? If so, that would be great! cc the PR reviewer, and nominating for compiler team prioritization.


Question: <ins> // ... continued from ./min-choice.rs // check-fail trait Cap<'a> {} impl<T> Cap<'_> for T {} fn type_test<'a, T: 'a>() -> &'a u8 { &0 } // Make sure we don't pick `'b`. fn test_b<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c> where 'a: 'b, 'a: 'c, T: 'b, { type_test::<'_, T>() // This should pass if we pick 'b. //~^ ERROR the parameter type `T` may not live long enough } // Make sure we don't pick `'c`. fn test_c<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c> where 'a: 'b, 'a: 'c, T: 'c, { type_test::<'_, T>() // This should pass if we pick 'c. //~^ ERROR the parameter type `T` may not live long enough } // We need to pick min_choice from `['b, 'c]`, but it's ambiguous which one to pick because // they're incomparable. fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> where 'a: 'b, 'a: 'c, { s //~^ ERROR captures lifetime that does not appear in bounds } 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: let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); <del> // phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here; // just default to a straight-forward invocation for now: let mut cmd = Command::new("rustdoc"); </del> <ins> // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); let mut cmd = Command::new(rustdoc); </ins> let extern_flag = "--extern"; let runtool_flag = "--runtool";

Currently we do ensure on CI that works, but doctests are enabled as I couldn't figure out how to get this to work within bootstrap. However, that has let slip through. So ideally we can figure out these bootstrap issues and test rustdoc inside on rustc CI.
Here's what currently happens: shows a similar error. So... probably we're using the wrong rustdoc? I assume it's the bootstrap rustdoc, if that's a thing? I can't even see a rustdoc being built in the build log. We want the rustdoc that is produced by stage 0 here, since we are testing the Miri produced by stage 0. How do we get that? Cc
looks to be the reason we're running a random rustdoc here. I suspect we'll need to thread through a custom bootstrap env variable, since IIRC there's no RUSTDOC_WRAPPER that miri can use to thread state. Alternatively it might work to adjust miri such that it remembers which toolchain is running earlier, but I suspect that'll be harder. As-is though it's almost certainly semi-broken for any Rust user doing something like presumably, where their default toolchain isn't nightly?
It seems to be working, AFAIK rustup ensures that nested calls use the -specified toolchain. Or maybe we are just lucky... But yes we should in the outermost wrapper, determine which rustdoc cargo would invoke using the same logic as cargo store that in a miri-private env var invoke that in I assume however we'll also need further changes in how bootstrap invokes cargo-miri to tell it where the right rustdoc lives? Currently we're not even building rustdoc so something surely needs to change in bootstrap. I see this snippet a few times, is that all we need?
Yeah, I'd expect that to be enough to start with at least. Also potentially relevant: If we're already using somewhere in there (we should be, probably?) then that should already get mostly setup, see here: ,
We do that already: Unless you are trying stage 0, you should be able to see rustdoc compilation in the build logs.
This is stage 0. It should still have to build rustdoc, stage 0 Miri needs stage 0 rustdoc (not bootstrap rustdoc) for its doctests.


Question: let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); <del> // phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here; // just default to a straight-forward invocation for now: let mut cmd = Command::new("rustdoc"); </del> <ins> // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); let mut cmd = Command::new(rustdoc); </ins> let extern_flag = "--extern"; let runtool_flag = "--runtool";

(...) ah fun, so if we invoke RUSTDOC we'll actually invoke bootstrap's rustdoc wrapper. We'll have to see if having both Miri and that wrapper around will work.^^
Never mind, that was for a build. For stage 0 this doesn't happen. I don't think this can work though... The staging with Miri is a bit weird; we need a stage 1 std as well for our stage 0 tests. Specifically we need a host sysroot that was built with a compiler that "is the same as" Miri, i.e. that is fully compatible. (The is wrong, it's not the compiler that built Miri.) This was needed to make build scripts and proc macros work in .
Yes, and if you want to use the actual rustdoc without wrapper, you can invoke . I tried using env instead of plain "rustdoc" and this is the output:
I had to manually pass from the cargo miri test caller; it turns out we are not passing it by default (or it somehow gets removed later?). Anyway, this is how I tested it:
Yeah currently this does not work due to But you have already come closer than I did. :) Was that with or stage 1? Maybe is ?
I guess that needs to be resolved first before we enable doctests on cargo miri test ? It was stage 1. Yeah, it seems like.
Yes. must continue working. I don't want to always build rustc twice when working on Miri in the tree.^^ But if necessary we could enable doc-tests only for higher stages... that would still be better than the status quo.


Question: // option. This file may not be copied, modified, or distributed // except according to those terms. <del> use prelude::*; use std::rand; use std::rand::Rng; use test::{Bencher, black_box}; pub fn insert_rand_n<M, I, R>(n: usize, map: &mut M, b: &mut Bencher, mut insert: I, mut remove: R) where I: FnMut(&mut M, usize), R: FnMut(&mut M, usize), { // setup let mut rng = rand::weak_rng(); for _ in 0..n { insert(map, rng.gen::<usize>() % n); } // measure b.iter(|| { let k = rng.gen::<usize>() % n; insert(map, k); remove(map, k); }); black_box(map); </del> <ins> macro_rules! map_insert_rand_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { use std::rand; use std::rand::Rng; use test::black_box; let n: usize = $n; let mut map = $map::new(); // setup let mut rng = rand::weak_rng(); for _ in 0..n { let i = rng.gen() % n; map.insert(i, i); } // measure b.iter(|| { let k = rng.gen() % n; map.insert(k, k); map.remove(&k); }); black_box(map); } ) </ins> } <del> pub fn insert_seq_n<M, I, R>(n: usize, map: &mut M, b: &mut Bencher, mut insert: I, mut remove: R) where I: FnMut(&mut M, usize), R: FnMut(&mut M, usize), { // setup for i in 0..n { insert(map, i * 2); } // measure let mut i = 1; b.iter(|| { insert(map, i); remove(map, i); i = (i + 2) % n; }); black_box(map); </del> <ins> macro_rules! map_insert_seq_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { use test::black_box; let mut map = $map::new(); let n: usize = $n; // setup for i in 0..n { map.insert(i * 2, i * 2); } // measure let mut i = 1; b.iter(|| { map.insert(i, i); map.remove(&i); i = (i + 2) % n; }); black_box(map); } ) </ins> } <del> pub fn find_rand_n<M, T, I, F>(n: usize, map: &mut M, b: &mut Bencher, mut insert: I, mut find: F) where I: FnMut(&mut M, usize), F: FnMut(&M, usize) -> T, { // setup let mut rng = rand::weak_rng(); let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect(); for k in &keys { insert(map, *k); } rng.shuffle(&mut keys); // measure let mut i = 0; b.iter(|| { let t = find(map, keys[i]); i = (i + 1) % n; black_box(t); }) </del> <ins> macro_rules! map_find_rand_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { use std::rand; use std::rand::Rng; use test::black_box; let mut map = $map::new(); let n: usize = $n; // setup let mut rng = rand::weak_rng(); let mut keys: Vec<_> = (0..n).map(|_| rng.gen() % n).collect(); for &k in &keys { map.insert(k, k); } rng.shuffle(&mut keys); // measure let mut i = 0; b.iter(|| { let t = map.get(&keys[i]); i = (i + 1) % n; black_box(t); }) } ) </ins> } <del> pub fn find_seq_n<M, T, I, F>(n: usize, map: &mut M, b: &mut Bencher, mut insert: I, mut find: F) where I: FnMut(&mut M, usize), F: FnMut(&M, usize) -> T, { // setup for i in 0..n { insert(map, i); } // measure let mut i = 0; b.iter(|| { let x = find(map, i); i = (i + 1) % n; black_box(x); }) </del> <ins> macro_rules! map_find_seq_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { use test::black_box; let mut map = $map::new(); let n: usize = $n; // setup for i in 0..n { map.insert(i, i); } // measure let mut i = 0; b.iter(|| { let x = map.get(&i); i = (i + 1) % n; black_box(x); }) } ) </ins> }

the closure being passed into in BTreeMap and VecMap's benches has a trailing semi-colon making the return value , and thus making the entire operation a no-op. Removing the semi-colon causes lifetime conflict issues. CC
I have a branch that just gives up and replaces these with macros. This results in clearer and more concise code like . Confirmed produces sane results in benchmark output. Hope to submit something tomorrow.


Question: <ins> // unit-test: ConstProp // compile-flags: -O // Regression test for https://github.com/rust-lang/rust/issues/118328 #![allow(unused_assignments)] struct SizeOfConst<T>(std::marker::PhantomData<T>); impl<T> SizeOfConst<T> { const SIZE: usize = std::mem::size_of::<T>(); } // EMIT_MIR overwrite_with_const_with_params.size_of.ConstProp.diff fn size_of<T>() -> usize { // CHECK-LABEL: fn size_of( // CHECK: _1 = const 0_usize; // CHECK-NEXT: _1 = const _; // CHECK-NEXT: _0 = _1; let mut a = 0; a = SizeOfConst::<T>::SIZE; a } fn main() { assert_eq!(size_of::<u32>(), std::mem::size_of::<u32>()); } </ins>

Fuzzer generated MIR, reduced, and UB-free under Miri (for real this time :sweatsmile:) Segfaults with enabled: , which is a valid pointer, somehow got propagated as 0: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
That seems undesirable. Is there a surface Rust program that can produce this MIR? Asking primarily for prioritization purposes.
WG-prioritization assigning priority (). label -I-prioritize +P-medium
Minimized test case:
Here's an example using stable surface syntax (). Seems to have been introduced in 1.70, with in particular.
Nevermind seems like I was wrong. <details</details
It's not an LLVM miscompilation, the code is already by the time it goes to LLVM. With So it's defiantly happening in MIR ConstProp
The problem seems to be that when running on the statement , the frames arn't updated, so when it runs on , it thinks is their for local . , on to add logging and test. ()
claim
Cc


Question: <del> // no-prefer-dynamic </del> #![feature(unsized_tuple_coercion)] static mut DROP_RAN: isize = 0;

Right now on our bots we're basically in a state where if valgrind rpass tests are compiled dynamically they will all fail, but when compiled statically they will pass. I'm not really sure what's going on unfortunately, but this is either a bug in valgrind or a bug with us, and we should know precisely what it is to ensure something more sinister isn't lurking. Some links: - first pass at linking tests statically, fixed - another pass at linking all tests statically
All the failures seem to be within platform’s dynamic loader. Here’s a few things to try: updating kernel+glibc to the most recent versions (4.4-ish and 2.23-ish, respectively) help? downgrading kernel+glibc to some older version help? non-linux/non-glibc work correctly?
Any news/changes on this one ?


Question: <ins> // Copyright 2014 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. // Test that moves of unsized values within closures are caught // and rejected. fn main() { (|| box *[0u].as_slice())(); //~^ ERROR cannot move a value of type [uint] } </ins>

Compilation backtrace Version Seems to be very similar to and , but the difference is trying to send the value over a channel (removing this gives a "cannot move a value of type [u8]: the size of [u8] cannot be statically determined)
Just to update after the 0.12 release. I tried compiling the above example and am getting the same result (so this issue is still relevant).
Reduced test case: Something about the closure lets it get past type checking when it shouldn't.
This looks simple, I'll hopefully have a PR shortly.
Closed by


Question: struct GoodVoid(Void); fn main() { <del> let w = SingleUnused(42, [0, 1, 2, 3], "abc".to_string()); let _ = w.0; let _ = w.2; </del> <ins> let u1 = UnusedAtTheEnd(42, 3.14, [0, 1, 2, 3], "def".to_string(), 4u8); let _ = u1.0; let _ = UnusedJustOneField(42); let u2 = UnusedInTheMiddle(42, 3.14, "def".to_string(), 4u8, 5); let _ = u2.0; let _ = u2.3; </ins> <del> let m = MultipleUnused(42, 3.14, "def".to_string(), 4u8); </del> let gu = GoodUnit(()); let gp = GoodPhantom(PhantomData); let gv = GoodVoid(Void); <del> let _ = (gu, gp, gv, m); </del> <ins> let _ = (gu, gp, gv); </ins> }

The idea of changing a field to unit type to preserve field numbering makes sense for fields in the middle of a tuple. However, if the unused field is at the end, or it's the only field, then deleting it won't affect field numbering of any other field. No response No response <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim


Question: let size = mem::size_of::<T>() .checked_mul(count) .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); <del> let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; </del> <ins> let diff = src_usize.abs_diff(dst_usize); </ins> // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. diff >= size

In , it was uncovered that is making some rather strong assumptions: two s with different address but the same type must not overlap. Not only is this a scarily non-local safety invariant, it is also fundamentally incomaptible with some APIs that ought to be correct, as demonstrated by this snippet (thanks to and for help with working out the example): to see the issue: will duplicate parts of the memory range when there is overlap, which leads to double-drop (other parts of the memory range are just lost, leading to memory leaks, but that is not the main issue here). This is not itself a soundness issue as it requires unsafe code to trigger UB. But this likely reflects an unintended consequence of . This got stabilized in as part of That commit references and an RFC, but is not mentioned in either of them. was in Accept that is unsound and document "non-overlap" as part of the safety invariant. This seems very fragile. Make not misbehave on overlap, either by panicking or by only swapping the non-overlapping parts. Cc
was in , which was authored by a "Charlie Fan". This is probably
Cc
This makes the method sound, but it seems like there could be other seems-like-they-should-be-ok cell projections that break under this behavior.
I don't think so. This makes the function behave "strangely", but since no data is duplicated nor discarded, I think it is sound.
I share this hunch, although the code, out of nowhere, may look very contrived. Consider: So it seems like -king (at least for non- types) is the only option that would allow us too keep the structural property of s, which, imho, is a very intuitive programmer mindset (and thus, a mistake that many would do should they not know about this caveat), and so a quite important thing to preserve .
That is an example of the "strange" behavior not being the right thing for this code, but it is not an unsoundness of per se. Your unsafe code is simply making wrong assumptions about the functional behavior of . Current favors the first operand in case of overlap (according to documentation); unsafe code that incorrectly assumes it would favor the second operand would be equally wrong. I don't see a bug in either way. IMO it seems rather strange to only panic for non- types.


Question: let size = mem::size_of::<T>() .checked_mul(count) .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); <del> let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; </del> <ins> let diff = src_usize.abs_diff(dst_usize); </ins> // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. diff >= size

Btw, also exists. does not have array/slice projection functions though and they would be wrong due to the counts, so overlapping probably truly are not a thing.
At the very least, an argument that aren't allowed to overlap is easier to defend than that aren't allowed to overlap. Plus also, doesn't have guaranteed layout in the first place, so any example using tuples is (currently) implementation-detail-tied even before hitting . You could still construct an example using only types, of course; just replace the tuple with an actual type. You could even make it . As I understand it, there's three main cases here. ping two nonoverlapping is fine. ping two partially overlapping without any bound on has a sound, if surprising, definition, where the nonoverlapping part of the arrays are swapped. ping two partially overlapping unknown is unsound in any definition, unless both has no safety invariants and the overlapping portion is . The third case is obviously the most restricting one, and is defined on . To expound on first of the two subissues: Consider a type with the extra safety invariant that the second must be double the first . could even be . It would be valid to create two from , as you'd have and . There is no possible definition of (other than a no-op) which preserves the safety invariant. And of course the impl doesn't even know about the safety invariant. I could probably create an even worse example using underaligned types and relying on a specific endianness, perhaps even accidentally breaking validity invariants (think around partially overlapping ). The only two resolutions I'm confident in are making always panic for overlapping cells (because there could be safety invariants being broken) or forbidding overlapping s to -compatible types (optionally: that would be broken by ). And I don't like the subtle implications of the latter (e.g. being unsound for unbound ).
I don't think would be immediately unsound, you would still need a way to create overlapping s.
In particular, they certainly can only overlap in restricted ways -- if they overlap such that one's sits on the other's , I can already cause UB without just by storing into that and then reading it as a . Oh I see... to only swap the non-overlapping parts we have to make an argument that these parts have the same type (safety+validity invariant).


Question: let size = mem::size_of::<T>() .checked_mul(count) .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); <del> let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; </del> <ins> let diff = src_usize.abs_diff(dst_usize); </ins> // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. diff >= size

Which... seems utterly bogus now that I think about it. Worse, the invariant could correlate the overlapping with the non-overlapping part, as in your example. (Removed a whole bunch of nonsense where I try to find some special cases that work.) Yeah we should make it panic.^^ It is unsound to create an to these though, even without I can already violate the safety invariant here by setting the second reference to . Ergo this is not a problem for , we can already assume such references do not exist. I am confused, is there a negation missing somewhere in this sentence?
Fair. I'm fairly confident that it'd be possible to come up with some safety invariant that a partial swap would break, though, with more data-dependent qualities. The parenthetical is an optional relaxation of the potential requirement (but at the cost of a lot of complexity).
But shouldn't it be forbidding overlapping s to -incompatible types? Not that I know what either of these things mean, but forbidding incompatible seems to make more sense than forbidding compatible.^^
Yeah, poor verbage. I meant roughly "forbidding overlapping s of types that can be used in (i.e. sized types)", with the optional extension of "only for those actually broken by " (however that would be defined).
that partially overlapping s through an enum is problematic even without :
Enums isn't really the same thing. That enum projections are unsound , but as also discussed in that article, struct projections are typically ok, and the array projection discussed here is essentially a struct projection, not an enum projection.
I would like to bring up my crate  which allows projecting through using a macro. example usage: Note: doesn't allow projecting through enums for exactly the reasons that explained. I'm not sure how could interact with to produce bad behavior, because you can only project to fields, which can't be swapped with their parent, but just in case someone else finds something interesting. i.e. This isn't possible, so it's not possible to project through to a field that's the same type as the parent. Alongside the fact that all fields are disjoint means that cell-project should only produce overlapping if they are also .
I agree with here. Sum types and product types are different, and really should commute around product types, i.e., ought to be sound.


Question: let size = mem::size_of::<T>() .checked_mul(count) .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); <del> let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; </del> <ins> let diff = src_usize.abs_diff(dst_usize); </ins> // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. diff >= size

You can use , which led me to this issue (it'd be good if we could support field projection inside of and ).
While you could use to check that the tuple layout conforms to the C-like layout needed to do such projection, I don't see how your specific use of would lead to two partially overlapping though. Note that the problem is not with projecting to a single field, but to a group/subset containing multiple fields (or like in the array/slice example, to a subarray/subslice with length ).
Oh I see, you're right. False alarm.


Question: // discriminant. if !def.repr.c() && !def.repr.transparent() && def.repr.int.is_none() { // Special-case types like `Option<extern fn()>`. <del> if !is_repr_nullable_ptr(cx, ty, def, substs) { </del> <ins> if !self.is_repr_nullable_ptr(ty, def, substs) { </ins> return FfiUnsafe { ty, reason: "enum has no representation hint".into(),

While reviewing I noticed for the first time that the improperctypes lint normalizes with the "revealall" mode. I don't have a nuanced understanding of what that means exactly but based on the general description in the rustc docs and experimentation (see below) I think that's probably the wrong choice for this lint, because it exposes details to the user that are normally hidden during type checking. For example, using existential types, the lint pierces through otherwise-opaque existentials to look at the underlying (hidden) type, thus it both accepts code that is only FFI-safe because of the particular type underlying the existential, which users of that type shouldn't know or rely on leaks the underlying type to the user in error messages when (correctly) rejecting uses of an existential type as FFI-unsafe I can't quickly find an equivalent using only stable , because we don't have , but if there's a way to write "Option of the return type of this function" in stable Rust, then that would presumably have the same issue. cc for fact-checking my understanding that this is because of reveal_all
User-facing diagnostics should avoid the mode, yeah. In fact, the other variant of is literally - also the doc comments are pretty explicit about this: cc
I've been using 's over in recent PRs that modify the lint (see , , and ). In each recent PR, I've ensured that opaque types are prohibited (in the spirit of "FFI-safety of a type not relying on particular type behind an opaque type being FFI-safe") - with the exception of when a opaque type is used in a projection (). Unless there are specific examples of behavior that still need to be changed as a result of this issue - should this issue be closed?
My litmus test for closing this would be "all the normalizing done in improper_ctypes uses ", which is hard to audit for while there's multiple PRs in flight that address parts of the problem. After those PRs are all merged, we can see if there's any remaining and if so, their location should tell us how to exercise any remaining questionable behavior.
I've opened to fix the remaining two places that is used now that the other PRs have landed.


Question: // Associated types in traits don't necessarily have a type that we can visit try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } <del> for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { </del> <ins> for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { </ins> try_visit!(visitor.visit(span, pred)); } }

https://crater-
searched nightlies: from nightly-2024-02-01 to nightly-2024-03-20 regressed nightly: nightly-2024-02-10 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.8</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </detailsprobably
WG-prioritization assigning priority (). label -I-prioritize +P-high
MCVE


Question: /// let src = [1, 2, 3, 4]; /// let mut dst = [0, 0]; /// <ins> /// // Because the slices have to be the same length, /// // we slice the source slice from four elements /// // to two. It will panic if we don't do this. </ins> /// dst.clone_from_slice(&src[2..]); /// /// assert_eq!(src, [1, 2, 3, 4]);

Would you like to fix this issue? I'm dealing with a case where I have to send a byte array buffer to a destructive function multiple times. This function requires the buffer to start with an initialization sequence that I have to set. I want to be able to efficiently reset the header bytes but the size of the initialization sequence is less than the total buffer and so I hit the error. The real question is, why is this required? Here's the current code: In theory, if is big enough to hold shouldn't that be enough? The adjusted call should be this then: I think the same should be done for clonefromslice.
The discussion of that decision is in
Holy bikeshed Batman! It’s impossible to find in all those comments! Thanks for pointing me there. It does seem from the first 30 or so posts that it was intentionally meant to fill the destination. If it does stick around, I do think the size checking should be done a little smarter.
Isn't fine? Personally, I find a bunch of value in the explicitness of requiring equal lengths since slicing to get the other three possible behaviours is so easy.
That's not a bad argument. Maybe we can adjust this to suggest that in the error message? I wouldn't have found that on my own.
some examples to the docs of using subslices with these methods. I don't know what the libs policy is on adding guidance to panics -- it does feel like one wouldn't want a long explanatory string built into one's binary in release mode, at least...
Agreed. In general, the longer the message the less likely people are going to read it clearly. I also believe not just stating the problem, but also offering a suggestion. “Destination and source slices have different lengths. Try sub-slicing the longer of the two.” This offers a jumping off point for Googling and reminds those (like me) that sub-slicing is a thing.
I'm personally against lengthening panic messages to suggest fixes, rather I'd expect someone to ask a question about this on StackOverflow or a similar platform eventually which would then get indexed by search engines. I'm going to mark this as an easy documentation issue; we can update documentation to note that subslicing is likely what users want to fix the panic in the panic section or the main section.


Question: /// let src = [1, 2, 3, 4]; /// let mut dst = [0, 0]; /// <ins> /// // Because the slices have to be the same length, /// // we slice the source slice from four elements /// // to two. It will panic if we don't do this. </ins> /// dst.clone_from_slice(&src[2..]); /// /// assert_eq!(src, [1, 2, 3, 4]);

I'm happy to mentor anyone who wants to fix this issue! Here's how: The relevant documentation lives here: This should be extended to describe how to use slicing to make the lengths the same. Something like the example, but with text pointing out how without the slice, it would panic, so slicing to the same length would make the guarantee. I'm happy to answer any more questions about how to accomplish this!
PR:


Question: <del> Subproject commit 7b8e8293d08d298579470f9d6c74731043c6601a </del> <ins> Subproject commit 7a943a9dfcdca98e5988da6d0b7d2f83a364b5ba </ins>

Hello, this is your friendly neighborhood mergebot. After merging PR rust-lang/rust, I observed that the tool clippy-driver no longer builds. A follow-up PR to the repository is needed to fix the fallout. cc do you think you would have time to do the follow-up work? If so, that would be great! cc the PR reviewer, and nominating for compiler team prioritization.


Question: }); } <del> fn get_lint_level(&self, lint: &'static Lint, idx: u32) </del> <ins> fn get_lint_level(&self, lint: &'static Lint, idx: u32, aux: Option<&FxHashMap<LintId, (Level, LintSource)>>) </ins> -> (Level, LintSource) { <del> let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx); </del> <ins> let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); </ins> // If `level` is none then we actually assume the default level for this // lint.

The following snippet works fine before but now it reports a warning: Steps to reproduce: clone rustup override set nightly-2017-08-11 cargo test Is this an expected behavior, or a bug? Thank you!
cc -- probably related to the new lint implementation
Yes this was caused by The bug is on . The check for whether is in scope is not checking the current set of attributes being linted. For example this does not warn: but this warns: (as you've noticed) The fix is to just take the local variable into account which has the up-to-that-point set of lint attributes collected.
I've opened a PR for this at


Question: let fcx = FnCtxt::new(&inh, param_env, id); if !inh.tcx.features().trivial_bounds { // As predicates are cached rather than obligations, this <del> // needsto be called first so that they are checked with an </del> <ins> // needs to be called first so that they are checked with an </ins> // empty `param_env`. check_false_global_bounds(&fcx, span, id); }

Repro: As of current nightly: This is the unreachable line: The same crash reproduces back to 1.47.0. Older stable compilers do not crash:
Bisect: searched nightlies: from nightly-2020-07-10 to nightly-2020-08-27 regressed nightly: nightly-2020-07-22 searched commits: from to regressed commit: () Mentioning because appears the most relevant.
Assigning .


Question: //! `&foo()` or `match foo() { ref x => ... }`, where the user is //! implicitly requesting a temporary. //! <del> //! Somewhat surprisingly, not all lvalue expressions yield lvalue datums //! when trans'd. Ultimately the reason for this is to micro-optimize //! the resulting LLVM. For example, consider the following code: //! //!     fn foo() -> Box<int> { ... } //!     let x = *foo(); //! //! The expression `*foo()` is an lvalue, but if you invoke `expr::trans`, //! it will return an rvalue datum. See `deref_once` in expr.rs for //! more details. //! </del> //! ### Rvalues in detail //! //! Rvalues datums are values with no cleanup scheduled. One must be

Rust compiler (rustc 1.1.0-nightly ( 2015-05-14) (built 2015-05-14) fails to compile this source: With the error: I can reproduce this ICE also on
Reduced it a bit:
The broken IR:
Looking through it quickly, it seems like the order of the cleanups is messed up? If is then from the switch we go to the label which just jumps to where we memcpy the value for into the alloca and then continue to the label. This is where the problem is since it tries to call on the value returned from . But that's the thing, we wouldn't have called in that arm of the branch and hence shouldn't need to call free either.
Adding a block around suppresses the error. I feel like we had a similar problem not too long ago.
This is "caused" by the micro optimization for dereferencing owned pointer rvalues in . Since is the "trailing" expression for the arm its cleanup will be scheduled in the same scope as the match expression. cc
Either way, this is a dupe of I believe had an idea for a fix.
it's simple, we remove the micro-optimization and always return an datum from . The possibility of returning datum also caused issues with field accesses - see for that fix. We have a static type system and the / marker types are there for a reason. If there is no answer to "how is an rvalue dereference or field meaningful?", then the return type for both of those should be .


Question: //! `&foo()` or `match foo() { ref x => ... }`, where the user is //! implicitly requesting a temporary. //! <del> //! Somewhat surprisingly, not all lvalue expressions yield lvalue datums //! when trans'd. Ultimately the reason for this is to micro-optimize //! the resulting LLVM. For example, consider the following code: //! //!     fn foo() -> Box<int> { ... } //!     let x = *foo(); //! //! The expression `*foo()` is an lvalue, but if you invoke `expr::trans`, //! it will return an rvalue datum. See `deref_once` in expr.rs for //! more details. //! </del> //! ### Rvalues in detail //! //! Rvalues datums are values with no cleanup scheduled. One must be

Original testcase by (reduced from ): The debug log reveals that a (shallow free) cleanup of the rvalue is scheduled in the scope of AST node , while the dereference expression itself has id : reveals that id refers to the entire function's block: This means the cleanup of a value valid only within a match arm is scheduled outside the arm. cc
Dupe of Leaving open for now but we can close either.
This is caused by a micro-optimization specific to dereferences of rvalues. Is this used oftenly enough to justify its existence in the first place? Even if it is, I guess we can disable it in problematic cases like this, where the temporary scope of the match arm's RHS is outside the arm.
I think we can probably remove it, in general removing special treatment of seems like a Good Thing
Triage: this still ICEs.
can you point me/us at the micro-optimization that you mentioned above, so that I (we) can try removing it ourselves and measure the impact?
I only vaguely recall this issue, but I'm pretty sure I was talking about .
triage: still ICEs.
Indeed, it doesn't even need : Does this at least continue to ICE even if LLVM is compiled without assertions? If not, we may want to up the priority on this ticket.