Question:
Given the following code (): Rust gives a diagnostic suggesting deriving : However, adding leads the compiler to still give an error about not supporting this. A non-nightly compiler should not give the second error at all; it should only give the first, saying that the only supported types are integers, and . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
assigning this to project-const-generics, getting worked on in https://rust-
claim
To fix this issue, you can do the following steps: grep for "forbidden as the type of a const generic parameter" look at that function for a bit change it so that the second error isn't emitted on stable (probably actually change the control flow to start by branching on In case you are interested but need more help to fix this, feel free to reach out to me on
claim

impl A for B {} fn test<const T: &'static dyn A>() { <del> //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used </del> <ins> //[full]~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used </ins> //[min]~^^ ERROR `&'static (dyn A + 'static)` is forbidden unimplemented!() }


Question:
Given the following code (): Rust gives a diagnostic suggesting deriving : However, adding leads the compiler to still give an error about not supporting this. A non-nightly compiler should not give the second error at all; it should only give the first, saying that the only supported types are integers, and . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
assigning this to project-const-generics, getting worked on in https://rust-
claim
To fix this issue, you can do the following steps: grep for "forbidden as the type of a const generic parameter" look at that function for a bit change it so that the second error isn't emitted on stable (probably actually change the control flow to start by branching on In case you are interested but need more help to fix this, feel free to reach out to me on
claim

= note: the only supported types are integers, `bool` and `char` = help: more complex types are supported with `#![feature(adt_const_params)]` <del> error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants --> $DIR/nested-type.rs:15:5 | LL |     Foo::<17>::value() |     ^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 2 previous errors </del> <ins> error: aborting due to previous error </ins> <del> For more information about this error, try `rustc --explain E0015`. </del>


Question:
Given the following code (): Rust gives a diagnostic suggesting deriving : However, adding leads the compiler to still give an error about not supporting this. A non-nightly compiler should not give the second error at all; it should only give the first, saying that the only supported types are integers, and . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
assigning this to project-const-generics, getting worked on in https://rust-
claim
To fix this issue, you can do the following steps: grep for "forbidden as the type of a const generic parameter" look at that function for a bit change it so that the second error isn't emitted on stable (probably actually change the control flow to start by branching on In case you are interested but need more help to fix this, feel free to reach out to me on
claim

} Foo::<17>::value() <del> //~^ ERROR cannot call non-const fn </del> <ins> //[full]~^ ERROR cannot call non-const fn </ins> }]>; fn main() {}


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

use super::{Custom, ErrorData, ErrorKind, SimpleMessage}; use alloc::boxed::Box; <ins> use core::marker::PhantomData; </ins> use core::mem::{align_of, size_of}; use core::ptr::NonNull;


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

const TAG_OS: usize = 0b10; const TAG_SIMPLE: usize = 0b11; <ins> /// The internal representation. /// /// See the module docs for more, this is just a way to hack in a check that we /// indeed are not unwind-safe. /// /// ```compile_fail,E0277 /// fn is_unwind_safe<T: core::panic::UnwindSafe>() {} /// is_unwind_safe::<std::io::Error>(); /// ``` </ins> #[repr(transparent)] <del> pub(super) struct Repr(NonNull<()>); </del> <ins> pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>); </ins> // All the types `Repr` stores internally are Send + Sync, and so is it. unsafe impl Send for Repr {}


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

// box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore, // `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the // `new_unchecked` is safe. <del> let res = Self(unsafe { NonNull::new_unchecked(tagged) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

pub(super) fn new_os(code: i32) -> Self { let utagged = ((code as usize) << 32) | TAG_OS; // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. <del> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

pub(super) fn new_simple(kind: ErrorKind) -> Self { let utagged = ((kind as usize) << 32) | TAG_SIMPLE; // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. <del> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }); </del> <ins> let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData); </ins> // quickly smoke-check we encoded the right thing (This generally will // only run in libstd's tests, unless the user uses -Zbuild-std) debug_assert!(


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 code: I expected to see this happen: either it to compile or not compile. Instead, this happened: it compiled but only on 64-bit platforms. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: Rust 1.59 (where it did not compile no matter what platform) <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Not sure what the best approach is here. We could just to restore consistency from which made auto-implement . cc
which non-64bit platform does reproduce the issue (not sure if this question matters a lot)?
All platforms that have and . For example, . This is caused by this code:
Ah, should have or something along those lines. I'll get a fix for this up later this evening or tomorrow.
Hmm, this should probably not be closed, unless prioritization will still see it if it is closed.
Yeah, for backports I think the issue stays open until the backport is landed or decided against. Reopened for tracking.

#[inline] pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self { // Safety: References are never null. <del> Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }) </del> <ins> Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData) </ins> } #[inline]


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

//! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. <del> use std::collections::HashSet; </del> use std::fs; use std::io; use std::path::{Path, PathBuf};


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

let paths = builder .paths .iter() <del> .map(components_simplified) .filter_map(|path| { if path.get(0) == Some(&"compiler") { path.get(1).map(|p| p.to_owned()) } else { None } </del> <ins> .filter(|path| { let components = components_simplified(path); components.len() >= 2 && components[0] == "compiler" </ins> }) .collect::<Vec<_>>();


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); <del> let mut compiler_crates = HashSet::new(); if paths.is_empty() { // Find dependencies for top level crates. for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { compiler_crates.extend( builder .in_tree_crates(root_crate, Some(target)) .into_iter() .map(|krate| krate.name), ); } </del> <ins> let root_crates = if paths.is_empty() { vec![ INTERNER.intern_str("rustc_driver"), INTERNER.intern_str("rustc_codegen_llvm"), INTERNER.intern_str("rustc_codegen_ssa"), ] </ins> } else { <del> for root_crate in paths { if !builder.src.join("compiler").join(&root_crate).exists() { builder.info(&format!( "tskipping - compiler/{} (unknown compiler crate)", root_crate )); } else { compiler_crates.extend( builder .in_tree_crates(root_crate, Some(target)) .into_iter() .map(|krate| krate.name), ); } } } </del> <ins> paths.into_iter().map(|p| builder.crate_paths[p]).collect() }; // Find dependencies for top level crates. let compiler_crates = root_crates.iter().flat_map(|krate| { builder.in_tree_crates(krate, Some(target)).into_iter().map(|krate| krate.name) }); </ins> let mut to_open = None; <del> for krate in &compiler_crates { </del> <ins> for krate in compiler_crates { </ins> // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself.


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

ar: HashMap<TargetSelection, PathBuf>, ranlib: HashMap<TargetSelection, PathBuf>, // Miscellaneous <ins> // allow bidirectional lookups: both name -> path and path -> name </ins> crates: HashMap<Interned<String>, Crate>, <ins> crate_paths: HashMap<PathBuf, Interned<String>>, </ins> is_sudo: bool, ci_env: CiEnv, delayed_failures: RefCell<Vec<String>>,


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

ar: HashMap::new(), ranlib: HashMap::new(), crates: HashMap::new(), <ins> crate_paths: HashMap::new(), </ins> is_sudo, ci_env: CiEnv::current(), delayed_failures: RefCell::new(Vec::new()),


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

.filter(|dep| dep.source.is_none()) .map(|dep| INTERNER.intern_string(dep.name)) .collect(); <del> build.crates.insert(name, Crate { name, deps, path }); </del> <ins> let krate = Crate { name, deps, path }; let relative_path = krate.local_path(build); build.crates.insert(name, krate); let existing_path = build.crate_paths.insert(relative_path, name); assert!(existing_path.is_none(), "multiple crates with the same path"); </ins> } } }


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

use crate::tool::{self, SourceType, Tool}; use crate::toolstate::ToolState; use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t}; <del> use crate::Crate as CargoCrate; </del> use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/tmp/work";


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

fn make_run(run: RunConfig<'_>) { let builder = run.builder; let compiler = builder.compiler(builder.top_stage, run.build_triple()); <ins> let krate = builder.crate_paths[&run.path]; let test_kind = builder.kind.into(); </ins> <del> for krate in builder.in_tree_crates("rustc-main", Some(run.target)) { if krate.path.ends_with(&run.path) { let test_kind = builder.kind.into(); builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, krate: krate.name, }); } } </del> <ins> builder.ensure(CrateLibrustc { compiler, target: run.target, test_kind, krate }); </ins> } fn run(self, builder: &Builder<'_>) {


Question:
I tried this code: I expected to see this happen: bootstrap documents the whole compiler, like it does for . Instead, this happened: The problem is that is too naive and expects the name of each crate to match its file path on disk: It needs to map from the path to the name somehow. There's already a way to go from the name to the path: but I don't think there's a way to do the reverse. HEAD is . label +A-bootstrap
label: +A-bootstrap
label: +E-mentor +A-rustbuild

fn make_run(run: RunConfig<'_>) { let builder = run.builder; let compiler = builder.compiler(builder.top_stage, run.build_triple()); <ins> let test_kind = builder.kind.into(); let krate = builder.crate_paths[&run.path]; </ins> <del> let make = |mode: Mode, krate: &CargoCrate| { let test_kind = builder.kind.into(); builder.ensure(Crate { compiler, target: run.target, mode, test_kind, krate: krate.name, }); }; for krate in builder.in_tree_crates("test", Some(run.target)) { if krate.path.ends_with(&run.path) { make(Mode::Std, krate); } } </del> <ins> builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, test_kind, krate }); </ins> } /// Runs all unit tests plus documentation tests for a given crate defined


Question:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --run this in miri to reproduce the ice: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Looks like it tries to access the discriminant (field 0 of ), but then this case does not apply: The case does not apply because has size 8, but the field only has size 1. I didn't know types can have padding in them... in fact this is a type with layout where the size of the layout is bigger than the size of the scalar. This has me slightly worried about our code path which has less strict sanity checks. Is it possible to have a ScalarPair layout with one field where that one field covers both components of the pair and yes is smaller than the entire type? Miri (and CTFE) would go completely wrong on that.
Oh, turns out codegen uses the same logic: So I think a similar bug can somehow be triggered in codegen. I am just not sure how to make it call in the right way...
I am still missing something, the bug doesn't reproduce as often as it should... e.g., this one doesn't ICE but this one does Also I noticed that this type has ABI. do you know why lose their newtype layout optimizations with but do not? Should we really give enums a layout? Or is "Scalars do not have padding" part of the contract of layout computation?
FWIW, if I put this kind of sanity check also into Miri, things explode spectacularly. This type from memchr ends up with a immediate while having ABI. I suspect this is because even when the enum has layout, its variant (after a downcast) can have layout. That sounds like yet another bug in layout computation to me. EDIT: Also, just fixing the logic in will not be enough. We'd still be loading an 8-byte scalar which is partially uninit (yielding an entirely uninit scalar in Miri) and then try to get an integer out of that, which would raise UB. The assumption that scalars do not have padding is laced throughout Miri.
Not really a why in the sense you're asking for, but the layout computation makes the struct decision right here: For fieldless enums, is def missing an alignment check
So this is just a bug in layout computation then, and we are okay with enums losing their layout (and hence their niche)? That would be a big relief. ;)
I made that a separate issue: So this issue now is about some enums violating the invariant that layout types do not have padding.
here is already , so this is not the place where the alignment check is missing. I am not sure where is the right place though... However, I also cannot see any code in the enum path that would take into account , so I am probably missing something.
Actually the problem is the fix () for (the same code as this problem^^): that introduced the branch, which uses scalar layout even when it should not be used.
This is quite interesting, and I am not sure what to do. The problem is that on the one hand, must have layout since it has padding. on the other hand, since this enum has explicit discriminants, parts of the compiler expect that they can on it, which means it must have layout. It is impossible to satisfy both of these constraints together. any ideas for what to do here?
(Digging a bit deeper) it's not [just] about having explicit discriminants, but rather that enums can be the input to a cast and cast values are expected to be represented as immediates. Allowing on enums looks like a mistake... (we disallow , FWIW)
FWIW, here's basically the same bug during CTFE, though for some reason it doesn't cause an ICE: So we can have this as a testcase in rustc.

if layout_variants.iter().all(|v| v.abi.is_uninhabited()) { abi = Abi::Uninhabited; <del> } else if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { // Without latter check aligned enums with custom discriminant values // Would result in ICE see the issue #92464 for more info </del> <ins> } else if tag.size(dl) == size { // Make sure we only use scalar layout when the enum is entirely its // own tag (i.e. it has no padding nor any non-ZST variant fields). </ins> abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums.


Question:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --run this in miri to reproduce the ice: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Looks like it tries to access the discriminant (field 0 of ), but then this case does not apply: The case does not apply because has size 8, but the field only has size 1. I didn't know types can have padding in them... in fact this is a type with layout where the size of the layout is bigger than the size of the scalar. This has me slightly worried about our code path which has less strict sanity checks. Is it possible to have a ScalarPair layout with one field where that one field covers both components of the pair and yes is smaller than the entire type? Miri (and CTFE) would go completely wrong on that.
Oh, turns out codegen uses the same logic: So I think a similar bug can somehow be triggered in codegen. I am just not sure how to make it call in the right way...
I am still missing something, the bug doesn't reproduce as often as it should... e.g., this one doesn't ICE but this one does Also I noticed that this type has ABI. do you know why lose their newtype layout optimizations with but do not? Should we really give enums a layout? Or is "Scalars do not have padding" part of the contract of layout computation?
FWIW, if I put this kind of sanity check also into Miri, things explode spectacularly. This type from memchr ends up with a immediate while having ABI. I suspect this is because even when the enum has layout, its variant (after a downcast) can have layout. That sounds like yet another bug in layout computation to me. EDIT: Also, just fixing the logic in will not be enough. We'd still be loading an 8-byte scalar which is partially uninit (yielding an entirely uninit scalar in Miri) and then try to get an integer out of that, which would raise UB. The assumption that scalars do not have padding is laced throughout Miri.
Not really a why in the sense you're asking for, but the layout computation makes the struct decision right here: For fieldless enums, is def missing an alignment check
So this is just a bug in layout computation then, and we are okay with enums losing their layout (and hence their niche)? That would be a big relief. ;)
I made that a separate issue: So this issue now is about some enums violating the invariant that layout types do not have padding.
here is already , so this is not the place where the alignment check is missing. I am not sure where is the right place though... However, I also cannot see any code in the enum path that would take into account , so I am probably missing something.
Actually the problem is the fix () for (the same code as this problem^^): that introduced the branch, which uses scalar layout even when it should not be used.
This is quite interesting, and I am not sure what to do. The problem is that on the one hand, must have layout since it has padding. on the other hand, since this enum has explicit discriminants, parts of the compiler expect that they can on it, which means it must have layout. It is impossible to satisfy both of these constraints together. any ideas for what to do here?
(Digging a bit deeper) it's not [just] about having explicit discriminants, but rather that enums can be the input to a cast and cast values are expected to be represented as immediates. Allowing on enums looks like a mistake... (we disallow , FWIW)
FWIW, here's basically the same bug during CTFE, though for some reason it doesn't cause an ICE: So we can have this as a testcase in rustc.

fn main() { let aligned = Aligned::Zero; let fo = aligned as u8; <del> println!("foo {}",fo); </del> <ins> println!("foo {}", fo); assert_eq!(fo, 0); println!("{}", tou8(Aligned::Zero)); assert_eq!(tou8(Aligned::Zero), 0); } #[inline(never)] fn tou8(al: Aligned) -> u8 { // Cast behind a function call so ConstProp does not see it // (so that we can test codegen). al as u8 </ins> }


Question:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --run this in miri to reproduce the ice: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Looks like it tries to access the discriminant (field 0 of ), but then this case does not apply: The case does not apply because has size 8, but the field only has size 1. I didn't know types can have padding in them... in fact this is a type with layout where the size of the layout is bigger than the size of the scalar. This has me slightly worried about our code path which has less strict sanity checks. Is it possible to have a ScalarPair layout with one field where that one field covers both components of the pair and yes is smaller than the entire type? Miri (and CTFE) would go completely wrong on that.
Oh, turns out codegen uses the same logic: So I think a similar bug can somehow be triggered in codegen. I am just not sure how to make it call in the right way...
I am still missing something, the bug doesn't reproduce as often as it should... e.g., this one doesn't ICE but this one does Also I noticed that this type has ABI. do you know why lose their newtype layout optimizations with but do not? Should we really give enums a layout? Or is "Scalars do not have padding" part of the contract of layout computation?
FWIW, if I put this kind of sanity check also into Miri, things explode spectacularly. This type from memchr ends up with a immediate while having ABI. I suspect this is because even when the enum has layout, its variant (after a downcast) can have layout. That sounds like yet another bug in layout computation to me. EDIT: Also, just fixing the logic in will not be enough. We'd still be loading an 8-byte scalar which is partially uninit (yielding an entirely uninit scalar in Miri) and then try to get an integer out of that, which would raise UB. The assumption that scalars do not have padding is laced throughout Miri.
Not really a why in the sense you're asking for, but the layout computation makes the struct decision right here: For fieldless enums, is def missing an alignment check
So this is just a bug in layout computation then, and we are okay with enums losing their layout (and hence their niche)? That would be a big relief. ;)
I made that a separate issue: So this issue now is about some enums violating the invariant that layout types do not have padding.
here is already , so this is not the place where the alignment check is missing. I am not sure where is the right place though... However, I also cannot see any code in the enum path that would take into account , so I am probably missing something.
Actually the problem is the fix () for (the same code as this problem^^): that introduced the branch, which uses scalar layout even when it should not be used.
This is quite interesting, and I am not sure what to do. The problem is that on the one hand, must have layout since it has padding. on the other hand, since this enum has explicit discriminants, parts of the compiler expect that they can on it, which means it must have layout. It is impossible to satisfy both of these constraints together. any ideas for what to do here?
(Digging a bit deeper) it's not [just] about having explicit discriminants, but rather that enums can be the input to a cast and cast values are expected to be represented as immediates. Allowing on enums looks like a mistake... (we disallow , FWIW)
FWIW, here's basically the same bug during CTFE, though for some reason it doesn't cause an ICE: So we can have this as a testcase in rustc.

<ins> // normalize-stderr-test "pref: Align([1-8] bytes)" -> "pref: $$PREF_ALIGN" #![crate_type = "lib"] #![feature(rustc_attrs)] // This cannot use `Scalar` abi since there is padding. #[rustc_layout(debug)] #[repr(align(8))] pub enum Aligned1 { //~ ERROR: layout_of Zero = 0, One = 1, } // This should use `Scalar` abi. #[rustc_layout(debug)] #[repr(align(1))] pub enum Aligned2 { //~ ERROR: layout_of Zero = 0, One = 1, } </ins>


Question:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --run this in miri to reproduce the ice: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Looks like it tries to access the discriminant (field 0 of ), but then this case does not apply: The case does not apply because has size 8, but the field only has size 1. I didn't know types can have padding in them... in fact this is a type with layout where the size of the layout is bigger than the size of the scalar. This has me slightly worried about our code path which has less strict sanity checks. Is it possible to have a ScalarPair layout with one field where that one field covers both components of the pair and yes is smaller than the entire type? Miri (and CTFE) would go completely wrong on that.
Oh, turns out codegen uses the same logic: So I think a similar bug can somehow be triggered in codegen. I am just not sure how to make it call in the right way...
I am still missing something, the bug doesn't reproduce as often as it should... e.g., this one doesn't ICE but this one does Also I noticed that this type has ABI. do you know why lose their newtype layout optimizations with but do not? Should we really give enums a layout? Or is "Scalars do not have padding" part of the contract of layout computation?
FWIW, if I put this kind of sanity check also into Miri, things explode spectacularly. This type from memchr ends up with a immediate while having ABI. I suspect this is because even when the enum has layout, its variant (after a downcast) can have layout. That sounds like yet another bug in layout computation to me. EDIT: Also, just fixing the logic in will not be enough. We'd still be loading an 8-byte scalar which is partially uninit (yielding an entirely uninit scalar in Miri) and then try to get an integer out of that, which would raise UB. The assumption that scalars do not have padding is laced throughout Miri.
Not really a why in the sense you're asking for, but the layout computation makes the struct decision right here: For fieldless enums, is def missing an alignment check
So this is just a bug in layout computation then, and we are okay with enums losing their layout (and hence their niche)? That would be a big relief. ;)
I made that a separate issue: So this issue now is about some enums violating the invariant that layout types do not have padding.
here is already , so this is not the place where the alignment check is missing. I am not sure where is the right place though... However, I also cannot see any code in the enum path that would take into account , so I am probably missing something.
Actually the problem is the fix () for (the same code as this problem^^): that introduced the branch, which uses scalar layout even when it should not be used.
This is quite interesting, and I am not sure what to do. The problem is that on the one hand, must have layout since it has padding. on the other hand, since this enum has explicit discriminants, parts of the compiler expect that they can on it, which means it must have layout. It is impossible to satisfy both of these constraints together. any ideas for what to do here?
(Digging a bit deeper) it's not [just] about having explicit discriminants, but rather that enums can be the input to a cast and cast values are expected to be represented as immediates. Allowing on enums looks like a mistake... (we disallow , FWIW)
FWIW, here's basically the same bug during CTFE, though for some reason it doesn't cause an ICE: So we can have this as a testcase in rustc.

<ins> error: layout_of(Aligned1) = Layout { fields: Arbitrary { offsets: [ Size(0 bytes), ], memory_index: [ 0, ], }, variants: Multiple { tag: Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, tag_encoding: Direct, tag_field: 0, variants: [ Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 0, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), }, Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 1, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), }, ], }, abi: Aggregate { sized: true, }, largest_niche: Some( Niche { offset: Size(0 bytes), value: Int( I8, false, ), valid_range: 0..=1, }, ), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: $PREF_ALIGN, }, size: Size(8 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:8:1 | LL | pub enum Aligned1 { | ^^^^^^^^^^^^^^^^^ error: layout_of(Aligned2) = Layout { fields: Arbitrary { offsets: [ Size(0 bytes), ], memory_index: [ 0, ], }, variants: Multiple { tag: Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, tag_encoding: Direct, tag_field: 0, variants: [ Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 0, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), }, Layout { fields: Arbitrary { offsets: [], memory_index: [], }, variants: Single { index: 1, }, abi: Aggregate { sized: true, }, largest_niche: None, align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), }, ], }, abi: Scalar( Initialized { value: Int( I8, false, ), valid_range: 0..=1, }, ), largest_niche: Some( Niche { offset: Size(0 bytes), value: Int( I8, false, ), valid_range: 0..=1, }, ), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $PREF_ALIGN, }, size: Size(1 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:16:1 | LL | pub enum Aligned2 { | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors </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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

// so add an empty section. if file.format() == object::BinaryFormat::Coff { file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text); <ins> // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the // default mangler in `object` crate. file.set_mangling(object::write::Mangling::None); </ins> } for (sym, kind) in symbols.iter() {


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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { if info.level.is_below_threshold(export_threshold) || info.used { symbols.push(( <del> symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum), </del> <ins> symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), </ins> info.kind, )); }


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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; <del> use rustc_middle::ty::{SymbolName, TyCtxt}; </del> <ins> use rustc_middle::ty::{self, SymbolName, TyCtxt}; </ins> use rustc_session::config::CrateType; use rustc_target::spec::SanitizerSet;


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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

} } <ins> /// This is the symbol name of the given instance as seen by the linker. /// /// On 32-bit Windows symbols are decorated according to their calling conventions. pub fn linking_symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, ) -> String { use rustc_target::abi::call::Conv; let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); let target = &tcx.sess.target; if !target.is_like_windows { // Mach-O has a global "_" suffix and `object` crate will handle it. // ELF does not have any symbol decorations. return undecorated; } let x86 = match &target.arch[..] { "x86" => true, "x86_64" => false, // Only x86/64 use symbol decorations. _ => return undecorated, }; let instance = match symbol { ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) if tcx.is_static(def_id) => { None } ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), ExportedSymbol::Generic(def_id, substs) => Some(Instance::new(def_id, substs)), // DropGlue always use the Rust calling convention and thus follow the target's default // symbol decoration scheme. ExportedSymbol::DropGlue(..) => None, // NoDefId always follow the target's default symbol decoration scheme. ExportedSymbol::NoDefId(..) => None, }; let (conv, args) = instance .map(|i| { tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty()))) .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) }) .map(|fnabi| (fnabi.conv, &fnabi.args[..])) .unwrap_or((Conv::Rust, &[])); // Decorate symbols with prefices, suffices and total number of bytes of arguments. // Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170 let (prefix, suffix) = match conv { Conv::X86Fastcall => ("@", "@"), Conv::X86Stdcall => ("_", "@"), Conv::X86VectorCall => ("", "@@"), _ => { if x86 { undecorated.insert(0, '_'); } return undecorated; } }; let args_in_bytes: u64 = args .iter() .map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8)) .sum(); format!("{prefix}{undecorated}{suffix}{args_in_bytes}") } </ins> fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, String> { // Build up a map from DefId to a `NativeLib` structure, where // `NativeLib` internally contains information about


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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

#![feature(nll)] #![feature(associated_type_bounds)] #![feature(strict_provenance)] <ins> #![feature(int_roundings)] </ins> #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)]


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 code: It seems like is not working anymore. <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --: <!-- Provide the version you are using that has the regression. --: </p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged --<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
Probably another issue with stdcall symbol name mangling uncovered by cc cc
Hmm, seems that we would have to replicate the name decoration scheme in Rust?
claim

<ins> // build-pass // only-x86-windows #![crate_type = "cdylib"] #![feature(abi_vectorcall)] #[no_mangle] extern "stdcall" fn foo(_: bool) {} #[no_mangle] extern "fastcall" fn bar(_: u8) {} #[no_mangle] extern "vectorcall" fn baz(_: u16) {} </ins>


Question:
IIRC there is a broken link checker, but somehow it doesn't catch this case: ! which is a 404 modify labels: A-docs
Also, all source links of the macros in are broken as well.
Another reexport bug. :) EDIT: so in here the problem is that the crate isn't documented on It should redirect to .
I think the right fix is to pass -Zrustdoc-map to cargo when documenting the standard library. We already do that for the compiler docs: mentoring instructions: add that same flag to .
cc , which is one way to fix this in rustdoc, but will result in a worse experience for the source view.
I just opened a PR for this issue: I confirmed that it fixes this issue. One of my concerns is that it is very similar to even if I followed the mentoring instructions. And the other concern is that although this PR fixes the main issue, there is another issue: Macros here seems still not working: Actually is working after this PR but others aren't; I think there is some mismatch about generating links between Cargo and I can investigate this second issue further in this issue or in a new issue but at first I wanna ensure that I am on the right way.

.arg("--target-dir") .arg(&*target_dir.to_string_lossy()) .arg("-Zskip-rustdoc-fingerprint") <ins> .arg("-Zrustdoc-map") .rustdocflag("--extern-html-root-url") .rustdocflag("std_detect=https://docs.rs/std_detect/latest/") .rustdocflag("--extern-html-root-takes-precedence") </ins> .rustdocflag("--resource-suffix") .rustdocflag(&builder.version); for arg in extra_args {


Question:
I noticed this bug while researching the same bug in Given , I expected: Instead, this happened: The related issue in the STL is microsoft/STL; the PR to fix this in the STL is microsoft/STL. The problem is that opens the file; this is not allowed for the following four files (not sure if there are additional files which act similarly): We can get around this by using instead of ; is that something that's desired, or is this considered a weird enough use case that we aren't interested in fixing it?
Documentation explicitly documents that is equivalent to accessing metadata of the file, doesn't it? Changing this behaviour would be a breaking change I'm afraid we wouldn't be able to afford.
true, the question was whether could use instead of followed by ; that's how we're solving this in the C++ standard library. (I'll note that this documentation is now wrong, since it now uses ) This would mean that the returned from would now have for but otherwise it'd be complete (although for reparse points, we'd still have to open the file). We could additionally do followed by , to fill out those fields. I'll note that we already have this behavior on UWP, and when getting metadata from a .
Hm, changing is not something I'd be minded to do lightly. At least not without further investigation. Some questions that spring to mind: What happens if the user does not have permission to read the directory but does have permission to read the file? Can we get all the metadata that's needed? Ah your edit answered that. Does this affect performance?
given that it's reading the directory, it should make performance better (assuming one doesn't do the double call thing). I'm personally not that invested, I just thought I'd share with y'all since I have to fix this bug for the STL
It's great that we have this report! I just want to make sure we investigate fully before making changes that may affect users of the standard library. I'll also note we do have the unstable whose behaviour can change.
Ok I tested with two users. For the sake of this example, I'll call them "Admin" and "User". As Admin I created a directory and denied User all access. Within the directory I then created a "" file and granted User access to just that file. As User, I tried using to test if the file exists. This failed with . I then tried using which succeeded. As does opening the file with , Thus can fail in situations where directly accessing the file would succeed.
FYI, has run into this in the wild: We'll work around it by falling back to if fails. Would be nice if could do something similar automatically, but I appreciate that there's a high bar for backwards compatibility and performance here.
To be clear, using FindFirstFile as a fallback (rather than replacement) answers my concerns and I think would be the best solution to this issue.

entry.unwrap(); } } <ins> /// Test the fallback for getting the metadata of files like hiberfil.sys that /// Windows holds a special lock on, preventing normal means of querying /// metadata. See #96980. /// /// Note this fails in CI because `hiberfil.sys` does not actually exist there. /// Therefore it's marked as ignored. #[test] #[ignore] #[cfg(windows)] fn hiberfil_sys() { let hiberfil = Path::new(r"C:hiberfil.sys"); assert_eq!(true, hiberfil.try_exists().unwrap()); fs::symlink_metadata(hiberfil).unwrap(); fs::metadata(hiberfil).unwrap(); assert_eq!(true, hiberfil.exists()); } </ins>


Question:
I noticed this bug while researching the same bug in Given , I expected: Instead, this happened: The related issue in the STL is microsoft/STL; the PR to fix this in the STL is microsoft/STL. The problem is that opens the file; this is not allowed for the following four files (not sure if there are additional files which act similarly): We can get around this by using instead of ; is that something that's desired, or is this considered a weird enough use case that we aren't interested in fixing it?
Documentation explicitly documents that is equivalent to accessing metadata of the file, doesn't it? Changing this behaviour would be a breaking change I'm afraid we wouldn't be able to afford.
true, the question was whether could use instead of followed by ; that's how we're solving this in the C++ standard library. (I'll note that this documentation is now wrong, since it now uses ) This would mean that the returned from would now have for but otherwise it'd be complete (although for reparse points, we'd still have to open the file). We could additionally do followed by , to fill out those fields. I'll note that we already have this behavior on UWP, and when getting metadata from a .
Hm, changing is not something I'd be minded to do lightly. At least not without further investigation. Some questions that spring to mind: What happens if the user does not have permission to read the directory but does have permission to read the file? Can we get all the metadata that's needed? Ah your edit answered that. Does this affect performance?
given that it's reading the directory, it should make performance better (assuming one doesn't do the double call thing). I'm personally not that invested, I just thought I'd share with y'all since I have to fix this bug for the STL
It's great that we have this report! I just want to make sure we investigate fully before making changes that may affect users of the standard library. I'll also note we do have the unstable whose behaviour can change.
Ok I tested with two users. For the sake of this example, I'll call them "Admin" and "User". As Admin I created a directory and denied User all access. Within the directory I then created a "" file and granted User access to just that file. As User, I tried using to test if the file exists. This failed with . I then tried using which succeeded. As does opening the file with , Thus can fail in situations where directly accessing the file would succeed.
FYI, has run into this in the wild: We'll work around it by falling back to if fails. Would be nice if could do something similar automatically, but I appreciate that there's a high bar for backwards compatibility and performance here.
To be clear, using FindFirstFile as a fallback (rather than replacement) answers my concerns and I think would be the best solution to this issue.

} pub fn metadata(&self) -> io::Result<FileAttr> { <del> Ok(FileAttr { attributes: self.data.dwFileAttributes, creation_time: self.data.ftCreationTime, last_access_time: self.data.ftLastAccessTime, last_write_time: self.data.ftLastWriteTime, file_size: ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64), reparse_tag: if self.data.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { // reserved unless this is a reparse point self.data.dwReserved0 } else { 0 }, volume_serial_number: None, number_of_links: None, file_index: None, }) </del> <ins> Ok(self.data.into()) </ins> } }


Question:
I noticed this bug while researching the same bug in Given , I expected: Instead, this happened: The related issue in the STL is microsoft/STL; the PR to fix this in the STL is microsoft/STL. The problem is that opens the file; this is not allowed for the following four files (not sure if there are additional files which act similarly): We can get around this by using instead of ; is that something that's desired, or is this considered a weird enough use case that we aren't interested in fixing it?
Documentation explicitly documents that is equivalent to accessing metadata of the file, doesn't it? Changing this behaviour would be a breaking change I'm afraid we wouldn't be able to afford.
true, the question was whether could use instead of followed by ; that's how we're solving this in the C++ standard library. (I'll note that this documentation is now wrong, since it now uses ) This would mean that the returned from would now have for but otherwise it'd be complete (although for reparse points, we'd still have to open the file). We could additionally do followed by , to fill out those fields. I'll note that we already have this behavior on UWP, and when getting metadata from a .
Hm, changing is not something I'd be minded to do lightly. At least not without further investigation. Some questions that spring to mind: What happens if the user does not have permission to read the directory but does have permission to read the file? Can we get all the metadata that's needed? Ah your edit answered that. Does this affect performance?
given that it's reading the directory, it should make performance better (assuming one doesn't do the double call thing). I'm personally not that invested, I just thought I'd share with y'all since I have to fix this bug for the STL
It's great that we have this report! I just want to make sure we investigate fully before making changes that may affect users of the standard library. I'll also note we do have the unstable whose behaviour can change.
Ok I tested with two users. For the sake of this example, I'll call them "Admin" and "User". As Admin I created a directory and denied User all access. Within the directory I then created a "" file and granted User access to just that file. As User, I tried using to test if the file exists. This failed with . I then tried using which succeeded. As does opening the file with , Thus can fail in situations where directly accessing the file would succeed.
FYI, has run into this in the wild: We'll work around it by falling back to if fails. Would be nice if could do something similar automatically, but I appreciate that there's a high bar for backwards compatibility and performance here.
To be clear, using FindFirstFile as a fallback (rather than replacement) answers my concerns and I think would be the best solution to this issue.

self.file_index } } <ins> impl From<c::WIN32_FIND_DATAW> for FileAttr { fn from(wfd: c::WIN32_FIND_DATAW) -> Self { FileAttr { attributes: wfd.dwFileAttributes, creation_time: wfd.ftCreationTime, last_access_time: wfd.ftLastAccessTime, last_write_time: wfd.ftLastWriteTime, file_size: ((wfd.nFileSizeHigh as u64) << 32) | (wfd.nFileSizeLow as u64), reparse_tag: if wfd.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { // reserved unless this is a reparse point wfd.dwReserved0 } else { 0 }, volume_serial_number: None, number_of_links: None, file_index: None, } } } </ins> fn to_u64(ft: &c::FILETIME) -> u64 { (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32)


Question:
I noticed this bug while researching the same bug in Given , I expected: Instead, this happened: The related issue in the STL is microsoft/STL; the PR to fix this in the STL is microsoft/STL. The problem is that opens the file; this is not allowed for the following four files (not sure if there are additional files which act similarly): We can get around this by using instead of ; is that something that's desired, or is this considered a weird enough use case that we aren't interested in fixing it?
Documentation explicitly documents that is equivalent to accessing metadata of the file, doesn't it? Changing this behaviour would be a breaking change I'm afraid we wouldn't be able to afford.
true, the question was whether could use instead of followed by ; that's how we're solving this in the C++ standard library. (I'll note that this documentation is now wrong, since it now uses ) This would mean that the returned from would now have for but otherwise it'd be complete (although for reparse points, we'd still have to open the file). We could additionally do followed by , to fill out those fields. I'll note that we already have this behavior on UWP, and when getting metadata from a .
Hm, changing is not something I'd be minded to do lightly. At least not without further investigation. Some questions that spring to mind: What happens if the user does not have permission to read the directory but does have permission to read the file? Can we get all the metadata that's needed? Ah your edit answered that. Does this affect performance?
given that it's reading the directory, it should make performance better (assuming one doesn't do the double call thing). I'm personally not that invested, I just thought I'd share with y'all since I have to fix this bug for the STL
It's great that we have this report! I just want to make sure we investigate fully before making changes that may affect users of the standard library. I'll also note we do have the unstable whose behaviour can change.
Ok I tested with two users. For the sake of this example, I'll call them "Admin" and "User". As Admin I created a directory and denied User all access. Within the directory I then created a "" file and granted User access to just that file. As User, I tried using to test if the file exists. This failed with . I then tried using which succeeded. As does opening the file with , Thus can fail in situations where directly accessing the file would succeed.
FYI, has run into this in the wild: We'll work around it by falling back to if fails. Would be nice if could do something similar automatically, but I appreciate that there's a high bar for backwards compatibility and performance here.
To be clear, using FindFirstFile as a fallback (rather than replacement) answers my concerns and I think would be the best solution to this issue.

} pub fn stat(path: &Path) -> io::Result<FileAttr> { <del> let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); // This flag is so we can open directories too opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); let file = File::open(path, &opts)?; file.file_attr() </del> <ins> metadata(path, ReparsePoint::Follow) </ins> } pub fn lstat(path: &Path) -> io::Result<FileAttr> { <ins> metadata(path, ReparsePoint::Open) } #[repr(u32)] #[derive(Clone, Copy, PartialEq, Eq)] enum ReparsePoint { Follow = 0, Open = c::FILE_FLAG_OPEN_REPARSE_POINT, } impl ReparsePoint { fn as_flag(self) -> u32 { self as u32 } } fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> { </ins> let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); <del> opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); let file = File::open(path, &opts)?; file.file_attr() </del> <ins> opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | reparse.as_flag()); // Attempt to open the file normally. // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileW`. // If the fallback fails for any reason we return the original error. match File::open(path, &opts) { Ok(file) => file.file_attr(), Err(e) if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => { // `ERROR_SHARING_VIOLATION` will almost never be returned. // Usually if a file is locked you can still read some metadata. // However, there are special system files, such as // `C:hiberfil.sys`, that are locked in a way that denies even that. unsafe { let path = maybe_verbatim(path)?; // `FindFirstFileW` accepts wildcard file names. // Fortunately wildcards are not valid file names and // `ERROR_SHARING_VIOLATION` means the file exists (but is locked) // therefore it's safe to assume the file name given does not // include wildcards. let mut wfd = mem::zeroed(); let handle = c::FindFirstFileW(path.as_ptr(), &mut wfd); if handle == c::INVALID_HANDLE_VALUE { // This can fail if the user does not have read access to the // directory. Err(e) } else { // We no longer need the find handle. c::FindClose(handle); // `FindFirstFileW` reads the cached file information from the // directory. The downside is that this metadata may be outdated. let attrs = FileAttr::from(wfd); if reparse == ReparsePoint::Follow && attrs.file_type().is_symlink() { Err(e) } else { Ok(attrs) } } } } Err(e) => Err(e), } </ins> } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

false } <ins> /// Build a textual representation of an unevaluated constant expression. /// /// If the const expression is too complex, an underscore `_` is returned. /// For const arguments, it's `{ _ }` to be precise. /// This means that the output is not necessarily valid Rust code. /// /// Currently, only /// /// * literals (optionally with a leading `-`) /// * unit `()` /// * blocks (`{ … }`) around simple expressions and /// * paths without arguments /// /// are considered simple enough. Simple blocks are included since they are /// necessary to disambiguate unit from the unit type. /// This list might get extended in the future. /// /// Without this censoring, in a lot of cases the output would get too large /// and verbose. Consider `match` expressions, blocks and deeply nested ADTs. /// Further, private and `doc(hidden)` fields of structs would get leaked /// since HIR datatypes like the `body` parameter do not contain enough /// semantic information for this function to be able to hide them – /// at least not without significant performance overhead. /// /// Whenever possible, prefer to evaluate the constant first and try to /// use a different method for pretty-printing. Ideally this function /// should only ever be used as a fallback. </ins> pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { let hir = tcx.hir(); let value = &hir.body(body).value; <del> let snippet = if !value.span.from_expansion() { tcx.sess.source_map().span_to_snippet(value.span).ok() } else { None }; </del> <ins> #[derive(PartialEq, Eq)] enum Classification { Literal, Simple, Complex, } </ins> <del> snippet.unwrap_or_else(|| rustc_hir_pretty::id_to_string(&hir, body.hir_id)) </del> <ins> use Classification::*; fn classify(expr: &hir::Expr<'_>) -> Classification { match &expr.kind { hir::ExprKind::Unary(hir::UnOp::Neg, expr) => { if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex } } hir::ExprKind::Lit(_) => Literal, hir::ExprKind::Tup([]) => Simple, hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => { if classify(expr) == Complex { Complex } else { Simple } } // Paths with a self-type or arguments are too “complex” following our measure since // they may leak private fields of structs (with feature `adt_const_params`). // Consider: `<Self as Trait<{ Struct { private: () } }>>::CONSTANT`. // Paths without arguments are definitely harmless though. hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => { if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex } } // FIXME: Claiming that those kinds of QPaths are simple is probably not true if the Ty //        contains const arguments. Is there a *concise* way to check for this? hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple, // FIXME: Can they contain const arguments and thus leak private struct fields? hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple, _ => Complex, } } let classification = classify(value); if classification == Literal && !value.span.from_expansion() && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) { // For literals, we avoid invoking the pretty-printer and use the source snippet instead to // preserve certain stylistic choices the user likely made for the sake legibility like // // * hexadecimal notation // * underscores // * character escapes // // FIXME: This passes through `-/*spacer*/0` verbatim. snippet } else if classification == Simple { // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and // other formatting artifacts. rustc_hir_pretty::id_to_string(&hir, body.hir_id) } else if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { // FIXME: Omit the curly braces if the enclosing expression is an array literal //        with a repeated element (an `ExprKind::Repeat`) as in such case it //        would not actually need any disambiguation. "{ _ }".to_owned() } else { "_".to_owned() } </ins> } /// Given a type Path, resolve it to a Type using the TyCtxt


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

ty = ty.print(cx), ); if let Some(default) = default { <ins> write!(w, " = "); </ins> // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the //        hood which adds noisy underscores and a type suffix to number literals. //        This hurts readability in this context especially when more complex expressions //        are involved and it doesn't add much of value. //        Find a way to print constants here without all that jazz. <del> write!(w, " = {}", default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx()))); </del> <ins> write!(w, "{}", Escape(&default.value(cx.tcx()).unwrap_or_else(|| default.expr(cx.tcx())))); </ins> } }


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

typ = c.type_.print(cx), ); <ins> // FIXME: The code below now prints //            ` = _; // 100i32` //        if the expression is //            `50 + 50` //        which looks just wrong. //        Should we print //            ` = 100i32;` //        instead? </ins> let value = c.value(cx.tcx()); let is_literal = c.is_literal(cx.tcx()); let expr = c.expr(cx.tcx());


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

// @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]'  //      'const BAR: usize' pub const BAR: usize = 3;  // @has - '//*[@id="associatedconstant.BAR_ESCAPED"]'  //      "const BAR_ESCAPED: &'static str = "markup"" pub const BAR_ESCAPED: &'static str = "markup";  } pub struct Baz<'a, U: 'a, T>(T, &'a [U]);


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

#![crate_name = "foo"] // @has 'foo/constant.HOUR_IN_SECONDS.html' <del> // @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = 60 * 60; // 3_600u64' </del> <ins> // @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64' </ins> pub const HOUR_IN_SECONDS: u64 = 60 * 60; // @has 'foo/constant.NEGATIVE.html' <del> // @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = -60 * 60; // -3_600i64' </del> <ins> // @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64' </ins> pub const NEGATIVE: i64 = -60 * 60;


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

<ins> // Test that certain unevaluated constant expression arguments that are // deemed too verbose or complex and that may leak private or // `doc(hidden)` struct fields are not displayed in the documentation. // // Read the documentation of `rustdoc::clean::utils::print_const_expr` // for further details. #![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] // @has hide_complex_unevaluated_const_arguments/trait.Stage.html pub trait Stage { // A helper constant that prevents const expressions containing it // from getting fully evaluated since it doesn't have a body and // thus is non-reducible. This allows us to specifically test the // pretty-printing of *unevaluated* consts. const ABSTRACT: usize; // Currently considered "overly complex" by the `generic_const_exprs` // feature. If / once this expression kind gets supported, this // unevaluated const expression could leak the private struct field. // // FIXME: Once the line below compiles, make this a test that //        ensures that the private field is not printed. // //const ARRAY0: [u8; Struct { private: () } + Self::ABSTRACT]; // This assoc. const could leak the private assoc. function `Struct::new`. // Ensure that this does not happen. // // @has - '//*[@id="associatedconstant.ARRAY1"]'  //        'const ARRAY1: [u8; { _ }]' const ARRAY1: [u8; Struct::new(/* ... */) + Self::ABSTRACT * 1_000]; // @has - '//*[@id="associatedconstant.VERBOSE"]'  //        'const VERBOSE: [u16; { _ }]' const VERBOSE: [u16; compute("thing", 9 + 9) * Self::ABSTRACT]; // Check that we do not leak the private struct field contained within // the path. The output could definitely be improved upon // (e.g. printing sth. akin to `<Self as Helper<{ _ }>>::OUT`) but // right now “safe is safe”. // // @has - '//*[@id="associatedconstant.PATH"]'  //        'const PATH: usize = _' const PATH: usize = <Self as Helper<{ Struct { private: () } }>>::OUT; } const fn compute(input: &str, extra: usize) -> usize { input.len() + extra } pub trait Helper<const S: Struct> { const OUT: usize; } impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St { const OUT: usize = St::ABSTRACT; } // Currently in rustdoc, const arguments are not evaluated in this position // and therefore they fall under the realm of `print_const_expr`. // If rustdoc gets patched to evaluate const arguments, it is fine to replace // this test as long as one can ensure that private fields are not leaked! // // @has hide_complex_unevaluated_const_arguments/trait.Sub.html  //      '//*[@class="rust trait"]'  //      'pub trait Sub: Sup<{ _ }, { _ }> { }' pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {} pub trait Sup<const N: usize, const S: Struct> {} pub struct Struct { private: () } impl Struct { const fn new() -> Self { Self { private: () } } } impl const std::ops::Add<usize> for Struct { type Output = usize; fn add(self, _: usize) -> usize { 0 } } </ins>


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

<ins> // Regression test for issue #97933. // // Test that certain unevaluated constant expressions that are // deemed too verbose or complex and that may leak private or // `doc(hidden)` struct fields are not displayed in the documentation. // // Read the documentation of `rustdoc::clean::utils::print_const_expr` // for further details. // @has hide_complex_unevaluated_consts/trait.Container.html pub trait Container { // A helper constant that prevents const expressions containing it // from getting fully evaluated since it doesn't have a body and // thus is non-reducible. This allows us to specifically test the // pretty-printing of *unevaluated* consts. const ABSTRACT: i32; // Ensure that the private field does not get leaked: // // @has - '//*[@id="associatedconstant.STRUCT0"]'  //        'const STRUCT0: Struct = _' const STRUCT0: Struct = Struct { private: () }; // @has - '//*[@id="associatedconstant.STRUCT1"]'  //        'const STRUCT1: (Struct,) = _' const STRUCT1: (Struct,) = (Struct{private: /**/()},); // Although the struct field is public here, check that it is not // displayed. In a future version of rustdoc, we definitely want to // show it. However for the time being, the printing logic is a bit // conservative. // // @has - '//*[@id="associatedconstant.STRUCT2"]'  //        'const STRUCT2: Record = _' const STRUCT2: Record = Record { public: 5 }; // Test that we do not show the incredibly verbose match expr: // // @has - '//*[@id="associatedconstant.MATCH0"]'  //        'const MATCH0: i32 = _' const MATCH0: i32 = match 234 { 0 => 1, _ => Self::ABSTRACT, }; // @has - '//*[@id="associatedconstant.MATCH1"]'  //        'const MATCH1: bool = _' const MATCH1: bool = match Self::ABSTRACT { _ => true, }; // Check that we hide complex (arithmetic) operations. // In this case, it is a bit unfortunate since the expression // is not *that* verbose and it might be quite useful to the reader. // // However in general, the expression might be quite large and // contain match expressions and structs with private fields. // We would need to recurse over the whole expression and even more // importantly respect operator precedence when pretty-printing // the potentially partially censored expression. // For now, the implementation is quite simple and the choices // rather conservative. // // @has - '//*[@id="associatedconstant.ARITH_OPS"]'  //        'const ARITH_OPS: i32 = _' const ARITH_OPS: i32 = Self::ABSTRACT * 2 + 1; } pub struct Struct { private: () } pub struct Record { pub public: i32 } </ins>


Question: <br<img width="300" src="https://user-"<br<img width="300" src="https://user-"<brI used the following script to bisect: It bisects to nightly-2022-04-14 and specifically , of which seems the most relevant because it involves associated constants in rustdoc.

// @!has show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32' pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32; <del> // @has show_const_contents/constant.CONST_CALC_I32.html '= 42 + 1; // 43i32' </del> <ins> // @has show_const_contents/constant.CONST_CALC_I32.html '= _; // 43i32' </ins> pub const CONST_CALC_I32: i32 = 42 + 1; // @!has show_const_contents/constant.CONST_REF_I32.html '= &42;'


Question:
Current docs on derive : I interpret the above statement as " compares enum discriminants", which is not the case. This is true for enums variants with no data, however for enum variants that are struct-like or tuple struct-like, derived actually compares the fields (which is expected) and not just discriminants: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label: +A-docs +C-cleanup +E-easy +T-libs-api
claim

/// /// This trait can be used with `#[derive]`. When `derive`d on structs, two /// instances are equal if all fields are equal, and not equal if any fields <del> /// are not equal. When `derive`d on enums, each variant is equal to itself /// and not equal to the other variants. </del> <ins> /// are not equal. When `derive`d on enums, two instances are equal if they /// are the same variant and all fields are equal. </ins> /// /// ## How can I implement `PartialEq`? ///


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

use crate::ffi::{CStr, CString}; use crate::fmt; use crate::io; <ins> use crate::marker::PhantomData; </ins> use crate::mem; use crate::num::NonZeroU64; use crate::num::NonZeroUsize;


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

unsafe fn spawn_unchecked_<'a, 'scope, F, T>( self, f: F, <del> scope_data: Option<&'scope scoped::ScopeData>, </del> <ins> scope_data: Option<Arc<scoped::ScopeData>>, </ins> ) -> io::Result<JoinInner<'scope, T>> where F: FnOnce() -> T,


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

})); let their_thread = my_thread.clone(); <del> let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) }); </del> <ins> let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData, }); </ins> let their_packet = my_packet.clone(); let output_capture = crate::io::set_output_capture(None);


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

unsafe { *their_packet.result.get() = Some(try_result) }; }; <del> if let Some(scope_data) = scope_data { </del> <ins> if let Some(scope_data) = &my_packet.scope { </ins> scope_data.increment_num_running_threads(); }


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

// An Arc to the packet is stored into a `JoinInner` which in turns is placed // in `JoinHandle`. struct Packet<'scope, T> { <del> scope: Option<&'scope scoped::ScopeData>, </del> <ins> scope: Option<Arc<scoped::ScopeData>>, </ins> result: UnsafeCell<Option<Result<T>>>, <ins> _marker: PhantomData<Option<&'scope scoped::ScopeData>>, </ins> } // Due to the usage of `UnsafeCell` we need to manually implement Sync.


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

rtabort!("thread result panicked on drop"); } // Book-keeping so the scope knows when it's done. <del> if let Some(scope) = self.scope { </del> <ins> if let Some(scope) = &self.scope { </ins> // Now that there will be no more user code running on this thread // that can use 'scope, mark the thread as 'finished'. // It's important we only do this after the `result` has been dropped,


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

/// See [`scope`] for details. #[stable(feature = "scoped_threads", since = "1.63.0")] pub struct Scope<'scope, 'env: 'scope> { <del> data: ScopeData, </del> <ins> data: Arc<ScopeData>, </ins> /// Invariance over 'scope, to make sure 'scope cannot shrink, /// which is necessary for soundness. ///


Question:
The following code sometimes causes a data race to be reported by Miri: Miri reports: The deallocation occurs when returns and its local variable gets deallocated. The read occurs here (I am fairly sure): This reads the contents of the field after the . But the moment the is done, the memory backing might be deallocated. That makes the read a potential use-after-free, and a race with the deallocation. Cc
The following patch fixes this: However, even with this patch, we still run into a problem like the gets deallocated while still runs. This is still UB even after my proposed because contains a field that is not inside an (the field). So that part of what points to is expected to stay live for the entire duration of the function call. Another alternative might be to put the entire into an rather than allocating it on the stack frame of .
Going to attach this to the 1.63 milestone, since this is in a newly stabilized feature -- we may wish to back out stabilization for a cycle or backport fixes.
Re-opening for beta backport.
The fix was backported in .

where F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T, { <ins> // We put the `ScopeData` into an `Arc` so that other threads can finish their // `decrement_num_running_threads` even after this function returns. </ins> let scope = Scope { <del> data: ScopeData { </del> <ins> data: Arc::new(ScopeData { </ins> num_running_threads: AtomicUsize::new(0), main_thread: current(), a_thread_panicked: AtomicBool::new(false), <del> }, </del> <ins> }), </ins> env: PhantomData, scope: PhantomData, };