Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

let id_substs = InternalSubsts::identity_for_item(tcx, def_id); debug!(?id_substs, ?substs); let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> = <del> substs.iter().enumerate().map(|(index, arg)| (arg, id_substs[index])).collect(); </del> <ins> std::iter::zip(substs, id_substs).collect(); </ins> debug!(?map); <ins> // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound // region substs that are synthesized during AST lowering. These are substs // that are appended to the parent substs (trait and trait method). However, // we're trying to infer the unsubstituted type value of the RPITIT inside // the *impl*, so we can later use the impl's method substs to normalize // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`). // // Due to the design of RPITITs, during AST lowering, we have no idea that // an impl method corresponds to a trait method with RPITITs in it. Therefore, // we don't have a list of early-bound region substs for the RPITIT in the impl. // Since early region parameters are index-based, we can't just rebase these // (trait method) early-bound region substs onto the impl, and there's no // guarantee that the indices from the trait substs and impl substs line up. // So to fix this, we subtract the number of trait substs and add the number of // impl substs to *renumber* these early-bound regions to their corresponding // indices in the impl's substitutions list. // // Also, we only need to account for a difference in trait and impl substs, // since we previously enforce that the trait method and impl method have the // same generics. let num_trait_substs = trait_to_impl_substs.len(); let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len(); </ins> let ty = tcx.fold_regions(ty, |region, _| { <del> if let ty::ReFree(_) = region.kind() { map[&region.into()].expect_region() } else { region } </del> <ins> let ty::ReFree(_) = region.kind() else { return region; }; let ty::ReEarlyBound(e) = map[&region.into()].expect_region().kind() else { bug!("expected ReFree to map to ReEarlyBound"); }; tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: e.def_id, name: e.name, index: (e.index as usize - num_trait_substs + num_impl_substs) as u32, })) </ins> }); debug!(%ty); collected_tys.insert(def_id, ty);


Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { #[cold] #[inline(never)] <del> fn region_param_out_of_range(data: ty::EarlyBoundRegion) -> ! { </del> <ins> fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! { </ins> bug!( <del> "Region parameter out of range when substituting in region {} (index={})", </del> <ins> "Region parameter out of range when substituting in region {} (index={}, substs = {:?})", data.name, data.index, substs, ) } #[cold] #[inline(never)] fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! { bug!( "Unexpected parameter {:?} when substituting in region {} (index={})", other, </ins> data.name, data.index )


Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), <del> _ => region_param_out_of_range(data), </del> <ins> Some(other) => region_param_invalid(data, other), None => region_param_out_of_range(data, self.substs), </ins> } } _ => r,


Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

} let impl_fn_def_id = leaf_def.item.def_id; <del> let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs); </del> <ins> // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque}, // since `data.substs` are the impl substs. let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs); </ins> let cause = ObligationCause::new( obligation.cause.span,


Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

<ins> // check-pass // edition:2021 #![feature(async_fn_in_trait)] #![allow(incomplete_features)] pub trait SpiDevice { async fn transaction<F, R>(&mut self); } impl SpiDevice for () { async fn transaction<F, R>(&mut self) {} } fn main() {} </ins>


Question:
While working on an experimental runtime and using a couple of experimental features I found that the compiler while in resolving the async call on a trait crash badly. This is a minimal reproducible example and this is the stacktrace generated N.B: I guess this happens with any runtime? BTW also if happens only with rio the compiler should not crash, but I do not think this is related to a specific runtime, but I guess instead, the runtime triggers the resolution of the futures <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
label +A-async-await +T-compiler
In the meanwhile, I will try to swim inside the codebase to catch the problem! claim
this is fixed by .
Minimized so it doesn't depend on rio:
Cool great work :)

<ins> // check-pass #![feature(return_position_impl_trait_in_trait)] #![allow(incomplete_features)] trait Foo<T> { fn foo<F2: Foo<T>>(self) -> impl Foo<T>; } struct Bar; impl Foo<u8> for Bar { fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> { self } } fn main() {} </ins>


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

kind: ast::VisibilityKind::Inherited, tokens: None, }, <del> span: ecx.with_def_site_ctxt(sp), </del> <ins> span: sp, </ins> tokens: None, })]) } else {


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

lint_builtin_export_name_fn = declaration of a function with `export_name` lint_builtin_export_name_method = declaration of a method with `export_name` lint_builtin_export_name_static = declaration of a static with `export_name` <ins> lint_builtin_global_asm = usage of `core::arch::global_asm` lint_builtin_global_macro_unsafety = using this macro is unsafe even though it does not need an `unsafe` block </ins> lint_builtin_impl_unsafe_method = implementation of an `unsafe` method lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

} } <ins> ast::ItemKind::GlobalAsm(..) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::GlobalAsm); } </ins> _ => {} } }


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

DeclUnsafeMethod, #[diag(lint_builtin_impl_unsafe_method)] ImplUnsafeMethod, <ins> #[diag(lint_builtin_global_asm)] #[note(lint_builtin_global_macro_unsafety)] GlobalAsm, </ins> } #[derive(LintDiagnostic)]


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

| LL | global_asm!(""); | ^^^^^^^^^^^^^^^ <del> | = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info) </del> error: aborting due to 2 previous errors


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

<ins> //@ needs-asm-support #![deny(unsafe_code)] use std::arch::global_asm; #[allow(unsafe_code)] mod allowed_unsafe { std::arch::global_asm!(""); } macro_rules! unsafe_in_macro { () => { global_asm!(""); //~ ERROR: usage of `core::arch::global_asm` }; } global_asm!(""); //~ ERROR: usage of `core::arch::global_asm` unsafe_in_macro!(); fn main() {} </ins>


Question:
Similar to how deny(unsafecode) prevents from being used, it should also prevent blocks from being allowed. If misused, they can do any number of strange and horrible thing simply by being within the crate. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
label +C-bug +T-compiler
I suppose it's probably too late to actually make it require ?
that isn't even currently possible from a syntax perspective because blocks only work as expressions, you can't just put them around a top level item. It would take a whole RFC thing, even separately from global_asm already being stable.

<ins> error: usage of `core::arch::global_asm` --> $DIR/lint-global-asm-as-unsafe.rs:17:1 | LL | global_asm!(""); | ^^^^^^^^^^^^^^^ | = note: using this macro is unsafe even though it does not need an `unsafe` block note: the lint level is defined here --> $DIR/lint-global-asm-as-unsafe.rs:2:9 | LL | #![deny(unsafe_code)] |         ^^^^^^^^^^^ error: usage of `core::arch::global_asm` --> $DIR/lint-global-asm-as-unsafe.rs:13:9 | LL |         global_asm!(""); |         ^^^^^^^^^^^^^^^ ... LL | unsafe_in_macro!(); | ------------------ in this macro invocation | = note: using this macro is unsafe even though it does not need an `unsafe` block = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors </ins>


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

/// Returns a new span representing the next character after the end-point of this span. /// Special cases: /// - if span is a dummy one, returns the same span <del> /// - if next_point reached the end of source, return span with lo = hi </del> <ins> /// - if next_point reached the end of source, return a span exceeding the end of source, ///   which means sm.span_to_snippet(next_point) will get `Err` </ins> /// - respect multi-byte characters pub fn next_point(&self, sp: Span) -> Span { if sp.is_dummy() {


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

let start_of_next_point = sp.hi().0; let width = self.find_width_of_character_at_span(sp, true); <del> if width == 0 { return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None); } </del> // If the width is 1, then the next span should only contain the next char besides current ending. // However, in the case of a multibyte character, where the width != 1, the next span should // span multiple bytes to include the whole character.


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

// Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { debug!("find_width_of_character_at_span: source indexes are malformed"); <del> return 0; </del> <ins> return 1; </ins> } let src = local_begin.sf.external_src.borrow();


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

assert_eq!(span.lo().0, 4); assert_eq!(span.hi().0, 5); <del> // A non-empty span at the last byte should advance to create an empty // span pointing at the end of the file. </del> <ins> // Reaching to the end of file, return a span that will get error with `span_to_snippet` </ins> let span = Span::with_root_ctxt(BytePos(4), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); <del> assert_eq!(span.hi().0, 5); </del> <ins> assert_eq!(span.hi().0, 6); assert!(sm.span_to_snippet(span).is_err()); </ins> <del> // Empty span pointing just past the last byte. </del> <ins> // Reaching to the end of file, return a span that will get error with `span_to_snippet` </ins> let span = Span::with_root_ctxt(BytePos(5), BytePos(5)); let span = sm.next_point(span); assert_eq!(span.lo().0, 5); <del> assert_eq!(span.hi().0, 5); </del> <ins> assert_eq!(span.hi().0, 6); assert!(sm.span_to_snippet(span).is_err()); </ins> }


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

<ins> // error-pattern: this file contains an unclosed delimiter // error-pattern: expected value, found struct `R` struct R { } struct S { x: [u8; R </ins>


Question:
This malformed code () hangs the compiler: Found by fuzzing with a . must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields. must be the last token to produce the hang: No opening brace (note that braces are required for literals of named-field structs) No closing delimiters Not even a comment If I understand correctly, the hang occurs in LateResolutionVisitor, with never finishing (while calling various functions such as and ) This also hangs. I'm guessing it's the same bug. : with: <details</summary<p</p</detailsregressed nightly: nightly-2022-10-21 regressed commit: (PR ) label +regression-from-stable-to-nightly +I-hang <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
claim
I can not reproduce it with latest code, did I missed anything?
Great cactch Confirmed the error is only triggered by commit: The root cause is I changed the edge corner case in : We think won't return a span which outside of source file, so is a valid one, then will always return a valid span, and we get from when reaching the end of source. So, there is a loop in previous , which will run infinitely loop: Lucky, my another PR merged at last day, this PR refactored this function:
Verif, I no longer get a hang after rollup Do you want to add one or two of these as tests?
Yes, we'd better add a testcase for it. I'm thinking whether we sould in when reaching to the end of source, so that may get an error.
This testcase seems not easy to be : If so, the trigger point will do not exist,
label -I-prioritize
There's an alternative kind of annotation for patterns that should work for this case:

<ins> error: this file contains an unclosed delimiter --> $DIR/issue-103451.rs:5:15 | LL | struct S { |          - unclosed delimiter LL |     x: [u8; R |        -      ^ |        | |        unclosed delimiter error: this file contains an unclosed delimiter --> $DIR/issue-103451.rs:5:15 | LL | struct S { |          - unclosed delimiter LL |     x: [u8; R |        -      ^ |        | |        unclosed delimiter error[E0423]: expected value, found struct `R` --> $DIR/issue-103451.rs:5:13 | LL | struct R { } | ------------ `R` defined here LL | struct S { LL |     x: [u8; R |             ^ help: use struct literal syntax instead: `R {}` error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0423`. </ins>


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

} /// Parses the parameter list of a function, including the `(` and `)` delimiters. <del> fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { </del> <ins> pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { </ins> let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| {


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

has_parens: bool, modifiers: BoundModifiers, ) -> PResult<'a, GenericBound> { <del> let lifetime_defs = self.parse_late_bound_lifetime_defs()?; let path = if self.token.is_keyword(kw::Fn) </del> <ins> let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; let mut path = if self.token.is_keyword(kw::Fn) </ins> && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) && let Some(path) = self.recover_path_from_fn() {


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

} else { self.parse_path(PathStyle::Type)? }; <ins> if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) { self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?; } </ins> if has_parens { if self.token.is_like_plus() { // Someone has written something like `&dyn (Trait + Other)`. The correct code


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

} } <ins> /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already /// been eaten. fn recover_fn_trait_with_lifetime_params( &mut self, fn_path: &mut ast::Path, lifetime_defs: &mut Vec<GenericParam>, ) -> PResult<'a, ()> { let fn_path_segment = fn_path.segments.last_mut().unwrap(); let generic_args = if let Some(p_args) = &fn_path_segment.args { p_args.clone().into_inner() } else { // Normally it wouldn't come here because the upstream should have parsed // generic parameters (otherwise it's impossible to call this function). return Ok(()); }; let lifetimes = if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) = &generic_args { args.into_iter() .filter_map(|arg| { if let ast::AngleBracketedArg::Arg(generic_arg) = arg && let ast::GenericArg::Lifetime(lifetime) = generic_arg { Some(lifetime) } else { None } }) .collect() } else { Vec::new() }; // Only try to recover if the trait has lifetime params. if lifetimes.is_empty() { return Ok(()); } // Parse `(T, U) -> R`. let inputs_lo = self.token.span; let inputs: Vec<_> = self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect(); let inputs_span = inputs_lo.to(self.prev_token.span); let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; let args = ast::ParenthesizedArgs { span: fn_path_segment.span().to(self.prev_token.span), inputs, inputs_span, output, } .into(); *fn_path_segment = ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID }; // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`. let mut generic_params = lifetimes .iter() .map(|lt| GenericParam { id: lt.id, ident: lt.ident, attrs: ast::AttrVec::new(), bounds: Vec::new(), is_placeholder: false, kind: ast::GenericParamKind::Lifetime, colon_span: None, }) .collect::<Vec<GenericParam>>(); lifetime_defs.append(&mut generic_params); let generic_args_span = generic_args.span(); let mut err = self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters"); let snippet = format!( "for<{}> ", lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(), ); let before_fn_path = fn_path.span.shrink_to_lo(); err.multipart_suggestion( "consider using a higher-ranked trait bound instead", vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)], Applicability::MaybeIncorrect, ) .emit(); Ok(()) } </ins> pub(super) fn check_lifetime(&mut self) -> bool { self.expected_tokens.push(TokenType::Lifetime); self.token.is_lifetime()


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

<ins> // Test that Fn-family traits with lifetime parameters shouldn't compile and // we suggest the usage of higher-rank trait bounds instead. fn fa(_: impl Fn<'a>(&'a str) -> bool) {} //~^ ERROR `Fn` traits cannot take lifetime parameters fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} //~^ ERROR `Fn` traits cannot take lifetime parameters fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} //~^ ERROR `Fn` traits cannot take lifetime parameters use std::ops::Fn as AliasedFn; fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} //~^ ERROR `Fn` traits cannot take lifetime parameters fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} //~^ ERROR `Fn` traits cannot take lifetime parameters fn main() {} </ins>


Question:
The following code: currently produces a heap of semi-helpful diagnostics: <details<summary<bstderr (7 errors)</b</summary</detailswhen instead we could special-case this and emit a single (or at least fewer) diagnostic that suggests the following: If the bound in not inside , like in: we currently emit the following: which is less verbose for sure but still, we should provide the same suggestion I propose above. Related issue: . label A-parser A-suggestion-diagnostics D-newcomer-roadblock <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Error: Parsing ping command in failed: ...'stbot ping' ''... Please file an issue on GitHub at if there's a problem with this bot, or reach out on on Zulip.
I'd like to take a look. claim
I'm wondering if taking an approach that suggests using higher-rank trait bounds () for an Fn-family trait with a lifetime parameter. Is it appropriate? I'm concerned that it may not a comprehensive solution because HRTB can be used outside of the Fn-family traits (as I understand). Or is it okay only for the Fn-family traits for now?
I am not sure I fully understand what you mean. As you probably know, none of , , take a lifetime parameter and probably never will. Of course, you could define such a trait with unstable features but there is no way to use them, so it's not relevant: Yes, I'd say so. I wouldn't look for names however (like , , …) but just look for an opening parenthesis after a generic parameter list. This way, we can emit the same suggestion for the following case (where the name is ):
Ah, definitely. Thank you!

<ins> error: `Fn` traits cannot take lifetime parameters --> $DIR/hrtb-malformed-lifetime-generics.rs:4:17 | LL | fn fa(_: impl Fn<'a>(&'a str) -> bool) {} |                 ^^^^ | help: consider using a higher-ranked trait bound instead | LL - fn fa(_: impl Fn<'a>(&'a str) -> bool) {} LL + fn fa(_: impl for<'a> Fn(&'a str) -> bool) {} | error: `Fn` traits cannot take lifetime parameters --> $DIR/hrtb-malformed-lifetime-generics.rs:7:20 | LL | fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} |                    ^^^^^^^^ | help: consider using a higher-ranked trait bound instead | LL - fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} LL + fn fb(_: impl for<'a, 'b> FnMut(&'a str, &'b str) -> bool) {} | error: `Fn` traits cannot take lifetime parameters --> $DIR/hrtb-malformed-lifetime-generics.rs:10:41 | LL | fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} |                                         ^^^^ | help: consider using a higher-ranked trait bound instead | LL - fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} LL + fn fc(_: impl std::fmt::Display + for<'a> FnOnce(&'a str) -> bool + std::fmt::Debug) {} | error: `Fn` traits cannot take lifetime parameters --> $DIR/hrtb-malformed-lifetime-generics.rs:14:24 | LL | fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} |                        ^^^^ | help: consider using a higher-ranked trait bound instead | LL - fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} LL + fn fd(_: impl for<'a> AliasedFn(&'a str) -> bool) {} | error: `Fn` traits cannot take lifetime parameters --> $DIR/hrtb-malformed-lifetime-generics.rs:17:27 | LL | fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} |                           ^^^^ | help: consider using a higher-ranked trait bound instead | LL - fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} LL + fn fe<F>(_: F) where F: for<'a> Fn(&'a str) -> bool {} | error: aborting due to 5 previous errors </ins>


Question:
Today for no reason in particular I was curious about the behaviour of arrays when zipped together and then mapped into a single array, roughly: I wrote some tests for this and disassembled them in Godbolt to see what was going on behind the scenes and wow was a whole lot going on that seemed like it didn't need to be. So I wrote something kinda like what's in the stdlib for mapping and zipping arrays, just without the iterators, to see if I could do any better. Turns out I absolutely can: Maybe the design isn't as optimal (or as safe) as it could be, but it performs perfectly well in benchmarks (read: as fast as an unguarded version and anywhere between 3-25 times faster than the definition shown at the top of this issue. Here's a rough table of execution times averaged over the primitive ops (, , &|^`): ! Not really liking how things are looking for . So, question then is: is there something in Rust that needs to change to let these optimisations happen, or do I need to look at putting this in a library somewhere (or maybe stdlib wink wink nudge nudge?)? *The 25x comes from the benchmarks. benches at 11.230ns, and benches at 452.593ps, which seems suspicious but I can't seem to find anything wrong with the result.
I suspect the issue here is that has the wrong shape. It returns but vector instructions generally want . isn't an iterator type that describes the desired iteration and then performs it once, rather it's one loop that creates an intermediate result and then a second loop that produces the final output. Perhaps we could massage the code into a shape that the optimizer can disentangle, but I think it would be better to offer something like your , albeit with a nicer name.
This is missing an actual reproducer... Tried a few sizes here: I assume the report is about the case where this doesn't get unrolled, like with N=128?
I'm not entirely sure what you're looking for in a reproducer, but I have a benchmark program set up using to check out the performance of the various functions (see the "Benchmark" section at the bottom of this post). More or less I have as shown above (renamed to ), and both of these: Then I set up a lot of benchmarks. These test the speed of some primitive operations (, , , , , ) on arrays of lengths 8, 16, 32, 64, 128, 256, and 512 for types u8, u16, u32, and u64. This gives a total of 168 benchmarks per function, which reduces down to 28 per test after the primitive tests are averaged for each function, length, and type. The results of this are: ! This was run on the latest nightly as of 2022-12-21. I think this is pretty hard evidence that performance using is not where it should be. and are grouped so close together in the bottom section of the graph you can't visually see the difference. But for ? It's very obviously slower than the other two. Notice how it takes more time to map together two than it takes the other methods to map together two . Even if we just look at shorter inputs like was suggested, it doesn't look good for : ! These are just the results for lengths up through 64, and we can pretty clearly see that is just always slower. <details<summary<strongBenchmark</strong</summary<p: </p</details
Part of this is the classic "too many copies" trio But some of it is probably just that, being eager, it won't optimize unless it fully unrolls.

drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f))) } <del> /// 'Zips up' two arrays into a single array of pairs. /// /// `zip()` returns a new array where every element is a tuple where the /// first element comes from the first array, and the second element comes /// from the second array. In other words, it zips two arrays together, /// into a single one. /// /// # Examples /// /// ``` /// #![feature(array_zip)] /// let x = [1, 2, 3]; /// let y = [4, 5, 6]; /// let z = x.zip(y); /// assert_eq!(z, [(1, 4), (2, 5), (3, 6)]); /// ``` #[unstable(feature = "array_zip", issue = "80094")] pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] { drain_array_with(self, |lhs| { drain_array_with(rhs, |rhs| from_trusted_iterator(crate::iter::zip(lhs, rhs))) }) } </del> /// Returns a slice containing the entire array. Equivalent to `&s[..]`. #[stable(feature = "array_as_slice", since = "1.57.0")] #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")]


Question:
Today for no reason in particular I was curious about the behaviour of arrays when zipped together and then mapped into a single array, roughly: I wrote some tests for this and disassembled them in Godbolt to see what was going on behind the scenes and wow was a whole lot going on that seemed like it didn't need to be. So I wrote something kinda like what's in the stdlib for mapping and zipping arrays, just without the iterators, to see if I could do any better. Turns out I absolutely can: Maybe the design isn't as optimal (or as safe) as it could be, but it performs perfectly well in benchmarks (read: as fast as an unguarded version and anywhere between 3-25 times faster than the definition shown at the top of this issue. Here's a rough table of execution times averaged over the primitive ops (, , &|^`): ! Not really liking how things are looking for . So, question then is: is there something in Rust that needs to change to let these optimisations happen, or do I need to look at putting this in a library somewhere (or maybe stdlib wink wink nudge nudge?)? *The 25x comes from the benchmarks. benches at 11.230ns, and benches at 452.593ps, which seems suspicious but I can't seem to find anything wrong with the result.
I suspect the issue here is that has the wrong shape. It returns but vector instructions generally want . isn't an iterator type that describes the desired iteration and then performs it once, rather it's one loop that creates an intermediate result and then a second loop that produces the final output. Perhaps we could massage the code into a shape that the optimizer can disentangle, but I think it would be better to offer something like your , albeit with a nicer name.
This is missing an actual reproducer... Tried a few sizes here: I assume the report is about the case where this doesn't get unrolled, like with N=128?
I'm not entirely sure what you're looking for in a reproducer, but I have a benchmark program set up using to check out the performance of the various functions (see the "Benchmark" section at the bottom of this post). More or less I have as shown above (renamed to ), and both of these: Then I set up a lot of benchmarks. These test the speed of some primitive operations (, , , , , ) on arrays of lengths 8, 16, 32, 64, 128, 256, and 512 for types u8, u16, u32, and u64. This gives a total of 168 benchmarks per function, which reduces down to 28 per test after the primitive tests are averaged for each function, length, and type. The results of this are: ! This was run on the latest nightly as of 2022-12-21. I think this is pretty hard evidence that performance using is not where it should be. and are grouped so close together in the bottom section of the graph you can't visually see the difference. But for ? It's very obviously slower than the other two. Notice how it takes more time to map together two than it takes the other methods to map together two . Even if we just look at shorter inputs like was suggested, it doesn't look good for : ! These are just the results for lengths up through 64, and we can pretty clearly see that is just always slower. <details<summary<strongBenchmark</strong</summary<p: </p</details
Part of this is the classic "too many copies" trio But some of it is probably just that, being eager, it won't optimize unless it fully unrolls.

// ignore-debug (the extra assertions get in the way) #![crate_type = "lib"] <del> #![feature(array_zip)] </del> // CHECK-LABEL: @short_integer_map #[no_mangle]


Question:
Today for no reason in particular I was curious about the behaviour of arrays when zipped together and then mapped into a single array, roughly: I wrote some tests for this and disassembled them in Godbolt to see what was going on behind the scenes and wow was a whole lot going on that seemed like it didn't need to be. So I wrote something kinda like what's in the stdlib for mapping and zipping arrays, just without the iterators, to see if I could do any better. Turns out I absolutely can: Maybe the design isn't as optimal (or as safe) as it could be, but it performs perfectly well in benchmarks (read: as fast as an unguarded version and anywhere between 3-25 times faster than the definition shown at the top of this issue. Here's a rough table of execution times averaged over the primitive ops (, , &|^`): ! Not really liking how things are looking for . So, question then is: is there something in Rust that needs to change to let these optimisations happen, or do I need to look at putting this in a library somewhere (or maybe stdlib wink wink nudge nudge?)? *The 25x comes from the benchmarks. benches at 11.230ns, and benches at 452.593ps, which seems suspicious but I can't seem to find anything wrong with the result.
I suspect the issue here is that has the wrong shape. It returns but vector instructions generally want . isn't an iterator type that describes the desired iteration and then performs it once, rather it's one loop that creates an intermediate result and then a second loop that produces the final output. Perhaps we could massage the code into a shape that the optimizer can disentangle, but I think it would be better to offer something like your , albeit with a nicer name.
This is missing an actual reproducer... Tried a few sizes here: I assume the report is about the case where this doesn't get unrolled, like with N=128?
I'm not entirely sure what you're looking for in a reproducer, but I have a benchmark program set up using to check out the performance of the various functions (see the "Benchmark" section at the bottom of this post). More or less I have as shown above (renamed to ), and both of these: Then I set up a lot of benchmarks. These test the speed of some primitive operations (, , , , , ) on arrays of lengths 8, 16, 32, 64, 128, 256, and 512 for types u8, u16, u32, and u64. This gives a total of 168 benchmarks per function, which reduces down to 28 per test after the primitive tests are averaged for each function, length, and type. The results of this are: ! This was run on the latest nightly as of 2022-12-21. I think this is pretty hard evidence that performance using is not where it should be. and are grouped so close together in the bottom section of the graph you can't visually see the difference. But for ? It's very obviously slower than the other two. Notice how it takes more time to map together two than it takes the other methods to map together two . Even if we just look at shorter inputs like was suggested, it doesn't look good for : ! These are just the results for lengths up through 64, and we can pretty clearly see that is just always slower. <details<summary<strongBenchmark</strong</summary<p: </p</details
Part of this is the classic "too many copies" trio But some of it is probably just that, being eager, it won't optimize unless it fully unrolls.

x.map(|x| 2 * x + 1) } <del> // CHECK-LABEL: @short_integer_zip_map #[no_mangle] pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] { // CHECK: %[[A:.+]] = load <8 x i32> // CHECK: %[[B:.+]] = load <8 x i32> // CHECK: sub <8 x i32> %[[B]], %[[A]] // CHECK: store <8 x i32> x.zip(y).map(|(x, y)| x - y) } </del> // This test is checking that LLVM can SRoA away a bunch of the overhead, // like fully moving the iterators to registers.  Notably, previous implementations // of `map` ended up `alloca`ing the whole `array::IntoIterator`, meaning both a


Question:
Today for no reason in particular I was curious about the behaviour of arrays when zipped together and then mapped into a single array, roughly: I wrote some tests for this and disassembled them in Godbolt to see what was going on behind the scenes and wow was a whole lot going on that seemed like it didn't need to be. So I wrote something kinda like what's in the stdlib for mapping and zipping arrays, just without the iterators, to see if I could do any better. Turns out I absolutely can: Maybe the design isn't as optimal (or as safe) as it could be, but it performs perfectly well in benchmarks (read: as fast as an unguarded version and anywhere between 3-25 times faster than the definition shown at the top of this issue. Here's a rough table of execution times averaged over the primitive ops (, , &|^`): ! Not really liking how things are looking for . So, question then is: is there something in Rust that needs to change to let these optimisations happen, or do I need to look at putting this in a library somewhere (or maybe stdlib wink wink nudge nudge?)? *The 25x comes from the benchmarks. benches at 11.230ns, and benches at 452.593ps, which seems suspicious but I can't seem to find anything wrong with the result.
I suspect the issue here is that has the wrong shape. It returns but vector instructions generally want . isn't an iterator type that describes the desired iteration and then performs it once, rather it's one loop that creates an intermediate result and then a second loop that produces the final output. Perhaps we could massage the code into a shape that the optimizer can disentangle, but I think it would be better to offer something like your , albeit with a nicer name.
This is missing an actual reproducer... Tried a few sizes here: I assume the report is about the case where this doesn't get unrolled, like with N=128?
I'm not entirely sure what you're looking for in a reproducer, but I have a benchmark program set up using to check out the performance of the various functions (see the "Benchmark" section at the bottom of this post). More or less I have as shown above (renamed to ), and both of these: Then I set up a lot of benchmarks. These test the speed of some primitive operations (, , , , , ) on arrays of lengths 8, 16, 32, 64, 128, 256, and 512 for types u8, u16, u32, and u64. This gives a total of 168 benchmarks per function, which reduces down to 28 per test after the primitive tests are averaged for each function, length, and type. The results of this are: ! This was run on the latest nightly as of 2022-12-21. I think this is pretty hard evidence that performance using is not where it should be. and are grouped so close together in the bottom section of the graph you can't visually see the difference. But for ? It's very obviously slower than the other two. Notice how it takes more time to map together two than it takes the other methods to map together two . Even if we just look at shorter inputs like was suggested, it doesn't look good for : ! These are just the results for lengths up through 64, and we can pretty clearly see that is just always slower. <details<summary<strongBenchmark</strong</summary<p: </p</details
Part of this is the classic "too many copies" trio But some of it is probably just that, being eager, it won't optimize unless it fully unrolls.

// compile-flags: -C opt-level=3 -Z merge-functions=disabled // only-x86_64 #![crate_type = "lib"] <del> #![feature(array_zip)] </del> // CHECK-LABEL: @auto_vectorize_direct #[no_mangle]


Question:
Today for no reason in particular I was curious about the behaviour of arrays when zipped together and then mapped into a single array, roughly: I wrote some tests for this and disassembled them in Godbolt to see what was going on behind the scenes and wow was a whole lot going on that seemed like it didn't need to be. So I wrote something kinda like what's in the stdlib for mapping and zipping arrays, just without the iterators, to see if I could do any better. Turns out I absolutely can: Maybe the design isn't as optimal (or as safe) as it could be, but it performs perfectly well in benchmarks (read: as fast as an unguarded version and anywhere between 3-25 times faster than the definition shown at the top of this issue. Here's a rough table of execution times averaged over the primitive ops (, , &|^`): ! Not really liking how things are looking for . So, question then is: is there something in Rust that needs to change to let these optimisations happen, or do I need to look at putting this in a library somewhere (or maybe stdlib wink wink nudge nudge?)? *The 25x comes from the benchmarks. benches at 11.230ns, and benches at 452.593ps, which seems suspicious but I can't seem to find anything wrong with the result.
I suspect the issue here is that has the wrong shape. It returns but vector instructions generally want . isn't an iterator type that describes the desired iteration and then performs it once, rather it's one loop that creates an intermediate result and then a second loop that produces the final output. Perhaps we could massage the code into a shape that the optimizer can disentangle, but I think it would be better to offer something like your , albeit with a nicer name.
This is missing an actual reproducer... Tried a few sizes here: I assume the report is about the case where this doesn't get unrolled, like with N=128?
I'm not entirely sure what you're looking for in a reproducer, but I have a benchmark program set up using to check out the performance of the various functions (see the "Benchmark" section at the bottom of this post). More or less I have as shown above (renamed to ), and both of these: Then I set up a lot of benchmarks. These test the speed of some primitive operations (, , , , , ) on arrays of lengths 8, 16, 32, 64, 128, 256, and 512 for types u8, u16, u32, and u64. This gives a total of 168 benchmarks per function, which reduces down to 28 per test after the primitive tests are averaged for each function, length, and type. The results of this are: ! This was run on the latest nightly as of 2022-12-21. I think this is pretty hard evidence that performance using is not where it should be. and are grouped so close together in the bottom section of the graph you can't visually see the difference. But for ? It's very obviously slower than the other two. Notice how it takes more time to map together two than it takes the other methods to map together two . Even if we just look at shorter inputs like was suggested, it doesn't look good for : ! These are just the results for lengths up through 64, and we can pretty clearly see that is just always slower. <details<summary<strongBenchmark</strong</summary<p: </p</details
Part of this is the classic "too many copies" trio But some of it is probably just that, being eager, it won't optimize unless it fully unrolls.

c } <del> // CHECK-LABEL: @auto_vectorize_array_zip_map </del> <ins> // CHECK-LABEL: @auto_vectorize_array_from_fn </ins> #[no_mangle] <del> pub fn auto_vectorize_array_zip_map(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { </del> <ins> pub fn auto_vectorize_array_from_fn(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { </ins> // CHECK: load <4 x float> // CHECK: load <4 x float> // CHECK: fadd <4 x float> // CHECK: store <4 x float> <del> a.zip(b).map(|(a, b)| a + b) </del> <ins> std::array::from_fn(|i| a[i] + b[i]) </ins> }


Question:
I tried this: I expected to see this happen: The second invocation takes essentially no time. Instead, this happened: The docs were completely rebuilt. The problem is that we remove the docs between each invocation: this is a regression from - do you think you'll have time to follow up? I think we can either add a stamp file to avoid rebuilding, or find some other way to avoid removing the whole directory - maybe we can only remove/copy the files, rather than everything? <!-- 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. --HEAD is branched from . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Ok, I confirmed that rustdoc only creates JSON files with --output-format json: So it should be enough to only copy .json files when passed --json, and only non-json files when it's not passed. We should also add a test that produces the same output in json-doc as , to avoid a regression if rustdoc starts emitting JSON files in the default HTML format.
I can't jump on it immediately, but I should be able to follow up in a couple of weeks
claim
We can do this validation for dir, but I am not sure if this is possible for dir since each time json output changes. The layout of json context is getting change even if you don't change anyhing on the source code. I print sha2 sums below to demonstrate the situation. 1st attempt: 2nd attempt right after the first attempt The demonstration is from
thanks for investigating; sounds like we should report that as a separate bug in rustdoc. But for now it's ok if the files don't match exactly as long as the file names are the same between runs.

let my_out = match mode { // This is the intended out directory for compiler documentation. Mode::Rustc | Mode::ToolRustc => self.compiler_doc_out(target), <del> Mode::Std => out_dir.join(target.triple).join("doc"), </del> <ins> Mode::Std => { if self.config.cmd.json() { out_dir.join(target.triple).join("json-doc") } else { out_dir.join(target.triple).join("doc") } } </ins> _ => panic!("doc mode {:?} not expected", mode), }; let rustdoc = self.rustdoc(compiler);


Question:
I tried this: I expected to see this happen: The second invocation takes essentially no time. Instead, this happened: The docs were completely rebuilt. The problem is that we remove the docs between each invocation: this is a regression from - do you think you'll have time to follow up? I think we can either add a stamp file to avoid rebuilding, or find some other way to avoid removing the whole directory - maybe we can only remove/copy the files, rather than everything? <!-- 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. --HEAD is branched from . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Ok, I confirmed that rustdoc only creates JSON files with --output-format json: So it should be enough to only copy .json files when passed --json, and only non-json files when it's not passed. We should also add a test that produces the same output in json-doc as , to avoid a regression if rustdoc starts emitting JSON files in the default HTML format.
I can't jump on it immediately, but I should be able to follow up in a couple of weeks
claim
We can do this validation for dir, but I am not sure if this is possible for dir since each time json output changes. The layout of json context is getting change even if you don't change anyhing on the source code. I print sha2 sums below to demonstrate the situation. 1st attempt: 2nd attempt right after the first attempt The demonstration is from
thanks for investigating; sounds like we should report that as a separate bug in rustdoc. But for now it's ok if the files don't match exactly as long as the file names are the same between runs.

); } let compiler = builder.compiler(stage, builder.config.build); <ins> let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; let target_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name); </ins> // This is directory where the compiler will place the output of the command. // We will then copy the files from this directory into the final `out` directory, the specified // as a function parameter. <del> let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc"); // `cargo` uses the same directory for both JSON docs and HTML docs. // This could lead to cross-contamination when copying files into the specified `out` directory. // For example: // ```bash // x doc std // x doc std --json // ``` // could lead to HTML docs being copied into the JSON docs output directory. // To avoid this issue, we clean the doc folder before invoking `cargo`. if out_dir.exists() { builder.remove_dir(&out_dir); } </del> <ins> let out_dir = target_dir.join(target.triple).join("doc"); </ins> let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc"); compile::std_cargo(builder, target, compiler.stage, &mut cargo); cargo <ins> .arg("--target-dir") .arg(&*target_dir.to_string_lossy()) </ins> .arg("-p") .arg(package) .arg("-Zskip-rustdoc-fingerprint")


Question:
I tried this: I expected to see this happen: The second invocation takes essentially no time. Instead, this happened: The docs were completely rebuilt. The problem is that we remove the docs between each invocation: this is a regression from - do you think you'll have time to follow up? I think we can either add a stamp file to avoid rebuilding, or find some other way to avoid removing the whole directory - maybe we can only remove/copy the files, rather than everything? <!-- 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. --HEAD is branched from . <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Ok, I confirmed that rustdoc only creates JSON files with --output-format json: So it should be enough to only copy .json files when passed --json, and only non-json files when it's not passed. We should also add a test that produces the same output in json-doc as , to avoid a regression if rustdoc starts emitting JSON files in the default HTML format.
I can't jump on it immediately, but I should be able to follow up in a couple of weeks
claim
We can do this validation for dir, but I am not sure if this is possible for dir since each time json output changes. The layout of json context is getting change even if you don't change anyhing on the source code. I print sha2 sums below to demonstrate the situation. 1st attempt: 2nd attempt right after the first attempt The demonstration is from
thanks for investigating; sounds like we should report that as a separate bug in rustdoc. But for now it's ok if the files don't match exactly as long as the file names are the same between runs.

<ins> include ../../run-make-fulldeps/tools.mk OUTPUT_DIR := "$(TMPDIR)/rustdoc" TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc" all: # Generate html docs $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) # Copy first output for to check if it's exactly same after second compilation cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) # Generate html docs once again on same output $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) # Check if everything exactly same $(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) # Generate json doc on the same output $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json # Check if expected json file is generated [ -e $(OUTPUT_DIR)/foobar.json ] # TODO # We should re-generate json doc once again and compare the diff with previously # generated one. Because layout of json docs changes in each compilation, we can't # do that currently. # # See https://github.com/rust-lang/rust/issues/103785#issuecomment-1307425590 for details. # remove generated json doc rm $(OUTPUT_DIR)/foobar.json # Check if json doc compilation broke any of the html files generated previously $(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) </ins>


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

*[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more } not covered <ins> mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future </ins> mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}`


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

pub interpreted_as_const: Option<InterpretedAsConst>, #[subdiagnostic] pub adt_defined_here: Option<AdtDefinedHere<'tcx>>, <ins> #[note(mir_build_privately_uninhabited)] pub witness_1_is_privately_uninhabited: Option<()>, </ins> #[note(mir_build_pattern_ty)] pub _p: (), pub pattern_ty: Ty<'tcx>,


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

AdtDefinedHere { adt_def_span, ty, variants } }; <ins> // Emit an extra note if the first uncovered witness is // visibly uninhabited anywhere in the current crate. let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, substs) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { let variant = adt.variant(*variant_index); let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs); assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module)); !inhabited.apply_ignore_module(cx.tcx, cx.param_env) } else { false }; </ins> self.error = Err(self.tcx.sess.emit_err(PatternNotCovered { span: pat.span, origin, uncovered: Uncovered::new(pat.span, &cx, witnesses), inform, interpreted_as_const, <ins> witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()), </ins> _p: (), pattern_ty, let_suggestion,


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

LL |     A(A), LL |     B(inner::Wrapper<B>), |     - not covered <ins> = note: pattern `Either::B(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future </ins> = note: the matched value is of type `Either<(), !>` help: you might want to use `if let` to ignore the variant that isn't matched |


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

} enum Foo { <ins> //~^ NOTE `Foo` defined here </ins> A(foo::SecretlyEmpty), <ins> //~^ NOTE not covered </ins> B(foo::NotSoSecretlyEmpty), C(NotSoSecretlyEmpty), D(u32, u32),


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

let Foo::D(_y, _z) = x; //~^ ERROR refutable pattern in local binding //~| `Foo::A(_)` not covered <ins> //~| NOTE `let` bindings require an "irrefutable pattern" //~| NOTE for more information //~| NOTE pattern `Foo::A(_)` is currently uninhabited //~| NOTE the matched value is of type `Foo` //~| HELP you might want to use `let else` </ins> }


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

error[E0005]: refutable pattern in local binding <del> --> $DIR/uninhabited-irrefutable.rs:27:9 </del> <ins> --> $DIR/uninhabited-irrefutable.rs:29:9 </ins> | LL |     let Foo::D(_y, _z) = x; |         ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered


Question:
The following code compiles on nightly (): But if the wrapper type is moved into a module to make the field private, then it does not: (): Making the field makes it compile again. Is this expected? I suppose I could understand if it is; the private fields could change to make actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like . If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an . label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve
label +F-exhaustive_patterns
are we sure this is actually a bug? As I said, I could understand how it's not:
I'm not sure either way - however at the very least, as you point out, it makes sense to have some better diagnostics
This is definitely intentional. But yeah, it should have a better error message. Not currently I don't think. It would probably require us to add an trait, eg. something like: This trait would then need to be a lang item so that the exhaustiveness check could make use of it. Adding this trait would require an RFC but I doubt there'll be much enthusiasm for adding another special trait for such a niche use-case. Alternatively, you could give an or method to expose the uninhabitedness of the inner value. It's not quite what you're asking for but it's still concise-ish:
Is supposed to be “injected” where an otherwise required match arm was omitted? Wouldn't that run into the same discussions project-deref-patterns had about impure code (code with side effects) inside patterns? Their existence would heavily hinder optimizations of match expressions (like translation to jump tables or reordering).
If the type implementing really is uninhabited then there won't actually be any impure code in the match. The call to would only need to be injected for types that fake uninhabitedness with an impl that panics/aborts. We could also rule that out be instead making -only like .
Making a trait isn't straightforward exactly because inhabitedness depends on visibility questions. It would probably have to mean "Uninhabited as far as the outside world is concerned", or it could use a trick like the in to make it depend on the module.

| LL | enum Foo { |      ^^^ <ins> LL | </ins> LL |     A(foo::SecretlyEmpty), |     - not covered <ins> = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future </ins> = note: the matched value is of type `Foo` help: you might want to use `let else` to handle the variant that isn't matched |


Question:
Found with a <details<summary<strongFull output including backtrace</strong</summary<p</p</detailsRegression in nightly-2022-09-18 from ( <details<summaryBisect info</summarysearched nightlies: from nightly-2022-09-04 to nightly-2022-11-07 regressed nightly: nightly-2022-09-18 searched commit range: regressed commit: bisected with <a href=''cargo-bisect-rustc</av0.6.4 Host triple: x86_64-apple-darwin </details
For the record, this isn't dependent on return type, which is a separate error. This also ICEs:
This don't ICE: I guess it's because terminated because the error type error.
Yeah, still needs to implement the trait in the -- this ICEs, for example:
I can take a look at this, unless you're already working on this
I think compiler-errors already submitted a PR to fix this, PR linked above, but he did not claim this issue.
Oh thanks, didn't see this.

let literal = constant.literal; match literal { ConstantKind::Ty(c) => match c.kind() { <del> ConstKind::Param(_) => {} </del> <ins> ConstKind::Param(_) | ConstKind::Error(_) => {} </ins> _ => bug!("only ConstKind::Param should be encountered here, got {:#?}", c), }, ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),


Question:
Found with a <details<summary<strongFull output including backtrace</strong</summary<p</p</detailsRegression in nightly-2022-09-18 from ( <details<summaryBisect info</summarysearched nightlies: from nightly-2022-09-04 to nightly-2022-11-07 regressed nightly: nightly-2022-09-18 searched commit range: regressed commit: bisected with <a href=''cargo-bisect-rustc</av0.6.4 Host triple: x86_64-apple-darwin </details
For the record, this isn't dependent on return type, which is a separate error. This also ICEs:
This don't ICE: I guess it's because terminated because the error type error.
Yeah, still needs to implement the trait in the -- this ICEs, for example:
I can take a look at this, unless you're already working on this
I think compiler-errors already submitted a PR to fix this, PR linked above, but he did not claim this issue.
Oh thanks, didn't see this.

<ins> fn f() -> impl Sized { 2.0E //~^ ERROR expected at least one digit in exponent } fn main() {} </ins>