Question:
Given the following code (): The current output is: This is rather confusing. It's not immediately clear what the difference between and this working code is (): Since is accepted, the user might be confused why would be considered a nominal type when isn't. The real reason why is an error is because it is an block for . Ideally the output should look like:
It seems like this only happens with auto traits. Regular traits already emit E0116 in this case (): Note that this still happens with auto traits in the same crate, but in this case wouldn't be applicable (): The diagnostic is still confusing in this case and could be rewritten to explicitly point out that is not allowed. modify labels: +D-confusing +F-auto_traits

<ins> An inherent `impl` was written on a dyn auto trait. Erroneous code example: ```compile_fail,E0785 #![feature(auto_traits)] auto trait AutoTrait {} impl dyn AutoTrait {} ``` Dyn objects allow any number of auto traits, plus at most one non-auto trait. The non-auto trait becomes the "principal trait". When checking if an impl on a dyn trait is coherent, the principal trait is normally the only one considered. Since the erroneous code has no principal trait, it cannot be implemented at all. Working example: ``` #![feature(auto_traits)] trait PrincipalTrait {} auto trait AutoTrait {} impl dyn PrincipalTrait + AutoTrait + Send {} ``` </ins>


Question:
Given the following code (): The current output is: This is rather confusing. It's not immediately clear what the difference between and this working code is (): Since is accepted, the user might be confused why would be considered a nominal type when isn't. The real reason why is an error is because it is an block for . Ideally the output should look like:
It seems like this only happens with auto traits. Regular traits already emit E0116 in this case (): Note that this still happens with auto traits in the same crate, but in this case wouldn't be applicable (): The diagnostic is still confusing in this case and could be rewritten to explicitly point out that is not allowed. modify labels: +D-confusing +F-auto_traits

ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } <ins> ty::Dynamic(..) => { struct_span_err!( self.tcx.sess, ty.span, E0785, "cannot define inherent `impl` for a dyn auto trait" ) .span_label(ty.span, "impl requires at least one non-auto trait") .note("define and implement a new trait or type instead") .emit(); } </ins> ty::Bool => { self.check_primitive_impl( item.def_id,


Question:
Given the following code (): The current output is: This is rather confusing. It's not immediately clear what the difference between and this working code is (): Since is accepted, the user might be confused why would be considered a nominal type when isn't. The real reason why is an error is because it is an block for . Ideally the output should look like:
It seems like this only happens with auto traits. Regular traits already emit E0116 in this case (): Note that this still happens with auto traits in the same crate, but in this case wouldn't be applicable (): The diagnostic is still confusing in this case and could be rewritten to explicitly point out that is not allowed. modify labels: +D-confusing +F-auto_traits

<ins> #![feature(auto_traits)] auto trait AutoTrait {} // You cannot impl your own `dyn AutoTrait`. impl dyn AutoTrait {} //~ERROR E0785 // You cannot impl someone else's `dyn AutoTrait` impl dyn Unpin {} //~ERROR E0785 fn main() {} </ins>


Question:
Given the following code (): The current output is: This is rather confusing. It's not immediately clear what the difference between and this working code is (): Since is accepted, the user might be confused why would be considered a nominal type when isn't. The real reason why is an error is because it is an block for . Ideally the output should look like:
It seems like this only happens with auto traits. Regular traits already emit E0116 in this case (): Note that this still happens with auto traits in the same crate, but in this case wouldn't be applicable (): The diagnostic is still confusing in this case and could be rewritten to explicitly point out that is not allowed. modify labels: +D-confusing +F-auto_traits

<ins> error[E0785]: cannot define inherent `impl` for a dyn auto trait --> $DIR/issue-85026.rs:5:6 | LL | impl dyn AutoTrait {} |      ^^^^^^^^^^^^^ impl requires at least one non-auto trait | = note: define and implement a new trait or type instead error[E0785]: cannot define inherent `impl` for a dyn auto trait --> $DIR/issue-85026.rs:8:6 | LL | impl dyn Unpin {} |      ^^^^^^^^^ impl requires at least one non-auto trait | = note: define and implement a new trait or type instead error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0785`. </ins>


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

from rust_types import * <del> rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True) </del> _gdb_version_matched = re.search('([0-9]+).([0-9]+)', gdb.VERSION) gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

return StdStringProvider(valobj) if rust_type == RustType.STD_OS_STRING: return StdOsStringProvider(valobj) <del> if rust_type == RustType.STD_STR and not rust_enabled: </del> <ins> if rust_type == RustType.STD_STR: </ins> return StdStrProvider(valobj) <ins> if rust_type == RustType.STD_SLICE: return StdSliceProvider(valobj) </ins> if rust_type == RustType.STD_VEC: return StdVecProvider(valobj) if rust_type == RustType.STD_VEC_DEQUE:


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

def display_hint(): return "string" <ins> def _enumerate_array_elements(element_ptrs): for (i, element_ptr) in enumerate(element_ptrs): key = "[{}]".format(i) element = element_ptr.dereference() try: # rust-lang/rust#64343: passing deref expr to `str` allows # catching exception on garbage pointer str(element) except RuntimeError: yield key, "inaccessible" break yield key, element class StdSliceProvider: def __init__(self, valobj): self.valobj = valobj self.length = int(valobj["length"]) self.data_ptr = valobj["data_ptr"] def to_string(self): return "{}(size={})".format(self.valobj.type, self.length) def children(self): return _enumerate_array_elements( self.data_ptr + index for index in xrange(self.length) ) @staticmethod def display_hint(): return "array" </ins> class StdVecProvider: def __init__(self, valobj):


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

return "Vec(size={})".format(self.length) def children(self): <del> saw_inaccessible = False for index in xrange(self.length): element_ptr = self.data_ptr + index if saw_inaccessible: return try: # rust-lang/rust#64343: passing deref expr to `str` allows # catching exception on garbage pointer str(element_ptr.dereference()) yield "[{}]".format(index), element_ptr.dereference() except RuntimeError: saw_inaccessible = True yield str(index), "inaccessible" </del> <ins> return _enumerate_array_elements( self.data_ptr + index for index in xrange(self.length) ) </ins> @staticmethod def display_hint():


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

return "VecDeque(size={})".format(self.size) def children(self): <del> for index in xrange(0, self.size): value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference() yield "[{}]".format(index), value </del> <ins> return _enumerate_array_elements( (self.data_ptr + ((self.tail + index) % self.cap)) for index in xrange(self.size) ) </ins> @staticmethod def display_hint():


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust <del> type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&str$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&[.+]$" --category Rust </del> <ins> type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?str$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?[.+]$" --category Rust </ins> type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

STD_STRING_REGEX = re.compile(r"^(alloc::(w+::)+)String$") <del> STD_STR_REGEX = re.compile(r"^&str$") STD_SLICE_REGEX = re.compile(r"^&[.+]$") </del> <ins> STD_STR_REGEX = re.compile(r"^&(mut )?str$") STD_SLICE_REGEX = re.compile(r"^&(mut )?[.+]$") </ins> STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(w+::)+)OsString$") STD_VEC_REGEX = re.compile(r"^(alloc::(w+::)+)Vec<.+>$") STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(w+::)+)VecDeque<.+>$")


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

// gdb-check:$1 = Vec(size=1000000000) = {[...]...} // gdb-command: print slice <del> // gdb-check:$2 = &[u8] {data_ptr: [...], length: 1000000000} </del> <ins> // gdb-check:$2 = &[u8](size=1000000000) = {[...]...} </ins> #![allow(unused_variables)]


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

<ins> // ignore-android: FIXME(#10381) // ignore-windows // compile-flags:-g // gdb-command: run // gdb-command: print slice // gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2} // gdbr-check: $1 = &[i32](size=3) = {0, 1, 2} // gdb-command: print mut_slice // gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7} // gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7} // gdb-command: print str_slice // gdb-check: $3 = "string slice" // gdb-command: print mut_str_slice // gdb-check: $4 = "mutable string slice" // lldb-command: run // lldb-command: print slice // lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 } // lldb-command: print mut_slice // lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 } // lldb-command: print str_slice // lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 } // lldb-command: print mut_str_slice // lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 } fn b() {} fn main() { let slice: &[i32] = &[0, 1, 2]; let mut_slice: &mut [i32] = &mut [2, 3, 5, 7]; let str_slice: &str = "string slice"; let mut mut_str_slice_buffer = String::from("mutable string slice"); let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str(); b(); // #break } </ins>


Question:
Currently, support for pretty-printing slice types is missing for rust-gdb.
Can you describe in more detail?
provides pretty-printing function for some Rust types, such as , , , etc. This allows gdb to display values of some types in a more readable way. I think it is implemented in the following files: , , Currently, slices can only be displayed as a pointer and a length value in the debugger. I hope rust-gdb can support displaying slices. I also noticed that already supports pretty-printing const slices (), but not mutable slices (). Maybe rust-lldb can also add pretty-printing support fur mutable slices.
label A-slice C-enhancement T-dev-tools

let rust_type_regexes = vec![ "^(alloc::([a-z_]+::)+)String$", <del> "^&str$", "^&[.+]$", </del> <ins> "^&(mut )?str$", "^&(mut )?[.+]$", </ins> "^(std::ffi::([a-z_]+::)+)OsString$", "^(alloc::([a-z_]+::)+)Vec<.+>$", "^(alloc::([a-z_]+::)+)VecDeque<.+>$",


Question:
As noted in which tracks the diagnostic issue, the standard library previously accepted code (with differing behavior) on a number of intrinsics with "intended to be const" arguments. Since , though, this code is rejected at compile-time. For example, this compiles on stable but not 1.54 (nightly as of this writing). I think at minimum we need to identify the set of code that changed behaviors and document that in release notes.
cc -- on the point about documenting this change in behavior in the release notes, would you be up for either identifying the set of intrinsics which changed behavior or documenting how to do so?
Looking back at the crater run, we only ran it in mode, which doesn't perform monomorphization. This is the reason why this wasn't caught earlier. The full crater run for beta is currently running, so we should be able to get a clearer picture of the breakage once it is done. Documenting this is difficult: the new behavior affects all intrinsics which use const arguments. A quick grep of stdarch shows 1741 intrinsics, of which about ~150 are stable.
This is in 1.54, not 1.53, so the currently running beta run won't catch anything, right? It may make sense to run a crater on the PR itself, though. It is worrying that so many intrinsics are affected towards a compile-error, vs. e.g. having a warning - perhaps deny-by-default - like clippy's on the atomic Ordering params...
run mode=build-only end= start= name=issue-
:okhand: Experiment created and queued. :mag: You can check out and . :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
The mechanism used to validate the immediates using const generics is: offering the validation feature: a post-monomorphization error while evaluating a forcing the evaluation of the const for the const generic parameters of a given intrinsic: e.g. the above is as and the body of the intrinsic will start with a static assertion ensuring is indeed a 4-bit value. Note that I've linked to the more common macros, but this mechanism is applied throughout including arch-specific intrinsics and validations: e.g. , or . Any intrinsic using these macros can cause an error like in the OP with an argument that doesn't pass the checks, but this set of functions should be equivalent to: all the intrinsics which have been ported to . This means this mechanism is very well centralized and could be deactivated depending on the new crater run results, however that'd mean that we would return to the current situation of, depending on the intrinsics, having assertions or crashes in LLVM instead.
And the move to 'proper' const generics and the new validation are coupled because we would otherwise have undefined behavior (or be unable to codegen? -- what would happen)? Or can we decouple them?
We get LLVM assertion failures if invalid values reach codegen. I'm not sure if decoupling is even possible. For example, these don't work in debug builds:
It might be possible to do something involving specialization on const arguments... that seems rather fragile though. An alternative might be to change the LLVM IR generated by rustc, but it seems like currently rustc has no idea about the structure of these LLVM intrinsics so that probably won't be easy either. How is it then possible that the example in the OP here compiles and runs on stable?
Previously stdarch had massive statements to convert the value to a constant argument for the intrinsic.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:rotatinglight: Experiment has encountered an error: command failed: exit code: 1 :hammerandwrench: If the error is fixed use the command. :sos: Can someone from the infra team check in on this? :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
retry
:hammerandwrench: Experiment queued again. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:rotatinglight: Experiment has encountered an error: command failed: exit code: 1 :hammerandwrench: If the error is fixed use the command. :sos: Can someone from the infra team check in on this? :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
edit end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master# name=issue-
:rotatinglight: Error: failed to parse the command :sos: If you have any trouble with Crater please ping ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
name=issue- end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master#
:rotatinglight: Error: it's only possible to edit queued experiments :sos: If you have any trouble with Crater please ping ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
retry
:hammerandwrench: Experiment queued again. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
name=issue- end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master#
:memo: Configuration of the experiment changed. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:tada: Experiment is completed! :barchart: 56 regressed and 14 fixed ( total) :newspaper: . :warning: If you notice any spurious failure ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
All of the new failures that weren't in the previous report seem to come from , which is already fixed.
And it seems it's only 2 new crates that depend on this version of . So while post-monomorphization errors are tough errors to trigger and find consistently, the results are at least encouraging. It can also be noted that the rough "evaluation of constant failed" error in the OP, has since improved on nightly, to somewhat acceptable levels. <details<summaryHere's how it looks now</summary</detailsAnd could be improved still if we, for example, specialized in the handful of actually used widths. It would allow mentioning the range bounds in the error message (or we could do some of the const fn string formatting hacks here of course).
Closing as working as intended. The error message has been improved, and a description of the potential breakage will be included in the 1.54 release notes ().

<ins> Version 1.54.0 (2021-07-29) ============================ Language ----------------------- - [You can now use macros for values in built-in attribute macros.][83366] While a seemingly minor addition on its own, this enables a lot of powerful functionality when combined correctly. Most notably you can now include external documentation in your crate by writing the following. ```rust #![doc = include_str!("README.md")] ``` You can also use this to include auto-generated modules: ```rust #[path = concat!(env!("OUT_DIR"), "/generated.rs")] mod generated; ``` - [You can now cast between unsized slice types (and types which contain unsized slices) in `const fn`.][85078] - [You can now use multiple generic lifetimes with `impl Trait` where the lifetimes don't explicitly outlive another.][84701] In code this means that you can now have `impl Trait<'a, 'b>` where as before you could only have `impl Trait<'a, 'b> where 'b: 'a`. Compiler ----------------------- - [Rustc will now search for custom JSON targets in `/lib/rustlib/<target-triple>/target.json` where `/` is the "sysroot" directory.][83800] You can find your sysroot directory by running `rustc --print sysroot`. - [Added `wasm` as a `target_family` for WebAssembly platforms.][84072] - [You can now use `#[target_feature]` on safe functions when targeting WebAssembly platforms.][84988] - [Improved debugger output for enums on Windows MSVC platforms.][85292] - [Added tier 3* support for `bpfel-unknown-none` and `bpfeb-unknown-none`.][79608] * Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries ----------------------- - [`panic::panic_any` will now `#[track_caller]`.][85745] - [Added `OutOfMemory` as a variant of `io::ErrorKind`.][84744] - [ `proc_macro::Literal` now implements `FromStr`.][84717] - [The implementations of vendor intrinsics in core::arch have been significantly refactored.][83278] The main user-visible changes are a 50% reduction in the size of libcore.rlib and stricter validation of constant operands passed to intrinsics. The latter is technically a breaking change, but allows Rust to more closely match the C vendor intrinsics API. Stabilized APIs --------------- - [`BTreeMap::into_keys`] - [`BTreeMap::into_values`] - [`HashMap::into_keys`] - [`HashMap::into_values`] - [`arch::wasm32`] - [`VecDeque::binary_search`] - [`VecDeque::binary_search_by`] - [`VecDeque::binary_search_by_key`] - [`VecDeque::partition_point`] Cargo ----------------------- - [Added the `--prune <spec>` option to `cargo-tree` to remove a package from the dependency graph.][cargo/9520] - [Added the `--depth` option to `cargo-tree` to print only to a certain depth in the tree ][cargo/9499] - [Added the `no-proc-macro` value to `cargo-tree --edges` to hide procedural macro dependencies.][cargo/9488] - [A new environment variable named `CARGO_TARGET_TMPDIR` is available.][cargo/9375] This variable points to a directory that integration tests and benches can use as a "scratchpad" for testing filesystem operations. [79608]: https://github.com/rust-lang/rust/pull/79608 [84988]: https://github.com/rust-lang/rust/pull/84988 [84701]: https://github.com/rust-lang/rust/pull/84701 [84072]: https://github.com/rust-lang/rust/pull/84072 [85745]: https://github.com/rust-lang/rust/pull/85745 [84744]: https://github.com/rust-lang/rust/pull/84744 [85078]: https://github.com/rust-lang/rust/pull/85078 [84717]: https://github.com/rust-lang/rust/pull/84717 [83800]: https://github.com/rust-lang/rust/pull/83800 [83366]: https://github.com/rust-lang/rust/pull/83366 [83278]: https://github.com/rust-lang/rust/pull/83278 [85292]: https://github.com/rust-lang/rust/pull/85292 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488 [cargo/9375]: https://github.com/rust-lang/cargo/pull/9375 [`BTreeMap::into_keys`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.into_keys [`BTreeMap::into_values`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.into_values [`HashMap::into_keys`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.into_keys [`HashMap::into_values`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.into_values [`arch::wasm32`]: https://doc.rust-lang.org/core/arch/wasm32/index.html [`VecDeque::binary_search`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search [`VecDeque::binary_search_by`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search_by [`VecDeque::binary_search_by_key`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.binary_search_by_key [`VecDeque::partition_point`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.partition_point </ins> Version 1.53.0 (2021-06-17) ============================


Question:
As noted in which tracks the diagnostic issue, the standard library previously accepted code (with differing behavior) on a number of intrinsics with "intended to be const" arguments. Since , though, this code is rejected at compile-time. For example, this compiles on stable but not 1.54 (nightly as of this writing). I think at minimum we need to identify the set of code that changed behaviors and document that in release notes.
cc -- on the point about documenting this change in behavior in the release notes, would you be up for either identifying the set of intrinsics which changed behavior or documenting how to do so?
Looking back at the crater run, we only ran it in mode, which doesn't perform monomorphization. This is the reason why this wasn't caught earlier. The full crater run for beta is currently running, so we should be able to get a clearer picture of the breakage once it is done. Documenting this is difficult: the new behavior affects all intrinsics which use const arguments. A quick grep of stdarch shows 1741 intrinsics, of which about ~150 are stable.
This is in 1.54, not 1.53, so the currently running beta run won't catch anything, right? It may make sense to run a crater on the PR itself, though. It is worrying that so many intrinsics are affected towards a compile-error, vs. e.g. having a warning - perhaps deny-by-default - like clippy's on the atomic Ordering params...
run mode=build-only end= start= name=issue-
:okhand: Experiment created and queued. :mag: You can check out and . :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
The mechanism used to validate the immediates using const generics is: offering the validation feature: a post-monomorphization error while evaluating a forcing the evaluation of the const for the const generic parameters of a given intrinsic: e.g. the above is as and the body of the intrinsic will start with a static assertion ensuring is indeed a 4-bit value. Note that I've linked to the more common macros, but this mechanism is applied throughout including arch-specific intrinsics and validations: e.g. , or . Any intrinsic using these macros can cause an error like in the OP with an argument that doesn't pass the checks, but this set of functions should be equivalent to: all the intrinsics which have been ported to . This means this mechanism is very well centralized and could be deactivated depending on the new crater run results, however that'd mean that we would return to the current situation of, depending on the intrinsics, having assertions or crashes in LLVM instead.
And the move to 'proper' const generics and the new validation are coupled because we would otherwise have undefined behavior (or be unable to codegen? -- what would happen)? Or can we decouple them?
We get LLVM assertion failures if invalid values reach codegen. I'm not sure if decoupling is even possible. For example, these don't work in debug builds:
It might be possible to do something involving specialization on const arguments... that seems rather fragile though. An alternative might be to change the LLVM IR generated by rustc, but it seems like currently rustc has no idea about the structure of these LLVM intrinsics so that probably won't be easy either. How is it then possible that the example in the OP here compiles and runs on stable?
Previously stdarch had massive statements to convert the value to a constant argument for the intrinsic.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:rotatinglight: Experiment has encountered an error: command failed: exit code: 1 :hammerandwrench: If the error is fixed use the command. :sos: Can someone from the infra team check in on this? :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
retry
:hammerandwrench: Experiment queued again. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:rotatinglight: Experiment has encountered an error: command failed: exit code: 1 :hammerandwrench: If the error is fixed use the command. :sos: Can someone from the infra team check in on this? :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
edit end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master# name=issue-
:rotatinglight: Error: failed to parse the command :sos: If you have any trouble with Crater please ping ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
name=issue- end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master#
:rotatinglight: Error: it's only possible to edit queued experiments :sos: If you have any trouble with Crater please ping ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
retry
:hammerandwrench: Experiment queued again. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
name=issue- end=masterc1ac408d93bb7adaa3a51dabab9266e82eee8 start=master#
:memo: Configuration of the experiment changed. :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:construction: Experiment is now running :information_source: Crater is a tool to run experiments across parts of the Rust ecosystem.
:tada: Experiment is completed! :barchart: 56 regressed and 14 fixed ( total) :newspaper: . :warning: If you notice any spurious failure ! :informationsource: Crater is a tool to run experiments across parts of the Rust ecosystem.
All of the new failures that weren't in the previous report seem to come from , which is already fixed.
And it seems it's only 2 new crates that depend on this version of . So while post-monomorphization errors are tough errors to trigger and find consistently, the results are at least encouraging. It can also be noted that the rough "evaluation of constant failed" error in the OP, has since improved on nightly, to somewhat acceptable levels. <details<summaryHere's how it looks now</summary</detailsAnd could be improved still if we, for example, specialized in the handful of actually used widths. It would allow mentioning the range bounds in the error message (or we could do some of the const fn string formatting hacks here of course).
Closing as working as intended. The error message has been improved, and a description of the potential breakage will be included in the 1.54 release notes ().

- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning that you can create an enum that has the exact layout and ABI of the type it contains. <del> - [You can now use outer attribute procedural macros on inline modules.][64273] </del> <ins> - [You can now use outer attribute procedural macros on inline modules.][64273] </ins> - [There are some *syntax-only* changes:][67131] - `default` is syntactically allowed before items in `trait` definitions. - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically


Question:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Since i don't know which version, when running on a project, the left sidebar of the docs no longer has a nav for all crates in the dependency graph. However, the documentation for all dependencies is still compiled. a Rust project with a few dependencies. : Left sidebar has a list of all dependencies, linking to each crate's local docs. : No such thing. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: I honestly don't remember. I update my nightly before every dev session. Allegedly that bug is 27 days old. <!-- Provide the version you are using that has the regression. --: <!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --
Appears to be a regression from , the call to was moved into , but this function is not called on the crate-root doc page. I tested locally that it fails on and works on .
Checking looks like this has made it onto the 1.53 beta.
cc
I think the ideal fix is around We should emit a sidebar- for the top page that just calls . And remove that comment, since we now have dynamic crate loading. A quicker fix is to just move the call to addSidebarCrates so it gets called independently from initSidebarItems. I like that less since the crates really are a sidebar item and should be treated as such.
I can do that if no one else wants to do it!
Go for it! I'm happy to review.
Assigning .
It's actually something I fixed in (still waiting for approval/review).
I propose we plan on landing and backporting to fix the regression: it's much smaller and limited to the specific fix. Then we can work on landing in nightly.
No, the approach taken in is problematic. The information is already there and we don't need this new file. EDIT: also, is ready, there is a debate for the other part of the PR (the change on module's sidebar) which I can move to another PR.
See - after some discussion, and concluded to merge as our quick fix. To explain why I proposed to add a tiny sidebar- We have one that's loaded by a variety of different pages. It also potentially has many different entry points. For instance, the primary entry point is that when itself is loaded, it runs various functions, adding event handlers and so on. Another entry point is that when sidebar- loads, it calls . That's the root cause of this bug - code in expected would get called, and for a subset of pages it wasn't. It's a bit inelegant to have a small file whose purpose is only to call a known function. But I think that inelegance is balanced against the improved maintainability of having most doc pages follow closer to the same code path through The more code paths, the more chances for bugs and the more complexity in testing. Another way to address this longer-term would be to eliminate the entrypoint entirely. Instead, when runs, it would trigger the load of sidebar-items and run any callbacks based on that load. Yet another way to address this would be to separate out from , so that is called unconditionally for all pages.

ty = it.type_(), path = relpath ); if parentlen == 0 { <del> // There is no sidebar-items.js beyond the crate root path // FIXME maybe dynamic crate loading can be merged here </del> <ins> write!( buffer, "<script defer src="{}sidebar-items{}.js"></script>", relpath, cx.shared.resource_suffix ); </ins> } else { <del> write!(buffer, "<script defer src="{path}sidebar-items.js"></script>", path = relpath); </del> <ins> write!(buffer, "<script defer src="{}sidebar-items.js"></script>", relpath); </ins> } // Closes sidebar-elems div. buffer.write_str("</div>"); }


Question:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Since i don't know which version, when running on a project, the left sidebar of the docs no longer has a nav for all crates in the dependency graph. However, the documentation for all dependencies is still compiled. a Rust project with a few dependencies. : Left sidebar has a list of all dependencies, linking to each crate's local docs. : No such thing. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: I honestly don't remember. I update my nightly before every dev session. Allegedly that bug is 27 days old. <!-- Provide the version you are using that has the regression. --: <!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --
Appears to be a regression from , the call to was moved into , but this function is not called on the crate-root doc page. I tested locally that it fails on and works on .
Checking looks like this has made it onto the 1.53 beta.
cc
I think the ideal fix is around We should emit a sidebar- for the top page that just calls . And remove that comment, since we now have dynamic crate loading. A quicker fix is to just move the call to addSidebarCrates so it gets called independently from initSidebarItems. I like that less since the crates really are a sidebar item and should be treated as such.
I can do that if no one else wants to do it!
Go for it! I'm happy to review.
Assigning .
It's actually something I fixed in (still waiting for approval/review).
I propose we plan on landing and backporting to fix the regression: it's much smaller and limited to the specific fix. Then we can work on landing in nightly.
No, the approach taken in is problematic. The information is already there and we don't need this new file. EDIT: also, is ready, there is a debate for the other part of the PR (the change on module's sidebar) which I can move to another PR.
See - after some discussion, and concluded to merge as our quick fix. To explain why I proposed to add a tiny sidebar- We have one that's loaded by a variety of different pages. It also potentially has many different entry points. For instance, the primary entry point is that when itself is loaded, it runs various functions, adding event handlers and so on. Another entry point is that when sidebar- loads, it calls . That's the root cause of this bug - code in expected would get called, and for a subset of pages it wasn't. It's a bit inelegant to have a small file whose purpose is only to call a known function. But I think that inelegance is balanced against the improved maintainability of having most doc pages follow closer to the same code path through The more code paths, the more chances for bugs and the more complexity in testing. Another way to address this longer-term would be to eliminate the entrypoint entirely. Instead, when runs, it would trigger the load of sidebar-items and run any callbacks based on that load. Yet another way to address this would be to separate out from , so that is called unconditionally for all pages.

)?; write_minify("search.js", static_files::SEARCH_JS)?; write_minify("settings.js", static_files::SETTINGS_JS)?; <ins> write_minify("sidebar-items.js", static_files::sidebar::ITEMS)?; </ins> if cx.shared.include_sources { write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?; }


Question:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --Since i don't know which version, when running on a project, the left sidebar of the docs no longer has a nav for all crates in the dependency graph. However, the documentation for all dependencies is still compiled. a Rust project with a few dependencies. : Left sidebar has a list of all dependencies, linking to each crate's local docs. : No such thing. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: I honestly don't remember. I update my nightly before every dev session. Allegedly that bug is 27 days old. <!-- Provide the version you are using that has the regression. --: <!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --
Appears to be a regression from , the call to was moved into , but this function is not called on the crate-root doc page. I tested locally that it fails on and works on .
Checking looks like this has made it onto the 1.53 beta.
cc
I think the ideal fix is around We should emit a sidebar- for the top page that just calls . And remove that comment, since we now have dynamic crate loading. A quicker fix is to just move the call to addSidebarCrates so it gets called independently from initSidebarItems. I like that less since the crates really are a sidebar item and should be treated as such.
I can do that if no one else wants to do it!
Go for it! I'm happy to review.
Assigning .
It's actually something I fixed in (still waiting for approval/review).
I propose we plan on landing and backporting to fix the regression: it's much smaller and limited to the specific fix. Then we can work on landing in nightly.
No, the approach taken in is problematic. The information is already there and we don't need this new file. EDIT: also, is ready, there is a debate for the other part of the PR (the change on module's sidebar) which I can move to another PR.
See - after some discussion, and concluded to merge as our quick fix. To explain why I proposed to add a tiny sidebar- We have one that's loaded by a variety of different pages. It also potentially has many different entry points. For instance, the primary entry point is that when itself is loaded, it runs various functions, adding event handlers and so on. Another entry point is that when sidebar- loads, it calls . That's the root cause of this bug - code in expected would get called, and for a subset of pages it wasn't. It's a bit inelegant to have a small file whose purpose is only to call a known function. But I think that inelegance is balanced against the improved maintainability of having most doc pages follow closer to the same code path through The more code paths, the more chances for bugs and the more complexity in testing. Another way to address this longer-term would be to eliminate the entrypoint entirely. Instead, when runs, it would trigger the load of sidebar-items and run any callbacks based on that load. Yet another way to address this would be to separate out from , so that is called unconditionally for all pages.

crate mod sidebar { /// File script to handle sidebar. crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); <ins> /// Top Level sidebar items script which will load a sidebar without items. crate static ITEMS: &str = include_str!("static/sidebar-items.js"); </ins> }


Question:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this: (at ) windows-gnu nightly: wasm target: the package for : Result: The invokes . depends on that is not present in the distribution. If I add it manually, the issue goes away. The flavor ships with that does not have this dependency. and (and likely everything between)
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-low +T-compiler +O-windows Edit: my assessment was wrong, this requires more prompt attention label -P-low +P-high
I have the same issue with "stable" rust 1.52.1 ( 2021-05-09) on Windows 10 with a wasm32-unknown-unknown target. Can you elaborate on how to quick-fix this by adding manually? Where can I get, and where do I put I only have from Mingw64, Mingw32, and many other SW packages. Is it the same? Btw. what hit me instantly is the move from LLVM 11 to 12. Might that be the issue?
Yes, at least enough so it works for me. Just rename any zlib binary, the library interface has been stable for a very long time, so it should just work. Or, if you are ok with using binaries received from strangers, take this: . When you have , you need to make it visible. Either place it in any location visible in environment variable, or place it next to the . For me it is located in . See if you want in-depth explanation where the Windows looks for the DLLs.
It works, thanks a lot. It was a bit confusing that I don't have rust-lld in the wasm target folder. Now I can work on my fullstack project again without worrying about OS specific issues :-)

.define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native); <del> if target != "aarch64-apple-darwin" { </del> <ins> if target != "aarch64-apple-darwin" && !target.contains("windows") { </ins> cfg.define("LLVM_ENABLE_ZLIB", "ON"); } else { cfg.define("LLVM_ENABLE_ZLIB", "OFF");


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

use crate::cell::UnsafeCell; <del> use crate::mem::MaybeUninit; </del> <ins> use crate::mem::{forget, MaybeUninit}; </ins> use crate::sys::cvt_nz; use crate::sys_common::lazy_box::{LazyBox, LazyInit};


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

unsafe { mutex.init() }; mutex } <ins> fn destroy(mutex: Box<Self>) { // We're not allowed to pthread_mutex_destroy a locked mutex, // so check first if it's unlocked. if unsafe { mutex.try_lock() } { unsafe { mutex.unlock() }; drop(mutex); } else { // The mutex is locked. This happens if a MutexGuard is leaked. // In this case, we just leak the Mutex too. forget(mutex); } } fn cancel_init(_: Box<Self>) { // In this case, we can just drop it without any checks, // since it cannot have been locked yet. } </ins> } impl Mutex {


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

use crate::cell::UnsafeCell; <ins> use crate::mem::forget; </ins> use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys_common::lazy_box::{LazyBox, LazyInit};


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

fn init() -> Box<Self> { Box::new(Self::new()) } <ins> fn destroy(mut rwlock: Box<Self>) { // We're not allowed to pthread_rwlock_destroy a locked rwlock, // so check first if it's unlocked. if *rwlock.write_locked.get_mut() || *rwlock.num_readers.get_mut() != 0 { // The rwlock is locked. This happens if a RwLock{Read,Write}Guard is leaked. // In this case, we just leak the RwLock too. forget(rwlock); } } fn cancel_init(_: Box<Self>) { // In this case, we can just drop it without any checks, // since it cannot have been locked yet. } </ins> } impl RwLock {


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

/// /// It might be called more than once per LazyBox, as multiple threads /// might race to initialize it concurrently, each constructing and initializing <del> /// their own box. (All but one of them will be destroyed right after.) </del> <ins> /// their own box. All but one of them will be passed to `cancel_init` right after. </ins> fn init() -> Box<Self>; <ins> /// Any surplus boxes from `init()` that lost the initialization race /// are passed to this function for disposal. /// /// The default implementation calls destroy(). fn cancel_init(x: Box<Self>) { Self::destroy(x); } /// This is called to destroy a used box. /// /// The default implementation just drops it. fn destroy(_: Box<Self>) {} </ins> } impl<T: LazyInit> LazyBox<T> {


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

Err(ptr) => { // Lost the race to another thread. // Drop the box we created, and use the one from the other thread instead. <del> drop(unsafe { Box::from_raw(new_ptr) }); </del> <ins> T::cancel_init(unsafe { Box::from_raw(new_ptr) }); </ins> ptr } }


Question:
I tried this code through miri: I expected to see this happen: No observable behaviour, including from miri (aside from "Unsupported Operation" errors). Instead, this happened: reports undefined behaviour in "Destroying locked mutex" when calling (Note: this report is correct, calling on a locked mutex is prescribed to be undefined behaviour by POSIX) This was tested on all latest versions of rustc, all using miri 0.1.54, on <details<summaryMiri Backtrace</summary<p</p</detailsThis is caused by issue presented in . However, I believe that it deserves new attention given that it causes miri to fail in safe code (and is not a miri false positive, as miri is correctly reporting undefined behaviour in calling ).
Assigning a priority according to the and removing . modify labels +P-high -I-prioritize
Well, Miri is just a tool to detect issues like this. It looks like back then the decision was made to ignore what POSIX says and instead to rely on what certain implementations do. Since Miri checks POSIX compliance as strictly as it can, this leads to Miri errors in safe code. Ideally we'd work towards getting the spec changed (there seems to be no good reason for this UB, and without something like Rust it is unclear why anyone in reasonable code would even want to do this). That's probably very hard though. Are there work-arounds where we can avoid calling when the lock is still held? Seems hard to do that atomically...
Indeed. And, as I've mentioned in the thread, I wouldn't consider this a bug in miri, for precisely that reason. One half of it could be destroying it potentially concurrent to it becoming locked, since destruction is presumably not atomic, though this wouldn't be an issue for rust. Another reasonable possibility would be for enhanced implementations that, for example, check and trap deadlocks, but as a consequence, couldn't permit being destroyed while locked (the issue was discussed somewhat on the Rust Community Discord, in the #black-magic channel, and this was one potential reason for the POSIX UB). I've actually considered this previously for my implementation, and that's really the only option to avoid strict UB, without fixing the spec (which will take some time, though I don't know how much). Since the destructor is &mut self, it doesn't need to be atomic. It could just be an AtomicBool (or any other atomic, possibly AtomicPtr, which IIRC is the only atomic dependency in libstd) that gets set on being locked, and cleared on unlock.
We could , and if we successfully acquire the lock, do and . If we couldn't acquire the lock, just leak...
I was about to ask what if someone else acquires the lock again just after we ... but that cannot happen since we have here. So, yeah, that could work.
Posix says it's UB to call that function on a different thread than the one that locked the mutex, so that wouldn't work, unfortunately.
I assume that was in the case that successfully called , so it's being unlocked on the thread that locked it.
Oh, right. I misread the comment. :) Then the only question that remains is whether it's okay to not call but still drop/reuse the memory. Without calling destroy, pthread doesn't know that memory is no longer a mutex it is managing. If it has some kind of linked list of mutexes or something, that could result in UB.
It probably has to be properly leaked. I would assume that the raw mutex needs to be properly treated as ned.
We can leak the box or drop the box depending on whether it's UB or not.
We have to leak the box.
A more extreme option is to get rid of pthread mutexes entirely. (So, implement our mutex/rwlock/condvars directly using atomics and platform-specific syscalls, like we already do for on most platforms.) That's still somewhere on my to do list. ^^'
You mean like (not sure if there's an issue for that)?
Yeah, either parking_lot, or something other thread parker based, or maybe something not thread parker based but directly using a futex (or whatever the platform supports) might be a better fit for std. It's a bit tricky to make those trade offs for all std users at once, but not having to deal with all this pthread stuff (and not having to Box them, etc.) would be very nice.
Lowering priority to P-medium because of the previous discussion in .
I honestly think this is the only reasonable solution. POSIX’s semantics are not a good fit for us.
We discussed this in a recent library team meeting, and we'll be going forward with this.
Yay!!! That gives Rust an opportunity to have better performance than pthreads, too. The one caveat is robust mutexes, but I don’t think Rust needs those.
That effort is now tracked here:
This has been fixed on Linux. We no longer use pthread locks on Linux. :)

fn drop(&mut self) { let ptr = *self.ptr.get_mut(); if !ptr.is_null() { <del> drop(unsafe { Box::from_raw(ptr) }); </del> <ins> T::destroy(unsafe { Box::from_raw(ptr) }); </ins> } } }


Question:
is not updated (line 1636) when (line 1623) panics. This lets 's implementation to retain the already dropped element. The bug was introduced in and affects stable Rust versions = 1.52. Here is the that demonstrates the double free without using unsafe Rust code. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
label regression-from-stable-to-stable
Assigning as discussed by and removing . modify labels +P-critical -I-prioritize
Interestingly there was a test for this, but it is wrong. The vec contains the index=5, even though it is the item that panics in its drop implementation. I guess the author of this test thought that returned the new value instead of the old value?
Learning about a double-free I introduced, a year later... :eyes: And honestly, I can clearly remember that when the test was first written, it caught the bug, but I just assumed it was an off-by-one error in the testing code itself, yikes

let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); if same_bucket(&mut *read_ptr, &mut *prev_ptr) { <ins> // Increase `gap.read` now since the drop may panic. gap.read += 1; </ins> /* We have found duplicate, drop it in-place */ ptr::drop_in_place(read_ptr); } else {


Question:
is not updated (line 1636) when (line 1623) panics. This lets 's implementation to retain the already dropped element. The bug was introduced in and affects stable Rust versions = 1.52. Here is the that demonstrates the double free without using unsafe Rust code. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
label regression-from-stable-to-stable
Assigning as discussed by and removing . modify labels +P-critical -I-prioritize
Interestingly there was a test for this, but it is wrong. The vec contains the index=5, even though it is the item that panics in its drop implementation. I guess the author of this test thought that returned the new value instead of the old value?
Learning about a double-free I introduced, a year later... :eyes: And honestly, I can clearly remember that when the test was first written, it caught the bug, but I just assumed it was an off-by-one error in the testing code itself, yikes

/* We have filled that place, so go further */ gap.write += 1; <ins> gap.read += 1; </ins> } <del> gap.read += 1; </del> } /* Technically we could let `gap` clean up with its Drop, but


Question:
is not updated (line 1636) when (line 1623) panics. This lets 's implementation to retain the already dropped element. The bug was introduced in and affects stable Rust versions = 1.52. Here is the that demonstrates the double free without using unsafe Rust code. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --:
label regression-from-stable-to-stable
Assigning as discussed by and removing . modify labels +P-critical -I-prioritize
Interestingly there was a test for this, but it is wrong. The vec contains the index=5, even though it is the item that panics in its drop implementation. I guess the author of this test thought that returned the new value instead of the old value?
Learning about a double-free I introduced, a year later... :eyes: And honestly, I can clearly remember that when the test was first written, it caught the bug, but I just assumed it was an off-by-one error in the testing code itself, yikes

#[test] fn test_vec_dedup_panicking() { #[derive(Debug)] <del> struct Panic { drop_counter: &'static AtomicU32, </del> <ins> struct Panic<'a> { drop_counter: &'a Cell<u32>, </ins> value: bool, index: usize, } <del> impl PartialEq for Panic { </del> <ins> impl<'a> PartialEq for Panic<'a> { </ins> fn eq(&self, other: &Self) -> bool { self.value == other.value } } <del> impl Drop for Panic { </del> <ins> impl<'a> Drop for Panic<'a> { </ins> fn drop(&mut self) { <del> let x = self.drop_counter.fetch_add(1, Ordering::SeqCst); assert!(x != 4); </del> <ins> self.drop_counter.set(self.drop_counter.get() + 1); if !std::thread::panicking() { assert!(self.index != 4); } </ins> } } <del> static DROP_COUNTER: AtomicU32 = AtomicU32::new(0); </del> <ins> let drop_counter = &Cell::new(0); </ins> let expected = [ <del> Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, </del> <ins> Panic { drop_counter, value: false, index: 0 }, Panic { drop_counter, value: false, index: 5 }, Panic { drop_counter, value: true, index: 6 }, Panic { drop_counter, value: true, index: 7 }, </ins> ]; let mut vec = vec![ <del> Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, </del> <ins> Panic { drop_counter, value: false, index: 0 }, </ins> // these elements get deduplicated <del> Panic { drop_counter: &DROP_COUNTER, value: false, index: 1 }, Panic { drop_counter: &DROP_COUNTER, value: false, index: 2 }, Panic { drop_counter: &DROP_COUNTER, value: false, index: 3 }, Panic { drop_counter: &DROP_COUNTER, value: false, index: 4 }, // here it panics Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, </del> <ins> Panic { drop_counter, value: false, index: 1 }, Panic { drop_counter, value: false, index: 2 }, Panic { drop_counter, value: false, index: 3 }, Panic { drop_counter, value: false, index: 4 }, // here it panics while dropping the item with index==4 Panic { drop_counter, value: false, index: 5 }, Panic { drop_counter, value: true, index: 6 }, Panic { drop_counter, value: true, index: 7 }, </ins> ]; <del> let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { vec.dedup(); })); </del> <ins> let _ = catch_unwind(AssertUnwindSafe(|| vec.dedup())).unwrap_err(); assert_eq!(drop_counter.get(), 4); </ins> let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index);


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

<del> Subproject commit 62046bf8b4eadd4fb398d59f1eebcc140506bf85 </del> <ins> Subproject commit 4fa9363ebba236f7c29ae11180db6051d7d2ce3b </ins>


Question:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: Compiling with , after the emsdk is activated and emcc works, to compile properly Instead, this happened: Prints this error: I've tried adding to no avail <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
runs successfully
Also is broken on ubuntu with the same error message (at least windows subsystem for linux)
rustc 1.53.0-nightly ( 2021-04-24) emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.12 () Here's some info I gathered: Rust tries to . I think Rust is assuming that this symbol comes from emscripten. emscripten has a : libc++abi.a: emscripten exceptions: this is what rustc is trying to use; libc++abi-noexcept.a: no exceptions: does not compile libc++abi-except.a: wasm exceptions: experimental; in emscripten's repo shows that was never compiled into libc++abi.a by This commit looks suspicious: Prior to emscripten SDK version 2.0.10, I think has been and never did anything. Rust probably shouldn't be calling a stubbed function. seems untested if you ask me because I don't know how it could ever have worked. I successfully compiled hello world with emscripten SDK version 2.0.9. That version still has the stub.
label I-prioritize T-compiler O-wasm
thanks for the analysis. Assigning priority as discussed in the of the Prioritization Working Group. Let's find someone who can have a look at this. label -I-prioritize +P-high +I-nominated
I recall with the LLVM 11 upgrade, the compat notes mentioned which version of Emscripten to use when compiling with the target. Once this bug is resolved, can we add a similar note for the releases that upgrade Rust to LLVM 12?
As mentioned the panic=unwind strategy is broken on wasm32-unknown-emscripten. I recommend to switch default to panic=abort. Note that also rust std lib has to be rebuilt with panic=abort to fix the undefined symbol errors. Testing on my side showed that the problem could be fixed by changing TargetOptions on line 38 to "panicstrategy: PanicStrategy::Abort," in file. Unfortunatelly I do not have experience in preparing pull request and have no capacity to get into it now.
This issue can be solved by setting the env var which will override any flags passed to emcc. See this comment - Passing these flags using the won't work, as they are not passed to the linker. I received this error in two places, one for symbol and one for , hence the flag.
Reported this on Emscripten:

} } <ins> // This is required by the compiler to exist (e.g., it's a lang item), but it's // never actually called by the compiler.  Emscripten EH doesn't use a // personality function at all, it instead uses __cxa_find_matching_catch. // Wasm error handling would use __gxx_personality_wasm0. </ins> #[lang = "eh_personality"] unsafe extern "C" fn rust_eh_personality( <del> version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, </del> <ins> _version: c_int, _actions: uw::_Unwind_Action, _exception_class: uw::_Unwind_Exception_Class, _exception_object: *mut uw::_Unwind_Exception, _context: *mut uw::_Unwind_Context, </ins> ) -> uw::_Unwind_Reason_Code { <del> __gxx_personality_v0(version, actions, exception_class, exception_object, context) </del> <ins> core::intrinsics::abort() </ins> } extern "C" {


Question:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: Compiling with , after the emsdk is activated and emcc works, to compile properly Instead, this happened: Prints this error: I've tried adding to no avail <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
runs successfully
Also is broken on ubuntu with the same error message (at least windows subsystem for linux)
rustc 1.53.0-nightly ( 2021-04-24) emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.12 () Here's some info I gathered: Rust tries to . I think Rust is assuming that this symbol comes from emscripten. emscripten has a : libc++abi.a: emscripten exceptions: this is what rustc is trying to use; libc++abi-noexcept.a: no exceptions: does not compile libc++abi-except.a: wasm exceptions: experimental; in emscripten's repo shows that was never compiled into libc++abi.a by This commit looks suspicious: Prior to emscripten SDK version 2.0.10, I think has been and never did anything. Rust probably shouldn't be calling a stubbed function. seems untested if you ask me because I don't know how it could ever have worked. I successfully compiled hello world with emscripten SDK version 2.0.9. That version still has the stub.
label I-prioritize T-compiler O-wasm
thanks for the analysis. Assigning priority as discussed in the of the Prioritization Working Group. Let's find someone who can have a look at this. label -I-prioritize +P-high +I-nominated
I recall with the LLVM 11 upgrade, the compat notes mentioned which version of Emscripten to use when compiling with the target. Once this bug is resolved, can we add a similar note for the releases that upgrade Rust to LLVM 12?
As mentioned the panic=unwind strategy is broken on wasm32-unknown-emscripten. I recommend to switch default to panic=abort. Note that also rust std lib has to be rebuilt with panic=abort to fix the undefined symbol errors. Testing on my side showed that the problem could be fixed by changing TargetOptions on line 38 to "panicstrategy: PanicStrategy::Abort," in file. Unfortunatelly I do not have experience in preparing pull request and have no capacity to get into it now.
This issue can be solved by setting the env var which will override any flags passed to emcc. See this comment - Passing these flags using the won't work, as they are not passed to the linker. I received this error in two places, one for symbol and one for , hence the flag.
Reported this on Emscripten:

tinfo: *const TypeInfo, dest: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void, ) -> !; <del> fn __gxx_personality_v0( version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context, ) -> uw::_Unwind_Reason_Code; </del> }


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

<del> Subproject commit 453affaaa1762a065d2857970b8333017211208c </del> <ins> Subproject commit 5dde0fe6de2941c9ef16bc1e9d91ecf20ac5ee8b </ins>