From 6d590ba9426f60459c66d19f73b52f774e23e308 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 26 Apr 2022 21:33:17 +0300 Subject: [PATCH 01/12] rustdoc: Resolve doc links on fields during early resolution --- .../passes/collect_intra_doc_links/early.rs | 14 +++++++++- src/test/rustdoc-ui/intra-doc/assoc-field.rs | 26 +++++++++++++++++++ .../intra-doc/auxiliary/assoc-field-dep.rs | 18 +++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/intra-doc/assoc-field.rs create mode 100644 src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 68e10e3a18c7e..1b80f6b93dc78 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -260,10 +260,22 @@ impl EarlyDocLinkResolver<'_, '_> { if let Res::Def(DefKind::Mod, ..) = child.res { self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope } - // Traits are processed in `add_extern_traits_in_scope`. + // `DefKind::Trait`s are processed in `process_extern_impls`. if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res { self.process_module_children_or_reexports(def_id); } + if let Res::Def(DefKind::Struct | DefKind::Union | DefKind::Variant, _) = + child.res + { + let field_def_ids = Vec::from_iter( + self.resolver + .cstore() + .associated_item_def_ids_untracked(def_id, self.sess), + ); + for field_def_id in field_def_ids { + self.resolve_doc_links_extern_outer(field_def_id, scope_id); + } + } } } } diff --git a/src/test/rustdoc-ui/intra-doc/assoc-field.rs b/src/test/rustdoc-ui/intra-doc/assoc-field.rs new file mode 100644 index 0000000000000..e18404e44306e --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/assoc-field.rs @@ -0,0 +1,26 @@ +// Traits in scope are collected for doc links in field attributes. + +// check-pass +// aux-build: assoc-field-dep.rs + +extern crate assoc_field_dep; +pub use assoc_field_dep::*; + +#[derive(Clone)] +pub struct Struct; + +pub mod mod1 { + pub struct Fields { + /// [crate::Struct::clone] + pub field: u8, + } +} + +pub mod mod2 { + pub enum Fields { + V { + /// [crate::Struct::clone] + field: u8, + }, + } +} diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs new file mode 100644 index 0000000000000..cfb24fc2c665c --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/assoc-field-dep.rs @@ -0,0 +1,18 @@ +#[derive(Clone)] +pub struct Struct; + +pub mod dep_mod1 { + pub struct Fields { + /// [crate::Struct::clone] + pub field: u8, + } +} + +pub mod dep_mod2 { + pub enum Fields { + V { + /// [crate::Struct::clone] + field: u8, + }, + } +} From 6d865f80f88fe7d8ed37bdfed4ff93ba9ce1a908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Mon, 2 May 2022 04:55:04 +0000 Subject: [PATCH 02/12] openbsd: unbreak build on native platform after #95612, only linux and windows target are build with -Zunstable-options, but others platforms might use -Csplit-debuginfo add "openbsd" target in the list of platforms using it. --- src/bootstrap/builder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index dd45bd3a213b1..c09784f844321 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1406,7 +1406,8 @@ impl<'a> Builder<'a> { // FIXME(davidtwco): #[cfg(not(bootstrap))] - #95612 needs to be in the bootstrap compiler // for this conditional to be removed. if !target.contains("windows") || compiler.stage >= 1 { - if target.contains("linux") || target.contains("windows") { + if target.contains("linux") || target.contains("windows") || target.contains("openbsd") + { rustflags.arg("-Zunstable-options"); } match self.config.rust_split_debuginfo { From 6d8b56972ce239f107f03001fef8982849be34a9 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Mon, 2 May 2022 18:50:54 +0900 Subject: [PATCH 03/12] remove the special case for nonexported macro_rules! macros --- src/librustdoc/doctest.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 82e367427ef6f..93ccf60a1de45 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1225,16 +1225,6 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx> fn visit_item(&mut self, item: &'hir hir::Item<'_>) { let name = match &item.kind { - hir::ItemKind::Macro(ref macro_def, _) => { - // FIXME(#88038): Non exported macros have historically not been tested, - // but we really ought to start testing them. - let def_id = item.def_id.to_def_id(); - if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { - intravisit::walk_item(self, item); - return; - } - item.ident.to_string() - } hir::ItemKind::Impl(impl_) => { rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id) } From 57967269e9946945dedd360e8e8654f5dd76ebd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 23 Apr 2022 16:41:36 -0700 Subject: [PATCH 04/12] When suggesting to import an item, also suggest changing the path if appropriate When we don't find an item we search all of them for an appropriate import and suggest `use`ing it. This is sometimes done for expressions that have paths with more than one segment. We now also suggest changing that path to work with the `use`. Fix #95413 --- compiler/rustc_resolve/src/diagnostics.rs | 21 +++++++++++--- compiler/rustc_resolve/src/late.rs | 2 ++ compiler/rustc_resolve/src/lib.rs | 3 ++ .../ui/macros/macro-outer-attributes.stderr | 7 ++++- src/test/ui/namespace/namespace-mix.stderr | 28 ++++++++++++++++--- .../ui/parser/circular_modules_main.stderr | 7 ++++- .../ui/resolve/enums-are-namespaced-xc.stderr | 21 ++++++++++++-- src/test/ui/resolve/issue-50599.stderr | 7 ++++- .../ui/resolve/missing-in-namespace.stderr | 7 ++++- src/test/ui/resolve/privacy-enum-ctor.stderr | 7 ++++- .../resolve/resolve-primitive-fallback.stderr | 7 ++++- ...dowed-path-in-trait-bound-suggestion.fixed | 16 +++++++++++ ...shadowed-path-in-trait-bound-suggestion.rs | 14 ++++++++++ ...owed-path-in-trait-bound-suggestion.stderr | 19 +++++++++++++ 14 files changed, 149 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed create mode 100644 src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs create mode 100644 src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index aef9fb57a6a7c..f75ea583d852e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -117,7 +117,7 @@ impl<'a> Resolver<'a> { } fn report_with_use_injections(&mut self, krate: &Crate) { - for UseError { mut err, candidates, def_id, instead, suggestion } in + for UseError { mut err, candidates, def_id, instead, suggestion, path } in self.use_injections.drain(..) { let (span, found_use) = if let Some(def_id) = def_id.as_local() { @@ -135,6 +135,7 @@ impl<'a> Resolver<'a> { if instead { Instead::Yes } else { Instead::No }, found_use, IsPattern::No, + path, ); } else if let Some((span, msg, sugg, appl)) = suggestion { err.span_suggestion(span, msg, sugg, appl); @@ -702,6 +703,7 @@ impl<'a> Resolver<'a> { Instead::No, FoundUse::Yes, IsPattern::Yes, + vec![], ); } err @@ -1482,6 +1484,7 @@ impl<'a> Resolver<'a> { Instead::No, FoundUse::Yes, IsPattern::No, + vec![], ); if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { @@ -2448,6 +2451,7 @@ fn show_candidates( instead: Instead, found_use: FoundUse, is_pattern: IsPattern, + path: Vec, ) { if candidates.is_empty() { return; @@ -2480,14 +2484,15 @@ fn show_candidates( ("one of these", "items", String::new()) }; + let tail = if path.len() > 1 { "..." } else { "" }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let IsPattern::Yes = is_pattern { format!( - "if you meant to match on {}{}{}, use the full path in the pattern", - kind, instead, name + "if you meant to match on {}{}{}, use the full path in the pattern{}", + kind, instead, name, tail ) } else { - format!("consider importing {} {}{}", determiner, kind, instead) + format!("consider importing {} {}{}{}", determiner, kind, instead, tail) }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { @@ -2515,6 +2520,14 @@ fn show_candidates( accessible_path_strings.into_iter().map(|a| a.0), Applicability::MaybeIncorrect, ); + if let [first, .., last] = &path[..] { + err.span_suggestion_verbose( + first.ident.span.until(last.ident.span), + "...and refer to it directly", + String::new(), + Applicability::Unspecified, + ); + } } else { msg.push(':'); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b89b9c376af63..21c9461a83d9a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2682,6 +2682,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { def_id, instead, suggestion, + path: path.into(), }); } @@ -2745,6 +2746,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { def_id, instead: false, suggestion: None, + path: path.into(), }); } else { err.cancel(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f6109b1dc1a1a..ff11aba49d836 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -696,6 +696,9 @@ struct UseError<'a> { instead: bool, /// Extra free-form suggestion. suggestion: Option<(Span, &'static str, String, Applicability)>, + /// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling + /// the user to import the item directly. + path: Vec, } #[derive(Clone, Copy, PartialEq, Debug)] diff --git a/src/test/ui/macros/macro-outer-attributes.stderr b/src/test/ui/macros/macro-outer-attributes.stderr index 8e064d980afab..a9fb79b7b27cf 100644 --- a/src/test/ui/macros/macro-outer-attributes.stderr +++ b/src/test/ui/macros/macro-outer-attributes.stderr @@ -4,10 +4,15 @@ error[E0425]: cannot find function `bar` in module `a` LL | a::bar(); | ^^^ not found in `a` | -help: consider importing this function +help: consider importing this function... | LL | use b::bar; | +help: ...and refer to it directly + | +LL - a::bar(); +LL + bar(); + | error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index b610857229201..dd9c969fc82fe 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -12,12 +12,17 @@ help: a tuple struct with a similar name exists | LL | check(m1::TS); | ~~ -help: consider importing one of these items instead +help: consider importing one of these items instead... | LL | use m2::S; | LL | use xm2::S; | +help: ...and refer to it directly + | +LL - check(m1::S); +LL + check(S); + | error[E0423]: expected value, found type alias `xm1::S` --> $DIR/namespace-mix.rs:40:11 @@ -35,12 +40,17 @@ help: a tuple struct with a similar name exists | LL | check(xm1::TS); | ~~ -help: consider importing one of these items instead +help: consider importing one of these items instead... | LL | use m2::S; | LL | use xm2::S; | +help: ...and refer to it directly + | +LL - check(xm1::S); +LL + check(S); + | error[E0423]: expected value, found struct variant `m7::V` --> $DIR/namespace-mix.rs:100:11 @@ -61,12 +71,17 @@ help: a tuple variant with a similar name exists | LL | check(m7::TV); | ~~ -help: consider importing one of these items instead +help: consider importing one of these items instead... | LL | use m8::V; | LL | use xm8::V; | +help: ...and refer to it directly + | +LL - check(m7::V); +LL + check(V); + | error[E0423]: expected value, found struct variant `xm7::V` --> $DIR/namespace-mix.rs:106:11 @@ -89,12 +104,17 @@ help: a tuple variant with a similar name exists | LL | check(xm7::TV); | ~~ -help: consider importing one of these items instead +help: consider importing one of these items instead... | LL | use m8::V; | LL | use xm8::V; | +help: ...and refer to it directly + | +LL - check(xm7::V); +LL + check(V); + | error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:33:11 diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index ee45f65a3bd5a..f6f3babc2d5e3 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -10,10 +10,15 @@ error[E0425]: cannot find function `hi_str` in module `circular_modules_main` LL | println!("{}", circular_modules_main::hi_str()); | ^^^^^^ not found in `circular_modules_main` | -help: consider importing this function +help: consider importing this function... | LL | use hi_str; | +help: ...and refer to it directly + | +LL - println!("{}", circular_modules_main::hi_str()); +LL + println!("{}", hi_str()); + | error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 621686dd292d6..f501683ebc95f 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -4,10 +4,15 @@ error[E0425]: cannot find value `A` in crate `namespaced_enums` LL | let _ = namespaced_enums::A; | ^ not found in `namespaced_enums` | -help: consider importing this unit variant +help: consider importing this unit variant... | LL | use namespaced_enums::Foo::A; | +help: ...and refer to it directly + | +LL - let _ = namespaced_enums::A; +LL + let _ = A; + | error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `namespaced_enums` --> $DIR/enums-are-namespaced-xc.rs:7:31 @@ -15,10 +20,15 @@ error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate ` LL | let _ = namespaced_enums::B(10); | ^ not found in `namespaced_enums` | -help: consider importing this tuple variant +help: consider importing this tuple variant... | LL | use namespaced_enums::Foo::B; | +help: ...and refer to it directly + | +LL - let _ = namespaced_enums::B(10); +LL + let _ = B(10); + | error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced_enums` --> $DIR/enums-are-namespaced-xc.rs:9:31 @@ -26,10 +36,15 @@ error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced LL | let _ = namespaced_enums::C { a: 10 }; | ^ not found in `namespaced_enums` | -help: consider importing this variant +help: consider importing this variant... | LL | use namespaced_enums::Foo::C; | +help: ...and refer to it directly + | +LL - let _ = namespaced_enums::C { a: 10 }; +LL + let _ = C { a: 10 }; + | error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index 7ec567a06f09d..ef0b30d98d884 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -4,12 +4,17 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64` LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; | ^^^^^^^ not found in `std::f64` | -help: consider importing one of these items +help: consider importing one of these items... | LL | use std::f32::consts::LOG10_2; | LL | use std::f64::consts::LOG10_2; | +help: ...and refer to it directly + | +LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; +LL + const M: usize = (f64::from(N) * LOG10_2) as usize; + | error: aborting due to previous error diff --git a/src/test/ui/resolve/missing-in-namespace.stderr b/src/test/ui/resolve/missing-in-namespace.stderr index 8b292aeda5074..265f370494aa7 100644 --- a/src/test/ui/resolve/missing-in-namespace.stderr +++ b/src/test/ui/resolve/missing-in-namespace.stderr @@ -4,10 +4,15 @@ error[E0433]: failed to resolve: could not find `hahmap` in `std` LL | let _map = std::hahmap::HashMap::new(); | ^^^^^^^ not found in `std::hahmap` | -help: consider importing this struct +help: consider importing this struct... | LL | use std::collections::HashMap; | +help: ...and refer to it directly + | +LL - let _map = std::hahmap::HashMap::new(); +LL + let _map = HashMap::new(); + | error: aborting due to previous error diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index c93ba915efb2f..4ac18c0e79599 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -99,12 +99,17 @@ help: a function with a similar name exists | LL | let _: E = m::f; | ~ -help: consider importing one of these items instead +help: consider importing one of these items instead... | LL | use std::f32::consts::E; | LL | use std::f64::consts::E; | +help: ...and refer to it directly + | +LL - let _: E = m::E; +LL + let _: E = E; + | error[E0423]: expected value, found struct variant `m::E::Struct` --> $DIR/privacy-enum-ctor.rs:45:16 diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr index 44631f954df33..3db3706ecf51d 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.stderr +++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr @@ -10,10 +10,15 @@ error[E0412]: cannot find type `u8` in the crate root LL | let _: ::u8; | ^^ not found in the crate root | -help: consider importing this builtin type +help: consider importing this builtin type... | LL | use std::primitive::u8; | +help: ...and refer to it directly + | +LL - let _: ::u8; +LL + let _: u8; + | error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/resolve-primitive-fallback.rs:3:5 diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed new file mode 100644 index 0000000000000..39e90d7a3f786 --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![allow(non_snake_case)] +mod A { + pub trait Trait {} + impl Trait for i32 {} +} + +mod B { + use A::Trait; + +pub struct A(pub H); //~ ERROR cannot find trait +} + +fn main() { + let _ = B::A(42); +} diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs new file mode 100644 index 0000000000000..ee6ed0cae671c --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(non_snake_case)] +mod A { + pub trait Trait {} + impl Trait for i32 {} +} + +mod B { + pub struct A(pub H); //~ ERROR cannot find trait +} + +fn main() { + let _ = B::A(42); +} diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr new file mode 100644 index 0000000000000..413a0c8d60e2c --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr @@ -0,0 +1,19 @@ +error[E0405]: cannot find trait `Trait` in `A` + --> $DIR/shadowed-path-in-trait-bound-suggestion.rs:9:24 + | +LL | pub struct A(pub H); + | ^^^^^ not found in `A` + | +help: consider importing this trait... + | +LL | use A::Trait; + | +help: ...and refer to it directly + | +LL - pub struct A(pub H); +LL + pub struct A(pub H); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. From 4934a9e6430b3fcb98f77205f8a625c7ffebd628 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 3 May 2022 02:07:47 +0000 Subject: [PATCH 05/12] Tweak wording --- compiler/rustc_resolve/src/diagnostics.rs | 9 ++++----- src/test/ui/macros/macro-outer-attributes.stderr | 4 ++-- src/test/ui/namespace/namespace-mix.stderr | 16 ++++++++-------- src/test/ui/parser/circular_modules_main.stderr | 4 ++-- .../ui/resolve/enums-are-namespaced-xc.stderr | 12 ++++++------ src/test/ui/resolve/issue-50599.stderr | 4 ++-- src/test/ui/resolve/missing-in-namespace.stderr | 4 ++-- src/test/ui/resolve/privacy-enum-ctor.stderr | 4 ++-- .../ui/resolve/resolve-primitive-fallback.stderr | 4 ++-- ...hadowed-path-in-trait-bound-suggestion.stderr | 4 ++-- 10 files changed, 32 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f75ea583d852e..5d80f49626a04 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2484,15 +2484,14 @@ fn show_candidates( ("one of these", "items", String::new()) }; - let tail = if path.len() > 1 { "..." } else { "" }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let IsPattern::Yes = is_pattern { format!( - "if you meant to match on {}{}{}, use the full path in the pattern{}", - kind, instead, name, tail + "if you meant to match on {}{}{}, use the full path in the pattern", + kind, instead, name ) } else { - format!("consider importing {} {}{}{}", determiner, kind, instead, tail) + format!("consider importing {} {}{}", determiner, kind, instead) }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { @@ -2523,7 +2522,7 @@ fn show_candidates( if let [first, .., last] = &path[..] { err.span_suggestion_verbose( first.ident.span.until(last.ident.span), - "...and refer to it directly", + &format!("if you import `{}`, refer to it directly", last.ident), String::new(), Applicability::Unspecified, ); diff --git a/src/test/ui/macros/macro-outer-attributes.stderr b/src/test/ui/macros/macro-outer-attributes.stderr index a9fb79b7b27cf..91073d3698d91 100644 --- a/src/test/ui/macros/macro-outer-attributes.stderr +++ b/src/test/ui/macros/macro-outer-attributes.stderr @@ -4,11 +4,11 @@ error[E0425]: cannot find function `bar` in module `a` LL | a::bar(); | ^^^ not found in `a` | -help: consider importing this function... +help: consider importing this function | LL | use b::bar; | -help: ...and refer to it directly +help: if you import `bar`, refer to it directly | LL - a::bar(); LL + bar(); diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index dd9c969fc82fe..037a858d7e101 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -12,13 +12,13 @@ help: a tuple struct with a similar name exists | LL | check(m1::TS); | ~~ -help: consider importing one of these items instead... +help: consider importing one of these items instead | LL | use m2::S; | LL | use xm2::S; | -help: ...and refer to it directly +help: if you import `S`, refer to it directly | LL - check(m1::S); LL + check(S); @@ -40,13 +40,13 @@ help: a tuple struct with a similar name exists | LL | check(xm1::TS); | ~~ -help: consider importing one of these items instead... +help: consider importing one of these items instead | LL | use m2::S; | LL | use xm2::S; | -help: ...and refer to it directly +help: if you import `S`, refer to it directly | LL - check(xm1::S); LL + check(S); @@ -71,13 +71,13 @@ help: a tuple variant with a similar name exists | LL | check(m7::TV); | ~~ -help: consider importing one of these items instead... +help: consider importing one of these items instead | LL | use m8::V; | LL | use xm8::V; | -help: ...and refer to it directly +help: if you import `V`, refer to it directly | LL - check(m7::V); LL + check(V); @@ -104,13 +104,13 @@ help: a tuple variant with a similar name exists | LL | check(xm7::TV); | ~~ -help: consider importing one of these items instead... +help: consider importing one of these items instead | LL | use m8::V; | LL | use xm8::V; | -help: ...and refer to it directly +help: if you import `V`, refer to it directly | LL - check(xm7::V); LL + check(V); diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index f6f3babc2d5e3..c5434c72b382b 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -10,11 +10,11 @@ error[E0425]: cannot find function `hi_str` in module `circular_modules_main` LL | println!("{}", circular_modules_main::hi_str()); | ^^^^^^ not found in `circular_modules_main` | -help: consider importing this function... +help: consider importing this function | LL | use hi_str; | -help: ...and refer to it directly +help: if you import `hi_str`, refer to it directly | LL - println!("{}", circular_modules_main::hi_str()); LL + println!("{}", hi_str()); diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index f501683ebc95f..1d26a2c005872 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -4,11 +4,11 @@ error[E0425]: cannot find value `A` in crate `namespaced_enums` LL | let _ = namespaced_enums::A; | ^ not found in `namespaced_enums` | -help: consider importing this unit variant... +help: consider importing this unit variant | LL | use namespaced_enums::Foo::A; | -help: ...and refer to it directly +help: if you import `A`, refer to it directly | LL - let _ = namespaced_enums::A; LL + let _ = A; @@ -20,11 +20,11 @@ error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate ` LL | let _ = namespaced_enums::B(10); | ^ not found in `namespaced_enums` | -help: consider importing this tuple variant... +help: consider importing this tuple variant | LL | use namespaced_enums::Foo::B; | -help: ...and refer to it directly +help: if you import `B`, refer to it directly | LL - let _ = namespaced_enums::B(10); LL + let _ = B(10); @@ -36,11 +36,11 @@ error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced LL | let _ = namespaced_enums::C { a: 10 }; | ^ not found in `namespaced_enums` | -help: consider importing this variant... +help: consider importing this variant | LL | use namespaced_enums::Foo::C; | -help: ...and refer to it directly +help: if you import `C`, refer to it directly | LL - let _ = namespaced_enums::C { a: 10 }; LL + let _ = C { a: 10 }; diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index ef0b30d98d884..4cc035cb11e20 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -4,13 +4,13 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64` LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; | ^^^^^^^ not found in `std::f64` | -help: consider importing one of these items... +help: consider importing one of these items | LL | use std::f32::consts::LOG10_2; | LL | use std::f64::consts::LOG10_2; | -help: ...and refer to it directly +help: if you import `LOG10_2`, refer to it directly | LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; LL + const M: usize = (f64::from(N) * LOG10_2) as usize; diff --git a/src/test/ui/resolve/missing-in-namespace.stderr b/src/test/ui/resolve/missing-in-namespace.stderr index 265f370494aa7..338a5423aa472 100644 --- a/src/test/ui/resolve/missing-in-namespace.stderr +++ b/src/test/ui/resolve/missing-in-namespace.stderr @@ -4,11 +4,11 @@ error[E0433]: failed to resolve: could not find `hahmap` in `std` LL | let _map = std::hahmap::HashMap::new(); | ^^^^^^^ not found in `std::hahmap` | -help: consider importing this struct... +help: consider importing this struct | LL | use std::collections::HashMap; | -help: ...and refer to it directly +help: if you import `HashMap`, refer to it directly | LL - let _map = std::hahmap::HashMap::new(); LL + let _map = HashMap::new(); diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 4ac18c0e79599..ed89170fd8a75 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -99,13 +99,13 @@ help: a function with a similar name exists | LL | let _: E = m::f; | ~ -help: consider importing one of these items instead... +help: consider importing one of these items instead | LL | use std::f32::consts::E; | LL | use std::f64::consts::E; | -help: ...and refer to it directly +help: if you import `E`, refer to it directly | LL - let _: E = m::E; LL + let _: E = E; diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr index 3db3706ecf51d..fcbc28475f998 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.stderr +++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr @@ -10,11 +10,11 @@ error[E0412]: cannot find type `u8` in the crate root LL | let _: ::u8; | ^^ not found in the crate root | -help: consider importing this builtin type... +help: consider importing this builtin type | LL | use std::primitive::u8; | -help: ...and refer to it directly +help: if you import `u8`, refer to it directly | LL - let _: ::u8; LL + let _: u8; diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr index 413a0c8d60e2c..a8b275f98034a 100644 --- a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr @@ -4,11 +4,11 @@ error[E0405]: cannot find trait `Trait` in `A` LL | pub struct A(pub H); | ^^^^^ not found in `A` | -help: consider importing this trait... +help: consider importing this trait | LL | use A::Trait; | -help: ...and refer to it directly +help: if you import `Trait`, refer to it directly | LL - pub struct A(pub H); LL + pub struct A(pub H); From 77390a152f8a235b3b5f2406ddd1c4eb41f88178 Mon Sep 17 00:00:00 2001 From: Rock Boynton Date: Mon, 2 May 2022 22:33:28 -0700 Subject: [PATCH 06/12] Fix typo in lint levels doc --- src/doc/rustc/src/lints/levels.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 7bd46fafadf83..fbec3cd9baf50 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -100,9 +100,8 @@ This lint level gives you that. 'force-warn' does for 'warn'. It's the same as 'deny' in that a lint at this level will produce an error, but unlike the 'deny' level, the 'forbid' level can not be overridden to be anything lower than an error. However, lint -levels may still be capped with `--cap-lints` (see below) so `rustc --cap- -lints warn` will make lints set to 'forbid' just -warn. +levels may still be capped with `--cap-lints` (see below) so `rustc --cap-lints warn` +will make lints set to 'forbid' just warn. ## Configuring warning levels From 3d12fd0fafa31e50d42745dea32c64e409949bf3 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Tue, 3 May 2022 18:33:56 +0900 Subject: [PATCH 07/12] ignore a doctest for the non-exported macro --- library/core/src/internal_macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index 7ef78e0b48af1..5d4c9ba73951a 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -190,7 +190,7 @@ macro_rules! impl_fn_for_zst { /// /// # Example /// -/// ``` +/// ```ignore(cannot-test-this-because-non-exported-macro) /// cfg_if! { /// if #[cfg(unix)] { /// fn foo() { /* unix specific functionality */ } From 4698a3fb8a35994f5532d208ad060f2985ed1427 Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Wed, 4 May 2022 00:53:46 +0900 Subject: [PATCH 08/12] ignore the doctest for map --- src/librustdoc/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index cd196a0184799..ef8c766180b8a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -96,7 +96,7 @@ use crate::passes::collect_intra_doc_links; /// /// Example: /// -/// ``` +/// ```ignore(cannot-test-this-because-non-exported-macro) /// let letters = map!{"a" => "b", "c" => "d"}; /// ``` /// From 56c2769de357ade8a3617e4a7da2f739225616ac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 May 2022 20:46:02 +0200 Subject: [PATCH 09/12] Fix flaky rustdoc-ui test because it did not replace time result --- src/test/rustdoc-ui/block-doc-comment.rs | 1 + src/test/rustdoc-ui/block-doc-comment.stdout | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-ui/block-doc-comment.rs b/src/test/rustdoc-ui/block-doc-comment.rs index c60dfa3f9518e..ce529916e5ede 100644 --- a/src/test/rustdoc-ui/block-doc-comment.rs +++ b/src/test/rustdoc-ui/block-doc-comment.rs @@ -1,5 +1,6 @@ // check-pass // compile-flags:--test +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" // This test ensures that no code block is detected in the doc comments. diff --git a/src/test/rustdoc-ui/block-doc-comment.stdout b/src/test/rustdoc-ui/block-doc-comment.stdout index e5c27bebbdb23..7326c0a25a069 100644 --- a/src/test/rustdoc-ui/block-doc-comment.stdout +++ b/src/test/rustdoc-ui/block-doc-comment.stdout @@ -1,5 +1,5 @@ running 0 tests -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME From bfcd191905ce48c5b746af12c2995ef535d61b83 Mon Sep 17 00:00:00 2001 From: ricked-twice <39213807+ricked-twice@users.noreply.github.com> Date: Tue, 3 May 2022 21:16:03 +0200 Subject: [PATCH 10/12] Quick fix for #96223. --- .../src/traits/error_reporting/suggestions.rs | 8 ++- src/test/ui/suggestions/issue-96223.rs | 53 +++++++++++++++++++ src/test/ui/suggestions/issue-96223.stderr | 28 ++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/issue-96223.rs create mode 100644 src/test/ui/suggestions/issue-96223.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a3d3c7c0cf3aa..fcf188228dcc0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -866,7 +866,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; } - let orig_ty = old_pred.self_ty().skip_binder(); + // This is a quick fix to resolve an ICE ([issue#96223](https://github.com/rust-lang/rust/issues/96223)). + // This change should probably be deeper. + // As suggested by @jackh726, `mk_trait_obligation_with_new_self_ty` could take a `Binder<(TraitRef, Ty)> + // instead of `Binder` leading to some changes to its call places. + let Some(orig_ty) = old_pred.self_ty().no_bound_vars() else { + return false; + }; let mk_result = |new_ty| { let obligation = self.mk_trait_obligation_with_new_self_ty(param_env, old_pred, new_ty); diff --git a/src/test/ui/suggestions/issue-96223.rs b/src/test/ui/suggestions/issue-96223.rs new file mode 100644 index 0000000000000..501373d96abec --- /dev/null +++ b/src/test/ui/suggestions/issue-96223.rs @@ -0,0 +1,53 @@ +// Test case for #96223. +// An ICE was triggered because of a failed assertion. +// Thanks to @Manishearth for the minimal test case. + +pub trait Foo<'de>: Sized {} + +pub trait Bar<'a>: 'static { + type Inner: 'a; +} + +pub trait Fubar { + type Bar: for<'a> Bar<'a>; +} + +pub struct Baz(pub T); + +impl<'de, T> Foo<'de> for Baz where T: Foo<'de> {} + +struct Empty; + +impl Dummy for Empty +where + M: Fubar, + for<'de> Baz<>::Inner>: Foo<'de>, +{ +} + +pub trait Dummy +where + M: Fubar, +{ +} + +pub struct EmptyBis<'a>(&'a [u8]); + +impl<'a> Bar<'a> for EmptyBis<'static> { + type Inner = EmptyBis<'a>; +} + +pub struct EmptyMarker; + +impl Fubar for EmptyMarker { + type Bar = EmptyBis<'static>; +} + +fn icey_bounds>(p: &D) {} + +fn trigger_ice() { + let p = Empty; + icey_bounds(&p); //~ERROR +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-96223.stderr b/src/test/ui/suggestions/issue-96223.stderr new file mode 100644 index 0000000000000..2737ebe517bef --- /dev/null +++ b/src/test/ui/suggestions/issue-96223.stderr @@ -0,0 +1,28 @@ +error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied + --> $DIR/issue-96223.rs:50:17 + | +LL | icey_bounds(&p); + | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo<'de>` is implemented for `Baz` +note: required because of the requirements on the impl of `for<'de> Foo<'de>` for `Baz>` + --> $DIR/issue-96223.rs:17:14 + | +LL | impl<'de, T> Foo<'de> for Baz where T: Foo<'de> {} + | ^^^^^^^^ ^^^^^^ +note: required because of the requirements on the impl of `Dummy` for `Empty` + --> $DIR/issue-96223.rs:21:9 + | +LL | impl Dummy for Empty + | ^^^^^^^^ ^^^^^ +note: required by a bound in `icey_bounds` + --> $DIR/issue-96223.rs:46:19 + | +LL | fn icey_bounds>(p: &D) {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 574bee35fb2ea0a94e5045bc714ab3884500648e Mon Sep 17 00:00:00 2001 From: ricked-twice <39213807+ricked-twice@users.noreply.github.com> Date: Tue, 3 May 2022 22:23:30 +0200 Subject: [PATCH 11/12] Taking review hints into account. --- .../src/traits/error_reporting/suggestions.rs | 2 +- src/test/ui/suggestions/issue-96223.rs | 7 +++---- src/test/ui/suggestions/issue-96223.stderr | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index fcf188228dcc0..bfb8ce6f1051c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -866,7 +866,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; } - // This is a quick fix to resolve an ICE ([issue#96223](https://github.com/rust-lang/rust/issues/96223)). + // This is a quick fix to resolve an ICE (#96223). // This change should probably be deeper. // As suggested by @jackh726, `mk_trait_obligation_with_new_self_ty` could take a `Binder<(TraitRef, Ty)> // instead of `Binder` leading to some changes to its call places. diff --git a/src/test/ui/suggestions/issue-96223.rs b/src/test/ui/suggestions/issue-96223.rs index 501373d96abec..85667bb849bd4 100644 --- a/src/test/ui/suggestions/issue-96223.rs +++ b/src/test/ui/suggestions/issue-96223.rs @@ -1,6 +1,5 @@ -// Test case for #96223. -// An ICE was triggered because of a failed assertion. -// Thanks to @Manishearth for the minimal test case. +// Previously ICEd because we didn't properly track binders in suggestions +// check-fail pub trait Foo<'de>: Sized {} @@ -47,7 +46,7 @@ fn icey_bounds>(p: &D) {} fn trigger_ice() { let p = Empty; - icey_bounds(&p); //~ERROR + icey_bounds(&p); //~ERROR the trait bound } fn main() {} diff --git a/src/test/ui/suggestions/issue-96223.stderr b/src/test/ui/suggestions/issue-96223.stderr index 2737ebe517bef..513725d99628c 100644 --- a/src/test/ui/suggestions/issue-96223.stderr +++ b/src/test/ui/suggestions/issue-96223.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied - --> $DIR/issue-96223.rs:50:17 + --> $DIR/issue-96223.rs:49:17 | LL | icey_bounds(&p); | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` @@ -8,17 +8,17 @@ LL | icey_bounds(&p); | = help: the trait `Foo<'de>` is implemented for `Baz` note: required because of the requirements on the impl of `for<'de> Foo<'de>` for `Baz>` - --> $DIR/issue-96223.rs:17:14 + --> $DIR/issue-96223.rs:16:14 | LL | impl<'de, T> Foo<'de> for Baz where T: Foo<'de> {} | ^^^^^^^^ ^^^^^^ note: required because of the requirements on the impl of `Dummy` for `Empty` - --> $DIR/issue-96223.rs:21:9 + --> $DIR/issue-96223.rs:20:9 | LL | impl Dummy for Empty | ^^^^^^^^ ^^^^^ note: required by a bound in `icey_bounds` - --> $DIR/issue-96223.rs:46:19 + --> $DIR/issue-96223.rs:45:19 | LL | fn icey_bounds>(p: &D) {} | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds` From a63d414031dc0cb4af3e3e8066a7a04ab8436bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 May 2022 00:00:00 +0000 Subject: [PATCH 12/12] Update `ProjectionElem::Downcast` documentation `ProjectionElem:::Downcast` is used when downcasting to a variant of an enum or a generator, regardless of the number of variants. --- compiler/rustc_middle/src/mir/mod.rs | 4 +--- compiler/rustc_middle/src/mir/tcx.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 188ca8048055c..924bacb7aae21 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2017,9 +2017,7 @@ pub enum ProjectionElem { from_end: bool, }, - /// "Downcast" to a variant of an ADT. Currently, we only introduce - /// this for ADTs with more than one variant. It may be better to - /// just introduce it always, or always for enums. + /// "Downcast" to a variant of an enum or a generator. /// /// The included Symbol is the name of the variant, used for printing MIR. Downcast(Option, VariantIdx), diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 597ade4223684..f1d5201454d69 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -12,7 +12,7 @@ use rustc_target::abi::VariantIdx; #[derive(Copy, Clone, Debug, TypeFoldable)] pub struct PlaceTy<'tcx> { pub ty: Ty<'tcx>, - /// Downcast to a particular variant of an enum, if included. + /// Downcast to a particular variant of an enum or a generator, if included. pub variant_index: Option, }