Question: use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; <del> use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; </del> <ins> use rustc_middle::ty::subst::{InternalSubsts, Subst}; </ins> use rustc_middle::ty::util::ExplicitSelf; <del> use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness}; </del> <ins> use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; </ins> use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use super::{potentially_plural_count, FnCtxt, Inherited}; <del> use std::iter; </del> /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait.

So I had a trait system in my (nightly) code for a while now that utilized specialization, but it no longer seems to be working after a recent update: Now, I haven't been following the development of the specialization feature too closely, so it is possible that this is somehow actually intended and I am missing something. However, given that this previously compiled and ran just fine a couple weeks ago and given that the specialization incomplete warning was only recently, I am inclined to think that it is probably a regression of some sort. compiler version:
Another MVCE (): Regressed in , looks like
cc as far as I can tell this wasn't an intended outcome of the change?
It wasn't really, it was just slightly more complex to have this still work after that PR.
Would you mind describing at a high level what needs to be done?
It looks like the problem stems from the bound predicate not being fully normalized when checking the defaulted associated type. From my reproducer above: which should instead be . I'm not certain yet how this ought to be implemented. Perhaps a pass after normalization that looks for occurrences of the defaulted type ( in this case) and replaces it with the defaulted type. Seems simple enough, in theory :) But maybe there are cases I'm not thinking of.


Question: } tcx.sess.track_errors(|| { <del> tcx.sess.time("impl_wf_inference", || { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) }); })?; tcx.sess.track_errors(|| { </del> tcx.sess.time("coherence_checking", || { <ins> // Check impls constrain their parameters tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); </ins> for &trait_def_id in tcx.all_local_trait_impls(()).keys() { tcx.ensure().coherent_trait(trait_def_id); }

No response No response No response
(for compiler people:) We could fix this by merging the impl WF and coherence checks into one compiler stage. I'll put up a PR and see what T-types thinks.
labels +AsyncAwait-Triaged We discussed this in a WG-async meeting and are deferring to the resolution suggested above. He noted that this is a fix to the diagnostics only. That fact that this is an error is correct.


Question: /// assert!(ptr::eq(ptr, inner.as_ptr())); /// ``` #[inline] <del> #[unstable(feature = "arc_unwrap_or_clone", issue = "93610")] </del> <ins> #[stable(feature = "arc_unwrap_or_clone", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn unwrap_or_clone(this: Self) -> T { Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) }

Feature gate: This is a tracking issue for . This feature adds methods to / to gain access to the contained value, by unwrapping if there is exactly one reference, or cloning otherwise. It is equivalent to cloning the inner value, but saves the clone operation if the caller has the only reference to the rc'd value. [x] Implementation: [ ] Final comment period (FCP) [ ] Stabilization PRThere seems to be consensus that the current name is good.
Apologies if this is the wrong place for this comment, feel free to delete. Is there a technical reason why is an associated function and not a method? If I have , I cannot call , but have to resort to which feels unwieldy.
it's because / are 'wrapper types' that implement . A lot of the methods are implemented as associated functions so they don't clash with method names on the . This makes it easier to change between different wrapper types like / etc without suddenly getting a name clash. Apologies if I'm using the wrong terminology but that's the gist of it.
That makes sense. Thanks for the explanation :)
sounds like a bad name to me: has a connotation of potentially panicking code in Rust. The other suggested names in all sound better to me. (Couldn't comment on the thread in IRLO as it has been closed.)
There is precedence for this pattern: for example.
True, I overlooked it.
I think this name is good, and it's easy for me to understand what it means. I'm really looking forward for this to be fcped and stabilized.
At $work we've been using the exact same implementation as the one used in nightly (), it works perfectly well
While I like the proposal very much (for it's convenience), I feel like I want to point out something that might be interesting as well in the future and is related: It's not possible to use where . In this case we have an , which is . However this is a conversion that is also very useful. It would be intersting to go from to . The other way is already possible, but this way is currently not possible, however there are sometimes cases where the count is known and converting back to a Box would be very useful. Consider wanting to remove an element from an for example.


Question: /// assert!(ptr::eq(ptr, inner.as_ptr())); /// ``` #[inline] <del> #[unstable(feature = "arc_unwrap_or_clone", issue = "93610")] </del> <ins> #[stable(feature = "arc_unwrap_or_clone", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn unwrap_or_clone(this: Self) -> T { Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) }

The current way to do this is to clone the vec, remove an element and make a new Rc, even when an Rc is empty. I understand that there would need to be something like a first, but I just wanted to bring it up, so it's clear that there's potentially more things that could "unwrap" from an Rc.
Try this: The code above will copy vector if needed. (I didn't test the code)
Yes, good point, thanks for bringing it up. However a Vec is unfortunately another layer of indirection. Typically I have something like .
Is there something that still needs to be done before this can go to FCP? I just came across the need for this and noticed that the comments seem positive with confirmation that it works at $work for at least one commenter above, so am wondering what if anything is preventing it moving forward?
Pinging here for input. There seems to be consensus on stabilizing this. Can anyone start an FCP? I'd be happy to work on a stabilization PR (with some guidance)
fcp merge Both of these are already expressible on stable using the following incantation, which is exactly the standard library's implementation too: . The rationale for a dedicated method is that "I need a " is a common enough use case that it's worthwhile to have one easy function prominently available in the type's API doing the thing you most likely want to do in that scenario.
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.
and others: is related
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon.
I believe that can check off the stabilization?
And update the documentation as this seems to have been stabilized.


Question: /// assert!(ptr::eq(ptr, inner.as_ptr())); /// ``` #[inline] <del> #[unstable(feature = "arc_unwrap_or_clone", issue = "93610")] </del> <ins> #[stable(feature = "arc_unwrap_or_clone", since = "CURRENT_RUSTC_VERSION")] </ins> pub fn unwrap_or_clone(this: Self) -> T { Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone()) }

I am getting this:
Arc<strstores the string inline on the heap together with the strongcount and weak_count of the Arc. This means it has a different in-memory representation than Box<strand thus can't be converted into a Box<strwithout copying the contents. A Box<strto Arc<strconversion also copies the string contents into the Arc allocation.
I understand that. But moving elements from an Rc to a Vec is different from cloning. The opposite direction is already possible. This means that you can write , but not . I understand that moving is different from . This would probably need to be named something like Vec::frommovedrcorclone`.
GitHub deleted all my angle brackets. I was specifically talking about converting between string types because there's no difference between moving and cloning characters.


Question: variant.fields.iter().enumerate().filter_map(move |(i, field)| { let ty = field.ty(cx.tcx, substs); <ins> // `field.ty()` doesn't normalize after substituting. let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty); </ins> let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); let is_uninhabited = cx.is_uninhabited(ty);

<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --When compiling on an Apple M1 processor: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Can also reproduce this when compiling on an Intel Macbook
I've encountered the same error on a different platform (x8664) when compiling . The project doesn't use cargo so repro is nontrivial, but from I can see that the ICE started occurring at which is a rollup of . <details<summary<strongBacktrace</strong</summary<p</p</details
Also seems to be hitting starlark-rust, , as per
Somewhat minimized standalone testcase: Builds on stable, fails on nightly. cc
Thanks for the minimization! Seems like we've hit again, but through a different code path. I'm investigating.
I think might be another duplicate of this, triggered when compiling the crate.


Question: ); } <del> let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig); </del> <ins> let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig); </ins> trait_sig.error_reported()?; let trait_return_ty = trait_sig.output(); <ins> // RPITITs are allowed to use the implied predicates of the method that // defines them. This is because we want code like: // ``` // trait Foo { //     fn test<'a, T>(_: &'a T) -> impl Sized; // } // impl Foo for () { //     fn test<'a, T>(x: &'a T) -> &'a T { x } // } // ``` // .. to compile. However, since we use both the normalized and unnormalized // inputs and outputs from the substituted trait signature, we will end up // seeing the hidden type of an RPIT in the signature itself. Naively, this // means that we will use the hidden type to imply the hidden type's own // well-formedness. // // To avoid this, we replace the infer vars used for hidden type inference // with placeholders, which imply nothing about outlives bounds, and then // prove below that the hidden types are well formed. let universe = infcx.create_next_universe(); let mut idx = 0; let mapping: FxHashMap<_, _> = collector .types .iter() .map(|(_, &(ty, _))| { assert!( infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(), "{ty:?} should not have been constrained via normalization", ty = infcx.resolve_vars_if_possible(ty) ); idx += 1; ( ty, Ty::new_placeholder( tcx, ty::Placeholder { universe, bound: ty::BoundTy { var: ty::BoundVar::from_usize(idx), kind: ty::BoundTyKind::Anon, }, }, ), ) }) .collect(); let mut type_mapper = BottomUpFolder { tcx, ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty), lt_op: |lt| lt, ct_op: |ct| ct, }; </ins> let wf_tys = FxIndexSet::from_iter( <del> unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()), </del> <ins> unnormalized_trait_sig .inputs_and_output .iter() .chain(trait_sig.inputs_and_output.iter()) .map(|ty| ty.fold_with(&mut type_mapper)), </ins> ); match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) {

This is a use-after-free that compiles with 1.74.0-nightly (2023-09-13 ): cc


Question: "README.md", "RELEASES.md", "configure", <del> "Makefile.in" </del> <ins> "Makefile.in", "x.py", </ins> ]; let src_dirs = [ "man",

The build system that we just turned on is not actually in the source code. cc
This is on beta and nightly too.
Reeopening until the backport is fixed because I'm putting this on the release milestone.
Backported in as


Question: attr: &Attribute, span: Span, target: Target, <ins> attrs: &[Attribute], </ins> ) -> bool { match target { <del> Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, </del> <ins> Target::Fn => { // `#[target_feature]` is not allowed in language items. if let Some((lang_item, _)) = hir::lang_items::extract(attrs) // Calling functions with `#[target_feature]` is // not unsafe on WASM, see #84988 && !self.tcx.sess.target.is_like_wasm && !self.tcx.sess.opts.actually_rustdoc { let hir::Node::Item(item) = self.tcx.hir().get(hir_id) else { unreachable!(); }; let hir::ItemKind::Fn(sig, _, _) = item.kind else { // target is `Fn` unreachable!(); }; self.tcx.sess.emit_err(errors::LangItemWithTargetFeature { attr_span: attr.span, name: lang_item, sig_span: sig.span, }); false } else { true } } Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, </ins> // FIXME: #[target_feature] was previously erroneously allowed on statements and some // crates used this, so only emit a warning. Target::Statement => {

This works (but it shouldn't): similar to , cc (tracking issue) label T-lang T-compiler C-bug I-unsound F-targetfeature11
cc , author of Note that this is about the nostd panic handler, not about the function. This fails as it should: gives
ugh we really need a way to make sure that every single "this is called by rust" function gets a check... I assume that these functions can't be unsafe, so I guess those checks are a food way to start looking and make sure to deduplicate the logic there?
Yeah sadly we do need to make sure, not just for the constructs that we have now but also it needs to be kept in mind for the future constructs we add or stabilize. A lot thankfully goes through either the trait system (operators or the GlobalAlloc trait used by ) or function pointers (alloc error hook, std panic hook). Functions that you can make callable solely by setting an attribute, those are rare. The best list of lang items I could find was in the , so that would be a great start for such an exhaustive search. Thankfully most of them are unstable, but still it needs to be addressed for each of them before stabilization (if that is a target).
WG-prioritization assigning priority (). label -I-prioritize +P-medium
label +requires-nightly
There is also another table of lang items in the source code, .


Question: <del> 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); } </del>

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> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::rc::Rc; struct Foo<'r>(&'r mut i32); impl<'r> Drop for Foo<'r> { fn drop(&mut self) { *self.0 += 1; } } fn main() { let mut drops = 0; { let _: Rc<Send> = Rc::new(Foo(&mut drops)); } assert_eq!(1, drops); } </ins>

The following function can drop any object arbitrary number of times, using only safe code: Probably bad :) Found while researching
Nominating for P-high
cc
Too bad this doesn't just cancel out the Leakocalypse :stuckouttongue:
(well, any object that implements . But yes, I see the point being made here.)
look, no required. I guess it doesn't work for types that are already unsized.
to be clear, I am looking at this now as well. :)
I guess is related.
I hope it is unrelated. In particular I wrote this on that ticket:
Yeah, it's unrelated. The call happens for , which does need drop.


Question: <del> { "message": "unnecessary parentheses around assigned value", "code": { "code": "unused_parens", "explanation": null }, "level": "warning", "spans": [ { "file_name": "$DIR/unused_parens_json_suggestion.rs", "byte_start": 654, "byte_end": 667, "line_start": 17, "line_end": 17, "column_start": 14, "column_end": 27, "is_primary": true, "text": [ { "text": "    let _a = (1 / (2 + 3));", "highlight_start": 14, "highlight_end": 27 } ], "label": null, "suggested_replacement": null, "suggestion_applicability": null, "expansion": null } ], "children": [ { "message": "lint level defined here", "code": null, "level": "note", "spans": [ { "file_name": "$DIR/unused_parens_json_suggestion.rs", "byte_start": 472, "byte_end": 485, "line_start": 11, "line_end": 11, "column_start": 9, "column_end": 22, "is_primary": true, "text": [ { "text": "#![warn(unused_parens)]", "highlight_start": 9, "highlight_end": 22 } ], "label": null, "suggested_replacement": null, "suggestion_applicability": null, "expansion": null } ], "children": [], "rendered": null }, { "message": "remove these parentheses", "code": null, "level": "help", "spans": [ { "file_name": "$DIR/unused_parens_json_suggestion.rs", "byte_start": 654, "byte_end": 667, "line_start": 17, "line_end": 17, "column_start": 14, "column_end": 27, "is_primary": true, "text": [ { "text": "    let _a = (1 / (2 + 3));", "highlight_start": 14, "highlight_end": 27 } ], "label": null, "suggested_replacement": "1 / (2 + 3)", "suggestion_applicability": "MachineApplicable", "expansion": null } ], "children": [], "rendered": null } ], "rendered": "warning: unnecessary parentheses around assigned value --> $DIR/unused_parens_json_suggestion.rs:17:14 </del> <ins> {"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3)); --> $DIR/unused_parens_json_suggestion.rs:16:14 </ins> | LL |     let _a = (1 / (2 + 3)); |              ^^^^^^^^^^^^^ help: remove these parentheses | note: lint level defined here <del> --> $DIR/unused_parens_json_suggestion.rs:11:9 </del> <ins> --> $DIR/unused_parens_json_suggestion.rs:10:9 </ins> | <del> LL | #![warn(unused_parens)] </del> <ins> LL | #![deny(unused_parens)] </ins> |         ^^^^^^^^^^^^^ <del> " } </del> <ins> "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error "} </ins>

Update test file to use + annotations instead of (see https://rust-) The files need to update are: - <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
is the correct file name , not ? And what about this comment?
Is the problem fixed ? If not, I would like to work on it !
WIP PR has been closed due to inactivity so you can work on this.
I would like to be assigned to this issue. Am I supposed to do a new pull request ?
claim Go ahead!
Error: Parsing assign command in failed: claim Please let know if you're having trouble with this bot.
claim
Error: Parsing assign command in failed: claim Please let know if you're having trouble with this bot.
Hmm, it's odd, anyway, you can assign the issue to yourself by comment Ah, I mistaken the command, the collect one is , sorry.
claim
If I understood well the problem: I must replace all the by just , even if comment exist ? Because the output changes, I should modify the .stderr version I must change with in , and as should raise an error we add why add in the version ?


Question: <del> // revisions: min_const_fn const_fn #![cfg_attr(const_fn, feature(const_fn))] enum E { V(i32), } const EXTERNAL_CONST: Option<i32> = {Some}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn const LOCAL_CONST: E = {E::V}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn const fn external_fn() { let _ = {Some}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn } const fn local_fn() { let _ = {E::V}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn } fn main() {} </del>

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


Question: <del> // revisions: min_const_fn const_fn #![cfg_attr(const_fn, feature(const_fn))] enum E { V(i32), } const EXTERNAL_CONST: Option<i32> = {Some}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn const LOCAL_CONST: E = {E::V}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn const fn external_fn() { let _ = {Some}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn } const fn local_fn() { let _ = {E::V}(1); //[min_const_fn]~^ ERROR is not yet stable as a const fn //[const_fn]~^^ ERROR is not yet stable as a const fn } fn main() {} </del>

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


Question: #[stable(feature = "rust1", since = "1.0.0")] impl<W: Write> Drop for BufWriter<W> { fn drop(&mut self) { <del> if self.inner.is_some() { </del> <ins> if self.inner.is_some() && !self.panicked { </ins> // dtors should not panic, so we ignore a failed flush let _r = self.flush_buf(); }

There is a panic safety issue in : after a call panics, the impl of calls again, which means the buffer contents are potentially written twice. This may cause an application to overwrite parts of a file that it did not mean to overwrite (in a DB engine written in Rust, this could cause unrecoverable data corruption!). Demonstration: The expected output of the demo program is , the actual output is: More generally, we need a story for panic safety in Rust. My takeaway from the related discussions (e.g. , , the trait) was that only code and impls should have to worry about panic safety. The demo app contains none of these, so I'd consider this a bug in . (otherwise all implementations would need to provide the strong exception safety guarantee?) Solution: could use temporarily mark the buffer as empty during the calls; so that the impl doesn't do anything after a panic. However, this doesn't help if the panic occurs during a call...
Note that Rust is normally referring to "memory safety" when talking about safety, so the issue here isn't in conflict with the related discussions. It's definitely a bug in , but I want to point out how specific it is here: the only reason you have odd behaviour is because you have a implementation that will panic after successfully writing the data it is given. I'm all for making more robust, but it's not just "if the call panics", it's "if the call panics after successfully writing data". Panicking before a successful write (or if the write fails), would not have the same issue.
If your impl is panicking in the middle of a write, it seems to me like you're in data corruption land with or without a second write. This is not quite the case - and thread locals expand that surface area. What's specifically the expected behavior here? Is the implementation specifically the thing that needs tweaking, or should the totally poison itself? For reference, Java's class has no special handling for exceptions thrown from the inner : , so adjusting alone seems like a reasonable route to take.
Without the , a panic in the middle of a write (without ) only corrupts the part of the file that the application meant to overwrite. In a DB engine context, that means the resulting corruption can be repaired when the transaction is rolled back.


Question: #[stable(feature = "rust1", since = "1.0.0")] impl<W: Write> Drop for BufWriter<W> { fn drop(&mut self) { <del> if self.inner.is_some() { </del> <ins> if self.inner.is_some() && !self.panicked { </ins> // dtors should not panic, so we ignore a failed flush let _r = self.flush_buf(); }

But with , a panic after some data was written might corrupt parts of the file that are not saved in the rollback journal, so recovery not possible. I think we need some guideline like: If a method call panics, it's a bug to call any additional methods on the same object. Thus, the bug is in . may need something similar to a poison-flag so that the impl can detect whether a previous call panicked, but it doesn't need to protect against it's own methods being called after a panic (that would be considered a bug in the caller). The Java has the same problem, but the expectation in the Java world is different: it's trivially possible to catch an exception and continue using the potentially-invalid state; so in Java's case I would argue that all implementations should provide the strong exception safety guarantee to avoid this kind of issue. Essentially, the Rust world needs to decide between a Java/C++-style "strong exception safety guarantee" (=failing method call should not have any side effects) or a new "no-use-after-panic guarantee" (=after a failing method call, no additional method calls should occur). Some types (like BufWriter) can be compatible with at most one of the guarantees -- strong exception safety requires that a panicking call has no side effects; no-use-after-panic requires that a panicking call has the side effect of suppressing the buffer flush in the impl. The trait seems to be roughly equivalent to basic exception safety. Types that do not implement instead live in the world. Generic types implementing need to be careful not to call any functions on the type parameter from within the implementation if a previous call panicked (unless they use a bound).
triage: P-medium is fixing the data corruption in


Question: /// /// # Panics /// <del> /// When the number is zero, or if the base is not at least 2; /// it panics in debug mode and the return value is 0 in release mode. </del> <ins> /// This function will panic if `self` is zero, or if `base` is less then 2. </ins> /// /// # Examples ///

Filing since it's in pFCP over at , and I don't think we can reasonably change it after stabilization (especially since it's documented). Currently, in release mode evaluates to . (And same for the other bases.) It's not obvious to me that that's necessarily the best option. For example, the implementation is slightly nicer on CPUs from the past or so (and I think would be just as nice on older ones ), but gives <subas u32</subin the wrapping case. It also might be nice to have the wrapping case give something clearly different from any of the successful cases, rather than having and give the same thing. For example returns in release mode, which isn't a power of two (according to ), so it's distinguishable from all the non-wrapping cases. This only affects // on . (The checked versions don't have an issue, nor do the ones on .)
I couldn't find any previous discussion of what the exact wrapping value ought to be, just that there ought to be one, as opposed to a . There was this note: For which I think the implementation I mention above is a counter-example, albeit only for the base-2 case. Also, currently in release mode is essentially , so we can pick any value we want to return for those cases. FWIW, the implementation in gives as the result for .
In Rust we try to do the right thing. Not even Python gives -1. Let's avoid in-band error values in Rust.
What's your proposal for what the "right" thing is, then? That panic in release too? Arguably the most-correct value is −∞ (like ), but that doesn't fit in any of our integer types. So would make sense, but release mode for the other un-prefixed things is wrapping, not saturating.
Python has some functions that return in-band values: "xy".find("y") 1 "xy".find("z") -1 From Rust I expect something better. In Rust if a function isn't naturally total and you can't restrict its input, then I expect it to return Option (or Result), or when that's isn't ergonomic enough, a panic (in release too). Returning -1 is dangerous as that Python find function, returning 0 is not math.


Question: /// /// # Panics /// <del> /// When the number is zero, or if the base is not at least 2; /// it panics in debug mode and the return value is 0 in release mode. </del> <ins> /// This function will panic if `self` is zero, or if `base` is less then 2. </ins> /// /// # Examples ///

I think returning (wrapped if necessary) is a clear distinguish between normal and error result. Returning an is not ideal currently because it will makes the function practically unusable in const context (before const unwrap is stabilized) If getting closest to the "correct" math answer, how about choosing ? However it seems weird and still seems better to me
Perhaps in other languages. Rust is known for being better than that. I have chosen to use Rust because it's a bit better than Python (see above). Let's return Option and and wait for const unwrap to be stabilized before making ilog const, then.
That's what does already. Is your proposal, then, that the version of just shouldn't exist on ? How do you square that with precedent of other things -- like or -- that have the version return , but the un-prefixed one wrap in release mode?
what about treating it like division by zero and just panicking?
I'd be fine with -1. The point of these methods is to get fast code (otherwise many won't use them and will prefer to do to keep the code branchless and avoid the ugly ) and a defined value outside of the usual input range. (from above) is a good example. If you want stricter guarantees than that, you can use .
A minor point: being 0 is actually a reasonable choice - even though 0 is not a power of two, it is congruent to the correct power of two modulo 2^32 (which is 2^32 itself), so exactly what is expected in wrapping arithmetic. But unfortunately there's no "−∞ mod 2^32" that could be used for .
Modular arithmetic is confusing in the context of logarithm, if you want to return the discrete logarithm of 0 in the release mode, then there are a lot of candidates, because (in case of ) therefore in the sense of modular arithmetic, could be any multiple of . If you really want to achieve something close to , then I guess the best value is as I mentioned above. (Interestingly though, = , which is a multiple of 8, 16, 32, 64, 128)
That's certainly a possibility. suggested not doing that back in the original PR, though:
Doesn't implicitly include a check for zero in the code generated?


Question: /// /// # Panics /// <del> /// When the number is zero, or if the base is not at least 2; /// it panics in debug mode and the return value is 0 in release mode. </del> <ins> /// This function will panic if `self` is zero, or if `base` is less then 2. </ins> /// /// # Examples ///

]
Also, since the methods are implemented for signed integers as well, another issue would be the log of negative values. For example for floating-point, would return −∞, but would return NaN. So if would return some value for −∞, would panic anyway, or return some value?
I don't think it makes sense to do anything other than panic in the case of negative values, which in turn is probably an argument for panicking on zero as well. I guess one could argue that "wrapping" could be interpreted as wrapping the preimage to fit in the function's domain (rather than just wrapping the image to fit in the range) but IMO that would be entirely unintuitive and unhelpful as well. After thinking about it a bit, it seems to me that simply cannot have a meaningful variant, because semantics (as reasonably interpreted) cannot answer the question "what should the result be for values for which the original function is undefined?" There are no elements in 's domain for which the function underflows or overflows.
That's only the case on old chips. As I linked in the OP (), that happens in the instruction generation very-last-phase of LLVM on old chips, and on newer chips it knows to emit a different instruction instead of the branching code: The good news is that it looks like newer LLVM has gotten smarter here. It used to be that, because of how the intrinsic gets translated, it would emit obviously-redundant assembly on old chips in some code patterns, as you could see in Rust 1.16:
is supposed to find the largest so that . Since computers use wrapping arithmetic, the equation is better put as . The largest satisfying this equation in the case is (aka ). So if we consider a wrapping to be the inverse of , makes perfect sense (and is very efficient on modern CPUs, as others have pointed out). I would also advocate for to be as a method which always has this behaviour. [Edit: it already behaves that way]
Note that's already how works . It's just that it wraps to in release right now -- this issue doesn't propose removing the panic in debug behaviour, just to figure out what the best value for release would be.


Question: /// /// # Panics /// <del> /// When the number is zero, or if the base is not at least 2; /// it panics in debug mode and the return value is 0 in release mode. </del> <ins> /// This function will panic if `self` is zero, or if `base` is less then 2. </ins> /// /// # Examples ///

Since, from the notes, it seems like the libs-api meeting today said "how about we panic instead of wrap", I'll try to answer my own question from above: I would propose the following rule: Conceptually, the result is first calculated in true ℤ (aka to infinite precision). Then for the non-prefixed versions If that result is undefined (, , etc), then it panics (regardless of compilation mode) If that result is defined and fits in the result type, it's returned. If that result is defined but not in-range for the result type, it panics if overflow checking is enabled, and wraps (mod 2<supN</supfor uN) if overflow checking is disabled. I think that's consistent with all the current precedent. ( also is good reading about the distinction I'm drawing here.)
I would redefine that to include cases where the result is defined but you can't wrap that to the result type, e.g. or . that would cover and
I agree, but was considering that implied by "in ℤ", as that set includes neither −∞ nor ⅈ. (Like how is , not a complex number.)
I'm not necessarily against panicking in that case. I just pointed out how it's a bit inconsistent with the other operations we have on integers. (Whether it makes sense for the other operations to have this difference in behavior between debug and release mode is an interesting discussion too, but I'm afraid that ship has sailed.) The reason we don't always panic on overflow for and etc. is performance. It's simply too costly to do. (We always panic on division by zero because that's both mathematically undefined (even modulo 2<supBITS</sup) and because on some platforms, the native division instruction will signal/abort/trap the program when the right hand side is zero.) We applied the same reasoning to things like and , although one might reasonably argue that for those it might be fine to always panic, since these are not as common as and . (You could then still use if you really want to make sure there's no check, if you're sure it's unnecessary.) That seems reasonable. It'd be nice if it'd still be easy to get the efficient calculation through some usage of or though.


Question: /// /// # Panics /// <del> /// When the number is zero, or if the base is not at least 2; /// it panics in debug mode and the return value is 0 in release mode. </del> <ins> /// This function will panic if `self` is zero, or if `base` is less then 2. </ins> /// /// # Examples ///

It looks like llvm isn't smart enough today to turn into simply a count-leading-zeros and a subtract instruction. :(
We discussed this again in the libs-api meeting, and we concluded pretty much the same as rule, meaning that these functions should panic on zero in all compilation modes, since there's not a modulo-2<supN</sup-correct result.


Question: <ins> // Issue #3878 // Issue Name: Unused move causes a crash // Abstract: zero-fill to block after drop fn main() { let y = ~1; move y; } </ins>  No newline at end of file

cc
cc
This was caused in the TOML refactor in Cargo, the fallback support to support malformed is likely broken.
Fixes are sent to Cargo, I'll send PRs to rust-lang/rust when they're merged
Submodules landed!


Question: unsafe { foo(); //~ ERROR: this function takes at least 2 parameters but 0 parameters were supplied //~^ NOTE the following parameter types were expected <ins> //~| NOTE expected at least 2 parameters </ins> foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied //~^ NOTE the following parameter types were expected <ins> //~| NOTE expected at least 2 parameters </ins> let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~^ ERROR: mismatched types

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: fn inner() { let _ = foo!(third); } <ins> #[allow(semicolon_in_expressions_from_macros)] async { let _ = foo!(fourth); }; </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. --I don't have a minimal example yet, but here's . Sample: The ICE happens on the and macros, which are both from the crate. <!-- 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. --This began with commit . <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
FYI, I think that link is only accessible to Googlers: !
Sorry, .
Minimized: Caused by
When we run on the AST, we create a definition for the desugared closure body inside an : As a result, the entry for our macro call will have the of the desugared closure. However, this desugared closure does not actually exist in the AST (it is created during lowering), so we will never check for lints with its when we emit buffered early lints.
Nightly has been broken for 3 days, if there's disagreement on how to fix the issue, can we revert while the fix is being worked on?
This will be fixed by PR
I'm still hitting this bug with the latest nightly.


Question: <ins> // check-pass // edition:2021 #![feature(async_fn_in_trait)] #![allow(incomplete_features)] use std::future::Future; async fn yield_now() {} trait AsyncIterator { type Item; async fn next(&mut self) -> Option<Self::Item>; } struct YieldingRange { counter: u32, stop: u32, } impl AsyncIterator for YieldingRange { type Item = u32; async fn next(&mut self) -> Option<Self::Item> { if self.counter == self.stop { None } else { let c = self.counter; self.counter += 1; yield_now().await; Some(c) } } } async fn async_main() { let mut x = YieldingRange { counter: 0, stop: 10 }; while let Some(v) = x.next().await { println!("Hi: {v}"); } } fn main() { let _ = async_main(); } </ins>

Example: yields <details<summaryBacktrace</summary</details
cc and
This has to do with late-bound regions and RPITITs. I have a fix, but it's probably not right nor is it cleaned up much. I'll put it up for scrutiny soon though.
Actually nvm, it was a silly little resolver bug.
label +I-ICE +C-bug


Question: <ins> // check-pass // edition:2021 #![feature(async_fn_in_trait)] #![allow(incomplete_features)] use std::future::Future; async fn yield_now() {} trait AsyncIterator { type Item; async fn next(&mut self) -> Option<Self::Item>; } struct YieldingRange { counter: u32, stop: u32, } impl AsyncIterator for YieldingRange { type Item = u32; async fn next(&mut self) -> Option<Self::Item> { if self.counter == self.stop { None } else { let c = self.counter; self.counter += 1; yield_now().await; Some(c) } } } async fn async_main() { let mut x = YieldingRange { counter: 0, stop: 10 }; while let Some(v) = x.next().await { println!("Hi: {v}"); } } fn main() { let _ = async_main(); } </ins>

I'm seeing an internal compiler error on the following input (found by ):
Report from : regressed nightly: nightly-2020-02-07
It looks like caused the regression. (The error happens at but not at .) cc
The specific commit where the error starts happening is .
triage: P-high. Removing nomination. Added regression stable-to-nightly tag.
Fixed by


Question: fn add_object(&mut self, path: &Path); fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); <ins> fn no_position_independent_executable(&mut self); </ins> fn partial_relro(&mut self); fn full_relro(&mut self); fn optimize(&mut self);

I'm having trouble linking a Rust program to a non-position-independent C library. When I manually remove the flag from the ld step that rustc runs, everything works correctly. I think that should remove the flag for me, but it doesn't. Here's what I think is going on: When I run It runs ld with the flag: But when I read the rustc code , it seems like the intention is that should only be passed to ld when . That is, if we're not compiling a position independent executable, then we should not pass the position independent executable flag to ld. I think what may be happening here is that somehow the defaults from are overriding the command line options I'm setting. This happens with stable and also the nightly I tried:
and are two distinct things. is also unrelated to the option. Interestingly, I do not remember us having an option to disable PIE; we should have one.
I did a bit of reading and here's what I figured out, please correct me if any of this is wrong. Linkers are new to me! Rust builds position independent executables by default on platforms that support it. These platforms have a relocation model of pic in their target config. The is what sets that linker option, except if it's disallowed by . The correct solution to this is to add a codegen flag, or something like that. Does this sound right?
Hi, I am having the same issue. I am trying to link against non-position-independent C library, build process ends without error but results returned by Rust bindings are different (and incorrect) than those returned from clean C implementation. In order to overcome that issue currently I am setting RUSTFLAGS="-C relocation-model=dynamic-no-pic -C linker=./linker" where linker is bash script that wraps cc and filter -pie flags:
I'm also having this problem. I assumed that passing when doing a build would suppress on the linker command line. (cc:
I'm still seeing this issue. Not sure if it's a regression or I'm doing something wrong. I have a "hello world" program in , and when I run , the resulting call to includes . I'm using nightly rust on Ubuntu: .
So, the problem here isn't with rust, but with the linker.


Question: fn add_object(&mut self, path: &Path); fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); <ins> fn no_position_independent_executable(&mut self); </ins> fn partial_relro(&mut self); fn full_relro(&mut self); fn optimize(&mut self);

In Ubuntu 15.10 and later the default GCC toolchain installed has been compiled with which causes and to be passed to during code generation and to during linking. Now, the linking part is what is important here as rust on most platforms uses as the linker for most targets. So, though no PIC or PIE code may have been generated by , the linker will still try to link as with PIE in mind, breaking when trying to compile with and the like. To work around this will need to see that the linker has been compiled with PIE as the default and pass to the linker if using GCC or something similar for other linkers. Code to do this can be seen in for Tarpaulin though it is only meant for Linux in that state and can be improved greatly if in tree. EDIT: Don't know why Github isn't linking cross-project PRs correctly right now.
Can this issue be resolved by always passing , except when compiling with ?
Sadly, no. In testing I have seen that any build of GCC that was not built with rejects the option and fails to run. This is why in the PR that I linked the linker was queried to see if it was compiled with before tacking on .
So it's came out from the discussion on an issue related to this in tarpaulin that passing -no-pie before -shared (and maybe then -static if it exists for static linkages as well) resolves the issue. I'm going to test this tarpaulin side and I can report back but I feel it would be best if this could be solved rustc side as it can affect any user in a similar situation.


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

In the 2017-12-14 Nightly I've seen a significant (almost 20%) compilation-time increase when I use on my code. And the successive day (2017-12-15) the compilation got a bit slower still and the run-time of the binary also got about 8% slower. The successive days the situation kept going slightly worse. Extracting parts of my code to show compiler/code performance is not easy, so I've composed this benchmark function (that solves an Euler problem. If this code isn't enough I will write other similar benchmarks): <details<summarySource code</summary</detailsCompiled with: host: x86_64-pc-windows-gnu Runtime: 2017-12-13: 0.30 seconds 2017-12-20: 0.53 seconds Asm from the the 2017-12-13 compiler: Asm from the the 2017-12-20 compiler:
Could someone try to reproduce and bisect this?
cc I think
We shouldn't have such big asm differences between successive nightlies, and I don't see anything suspicious in the middle, so it would be good to try and nail down the commit that made the difference.
I see a regression with this code (note: this is distinct from ). the bad code accesses the stack pointer (%rsp) You have a fast network connection and know how to use . Could you please do so? You should grep for to tell if the code is bad - the bad code includes the following line:
I bisected original example, just testing the speed of the executable created by a stage 1 and came upon (PR ) as the culprit: the runtime on my machine is around 0.3 seconds before that commit and around 0.7 seconds after. latest example also has a clear difference. The code before that commit (just disassembling the ): And after:
That's unfortunate. cc
cc
Thanks We're looking into it
just testing the speed of the executable I am not sure if they share the same cause, first a significant compiler performance decrease using --emit=metadata , then the successive Nightly the decrease of the produced binary performance.
They should not. However, quite a few big commits landed in the Dec 14 nightly.


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

If you could provide an example that exhibits the slowdown with , that would allow us to fix it (is the Dec 13 nightly faster than the Dec 14 nightly which has the same speed, but worse runtime performance, than the Dec 15 nightly?)
The last nightly (2017-12-21) has fixed all three problems. Despite some attempts I failed finding a small amount of code that shows a significant compilation slowdown from 2017-12-14 to 2017-12-20, perhaps it's a more diffuse problem that emerges from compiling my whole big amount of code. I am sorry. I don't fully understand your question, but I try to answer creating a table with some data for some of the last Nightlies: Rustc version --emit=metadata Opt build Binary size Run-time 1.24.0-nightly 2017-12-11 4.32 49.78 12.93 1.24.0-nightly 2017-12-12 4.31 48.50 12.84 1.24.0-nightly 2017-12-13 5.15 50.69 12.86 1.24.0-nightly 2017-12-15 5.33 52.98 14.04 1.24.0-nightly 2017-12-17 5.44 53.31 14.03 1.24.0-nightly 2017-12-20 5.47 54.49 14.14 1.24.0-nightly 2017-12-21 4.28 48.82 12.96 The --emit=metadata is a check time. The Opt build is the compilation time for a well optimized build. The binary size is stripped and in bytes. The times are all in seconds.
EDIT: told me about , so the range is .... EDIT2: at a quick glance, none of those changes should affect binary size or run time. How many times have you run each of these? How much do they vary?


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

They should be: rustc 1.24.0-nightly ( 2017-12-20) binary: rustc commit-hash: commit-date: 2017-12-20 host: x8664-pc-windows-gnu release: 1.24.0-nightly LLVM version: 4.0 rustc 1.24.0-nightly ( 2017-12-21) binary: rustc commit-hash: commit-date: 2017-12-21 host: x8664-pc-windows-gnu release: 1.24.0-nightly LLVM version: 4.0 Mixing up things seems quite easy here.
Ah, that's why I asked, so the range is .... Still not seeing anything clearly relevant, but maybe someone else from does?
The --emit=metadata times are computed as the minimum of four tries. Their variance is very small (on the order of +-0.05) so I think they are reliable. The binary run-time is the minimum of 5 runs, their variance is higher perhaps because they do some I/O, despite using a SSD, about +-0.12. The compilation is slow so there I've done only one time, so those values are the less reliable, but differences above 1.5 seconds should be reliable.
For the compilation time issue, maybe there was a bug in NLL that made it active without it being enabled. For the run-time issue, we need to actually investigate this.
As in, investigate the cause of the run-time fluctuations and how it unregressed?
This is my good old friend the torpedo. LLVM optimizes into this: This is basically equivalent to this pseudo-Rust code After the "non-constant-address" write is generated, LLVM is sunk - LLVM has no way of getting rid of the non constant address, and no way of optimizing accesses to the target with that non-constant address.
Upstream LLVM (that's the yet-to-be-released LLVM 6) has this patch, which avoids the SimplifyCfg sink problem by not running sinking before inlining I have confirmed that - e.g. this code is optimized correctly with the new Until then, I think representing small enums using a struct (rather than an array) should work around this problem.


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

With the 2017-12-22 Nightly all the problems are back: Rustc version --emit=metadata Opt build Binary size Run-time 1.24.0-nightly 2017-12-22 5.36 53.57 13.96
Coud you open a PR that turns small unions into LLVM structs (rather than arrays)? That should fix the problem.
The binaries generated by the last Nightly (1.24.0-nightly 2017-12-25) is further few percents slower (perhaps because of thinLTO?), the compilation times can't be compared now.
Is there more stable measure besides compile time / run time? They can be affected too easily by the environment especially when the run time is expected to take less than 1 second. The generated assembly size seems to be a good measure.
Please re-test next nightly and reopen if not fixed.
The run-time of the binary is now OK. The compilation time with --emit=metadata is still quite large.
Can you open a separate one for compilation times? Seems to be a separate issue.
, I've tried here:


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

I was looking at the generated asm for to see what happens to the array, and was surprised to see a large function with 5(!) call sites for . The generated code doesn't seem to vary with the number of elements in the array. That got me to compare with the functionally equivalent code: which doesn't yield the same assembly at all. The first difference being that the latter doesn't even store the array (only the strs) while the former does. That got me even further in comparing with equivalent loops, up to the extreme (and stupid): vs. The latter generates the simplest code possible: The former not so much:
Documenting my thinking in the hopes that it will be useful, or at least that someone will correct me via Campbell's Law. We know that the ASM outputs are different, so let's go back a few steps until we can find where in the toolchain we want to add our improvement. I compiled this on 1.19 with , but the important thing to note is that while iterany is quite bloated, it looks like the for loop has already been optimized: So is just as trivial in LLVM bytecode as it is in assembler - whatever optimizations we needed to do have already happened. We need to go back farther. . Notice that the tables have turned! is more concise than , so the code we need to add should change the MIR output. Note that . So the problem here seems to be that we aren't inlining before we generate LLVM bytecode. But that answer doesn't satisfy me either, because neither the nor the has any calls to , and in fact . So... one of these things is happening: 're failing to inline , and we haven't noticed because LLVM's been inlining this code for us. LLVM doesn't have as much knowledge as we do, so it can't do as good a job as we theoretically could. 've been looking at unoptimized MIR this whole time. This hypothesis seems to be borne out by the fact that when I rerun rustc without optimizations, I get exactly the same MIR output. But , and ? It's possible that both of these hypotheses are correct; maybe this is unoptimized MIR, because the MIR optimizations are doing absolutely nothing to this file!


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

I'm still cloning rustc, but once I do I'll comment out the MIR optimizations and see where that gets us.
Well, I can oblige that in one aspect :) You put far too much hope into MIR optimizations. They do very little right now—inlining, for example, isn't even enabled by default (only with ). Even in the future, when all the MIR optimizations we've ever wanted are implemented, they will only cover a small subset of what LLVM does (there's no point in duplicating all the work that went into LLVM, and that would be impractical anyway). This code looks sufficiently messy that I don't expect MIR optimizations to ever fully optimize it away. For example, that would probably require loop unrolling, which hasn't ever been proposed AFAIK (and if it was, I'd be skeptical of it). In any case, the more interesting question is why LLVM can't optimize the iterator version as well as the alternative. Whatever goes awry in optimizing this, it happens in one of LLVM's many passes.
The LLVM IR you posted is very weird. It has multiple branches on constants, and presumably dead code consequently. There's also several branches on values?!? These should all have been cleaned up. After running it through again, I get this IR (names are all messed up cause I did it on , which insists on applying C++ name demangling): <details</detailsThat's... less code, but still very stupid. Why are the adjacent loads and stores not folded away?! A third pass (just at this point) gets rid of them, constant folds the rest, and winds up with . Looks like a nasty phase ordering issue. But what about this IR confuses LLVM so much?
Neat discovery. Should we move this discussion to LLVM's bug tracker and close this task, then?
Not necessarily, no. In the past people have tweaked the definitions of iterator methods to help the optimizer. rustc might also be able to help by changing the pass pipeline or by generating better/different IR in the first place.
This did optimize out in LLVM 3.9, and was broken by LLVM 4.0.


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

In more detail, LLVM 3.9 generates the following small code for ( metadata stripped - it doesn't matter, with this function substituted in both 3.9 and 4.0 manage to optimize everything out): While LLVM 4.0 manages to screw up and generate this monstrosity: I think the somehow prevents SROA.
Going closer to the root: LLVM 3.9 optimizes the closure in to this: While LLVM 4.0 for some reason generates this:
caused by
The initial nonequivalence in the filing of the bug report is due to the slice iterator's explicit manual unrolling by 4 in its implementation of any. That might seem bad but as soon as llvm learns to loop optimize a loop with two exits (either the element was found or the iterator reached the end), the explicit unrolling can be removed.
is the PR that fixed this intended to be a permanent solution, or is it just a workaround? IOW, should we open a new bug to track reevaluating this fix when LLVM is resolved?
Hmmm, mentioned this bug, but you're right, this is older so me "fixing it" is probably more coincidental than anything else.
That LLVM bug is now tracked at and appears to have had no motion on it in the past 5 years. Assembly in the initial comparison cases remains identical per No other changes, as far as I can tell.
This was nominally resolved on our end, but was left open in the possibility that the LLVM issue was going to be resolved, so as to remove the "temporary" workaround. However, if we wish to track LLVM-side bugs that are not currently an impact on us, but may allow upgrades later, then I believe we may wish to consider tracking them in another form than an issue on the GH tracker, as they are "not an issue", so to speak. Alternatively, if we want to track them on this tracker, we may wish to track them in a more organized fashion (e.g. a metabug). I am going to close this issue. Do feel free to reopen this if it regresses again, or it becomes otherwise currently actionable, or if there is a particular reason we must have an open issue on our end to track this LLVM issue for potential improvements as opposed to any of the other currently-open LLVM issues we could be potentially waiting on in order to make an improvement.


Question: discr, variants }, <del> // FIXME(eddyb): using `FieldPlacement::Arbitrary` here results // in lost optimizations, specifically around allocations, see // `test/codegen/{alloc-optimisation,vec-optimizes-away}.rs`. fields: FieldPlacement::Union(1), </del> <ins> fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], memory_index: vec![0] }, </ins> abi, align, size

The LLVM issue has long since been fixed, so it's possible that the workaround may be removed.
I think any workarounds here are long gone, since moved to internal iteration way back in


Question: fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> { let pcstr = cstr(p)?; <del> // entry is expected to be a directory, open as such let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; </del> <ins> // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &pcstr) { Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => { // not a directory - don't traverse further return match parent_fd { // unlink... Some(parent_fd) => { cvt(unsafe { unlinkat(parent_fd, pcstr.as_ptr(), 0) }).map(drop) } // ...unless this was supposed to be the deletion root directory None => Err(err), }; } result => result?, }; </ins> // open the directory passing ownership of the fd let (dir, fd) = fdreaddir(fd)?;

The fix for CVE-2022- (, ) appears to have introduced a regression that can cause file system corruption on some UNIX systems. The new code will attempt to use in any case where it does not know what type of file a directory entry represents. Some systems do not provide that information along with the entry names returned while reading a directory, and even on systems which provide a type hint, that hint may be . In cases where we do not know the type of the entry, the code tries first to unlink it as if it were something other than a directory: The code assumes that on a directory will fail with , or on Linux with the non-standard , but this is not always the case. POSIX does suggests as a failure in some, but not all cases: (See in The Open Group Base Specifications Issue 7, 2018 edition) Implementations are not required to prohibit on directories, and indeed UFS file systems on present day illumos and presumably at least some Solaris systems allow of a directory if the user has sufficient privileges. Other platforms may as well. Unfortunately unlinking a directory on UFS causes a sort of file system corruption that requires an unmount and a trip through to correct. Any code that uses on UFS has since started causing that kind of corruption, which took a bit of work to track down. I think the fix is probably relatively simple, and has the benefit of not touching the code path where we believe we know what sort of entry we are removing: In short, we should try to first, rather than first, as that always fails in a safe way that we can detect. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
cc (as you're the one how wrote the new code)
Thanks for the ping claim
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-critical
Was this issue reported upstream? Filesystems corrupting themselves seem like a poor failure mode in any case, and in some ways is a violation of the sandboxing that the kernel ought to provide for the user-space applications.


Question: fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> { let pcstr = cstr(p)?; <del> // entry is expected to be a directory, open as such let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; </del> <ins> // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &pcstr) { Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => { // not a directory - don't traverse further return match parent_fd { // unlink... Some(parent_fd) => { cvt(unsafe { unlinkat(parent_fd, pcstr.as_ptr(), 0) }).map(drop) } // ...unless this was supposed to be the deletion root directory None => Err(err), }; } result => result?, }; </ins> // open the directory passing ownership of the fd let (dir, fd) = fdreaddir(fd)?;

It was reported upstream, and we're working on a fix -- but that fix will obviously only be in new versions of the operating system. To expand further on the corruption: the file system becomes inconsistent and requires repair, and the damage such as it is can only be caused by privileged users; i.e., by root or a user with root equivalent privileges. I am not yet aware of a way that it would cause actual data loss, just an interruption to service, but anything is possible. Allowing the linking and unlinking of directories is a regrettable, but seemingly intentional feature we are saddled with through our UNIX heritage. I'm working to disable and eventually remove the feature in the OS -- although we strongly value backwards compatibility, in this case I can't really see a legitimate use case or find a consumer that would be broken by doing so, but we won't know for sure until we try. While this specific case is unfortunate, and we can and will work on our end to try to mitigate the impact, the fact remains that POSIX explicitly documents and allows for implementations where on a directory does not return . For the code to be completely correct on all POSIX systems, it cannot make that assumption. In addition, working around the issue in new versions of the OS doesn't fix existing deployments out there already. Enterprise customers are often reluctant to promptly update their operating system, even though they may update software built and deployed on it -- software that may be written in Rust. I myself hit this issue by upgrading only the Rust compiler to a new stable version, and trying to build and use Rust-based software we have to build UFS ramdisks on illumos. We aim to fix the OS for the future, but the critical regression in Rust needs to be fixed as well for the present. We appreciate everybody who has looked at this so far -- please let me know how I can help expedite the process!
Thanks again for the report. The linked PR should fix the issue. Apparently only and guarantee that trying to a directory fails. , and allow it, at least in theory. After looking around a bit I found that it is even explicitly documented for and . So it is not a bug but a feature there... After changing that in you might want to adapt the man page as well.


Question: fn remove_dir_all_recursive(parent_fd: Option<RawFd>, p: &Path) -> io::Result<()> { let pcstr = cstr(p)?; <del> // entry is expected to be a directory, open as such let fd = openat_nofollow_dironly(parent_fd, &pcstr)?; </del> <ins> // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, &pcstr) { Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => { // not a directory - don't traverse further return match parent_fd { // unlink... Some(parent_fd) => { cvt(unsafe { unlinkat(parent_fd, pcstr.as_ptr(), 0) }).map(drop) } // ...unless this was supposed to be the deletion root directory None => Err(err), }; } result => result?, }; </ins> // open the directory passing ownership of the fd let (dir, fd) = fdreaddir(fd)?;

We can try to avoid this case by default, as is switching to try unknown as a directory first, but you should note that this is still going to be racy. If there's an unprivileged adversary like the CVE supposes, then they can try to race changes between "try (and fail) as a directory" to "unlink as a file", to make it unlink a directory after all and induce corruption. IOW, it sounds like it's not safe for a privileged process to unlink paths at all if they may be changed by lesser privileges .
It should not really cause corruption according to the , just orphaned directories: Of course this can lead to resource exhaustion since the disk space and the inodes cannot be reclaimed until the next .
And that user is only root or otherwise root-like? i.e. it's not just talking about regular access privileges?
For Illumos the process must have root privileges or needs to be in the process privilege set (). Solaris has at some point abolished this privilege and apparently does not allow unlinking directories anymore ().


Question: <ins> - // MIR for `call` before Inline + // MIR for `call` after Inline fn call(_1: &T) -> i32 { debug s => _1; let mut _0: i32; let mut _2: &T; +     scope 1 (inlined <T as Foo>::bar) { +         debug self => _2; +     } bb0: { StorageLive(_2); _2 = &(*_1); -         _0 = <T as Foo>::bar(move _2) -> [return: bb1, unwind unreachable]; -     } - -     bb1: { +         _0 = const 0_i32; StorageDead(_2); return; } } </ins>

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: The three printed TypeIds should be identical, as with the behavior in Rust <=1.70 Instead, this happened: switch between rust versions. I could not find reference in the that could explain such behavioral changes.
if my bisection is correct, this surfaced in commit cc (makes sense?)
I do not believe that is the correct PR to point at. Bisecting anything related to MIR opts can be tricky because you need to stabilize the MIR opt pipeline against changes like in that PR which don't actually implement any new behavior, they just change the meaning of MIR opt levels. Try bisecting with ? The above PR just changes the opt level 3 inliner behavior to be the default.
Reproduces since before with
This has to do with the fact that this impl: ... applies even when . Therefore in a polymorphic function like , we're eagerly inlining from that impl even though during monomorphization we'd prefer the built-in candidate instead. This seems problematic.
WG-prioritization assigning priority (). label -I-prioritize +P-high


Question: cx: X, input: X::Input, <del> result: X::Result, </del> <ins> origin_result: X::Result, </ins> dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, nested_goals: NestedGoals<X>, ) { <del> let result = cx.mk_tracked(result, dep_node); </del> <ins> let result = cx.mk_tracked(origin_result, dep_node); </ins> let entry = self.map.entry(input).or_default(); if encountered_overflow { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(additional_depth, with_overflow); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </ins> } else { let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </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. --After adding to , I get the ICE. The resulting : The full project: <!-- 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. . --
Looks like another label: +T-types +WG-trait-system-refactor +regression-from-stable-to-nightly
Stable passes, beta passes. Nightly passes with either or Discovered with It does sporadically succeed, thus needing to clean and rerun the build to make sure. Either something is up with or it only barely exercises these conditions in the parallel frontend, even after cleaning and running the build 100 times. Meanwhile, fails something like ~50% of the time on my machine.
stable passes obviously, as -Zthreads this is a unstable nightly-only flag?
Hm, not actually obvious given that works, though I suppose that does mean it isn't a regression per se. :^)
oh I thought you knew by now that this is the forbidden env flag that should only ever be used for bootstrapping and nothing else and we should not even tell users about it. If you set the flag, your "stable" will also eat nightly-only features, but why would that make a "to-stable" regression if you explicitly tell the compiler "please act like you are NOT a stable release"? I don't think it make sense to backport fixes for untable nightly features into stable lol
who mentioned backports?
The label is used to gather regressions between release channels, which are then discussed whether they are backport-worthy or not. Is that not how the label is used?
I don't really think regression-from-stable-to-nightly nor regression-from-stable-to-stable are used for that at all? Probably regression-from-stable-to-beta is?


Question: cx: X, input: X::Input, <del> result: X::Result, </del> <ins> origin_result: X::Result, </ins> dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, nested_goals: NestedGoals<X>, ) { <del> let result = cx.mk_tracked(result, dep_node); </del> <ins> let result = cx.mk_tracked(origin_result, dep_node); </ins> let entry = self.map.entry(input).or_default(); if encountered_overflow { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(additional_depth, with_overflow); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </ins> } else { let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </ins> } }

Pretty much what the title says, I've narrowed it down to and today's nightly with the following: I've attached some backtraces.
probably duplicate of but made more prevalent by next solver
Is it possible to provide a link to or a snippet of a reproducer? I know it probably happens to various crates, but it still would be nice to have something that reproduces.
See for an attached repro.
The repro case is basically the same as , but with other crates mentioned in the ICE logs from the issue comment.


Question: cx: X, input: X::Input, <del> result: X::Result, </del> <ins> origin_result: X::Result, </ins> dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, nested_goals: NestedGoals<X>, ) { <del> let result = cx.mk_tracked(result, dep_node); </del> <ins> let result = cx.mk_tracked(origin_result, dep_node); </ins> let entry = self.map.entry(input).or_default(); if encountered_overflow { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(additional_depth, with_overflow); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </ins> } else { let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); <del> assert!(prev.is_none()); </del> <ins> if let Some(prev) = &prev { assert!(cx.evaluation_is_concurrent()); assert_eq!(cx.get_tracked(&prev.result), origin_result); } </ins> } }

Compile with latest Nightly got ICE like below: when compiling in code OS: x86_64-apple-darwin
cc
Wyvern, could you provide some sort of reproducer? A link to some commit in some repository or better yet a smaller stripped down version of it?
Can you provide an example which triggers this behavior?
I'm not sure which commit/PR of lead to this crash, sometimes it compiled successfully, sometimes it not. Add this info to original post, hope to help investigation.
are you running with greater than 1? The cache is broken when used with more than 1 thread (which we should fix)
Sorry, I wasn't clear. I meant a link to your project (the project you are trying to compile) if publicly accessible / not proprietary.
I can hit plenty of these while fuzzing with -Zthreads so yeah its probably that.
Yeah, I think was the culprit. Comment out this option crashes disappears.
the easiest fix to rustc is to just disable this assert when we're using more than 1 thread. I've only it for debugging purposes to detect cases where we unnecessarily recompute cache entries
just hit this while trying to bootstrap with Zthreads :sweat_smile:
cc as this also showed up in your ci test run ^^
When I just disable this assert, all relevant UI tests passed with no other bugs or ICE
samle code that triggers this in around 5 of 6 cases with -Zthreads=16


Question: <ins> error[E0658]: generic associated types are unstable --> $DIR/gat-dont-ice-on-absent-feature.rs:7:5 | LL |     type Item<'b> = &'b Foo; |     ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/44265 = help: add #![feature(generic_associated_types)] to the crate attributes to enable error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. </ins>

The following minimal example causes an internal compiler error. Error in question: rustc version: This error was encountered on stable, but I can confirm that it also occurs on the latest nightly ().
Hasn't the feature gate issue been fixed? :|
I've removed the nomination and this to the tracking issue for GATs . The current impl is highly incomplete and ICEs are, sadly, expected. Also, I verified that a feature gate is indeed required.
triage: P-medium
I don't know if I get you wrong, but the example above ICEs on stable, beta and nightly without feature gate
oops, looks like I accidentally left the feature gate in there when I tried it out, but it produces the same ICE when it is omitted as well.
No, niko edited your question. ping I think you got something wrong there. Can you please clarify that?
Oh, I guess I was indeed incorreect. I tried it on play but didn't notice that, after the "correct" error, it goes on to print an ICE.
What about adding the I-nominated tag again?
I'm not sure why we would nominate this for discussion. Yes, it is an ICE (and an ICE that occurs without the user adding a feature gate), but the message pretty clearly states that you're using an unstable feature. It would be great to fix it so that it issues the error diagnostic without ICEing, but I wouldn't re-prioritize that work above P-medium.
assigning to self since its a clear annoyance
triage: P-medium. (dupe of )
(the remaining bug, when the feature gate is enabled, is tracked in issue )


Question: pub fn normal_test_fn() { #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] //~^ WARNING this lint expectation is unfulfilled <ins> //~| WARNING this lint expectation is unfulfilled </ins> //~| NOTE this expectation will create a diagnostic with the default lint level <ins> //~| NOTE this expectation will create a diagnostic with the default lint level //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` </ins> let mut v = vec![1, 1, 2, 3, 5]; v.sort(); // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] //~^ WARNING this lint expectation is unfulfilled <ins> //~| WARNING this lint expectation is unfulfilled //~| NOTE the expectation for `unused` should be fulfilled </ins> //~| NOTE the expectation for `unused` should be fulfilled //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message <ins> //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` </ins> let value = "I'm unused"; }

I tried this code: I expected to catch lint and suppress it, as it should. Instead, compiler issues a diagnostic both about unused value and unfulfilled lint expectation: It does work as expected though if is applied to function. I used the latest stable (Rust 1.81), but it is reproducible both on latest beta (2024-09-04 ) and latest nightly (2024-09-05 ). labels: +F-lintreasons, +A-diagnostics <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
This issue is not limited to just . Others attrs like or don't work either. For instance, the following variant of the reproducer with replaced with emits the warning even though it shouldn't: Playground: This broken behaviour goes as far back as at least 2021 (couldn't build and test earlier rustc) We emit the lint on the HIR node corresponding to . However, the or levels, which are supposed to override the default level of the lint, are associated with or bound to the node underlying the as shown in the figure below: The end result is that the lint's level is never knocked down to or since when searching for levels we start from the node on which the lint is triggered and go up the chain of parents. So in this case we look for the level on and then on the and so on. We never look for it on the where the levels actually exist. As it happens in the lowered HIR does have the / attrs for both the node and its child node. However when adding the levels in the we do not add anything for the node as shown here (note the comment): If were to add the level for as well the issue will go away. However, if we do that we will still have one problem in the case of which is that we will end up with two expectations and the one on the will not be fullfilled and hence we will still see a warning about unfulfilled expectation. To prevent that I think we should take the following approach: when an attr like or etc.


Question: pub fn normal_test_fn() { #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] //~^ WARNING this lint expectation is unfulfilled <ins> //~| WARNING this lint expectation is unfulfilled </ins> //~| NOTE this expectation will create a diagnostic with the default lint level <ins> //~| NOTE this expectation will create a diagnostic with the default lint level //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` </ins> let mut v = vec![1, 1, 2, 3, 5]; v.sort(); // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] //~^ WARNING this lint expectation is unfulfilled <ins> //~| WARNING this lint expectation is unfulfilled //~| NOTE the expectation for `unused` should be fulfilled </ins> //~| NOTE the expectation for `unused` should be fulfilled //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message <ins> //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message //~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` </ins> let value = "I'm unused"; }

are present for more than one HIR node in the and if one node is the (direct or indirect) parent of the other node, then add the level only_ for parent node. This will take care of any lints on the child (since we always walk up the HIR hierachy as mentioned earlier) as well as the parent and it will not cause any warnings about missed expectations. I am new to this area so if someone can review this idea or suggest alternatives that will be great. since you seemed to have worked in this area recently, can you please weigh in?
Your investigation is accurate, and the fix is simple: visit the statement node when building lint levels. Do you mind making such a pr ? I don't think we need any special adjustment for cases, duplicated attributes are already taken into account, but a test won't hurt.
Thanks . Yes, I'll put together a PR. My only concern is if all we do is add the level at , although it will work perfectly for , etc., in the case of we will end up with an unfulfilled expectation on the node which will appear to the user as a warning. But anyway let me have a go and see what happens.
Opened draft PR that adds the lint on . It does suffer from the extra warning problem.


Question: } if (*task).unwinder.unwinding { <del> rtabort!("unwinding again"); </del> <ins> // If a task fails while it's already unwinding then we // have limited options. Currently our preference is to // just abort. In the future we may consider resuming // unwinding or otherwise exiting the task cleanly. rterrln!("task failed during unwinding (double-failure - total drag!)") rterrln!("rust must abort now. so sorry."); intrinsics::abort(); </ins> } }

Currently there are no landing pads generated for resource destructors so they are leaky when they fail. We don't have the same tricky situation that C++ has with throwing destructors but I haven't thought through how it should work yet. Edit: This issue has changed into what to do after a dtor fails during unwinding. The previous issue of dtor failure not working at all has been resolved.
There's a failing test in run-fail/unwind-resource-
And another in run-fail/unwind-resource-
The language reference is actually quite explicit about this: "A task may transition to the failing state at any time, due to an un-trapped signal or the evaluation of a fail expression. Once failing, a task unwinds its stack and transitions to the dead state. Unwinding the stack of a task is done by the task itself, on its own control stack. If a value with a destructor is freed during unwinding, the code for the destructor is run, also on the task's control stack. Running the destructor code causes a temporary transition to a running state, and allows the destructor code to cause any subsequent state transitions. The original task of unwinding and failing thereby may suspend temporarily, and may involve (recursive) unwinding of the stack of a failed destructor. Nonetheless, the outermost unwinding activity will continue until the stack is unwound and the task transitions to the dead state. There is no way to “recover” from task failure. Once a task has temporarily suspended its unwinding in the failing state, failure occurring from within this destructor results in hard failure. The unwinding procedure of hard failure frees resources but does not execute destructors. The original (soft) failure is still resumed at the point where it was temporarily suspended. "
Yeah. The hard/soft thing has never been implemented, as far as I know, but I think it's the best we can do: retain correctness of our memory model and try to retain correctness of user code, but not at the cost of infinite-recursion. If their dtor itself fails, just unwind that sub-failure w/o the opportunity for sub-sub-failures.
It would be good to revise the title of this bug to reflect what the task is.


Question: } if (*task).unwinder.unwinding { <del> rtabort!("unwinding again"); </del> <ins> // If a task fails while it's already unwinding then we // have limited options. Currently our preference is to // just abort. In the future we may consider resuming // unwinding or otherwise exiting the task cleanly. rterrln!("task failed during unwinding (double-failure - total drag!)") rterrln!("rust must abort now. so sorry."); intrinsics::abort(); </ins> } }

(From the comments thus far, it sounds like the task is to implement the hard/sort failure unwindin protocol; but it might also be useful to clean up the docs here.)
Not critical for 0.6; de-milestoning
confirmed again; current code that can crash is as follows: If my idea for an effect system goes through, we might make this sound again by simply requiring no failure in destructors, e.g. .
nominating for well-defined milestone
there is language about this in the manual already in the task section, so I think it's well defined already. just not implemented. feature completeness issue.
accepted for feature-complete milestone
Triage: the updated version of example still crashes:
0 backcompat
This not only applies to destructors failing while failing, but this appears to also apply to linked failure as well. A program may only contain one statement, but it may still leak due to linked failure. An example of this would be: The destructor for never runs in this program because the call to invokes scheduler business which will realize that it needs to fail due to linked failure. It seems odd to me that if a task only contains one source of failure then we can still leak. This specific use case may not entirely fall under this issue, but it seems fairly serious.
The scheduler does have logic for not failing from linked failure when a task is already failing. So if, for example, the sleeping destructor here were to happen during unwinding, I think it should be fine. But if it happens normally you could still get failure.
I've updated the title to reflect what we're currently talking about. My understanding is that it is just impossible to throw from a landing pad because it will potentially corrupt the unwinder and our three options are: abort - this is what C++ does resume unwinding without completing the landing pad - this is what Ada does and we haven't discussed this option abort the task without completing unwinding - this is "hard" failure we've talked about The "hard" failure is made more difficult by tasks that are not simply green threads. For example, we have use cases where we want to run in a 'task context', on the current thread, and then be told whether the task succeeded or failed, all on the same thread. There's no way in that scenario to just terminate the task cleanly.


Question: } if (*task).unwinder.unwinding { <del> rtabort!("unwinding again"); </del> <ins> // If a task fails while it's already unwinding then we // have limited options. Currently our preference is to // just abort. In the future we may consider resuming // unwinding or otherwise exiting the task cleanly. rterrln!("task failed during unwinding (double-failure - total drag!)") rterrln!("rust must abort now. so sorry."); intrinsics::abort(); </ins> } }

My current opinion is that, for 1.0 we should take the most conservative approach and abort. For future versions we should consider trying to do what Ada does and skip a single landing pad, but still proceed to catch the exception.
I agree with double-abort for 1.0. Thinking about the other two schemes in terms of how RWARCs (or whatever they're called these days) behave, aborting just a single task strikes me as risky in terms of unexpected behaviour befalling the user. If a double-failure occurs inside an access to a RWARC, it won't be automatically unlocked during unwinding, and other contending tasks will block forever. I think that resuming the unwinding and skipping the one landing pad still makes sense, though. If double-failure occurs in a user-provided destructor (or in the destructor of some buggy library), skipping the rest of the destructor can only "surprise" other code directly associated with the faulty destructor.
I agree too.


Question: // Verify that '>' is not both expected and found at the same time, as it used // to happen in #24780. For example, following should be an error: <del> // expected one of ..., `>`, ... found `>`. No longer exactly this, but keeping for posterity. </del> <ins> // expected one of ..., `>`, ... found `>`. </ins> <del> fn foo() -> Vec<usize>> { //~ ERROR unmatched angle bracket </del> <ins> fn foo() -> Vec<usize>> { //~ ERROR expected one of `!`, `+`, `::`, `;`, `where`, or `{`, found `>` </ins> Vec::new() }

Alternate title: "Rust is literally C++" As of nightly-2020-10-29, rustc fails to parse the following code. The previous nightly and all past stable releases since 1.0.0 are not affected. The relevant commit range is
Mentioning because "Tweak invalid  header and body parsing" sounds extremely relevant.
Assigning and removing as in the prioritization working group.
searched nightlies: from nightly-2020-10-27 to nightly-2020-10-29 regressed nightly: nightly-2020-10-29 searched commits: from to regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.0</summaryHost triple: x86_64-apple-darwin Reproduce with: </detailsYeah, seems likely that is the culprit.
Yep, this was me :-/ I'll have a PR up in the next hour.


Question: .emit(); } <del> if has_trait_upcasting_coercion && !self.tcx().features().trait_upcasting { feature_err( </del> <ins> if let Some((sub, sup)) = has_trait_upcasting_coercion && !self.tcx().features().trait_upcasting { // Renders better when we erase regions, since they're not really the point here. let (sub, sup) = self.tcx.erase_regions((sub, sup)); let mut err = feature_err( </ins> &self.tcx.sess.parse_sess, sym::trait_upcasting, self.cause.span, <del> "trait upcasting coercion is experimental", ) .emit(); </del> <ins> &format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"), ); err.note(&format!("required when coercing `{source}` into `{target}`")); err.emit(); </ins> } Ok(coercion)

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. --Given the following code: <!-- Please provide a link to -- The current output is: <!-- The following is not always necessary. --It should name the traits are attempted to be coerced, maybe tell me why that's not allowed (yet), etc. Right now it just highlights the entire line. The original example I had that made me run into this issue had an even longer expression there (multiple chained iterator methods) which just got all highlighted as one big block saying "somewhere here trait coercion is used and it's not allowed". Note that I understand why it's not allowed, I was just disappointed by the error message. I already talked to about this, and they also thought this output may be problematic. Even though the feature may be unstable, it's quite easy to arrive at a situation where you may get this error. <!-- If the problem is not self-explanatory, please provide a rationale for the change. --<!-- If dramatically different output is caused by small changes, consider also adding them here. 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. The output might also be different depending on the Edition. --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim