Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> // check-pass // ignore-emscripten no llvm_asm! support #![feature(llvm_asm)] pub fn boot(addr: Option<u32>) { unsafe { llvm_asm!("mov sp, $0"::"r" (addr)); } } fn main() {} </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> // edition:2018 use std::sync::{Arc, Mutex}; pub async fn f(_: ()) {} pub async fn run() { let x: Arc<Mutex<()>> = unimplemented!(); f(*x.lock().unwrap()).await; } </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> // aux-build: issue_67893.rs // edition:2018 // dont-check-compiler-stderr // FIXME(#71222): Add above flag because of the difference of stderrs on some env. extern crate issue_67893; fn g(_: impl Send) {} fn main() { g(issue_67893::run()) //~^ ERROR: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely } </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> #![feature(intrinsics)] extern "C" { pub static FOO: extern "rust-intrinsic" fn(); } fn main() { FOO() //~ ERROR: use of extern static is unsafe } </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-28575.rs:8:5 | LL |     FOO() |     ^^^ use of extern static | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior error: aborting due to previous error For more information about this error, try `rustc --explain E0133`. </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> pub static TEST_STR: &'static str = "Hello world"; </ins>


Question:
When learning async/await feature I was struggling with running multiple tasks simultaneously. Loop causes compiler to crash Github Action crash output: I expected to see this happen: Error message if something goes wrong. Instead, this happened: Compiler crashed Crash happens on macOS rustc 1.40 / Linux rustc 1.40 / Linux rustc 1.39 ( github actions ) :
If you could provide an example that ICEs in e.g. the playground that would be helpful towards fixing the issue. :)
Provided example is pretty small, but it is dependent on tokio and actix-web. I do not know how to create such an example in playground, I do know know how I can replace async tokio::sync::mpsc with standard library which does not have async alternative as far as i know. I have tried to simplify code but then crash disappear. Just putting everything into one file and crash is gone, code wont compile and reasonable errors show up.
Visiting from triage.. we decided that as the first step we should reduce this reproducer to a more self-contained one.
Can repro. Will try and min.
Reduced version so far is here:
This no longer ICEs on the latest nightly.
Let's see if we can shrink further so that we can add a test. ping cleanup
Hey Cleanup Crew ICE-breakers! This bug has been identified as a good "Cleanup ICE-breaking candidate". In case it's useful, here are some [instructions] for tackling these sorts of bugs. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev- cc
I’ve reduced it quite a bit. Down to dependencies on only. Appears to need 2 crates.

<ins> // aux-build: issue_24843.rs // check-pass extern crate issue_24843; static _TEST_STR_2: &'static str = &issue_24843::TEST_STR; fn main() {} </ins>


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

<del> Subproject commit 732825dcff6d1f115225305ce5e0c9c9d876a0ff </del> <ins> Subproject commit e8642c7a2900bed28003a98d4db8b62290ac802f </ins>


Question:
This code crashes in LLVM during codegen on stable, beta, and nightly: This originally happened in real-world code (a code base derived from ). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
We generally don't guarantee behavior with no_mangle, I think. I guess a segfault in llvm is unexpected though :)
I think the is a red herring, since the name of that function doesn't actually matter (ie. it can be or something completely harmless). I think it's just needed to make sure the function is codegen-ed.
I keep seeing this in my output when I play around with this on the playpen: that does not use , adding credence to 's point that it is probably a red herring.
triage: P-high. Leaving nominated in hopes that someone at triage meeting has a bright idea has to what's going on here (and what we might do about it).
Hm, bad_alloc implies OOM to me, but maybe that's not always the case.
Compiling with LLVM debug symbols + assertions, I get the same assertion failure for both: Tracing the callstack with gdb, the assertion is triggered on the call in this function: As the error suggests, this means that the downcast from to failed for . Printing out what type is (with some casting because gdb doesn't know what the return types are): That's strange -- it's reported as a function pointer, which is the same as what's reported for actual s, but we're still failing the downcast. Usually, dumping an should give you the contents of the function. For example: gives us But dumping gives this: So it appears to be pointing to a instruction? I'm not 100% sure -- I've ever seen a instruction being prefixed with a type, but I've taken it to be indicating the type of , the operand. I'll do a bit more digging. claim
After manually removing the LLVM build to force a complete rebuild with debug symbols, I was able to get a proper dump which makes far more sense: Note that this is not a bitcast instruction but a constant expr bitcast -- ie, one generated at compile time. As it turns out, in the event that a function exists with athe same name but a different type in a module, will return a compile time bitcast to that function: which is the overload called here So, later, when we attempt to use any functions that do a downcast to , we trigger the assertion failure because the downcast from constant expr bitcast to is not valid. We run into this in both your cases because when codegen attempts to insert a declaration for with signature , the program's already exists in the module with the signature , so the bitcast is returned instead of an . This issue can be reproduced without causing a crash by forcing a name collision with a function that's not (as we don't end up trying to cast the bitcast to a Function in this scenario): Compiling with we get this bitcode here: which I think exposes the problem more clearly: In an extern block which declares a function with the same name as some existing function within the module, we'll end up generating a call to the function in the module (potentially with an unsafe bitcast), instead of shadowing the module's function and generating a call to the external function (which, to me, appeared to be the intent of the example). You can see that this example shows that the in the original example isn't quite so much a red herring as it might seem -- in my example particularly, it's needed to ensure the name collision which demonstrates this behaviour. The examples without work because we induce a name collision on the unmangled function instead (not the user-defined one; the one which calls ). At this point, I'm not sure how to proceed. Should we error out here because of the name collision to avoid generating crazy function pointer bitcasts? Or should we do some kind of trickery to rename the shadowing symbol so that it correctly calls the extern function? Or is it as says -- is the current codegen into bitcast fine because we don't make any behaviour guarantees for symbols?

// listing. let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap()); <del> if cx.get_defined_value("main").is_some() { </del> <ins> if cx.get_declared_value("main").is_some() { </ins> // FIXME: We should be smart and show a better diagnostic here. cx.sess() <del> .struct_span_err(sp, "entry symbol `main` defined multiple times") </del> <ins> .struct_span_err(sp, "entry symbol `main` declared multiple times") </ins> .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") .emit(); cx.sess().abort_if_errors();


Question:
This code crashes in LLVM during codegen on stable, beta, and nightly: This originally happened in real-world code (a code base derived from ). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
We generally don't guarantee behavior with no_mangle, I think. I guess a segfault in llvm is unexpected though :)
I think the is a red herring, since the name of that function doesn't actually matter (ie. it can be or something completely harmless). I think it's just needed to make sure the function is codegen-ed.
I keep seeing this in my output when I play around with this on the playpen: that does not use , adding credence to 's point that it is probably a red herring.
triage: P-high. Leaving nominated in hopes that someone at triage meeting has a bright idea has to what's going on here (and what we might do about it).
Hm, bad_alloc implies OOM to me, but maybe that's not always the case.
Compiling with LLVM debug symbols + assertions, I get the same assertion failure for both: Tracing the callstack with gdb, the assertion is triggered on the call in this function: As the error suggests, this means that the downcast from to failed for . Printing out what type is (with some casting because gdb doesn't know what the return types are): That's strange -- it's reported as a function pointer, which is the same as what's reported for actual s, but we're still failing the downcast. Usually, dumping an should give you the contents of the function. For example: gives us But dumping gives this: So it appears to be pointing to a instruction? I'm not 100% sure -- I've ever seen a instruction being prefixed with a type, but I've taken it to be indicating the type of , the operand. I'll do a bit more digging. claim
After manually removing the LLVM build to force a complete rebuild with debug symbols, I was able to get a proper dump which makes far more sense: Note that this is not a bitcast instruction but a constant expr bitcast -- ie, one generated at compile time. As it turns out, in the event that a function exists with athe same name but a different type in a module, will return a compile time bitcast to that function: which is the overload called here So, later, when we attempt to use any functions that do a downcast to , we trigger the assertion failure because the downcast from constant expr bitcast to is not valid. We run into this in both your cases because when codegen attempts to insert a declaration for with signature , the program's already exists in the module with the signature , so the bitcast is returned instead of an . This issue can be reproduced without causing a crash by forcing a name collision with a function that's not (as we don't end up trying to cast the bitcast to a Function in this scenario): Compiling with we get this bitcode here: which I think exposes the problem more clearly: In an extern block which declares a function with the same name as some existing function within the module, we'll end up generating a call to the function in the module (potentially with an unsafe bitcast), instead of shadowing the module's function and generating a call to the external function (which, to me, appeared to be the intent of the example). You can see that this example shows that the in the original example isn't quite so much a red herring as it might seem -- in my example particularly, it's needed to ensure the name collision which demonstrates this behaviour. The examples without work because we induce a name collision on the unmangled function instead (not the user-defined one; the one which calls ). At this point, I'm not sure how to proceed. Should we error out here because of the name collision to avoid generating crazy function pointer bitcasts? Or should we do some kind of trickery to rename the shadowing symbol so that it correctly calls the extern function? Or is it as says -- is the current codegen into bitcast fine because we don't make any behaviour guarantees for symbols?

// build-fail // <del> // error-pattern: entry symbol `main` defined multiple times </del> <ins> // error-pattern: entry symbol `main` declared multiple times </ins> // FIXME https://github.com/rust-lang/rust/issues/59774 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*n" -> ""


Question:
This code crashes in LLVM during codegen on stable, beta, and nightly: This originally happened in real-world code (a code base derived from ). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
We generally don't guarantee behavior with no_mangle, I think. I guess a segfault in llvm is unexpected though :)
I think the is a red herring, since the name of that function doesn't actually matter (ie. it can be or something completely harmless). I think it's just needed to make sure the function is codegen-ed.
I keep seeing this in my output when I play around with this on the playpen: that does not use , adding credence to 's point that it is probably a red herring.
triage: P-high. Leaving nominated in hopes that someone at triage meeting has a bright idea has to what's going on here (and what we might do about it).
Hm, bad_alloc implies OOM to me, but maybe that's not always the case.
Compiling with LLVM debug symbols + assertions, I get the same assertion failure for both: Tracing the callstack with gdb, the assertion is triggered on the call in this function: As the error suggests, this means that the downcast from to failed for . Printing out what type is (with some casting because gdb doesn't know what the return types are): That's strange -- it's reported as a function pointer, which is the same as what's reported for actual s, but we're still failing the downcast. Usually, dumping an should give you the contents of the function. For example: gives us But dumping gives this: So it appears to be pointing to a instruction? I'm not 100% sure -- I've ever seen a instruction being prefixed with a type, but I've taken it to be indicating the type of , the operand. I'll do a bit more digging. claim
After manually removing the LLVM build to force a complete rebuild with debug symbols, I was able to get a proper dump which makes far more sense: Note that this is not a bitcast instruction but a constant expr bitcast -- ie, one generated at compile time. As it turns out, in the event that a function exists with athe same name but a different type in a module, will return a compile time bitcast to that function: which is the overload called here So, later, when we attempt to use any functions that do a downcast to , we trigger the assertion failure because the downcast from constant expr bitcast to is not valid. We run into this in both your cases because when codegen attempts to insert a declaration for with signature , the program's already exists in the module with the signature , so the bitcast is returned instead of an . This issue can be reproduced without causing a crash by forcing a name collision with a function that's not (as we don't end up trying to cast the bitcast to a Function in this scenario): Compiling with we get this bitcode here: which I think exposes the problem more clearly: In an extern block which declares a function with the same name as some existing function within the module, we'll end up generating a call to the function in the module (potentially with an unsafe bitcast), instead of shadowing the module's function and generating a call to the external function (which, to me, appeared to be the intent of the example). You can see that this example shows that the in the original example isn't quite so much a red herring as it might seem -- in my example particularly, it's needed to ensure the name collision which demonstrates this behaviour. The examples without work because we induce a name collision on the unmangled function instead (not the user-defined one; the one which calls ). At this point, I'm not sure how to proceed. Should we error out here because of the name collision to avoid generating crazy function pointer bitcasts? Or should we do some kind of trickery to rename the shadowing symbol so that it correctly calls the extern function? Or is it as says -- is the current codegen into bitcast fine because we don't make any behaviour guarantees for symbols?

<del> error: entry symbol `main` defined multiple times </del> <ins> error: entry symbol `main` declared multiple times </ins> --> $DIR/dupe-symbols-7.rs:12:1 | LL | fn main(){}


Question:
This code crashes in LLVM during codegen on stable, beta, and nightly: This originally happened in real-world code (a code base derived from ). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
We generally don't guarantee behavior with no_mangle, I think. I guess a segfault in llvm is unexpected though :)
I think the is a red herring, since the name of that function doesn't actually matter (ie. it can be or something completely harmless). I think it's just needed to make sure the function is codegen-ed.
I keep seeing this in my output when I play around with this on the playpen: that does not use , adding credence to 's point that it is probably a red herring.
triage: P-high. Leaving nominated in hopes that someone at triage meeting has a bright idea has to what's going on here (and what we might do about it).
Hm, bad_alloc implies OOM to me, but maybe that's not always the case.
Compiling with LLVM debug symbols + assertions, I get the same assertion failure for both: Tracing the callstack with gdb, the assertion is triggered on the call in this function: As the error suggests, this means that the downcast from to failed for . Printing out what type is (with some casting because gdb doesn't know what the return types are): That's strange -- it's reported as a function pointer, which is the same as what's reported for actual s, but we're still failing the downcast. Usually, dumping an should give you the contents of the function. For example: gives us But dumping gives this: So it appears to be pointing to a instruction? I'm not 100% sure -- I've ever seen a instruction being prefixed with a type, but I've taken it to be indicating the type of , the operand. I'll do a bit more digging. claim
After manually removing the LLVM build to force a complete rebuild with debug symbols, I was able to get a proper dump which makes far more sense: Note that this is not a bitcast instruction but a constant expr bitcast -- ie, one generated at compile time. As it turns out, in the event that a function exists with athe same name but a different type in a module, will return a compile time bitcast to that function: which is the overload called here So, later, when we attempt to use any functions that do a downcast to , we trigger the assertion failure because the downcast from constant expr bitcast to is not valid. We run into this in both your cases because when codegen attempts to insert a declaration for with signature , the program's already exists in the module with the signature , so the bitcast is returned instead of an . This issue can be reproduced without causing a crash by forcing a name collision with a function that's not (as we don't end up trying to cast the bitcast to a Function in this scenario): Compiling with we get this bitcode here: which I think exposes the problem more clearly: In an extern block which declares a function with the same name as some existing function within the module, we'll end up generating a call to the function in the module (potentially with an unsafe bitcast), instead of shadowing the module's function and generating a call to the external function (which, to me, appeared to be the intent of the example). You can see that this example shows that the in the original example isn't quite so much a red herring as it might seem -- in my example particularly, it's needed to ensure the name collision which demonstrates this behaviour. The examples without work because we induce a name collision on the unmangled function instead (not the user-defined one; the one which calls ). At this point, I'm not sure how to proceed. Should we error out here because of the name collision to avoid generating crazy function pointer bitcasts? Or should we do some kind of trickery to rename the shadowing symbol so that it correctly calls the extern function? Or is it as says -- is the current codegen into bitcast fine because we don't make any behaviour guarantees for symbols?

<ins> // build-fail // error-pattern: entry symbol `main` declared multiple times // // See #67946. #![allow(warnings)] fn main() { extern "Rust" { fn main(); } unsafe { main(); } } </ins>


Question:
This code crashes in LLVM during codegen on stable, beta, and nightly: This originally happened in real-world code (a code base derived from ). <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
We generally don't guarantee behavior with no_mangle, I think. I guess a segfault in llvm is unexpected though :)
I think the is a red herring, since the name of that function doesn't actually matter (ie. it can be or something completely harmless). I think it's just needed to make sure the function is codegen-ed.
I keep seeing this in my output when I play around with this on the playpen: that does not use , adding credence to 's point that it is probably a red herring.
triage: P-high. Leaving nominated in hopes that someone at triage meeting has a bright idea has to what's going on here (and what we might do about it).
Hm, bad_alloc implies OOM to me, but maybe that's not always the case.
Compiling with LLVM debug symbols + assertions, I get the same assertion failure for both: Tracing the callstack with gdb, the assertion is triggered on the call in this function: As the error suggests, this means that the downcast from to failed for . Printing out what type is (with some casting because gdb doesn't know what the return types are): That's strange -- it's reported as a function pointer, which is the same as what's reported for actual s, but we're still failing the downcast. Usually, dumping an should give you the contents of the function. For example: gives us But dumping gives this: So it appears to be pointing to a instruction? I'm not 100% sure -- I've ever seen a instruction being prefixed with a type, but I've taken it to be indicating the type of , the operand. I'll do a bit more digging. claim
After manually removing the LLVM build to force a complete rebuild with debug symbols, I was able to get a proper dump which makes far more sense: Note that this is not a bitcast instruction but a constant expr bitcast -- ie, one generated at compile time. As it turns out, in the event that a function exists with athe same name but a different type in a module, will return a compile time bitcast to that function: which is the overload called here So, later, when we attempt to use any functions that do a downcast to , we trigger the assertion failure because the downcast from constant expr bitcast to is not valid. We run into this in both your cases because when codegen attempts to insert a declaration for with signature , the program's already exists in the module with the signature , so the bitcast is returned instead of an . This issue can be reproduced without causing a crash by forcing a name collision with a function that's not (as we don't end up trying to cast the bitcast to a Function in this scenario): Compiling with we get this bitcode here: which I think exposes the problem more clearly: In an extern block which declares a function with the same name as some existing function within the module, we'll end up generating a call to the function in the module (potentially with an unsafe bitcast), instead of shadowing the module's function and generating a call to the external function (which, to me, appeared to be the intent of the example). You can see that this example shows that the in the original example isn't quite so much a red herring as it might seem -- in my example particularly, it's needed to ensure the name collision which demonstrates this behaviour. The examples without work because we induce a name collision on the unmangled function instead (not the user-defined one; the one which calls ). At this point, I'm not sure how to proceed. Should we error out here because of the name collision to avoid generating crazy function pointer bitcasts? Or should we do some kind of trickery to rename the shadowing symbol so that it correctly calls the extern function? Or is it as says -- is the current codegen into bitcast fine because we don't make any behaviour guarantees for symbols?

<ins> error: entry symbol `main` declared multiple times --> $DIR/dupe-symbols-8.rs:7:1 | LL | / fn main() { LL | |     extern "Rust" { LL | |      fn main(); LL | |     } LL | |     unsafe { main(); } LL | | } | |_^ | = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead error: aborting due to previous error </ins>


Question:
Got this error message when trying to compile a crate using rustc 1.42.0-nightly ( 2020-01-07). The text reads substract instead of subtract.
if you want to contribute a fix, you would just need to modify these three lines:
thanks for your response, I submitted a PR to fix this.

Some("std::ops::Add"), ), hir::BinOpKind::Sub => ( <del> format!("cannot substract `{}` from `{}`", rhs_ty, lhs_ty), </del> <ins> format!("cannot subtract `{}` from `{}`", rhs_ty, lhs_ty), </ins> Some("std::ops::Sub"), ), hir::BinOpKind::Mul => (


Question:
Got this error message when trying to compile a crate using rustc 1.42.0-nightly ( 2020-01-07). The text reads substract instead of subtract.
if you want to contribute a fix, you would just need to modify these three lines:
thanks for your response, I submitted a PR to fix this.

a + a; //~ ERROR cannot add `A` to `A` <del> a - a; //~ ERROR cannot substract `A` from `A` </del> <ins> a - a; //~ ERROR cannot subtract `A` from `A` </ins> a * a; //~ ERROR cannot multiply `A` to `A`


Question:
Got this error message when trying to compile a crate using rustc 1.42.0-nightly ( 2020-01-07). The text reads substract instead of subtract.
if you want to contribute a fix, you would just need to modify these three lines:
thanks for your response, I submitted a PR to fix this.

| = note: an implementation of `std::ops::Add` might be missing for `A` <del> error[E0369]: cannot substract `A` from `A` </del> <ins> error[E0369]: cannot subtract `A` from `A` </ins> --> $DIR/issue-28837.rs:8:7 | LL |     a - a;


Question:
Attempting to compile this code: Playground link: Causes this ICE in nightly 2019-12-29 ,and stable with a slightly different stack trace.
reduced to 2 lines: also, when the is removed from the line, OR both 's are removed, it compiles fine.
yeah, I prepared the fix but has already submitted another fix so assignment is unnecessary?

if let Some(item) = module .res .and_then(|res| res.mod_def_id()) <ins> // If the module is `self`, i.e. the current crate, // there will be no corresponding item. .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE) </ins> .and_then(|def_id| self.tcx.hir().as_local_hir_id(def_id)) .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) {


Question:
Attempting to compile this code: Playground link: Causes this ICE in nightly 2019-12-29 ,and stable with a slightly different stack trace.
reduced to 2 lines: also, when the is removed from the line, OR both 's are removed, it compiles fine.
yeah, I prepared the fix but has already submitted another fix so assignment is unnecessary?

<ins> // check-pass pub extern crate self as name; pub use name::name as bug; fn main() {} </ins>


Question:
I'm not sure when exactly it happens, but it reproduces roughly like this: Rebase my working branch on upstream/master. Run , the build starts from or later and succeeds. Run again, should be a trivial build, but the build starts from or again and succeeds. Run again, trivial build happens. The target is x86_64-pc-windows-gnu. The issue exists for several weeks, so it's a regression. cc
Reproduction script: You might have to run it multiple times to cause the spurious rebuild in the last command.
For some reason is getting recompiled:
cc
I think was hitting this at some point as well, though we weren't able to determine quite why.
I haven't encountered these rebuilds before, but recently (since December?) they happen quite often, like every second or third build, and that's pretty inconvenient given the long builds. Perhaps something changed in itself?
I don't think we've changed backtrace itself recently. It would perhaps be handy to check if this still happens before (which changed how/when we clear out std's target directory). However, I don't expect it would have, as that would cause all of std to be rebuilt, not just backtrace. Maybe backtrace is unique in being a dependency of both std and the compiler (for example?). I'm not sure what could be causing this odd behavior :/
I'm pretty sure the rebuilds appeared before (and I hoped that PR would fix them, but it didn't).
I suspect to be the cause, at least based on timing.
I've been hitting similar (this?) issue with x86_64-pc-windows-gnu when doing builds. Somehow it disappeared whenever I ran before so I kept doing that as the workaround.
Hm, so in theory at least wouldn't have affected backtrace specifically, I think, though there may have been knock on effects. One thing that might be helpful is getting a log with on the spurious rebuild (to know why Cargo thinks it needs to rebuild it).
Update: this reproduces on too (which runs much quicker and involves less moving parts), just got a rebuild after a clean build this way. I'll try .
Reproduced on () with :
I was able to reproduce this once, but I'm having trouble reproducing it again. When I did reproduce it, I noticed that the included . That is not normal, and I think points to a race condition with the libcore rlib getting emitted at just the wrong time. I suspect it is due to pipelining and maybe . I'm still trying to figure that out.
binary-dep-depinfo should not include backtrace into libcore, I think, since we don't pass to libcore (nor is there an implicit "sysroot" dep from libcore; core depends on nothing). I don't know why we're including dep-lib-backtrace in the libcore dep file though, that does sound like a bug. I guess this is then likely an upstream bug in some sense? I think leaving it here for tracking at least for now makes sense though.
It's the other way around. 's dep-info file noted a dependency on , which is normal. Normally it should only list the file, but when I saw it, it also included the file. That normally shouldn't happen because the libcore codegen step takes such a long time (normally finishes after backtrace is finished). I'm not too familiar with the compiler, so it's a little slow for me to figure out. I seem to recall being told that writing the file is not done in an atomic fashion, is that correct? Perhaps writing it can take a long time, and backtrace started after the was created and finished running before the was done? I also seem to recall that there are protections in rustc to deal with partially written rlib files, but I'm not sure how that is accomplished (are there checksums?).
We currently emit a dependency on both the rmeta and rlib files (presuming they were found during building, I guess?) with . That might be in error! I did so as the most pessimistic option when initially adding that feature, but perhaps I was too eager in pulling in dependencies. If I'm understanding correctly, that may mean that if libcore's codegen completes before backtrace is built, we'll pull in the libcore rlib as a dependency of backtrace, and then when backtrace is checked for freshness in the future, we'll notice that it's actually been built before the rlib (which we finished writing after libbacktrace started). Is there ever a case where there's a dependency on rlibs directly? Maybe we should only emit rmeta/dylib filepaths in binary-dep-depinfo?
For reference, here's what I have in that file (with NUL bytes removed):
Hm, so it looks like in practice we that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. I guess there's not really any tracking for which one we've used metadata from, but in practice, we should probably only emit one of these (probably rmeta/rlib/dylib, in that order) that we have set as the CrateSource.
Hm, so it looks like in practice we read metadata from the first of the three that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. This is actually something that I wanted to try to change () and read from the rmeta first.
Even if is used for reading metadata, can still be used for reading object code, in that case both should indeed be in dependencies? Perhaps cargo just timestamps the link time dependencies at the wrong time? (Earlier than necessary, together with .)
I was able to record exactly what happens. The timeline is: T1. emitted T2. backtrace build starts T3. emitted T4. backtrace loads T5. backtrace writes dep-info with and T6. backtrace finishes T7. Cargo reverses backtrace dep-info timestamp to T2 () (this is intended to deal with files that are modified in the middle of the build) The result is that 's timestamp is T3 and backtrace dep-info timestamp is T2, and since T3 T2, the next time Cargo runs it thinks backtrace needs to be rebuilt. I'm not sure how to fix this. One solution would be to change the priority to load rmeta over rlib, and have only emit one file. Or Cargo could hash the files :wink:. Maybe has ideas?
I like the idea of inverting rustc's preference, using only the rmeta rather than both the rmeta and rlib if they're available. Other than that though I don't know of a great way to solve this :( I may be missing something though, is this rustc-specific? This seems like a bug that everyone should be hitting naively which makes it quite serious?
It is only with . Also, the timing has to be just right for the rlib to be created in a very small window (the time between T2 and T4 is extremely small).
Ah I see, makes sense! Here's another possible question and/or solution. When Cargo builds libbacktrace it's presumably only passing , so I think it's rustc's automatic logic to pick up . Is that correct? If so it may be more correct to, if is passed, disable all other auto-loading?
Backtrace only sees via . is loaded as a dependency of that. (Via I think?)
I think this is our best bet -- furthermore, I wonder if there's some wins to be had in terms of compile times. It seems like we are currently loading libcore's rmeta/rlib for all crates out there, which presumably is not great (more IO, etc.). I can pursue a PR to that effect soon.
aha ok that makes sense as well. Then yeah I think your suggestion is indeed the only thing I can think of as well!
Hm, actually, in going to do this, it sounds like we can't quite just emit one of them, per "Even if rmeta is used for reading metadata, rlib can still be used for reading object code, in that case both should indeed be in dependencies?" -- right?
When building an rlib we never use contents of upstream rlibs. When building dynamically linked artifacts, though (or executables) we do use upstream object code. (this is basically pipelining)
Aha, okay, so it sounds like a partial fix would be to: If we're producing rmeta/rlib: emit just rmeta dependency if we're producing dylib/cydlib/binary: emit just rlib dependency Does that sound right? Basically, we emit "worst case" for either situation which I think might mean that for dylibs this bug persists -- since they'll start compilation before the rlib is finished -- but I don't know how much we can do about it under the current model.
That should be right yeah, and I think the dylib bug won't be an issue because Cargo won't start libstd until all subsequent rlib compilations are finished (e.g. it doesn't pipeline it)
Great! Okay, then I'll try to get that impl up. (I presume the "dylib bug won't be an issue" also applies to dylibs in the wild, right?)
That's the theory at least!

dylibs: FxHashMap<PathBuf, PathKind>, ) -> Option<(Svh, Library)> { let mut slot = None; <ins> // Order here matters, rmeta should come first. See comment in // `extract_one` below. </ins> let source = CrateSource { <del> rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), </del> rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot), <ins> rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), </ins> dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot), }; slot.map(|(svh, metadata)| (svh, Library { source, metadata })) } <ins> fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool { if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) { return true; } // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == config::CrateType::Rlib); let needs_object_code = self.sess.opts.output_types.should_codegen(); // If we're producing an rlib, then we don't need object code. // Or, if we're not producing object code, then we don't need it either // (e.g., if we're a cdylib but emitting just metadata). if is_rlib || !needs_object_code { flavor == CrateFlavor::Rmeta } else { // we need all flavors (perhaps not true, but what we do for now) true } } </ins> // Attempts to extract *one* library from the set `m`. If the set has no // elements, `None` is returned. If the set has more than one element, then // the errors and notes are emitted about the set of libraries.


Question:
I'm not sure when exactly it happens, but it reproduces roughly like this: Rebase my working branch on upstream/master. Run , the build starts from or later and succeeds. Run again, should be a trivial build, but the build starts from or again and succeeds. Run again, trivial build happens. The target is x86_64-pc-windows-gnu. The issue exists for several weeks, so it's a regression. cc
Reproduction script: You might have to run it multiple times to cause the spurious rebuild in the last command.
For some reason is getting recompiled:
cc
I think was hitting this at some point as well, though we weren't able to determine quite why.
I haven't encountered these rebuilds before, but recently (since December?) they happen quite often, like every second or third build, and that's pretty inconvenient given the long builds. Perhaps something changed in itself?
I don't think we've changed backtrace itself recently. It would perhaps be handy to check if this still happens before (which changed how/when we clear out std's target directory). However, I don't expect it would have, as that would cause all of std to be rebuilt, not just backtrace. Maybe backtrace is unique in being a dependency of both std and the compiler (for example?). I'm not sure what could be causing this odd behavior :/
I'm pretty sure the rebuilds appeared before (and I hoped that PR would fix them, but it didn't).
I suspect to be the cause, at least based on timing.
I've been hitting similar (this?) issue with x86_64-pc-windows-gnu when doing builds. Somehow it disappeared whenever I ran before so I kept doing that as the workaround.
Hm, so in theory at least wouldn't have affected backtrace specifically, I think, though there may have been knock on effects. One thing that might be helpful is getting a log with on the spurious rebuild (to know why Cargo thinks it needs to rebuild it).
Update: this reproduces on too (which runs much quicker and involves less moving parts), just got a rebuild after a clean build this way. I'll try .
Reproduced on () with :
I was able to reproduce this once, but I'm having trouble reproducing it again. When I did reproduce it, I noticed that the included . That is not normal, and I think points to a race condition with the libcore rlib getting emitted at just the wrong time. I suspect it is due to pipelining and maybe . I'm still trying to figure that out.
binary-dep-depinfo should not include backtrace into libcore, I think, since we don't pass to libcore (nor is there an implicit "sysroot" dep from libcore; core depends on nothing). I don't know why we're including dep-lib-backtrace in the libcore dep file though, that does sound like a bug. I guess this is then likely an upstream bug in some sense? I think leaving it here for tracking at least for now makes sense though.
It's the other way around. 's dep-info file noted a dependency on , which is normal. Normally it should only list the file, but when I saw it, it also included the file. That normally shouldn't happen because the libcore codegen step takes such a long time (normally finishes after backtrace is finished). I'm not too familiar with the compiler, so it's a little slow for me to figure out. I seem to recall being told that writing the file is not done in an atomic fashion, is that correct? Perhaps writing it can take a long time, and backtrace started after the was created and finished running before the was done? I also seem to recall that there are protections in rustc to deal with partially written rlib files, but I'm not sure how that is accomplished (are there checksums?).
We currently emit a dependency on both the rmeta and rlib files (presuming they were found during building, I guess?) with . That might be in error! I did so as the most pessimistic option when initially adding that feature, but perhaps I was too eager in pulling in dependencies. If I'm understanding correctly, that may mean that if libcore's codegen completes before backtrace is built, we'll pull in the libcore rlib as a dependency of backtrace, and then when backtrace is checked for freshness in the future, we'll notice that it's actually been built before the rlib (which we finished writing after libbacktrace started). Is there ever a case where there's a dependency on rlibs directly? Maybe we should only emit rmeta/dylib filepaths in binary-dep-depinfo?
For reference, here's what I have in that file (with NUL bytes removed):
Hm, so it looks like in practice we that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. I guess there's not really any tracking for which one we've used metadata from, but in practice, we should probably only emit one of these (probably rmeta/rlib/dylib, in that order) that we have set as the CrateSource.
Hm, so it looks like in practice we read metadata from the first of the three that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. This is actually something that I wanted to try to change () and read from the rmeta first.
Even if is used for reading metadata, can still be used for reading object code, in that case both should indeed be in dependencies? Perhaps cargo just timestamps the link time dependencies at the wrong time? (Earlier than necessary, together with .)
I was able to record exactly what happens. The timeline is: T1. emitted T2. backtrace build starts T3. emitted T4. backtrace loads T5. backtrace writes dep-info with and T6. backtrace finishes T7. Cargo reverses backtrace dep-info timestamp to T2 () (this is intended to deal with files that are modified in the middle of the build) The result is that 's timestamp is T3 and backtrace dep-info timestamp is T2, and since T3 T2, the next time Cargo runs it thinks backtrace needs to be rebuilt. I'm not sure how to fix this. One solution would be to change the priority to load rmeta over rlib, and have only emit one file. Or Cargo could hash the files :wink:. Maybe has ideas?
I like the idea of inverting rustc's preference, using only the rmeta rather than both the rmeta and rlib if they're available. Other than that though I don't know of a great way to solve this :( I may be missing something though, is this rustc-specific? This seems like a bug that everyone should be hitting naively which makes it quite serious?
It is only with . Also, the timing has to be just right for the rlib to be created in a very small window (the time between T2 and T4 is extremely small).
Ah I see, makes sense! Here's another possible question and/or solution. When Cargo builds libbacktrace it's presumably only passing , so I think it's rustc's automatic logic to pick up . Is that correct? If so it may be more correct to, if is passed, disable all other auto-loading?
Backtrace only sees via . is loaded as a dependency of that. (Via I think?)
I think this is our best bet -- furthermore, I wonder if there's some wins to be had in terms of compile times. It seems like we are currently loading libcore's rmeta/rlib for all crates out there, which presumably is not great (more IO, etc.). I can pursue a PR to that effect soon.
aha ok that makes sense as well. Then yeah I think your suggestion is indeed the only thing I can think of as well!
Hm, actually, in going to do this, it sounds like we can't quite just emit one of them, per "Even if rmeta is used for reading metadata, rlib can still be used for reading object code, in that case both should indeed be in dependencies?" -- right?
When building an rlib we never use contents of upstream rlibs. When building dynamically linked artifacts, though (or executables) we do use upstream object code. (this is basically pipelining)
Aha, okay, so it sounds like a partial fix would be to: If we're producing rmeta/rlib: emit just rmeta dependency if we're producing dylib/cydlib/binary: emit just rlib dependency Does that sound right? Basically, we emit "worst case" for either situation which I think might mean that for dylibs this bug persists -- since they'll start compilation before the rlib is finished -- but I don't know how much we can do about it under the current model.
That should be right yeah, and I think the dylib bug won't be an issue because Cargo won't start libstd until all subsequent rlib compilations are finished (e.g. it doesn't pipeline it)
Great! Okay, then I'll try to get that impl up. (I presume the "dylib bug won't be an issue" also applies to dylibs in the wild, right?)
That's the theory at least!

let mut ret: Option<(PathBuf, PathKind)> = None; let mut error = 0; <ins> // If we are producing an rlib, and we've already loaded metadata, then // we should not attempt to discover further crate sources (unless we're // locating a proc macro; exact logic is in needs_crate_flavor). This means // that under -Zbinary-dep-depinfo we will not emit a dependency edge on // the *unused* rlib, and by returning `None` here immediately we // guarantee that we do indeed not use it. // // See also #68149 which provides more detail on why emitting the // dependency on the rlib is a bad thing. // // We currenty do not verify that these other sources are even in sync, // and this is arguably a bug (see #10786), but because reading metadata // is quite slow (especially from dylibs) we currently do not read it // from the other crate sources. </ins> if slot.is_some() { <del> // FIXME(#10786): for an optimization, we only read one of the //                libraries' metadata sections. In theory we should //                read both, but reading dylib metadata is quite //                slow. if m.is_empty() { </del> <ins> if m.is_empty() || !self.needs_crate_flavor(flavor) { </ins> return None; } else if m.len() == 1 { return Some(m.into_iter().next().unwrap());


Question:
I'm not sure when exactly it happens, but it reproduces roughly like this: Rebase my working branch on upstream/master. Run , the build starts from or later and succeeds. Run again, should be a trivial build, but the build starts from or again and succeeds. Run again, trivial build happens. The target is x86_64-pc-windows-gnu. The issue exists for several weeks, so it's a regression. cc
Reproduction script: You might have to run it multiple times to cause the spurious rebuild in the last command.
For some reason is getting recompiled:
cc
I think was hitting this at some point as well, though we weren't able to determine quite why.
I haven't encountered these rebuilds before, but recently (since December?) they happen quite often, like every second or third build, and that's pretty inconvenient given the long builds. Perhaps something changed in itself?
I don't think we've changed backtrace itself recently. It would perhaps be handy to check if this still happens before (which changed how/when we clear out std's target directory). However, I don't expect it would have, as that would cause all of std to be rebuilt, not just backtrace. Maybe backtrace is unique in being a dependency of both std and the compiler (for example?). I'm not sure what could be causing this odd behavior :/
I'm pretty sure the rebuilds appeared before (and I hoped that PR would fix them, but it didn't).
I suspect to be the cause, at least based on timing.
I've been hitting similar (this?) issue with x86_64-pc-windows-gnu when doing builds. Somehow it disappeared whenever I ran before so I kept doing that as the workaround.
Hm, so in theory at least wouldn't have affected backtrace specifically, I think, though there may have been knock on effects. One thing that might be helpful is getting a log with on the spurious rebuild (to know why Cargo thinks it needs to rebuild it).
Update: this reproduces on too (which runs much quicker and involves less moving parts), just got a rebuild after a clean build this way. I'll try .
Reproduced on () with :
I was able to reproduce this once, but I'm having trouble reproducing it again. When I did reproduce it, I noticed that the included . That is not normal, and I think points to a race condition with the libcore rlib getting emitted at just the wrong time. I suspect it is due to pipelining and maybe . I'm still trying to figure that out.
binary-dep-depinfo should not include backtrace into libcore, I think, since we don't pass to libcore (nor is there an implicit "sysroot" dep from libcore; core depends on nothing). I don't know why we're including dep-lib-backtrace in the libcore dep file though, that does sound like a bug. I guess this is then likely an upstream bug in some sense? I think leaving it here for tracking at least for now makes sense though.
It's the other way around. 's dep-info file noted a dependency on , which is normal. Normally it should only list the file, but when I saw it, it also included the file. That normally shouldn't happen because the libcore codegen step takes such a long time (normally finishes after backtrace is finished). I'm not too familiar with the compiler, so it's a little slow for me to figure out. I seem to recall being told that writing the file is not done in an atomic fashion, is that correct? Perhaps writing it can take a long time, and backtrace started after the was created and finished running before the was done? I also seem to recall that there are protections in rustc to deal with partially written rlib files, but I'm not sure how that is accomplished (are there checksums?).
We currently emit a dependency on both the rmeta and rlib files (presuming they were found during building, I guess?) with . That might be in error! I did so as the most pessimistic option when initially adding that feature, but perhaps I was too eager in pulling in dependencies. If I'm understanding correctly, that may mean that if libcore's codegen completes before backtrace is built, we'll pull in the libcore rlib as a dependency of backtrace, and then when backtrace is checked for freshness in the future, we'll notice that it's actually been built before the rlib (which we finished writing after libbacktrace started). Is there ever a case where there's a dependency on rlibs directly? Maybe we should only emit rmeta/dylib filepaths in binary-dep-depinfo?
For reference, here's what I have in that file (with NUL bytes removed):
Hm, so it looks like in practice we that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. I guess there's not really any tracking for which one we've used metadata from, but in practice, we should probably only emit one of these (probably rmeta/rlib/dylib, in that order) that we have set as the CrateSource.
Hm, so it looks like in practice we read metadata from the first of the three that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. This is actually something that I wanted to try to change () and read from the rmeta first.
Even if is used for reading metadata, can still be used for reading object code, in that case both should indeed be in dependencies? Perhaps cargo just timestamps the link time dependencies at the wrong time? (Earlier than necessary, together with .)
I was able to record exactly what happens. The timeline is: T1. emitted T2. backtrace build starts T3. emitted T4. backtrace loads T5. backtrace writes dep-info with and T6. backtrace finishes T7. Cargo reverses backtrace dep-info timestamp to T2 () (this is intended to deal with files that are modified in the middle of the build) The result is that 's timestamp is T3 and backtrace dep-info timestamp is T2, and since T3 T2, the next time Cargo runs it thinks backtrace needs to be rebuilt. I'm not sure how to fix this. One solution would be to change the priority to load rmeta over rlib, and have only emit one file. Or Cargo could hash the files :wink:. Maybe has ideas?
I like the idea of inverting rustc's preference, using only the rmeta rather than both the rmeta and rlib if they're available. Other than that though I don't know of a great way to solve this :( I may be missing something though, is this rustc-specific? This seems like a bug that everyone should be hitting naively which makes it quite serious?
It is only with . Also, the timing has to be just right for the rlib to be created in a very small window (the time between T2 and T4 is extremely small).
Ah I see, makes sense! Here's another possible question and/or solution. When Cargo builds libbacktrace it's presumably only passing , so I think it's rustc's automatic logic to pick up . Is that correct? If so it may be more correct to, if is passed, disable all other auto-loading?
Backtrace only sees via . is loaded as a dependency of that. (Via I think?)
I think this is our best bet -- furthermore, I wonder if there's some wins to be had in terms of compile times. It seems like we are currently loading libcore's rmeta/rlib for all crates out there, which presumably is not great (more IO, etc.). I can pursue a PR to that effect soon.
aha ok that makes sense as well. Then yeah I think your suggestion is indeed the only thing I can think of as well!
Hm, actually, in going to do this, it sounds like we can't quite just emit one of them, per "Even if rmeta is used for reading metadata, rlib can still be used for reading object code, in that case both should indeed be in dependencies?" -- right?
When building an rlib we never use contents of upstream rlibs. When building dynamically linked artifacts, though (or executables) we do use upstream object code. (this is basically pipelining)
Aha, okay, so it sounds like a partial fix would be to: If we're producing rmeta/rlib: emit just rmeta dependency if we're producing dylib/cydlib/binary: emit just rlib dependency Does that sound right? Basically, we emit "worst case" for either situation which I think might mean that for dylibs this bug persists -- since they'll start compilation before the rlib is finished -- but I don't know how much we can do about it under the current model.
That should be right yeah, and I think the dylib bug won't be an issue because Cargo won't start libstd until all subsequent rlib compilations are finished (e.g. it doesn't pipeline it)
Great! Okay, then I'll try to get that impl up. (I presume the "dylib bug won't be an issue" also applies to dylibs in the wild, right?)
That's the theory at least!

// run-pass // Test that using rlibs and rmeta dep crates work together. Specifically, that <del> // there can be both an rmeta and an rlib file and rustc will prefer the rlib. </del> <ins> // there can be both an rmeta and an rlib file and rustc will prefer the rmeta // file. // // This behavior is simply making sure this doesn't accidentally change; in this // case we want to make sure that the rlib isn't being used as that would cause // bugs in -Zbinary-dep-depinfo (see #68298). </ins> // aux-build:rmeta-rmeta.rs // aux-build:rmeta-rlib-rpass.rs


Question:
I'm not sure when exactly it happens, but it reproduces roughly like this: Rebase my working branch on upstream/master. Run , the build starts from or later and succeeds. Run again, should be a trivial build, but the build starts from or again and succeeds. Run again, trivial build happens. The target is x86_64-pc-windows-gnu. The issue exists for several weeks, so it's a regression. cc
Reproduction script: You might have to run it multiple times to cause the spurious rebuild in the last command.
For some reason is getting recompiled:
cc
I think was hitting this at some point as well, though we weren't able to determine quite why.
I haven't encountered these rebuilds before, but recently (since December?) they happen quite often, like every second or third build, and that's pretty inconvenient given the long builds. Perhaps something changed in itself?
I don't think we've changed backtrace itself recently. It would perhaps be handy to check if this still happens before (which changed how/when we clear out std's target directory). However, I don't expect it would have, as that would cause all of std to be rebuilt, not just backtrace. Maybe backtrace is unique in being a dependency of both std and the compiler (for example?). I'm not sure what could be causing this odd behavior :/
I'm pretty sure the rebuilds appeared before (and I hoped that PR would fix them, but it didn't).
I suspect to be the cause, at least based on timing.
I've been hitting similar (this?) issue with x86_64-pc-windows-gnu when doing builds. Somehow it disappeared whenever I ran before so I kept doing that as the workaround.
Hm, so in theory at least wouldn't have affected backtrace specifically, I think, though there may have been knock on effects. One thing that might be helpful is getting a log with on the spurious rebuild (to know why Cargo thinks it needs to rebuild it).
Update: this reproduces on too (which runs much quicker and involves less moving parts), just got a rebuild after a clean build this way. I'll try .
Reproduced on () with :
I was able to reproduce this once, but I'm having trouble reproducing it again. When I did reproduce it, I noticed that the included . That is not normal, and I think points to a race condition with the libcore rlib getting emitted at just the wrong time. I suspect it is due to pipelining and maybe . I'm still trying to figure that out.
binary-dep-depinfo should not include backtrace into libcore, I think, since we don't pass to libcore (nor is there an implicit "sysroot" dep from libcore; core depends on nothing). I don't know why we're including dep-lib-backtrace in the libcore dep file though, that does sound like a bug. I guess this is then likely an upstream bug in some sense? I think leaving it here for tracking at least for now makes sense though.
It's the other way around. 's dep-info file noted a dependency on , which is normal. Normally it should only list the file, but when I saw it, it also included the file. That normally shouldn't happen because the libcore codegen step takes such a long time (normally finishes after backtrace is finished). I'm not too familiar with the compiler, so it's a little slow for me to figure out. I seem to recall being told that writing the file is not done in an atomic fashion, is that correct? Perhaps writing it can take a long time, and backtrace started after the was created and finished running before the was done? I also seem to recall that there are protections in rustc to deal with partially written rlib files, but I'm not sure how that is accomplished (are there checksums?).
We currently emit a dependency on both the rmeta and rlib files (presuming they were found during building, I guess?) with . That might be in error! I did so as the most pessimistic option when initially adding that feature, but perhaps I was too eager in pulling in dependencies. If I'm understanding correctly, that may mean that if libcore's codegen completes before backtrace is built, we'll pull in the libcore rlib as a dependency of backtrace, and then when backtrace is checked for freshness in the future, we'll notice that it's actually been built before the rlib (which we finished writing after libbacktrace started). Is there ever a case where there's a dependency on rlibs directly? Maybe we should only emit rmeta/dylib filepaths in binary-dep-depinfo?
For reference, here's what I have in that file (with NUL bytes removed):
Hm, so it looks like in practice we that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. I guess there's not really any tracking for which one we've used metadata from, but in practice, we should probably only emit one of these (probably rmeta/rlib/dylib, in that order) that we have set as the CrateSource.
Hm, so it looks like in practice we read metadata from the first of the three that we find -- so in some sense, we don't actually depend on all three, but rather rlib/rmeta/dylib, in that order, when we're loading up dependency information. This is actually something that I wanted to try to change () and read from the rmeta first.
Even if is used for reading metadata, can still be used for reading object code, in that case both should indeed be in dependencies? Perhaps cargo just timestamps the link time dependencies at the wrong time? (Earlier than necessary, together with .)
I was able to record exactly what happens. The timeline is: T1. emitted T2. backtrace build starts T3. emitted T4. backtrace loads T5. backtrace writes dep-info with and T6. backtrace finishes T7. Cargo reverses backtrace dep-info timestamp to T2 () (this is intended to deal with files that are modified in the middle of the build) The result is that 's timestamp is T3 and backtrace dep-info timestamp is T2, and since T3 T2, the next time Cargo runs it thinks backtrace needs to be rebuilt. I'm not sure how to fix this. One solution would be to change the priority to load rmeta over rlib, and have only emit one file. Or Cargo could hash the files :wink:. Maybe has ideas?
I like the idea of inverting rustc's preference, using only the rmeta rather than both the rmeta and rlib if they're available. Other than that though I don't know of a great way to solve this :( I may be missing something though, is this rustc-specific? This seems like a bug that everyone should be hitting naively which makes it quite serious?
It is only with . Also, the timing has to be just right for the rlib to be created in a very small window (the time between T2 and T4 is extremely small).
Ah I see, makes sense! Here's another possible question and/or solution. When Cargo builds libbacktrace it's presumably only passing , so I think it's rustc's automatic logic to pick up . Is that correct? If so it may be more correct to, if is passed, disable all other auto-loading?
Backtrace only sees via . is loaded as a dependency of that. (Via I think?)
I think this is our best bet -- furthermore, I wonder if there's some wins to be had in terms of compile times. It seems like we are currently loading libcore's rmeta/rlib for all crates out there, which presumably is not great (more IO, etc.). I can pursue a PR to that effect soon.
aha ok that makes sense as well. Then yeah I think your suggestion is indeed the only thing I can think of as well!
Hm, actually, in going to do this, it sounds like we can't quite just emit one of them, per "Even if rmeta is used for reading metadata, rlib can still be used for reading object code, in that case both should indeed be in dependencies?" -- right?
When building an rlib we never use contents of upstream rlibs. When building dynamically linked artifacts, though (or executables) we do use upstream object code. (this is basically pipelining)
Aha, okay, so it sounds like a partial fix would be to: If we're producing rmeta/rlib: emit just rmeta dependency if we're producing dylib/cydlib/binary: emit just rlib dependency Does that sound right? Basically, we emit "worst case" for either situation which I think might mean that for dylibs this bug persists -- since they'll start compilation before the rlib is finished -- but I don't know how much we can do about it under the current model.
That should be right yeah, and I think the dylib bug won't be an issue because Cargo won't start libstd until all subsequent rlib compilations are finished (e.g. it doesn't pipeline it)
Great! Okay, then I'll try to get that impl up. (I presume the "dylib bug won't be an issue" also applies to dylibs in the wild, right?)
That's the theory at least!

use rmeta_aux::Foo; pub fn main() { <del> let _ = Foo { field: 42 }; </del> <ins> let _ = Foo { field2: 42 }; </ins> }


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

<del> Subproject commit fd0428f622feee209e6014b802f5717d48d9e978 </del> <ins> Subproject commit 3e74853d1f9893cf2a47f28b658711d8f9f97b6b </ins>


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load <del> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. </del> <ins> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note:** This method is only available on platforms that support atomic /// operations on `u8`.


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], <del> /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the /// success ordering. </del> <ins> /// [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note:** This method is only available on platforms that support atomic /// operations on `u8`.


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load <del> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. </del> <ins> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note:** This method is only available on platforms that support atomic /// operations on pointers.


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], <del> /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the /// success ordering. </del> <ins> /// [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note:** This method is only available on platforms that support atomic /// operations on pointers.


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load <del> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. </del> <ins> /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note**: This method is only available on platforms that support atomic operations on #[doc = concat!("[`", $s_int_type, "`].")]


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

/// /// Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load <del> /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`] /// and must be equivalent to or weaker than the success ordering. </del> <ins> /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. </ins> /// /// **Note**: This method is only available on platforms that support atomic operations on #[doc = concat!("[`", $s_int_type, "`].")]


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new), <del> //(Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new), //(Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new), #[cfg(not(bootstrap))] (Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new), </ins> (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new), <del> //(Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new), </ins> (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new), <del> //(Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new), //(Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new), #[cfg(not(bootstrap))] (Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new), </ins> (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new), <del> //(AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new), </ins> (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), <ins> #[cfg(bootstrap)] </ins> _ => panic!("a failure ordering can't be stronger than a success ordering"), } };


Question:
Currently requires the failure ordering to "be equivalent to or weaker than a success ordering". On the other hand C11/C++11 requires only that "failure shall be no stronger than the success", which arguably means that one can write e.g. in C/C++ but not in Rust. Arguably, because neither C11 standard nor C++11 standard defines what it means for an ordering to be stronger from another. When the issue was raised in [LWG2445], the proposed and accepted resolution was to lift those restrictions altogether, leaving only requirement that "the failure argument shall not be nor ". It would be beneficial to remove success/failure ordering restrictions for reasons described in C++ proposal [P0418r2]. [LWG2445]: [P0418r2]: EDIT: Restrictions were lifted in clang & LLVM:
Blocked on The cmpxchg release acquire is accepted by LLVM but miscompiled on AArch64.
I'm about to send a PR that implements this.
I do have implementation ready as well, but that's fine, I can review instead :-).
I split it in a PR that renames the intrinsics first, and a separate PR for exposing the new ordering combinations afterwards.
Looks like llvm 12 doesn't support this: Can we make things conditionally fall back to a stronger ordering depending on the llvm version? I don't think we do anything like that in the library right now, but maybe the compiler already does things differently for different llvm versions?
Ah yes, some code checks . I suppose Builder::atomic_cmpxchg could check the same, and upgrade the ordering if necessary in that case.
Did exactly that in
To do: [x] Add codegen test. [x] Publicly expose the new orderings. [x] Update memory order lint to accept the new orderings.

let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new), <del> //(Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new), //(Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new), #[cfg(not(bootstrap))] (Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new), </ins> (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new), <del> //(Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new), </ins> (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new), <del> //(Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new), //(Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new), #[cfg(not(bootstrap))] (Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new), </ins> (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new), <del> //(AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new), </del> <ins> #[cfg(not(bootstrap))] (AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new), </ins> (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new), (_, AcqRel) => panic!("there is no such thing as an acquire-release failure ordering"), (_, Release) => panic!("there is no such thing as a release failure ordering"), <ins> #[cfg(bootstrap)] </ins> _ => panic!("a failure ordering can't be stronger than a success ordering"), } };


Question:
Here's the crashing code I came down to: An empty contains a single line: "pub mod " a file with the following code: This happened as I permuted type and size in my array definition. My intention was not to declare a zero sized array but to declare an array filled with zeros. Anyway, the compiler crashed. I noticed that if I remove the from the line in , it compiles fine. Backtrace:
cc
cc did the value visitor changes get merged?
is still waiting for review if that's the one you mean.
The ICE seems to be , though. So likely just needs a test (or checking that we already have an appropriate test)?
Maybe we should also find the PR that fixed this and beta nominate?
points to as being responsible for fixing this.
That PR is too big to backport. I suggest to just remove the assertion on beta as the ICE is properly fixed on master
Still need to backport
The fix is already on beta so backport is unneeded?
Yeah, playground confirms that this ICEs on stable but works fine on beta and nightly.

<ins> // build-pass // Verify that the compiler doesn't ICE during const prop while evaluating the index operation. #![allow(unconditional_panic)] fn main() { let cols = [0u32; 0]; cols[0]; } </ins>