From e9d49b2bfc4e4c327987bb9d2a65b113b10100de Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 10 Jun 2022 23:18:42 +0400 Subject: [PATCH 01/13] Fix suggestions for `&a: T` parameters Previously we were suggesting stuff like `fn f( &u32) {}` --- compiler/rustc_typeck/src/check/pat.rs | 55 ++-- src/test/ui/destructure-trait-ref.stderr | 12 +- .../mismatched_types/issue-38371-unfixable.rs | 5 + .../issue-38371-unfixable.stderr | 21 ++ .../ui/mismatched_types/issue-38371.fixed | 18 ++ src/test/ui/mismatched_types/issue-38371.rs | 29 +- .../ui/mismatched_types/issue-38371.stderr | 47 ++- .../ref-pat-suggestions.fixed | 24 ++ .../mismatched_types/ref-pat-suggestions.rs | 24 ++ .../ref-pat-suggestions.stderr | 297 ++++++++++++++++++ src/test/ui/pattern/for-loop-bad-item.stderr | 6 +- .../ui/suggestions/match-ergonomics.stderr | 26 +- 12 files changed, 476 insertions(+), 88 deletions(-) create mode 100644 src/test/ui/mismatched_types/issue-38371-unfixable.rs create mode 100644 src/test/ui/mismatched_types/issue-38371-unfixable.stderr create mode 100644 src/test/ui/mismatched_types/issue-38371.fixed create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.fixed create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.rs create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5eba95b495dd7..8727ae4ea51ae 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -649,39 +649,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn borrow_pat_suggestion( - &self, - err: &mut Diagnostic, - pat: &Pat<'_>, - inner: &Pat<'_>, - expected: Ty<'tcx>, - ) { + fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>, inner: &Pat<'_>) { let tcx = self.tcx; - if let PatKind::Binding(..) = inner.kind { + if let PatKind::Ref(_, mutbl) = pat.kind + && let PatKind::Binding(_, _, binding, ..) = inner.kind { let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); let binding_parent = tcx.hir().get(binding_parent_id); - debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); + debug!(?inner, ?pat, ?binding_parent); + + let mutability = match mutbl { + ast::Mutability::Mut => "mut", + ast::Mutability::Not => "", + }; + match binding_parent { - hir::Node::Param(hir::Param { span, .. }) - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) => - { - err.span_suggestion( - *span, - &format!("did you mean `{snippet}`"), - format!(" &{expected}"), - Applicability::MachineApplicable, + hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { + err.multipart_suggestion_verbose( + format!("to take parameter by ref, move `&{mutability}` to the type"), + vec![ + (pat.span.until(inner.span), "".to_owned()), + (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), + ], + Applicability::MachineApplicable ); } - hir::Node::Arm(_) | hir::Node::Pat(_) => { + hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => { // rely on match ergonomics or it might be nested `&&pat` - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { - err.span_suggestion( - pat.span, - "you can probably remove the explicit borrow", - snippet, - Applicability::MaybeIncorrect, - ); - } + err.span_suggestion_verbose( + pat.span.until(inner.span), + format!("consider removing `&{mutability}` from the pattern"), + "", + Applicability::MaybeIncorrect, + ); } _ => {} // don't provide suggestions in other cases #55175 } @@ -1853,7 +1852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Take region, inner-type from expected type if we can, // to avoid creating needless variables. This also helps with - // the bad interactions of the given hack detailed in (note_1). + // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match *expected.kind() { ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty), @@ -1869,7 +1868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, pat, inner, expected); + self.borrow_pat_suggestion(&mut err, pat, inner); err.emit(); } (rptr_ty, inner_ty) diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr index 302917ca02e00..1291517928e3d 100644 --- a/src/test/ui/destructure-trait-ref.stderr +++ b/src/test/ui/destructure-trait-ref.stderr @@ -23,10 +23,14 @@ LL | let &&x = &1isize as &dyn T; | ^^ ----------------- this expression has type `&dyn T` | | | expected trait object `dyn T`, found reference - | help: you can probably remove the explicit borrow: `x` | = note: expected trait object `dyn T` found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&x = &1isize as &dyn T; +LL + let &x = &1isize as &dyn T; + | error[E0308]: mismatched types --> $DIR/destructure-trait-ref.rs:36:11 @@ -35,10 +39,14 @@ LL | let &&&x = &(&1isize as &dyn T); | ^^ -------------------- this expression has type `&&dyn T` | | | expected trait object `dyn T`, found reference - | help: you can probably remove the explicit borrow: `x` | = note: expected trait object `dyn T` found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&&x = &(&1isize as &dyn T); +LL + let &&x = &(&1isize as &dyn T); + | error[E0308]: mismatched types --> $DIR/destructure-trait-ref.rs:40:13 diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.rs b/src/test/ui/mismatched_types/issue-38371-unfixable.rs new file mode 100644 index 0000000000000..c4316bfdd18dc --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371-unfixable.rs @@ -0,0 +1,5 @@ +fn ugh(&[bar]: &u32) {} //~ ERROR expected an array or slice + +fn bgh(&&bar: u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.stderr b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr new file mode 100644 index 0000000000000..3c5e765abfbe2 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr @@ -0,0 +1,21 @@ +error[E0529]: expected an array or slice, found `u32` + --> $DIR/issue-38371-unfixable.rs:1:9 + | +LL | fn ugh(&[bar]: &u32) {} + | ^^^^^ pattern cannot match with input type `u32` + +error[E0308]: mismatched types + --> $DIR/issue-38371-unfixable.rs:3:8 + | +LL | fn bgh(&&bar: u32) {} + | ^^^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-38371.fixed b/src/test/ui/mismatched_types/issue-38371.fixed new file mode 100644 index 0000000000000..0e20835bef05f --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371.fixed @@ -0,0 +1,18 @@ +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo {} + +fn foo(_a: &Foo) {} //~ ERROR mismatched types + +fn bar(_a: Foo) {} + +fn qux(_a: &Foo) {} + +fn zar(&_a: &Foo) {} + +fn agh(&_a: &u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs index d2cd2b88ab706..fb9e4c173e7a8 100644 --- a/src/test/ui/mismatched_types/issue-38371.rs +++ b/src/test/ui/mismatched_types/issue-38371.rs @@ -1,27 +1,18 @@ -struct Foo { -} +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] -fn foo(&foo: Foo) { //~ ERROR mismatched types -} +#[derive(Copy, Clone)] +struct Foo {} -fn bar(foo: Foo) { -} +fn foo(&_a: Foo) {} //~ ERROR mismatched types -fn qux(foo: &Foo) { -} +fn bar(_a: Foo) {} -fn zar(&foo: &Foo) { -} +fn qux(_a: &Foo) {} -// The somewhat unexpected help message in this case is courtesy of -// match_default_bindings. -fn agh(&&bar: &u32) { //~ ERROR mismatched types -} +fn zar(&_a: &Foo) {} -fn bgh(&&bar: u32) { //~ ERROR mismatched types -} - -fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice -} +fn agh(&&_a: &u32) {} //~ ERROR mismatched types fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 5d2ce9302ece6..5a0146dfd210b 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -1,46 +1,35 @@ error[E0308]: mismatched types - --> $DIR/issue-38371.rs:4:8 + --> $DIR/issue-38371.rs:8:8 | -LL | fn foo(&foo: Foo) { - | ^^^^----- - | | | - | | expected due to this +LL | fn foo(&_a: Foo) {} + | ^^^ --- expected due to this + | | | expected struct `Foo`, found reference - | help: did you mean `foo`: `&Foo` | = note: expected struct `Foo` found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - fn foo(&_a: Foo) {} +LL + fn foo(_a: &Foo) {} + | error[E0308]: mismatched types - --> $DIR/issue-38371.rs:18:9 + --> $DIR/issue-38371.rs:16:9 | -LL | fn agh(&&bar: &u32) { - | ^^^^ ---- expected due to this +LL | fn agh(&&_a: &u32) {} + | ^^^ ---- expected due to this | | | expected `u32`, found reference - | help: you can probably remove the explicit borrow: `bar` - | - = note: expected type `u32` - found reference `&_` - -error[E0308]: mismatched types - --> $DIR/issue-38371.rs:21:8 - | -LL | fn bgh(&&bar: u32) { - | ^^^^^ --- expected due to this - | | - | expected `u32`, found reference | = note: expected type `u32` found reference `&_` - -error[E0529]: expected an array or slice, found `u32` - --> $DIR/issue-38371.rs:24:9 +help: consider removing `&` from the pattern | -LL | fn ugh(&[bar]: &u32) { - | ^^^^^ pattern cannot match with input type `u32` +LL - fn agh(&&_a: &u32) {} +LL + fn agh(&_a: &u32) {} + | -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0529. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed new file mode 100644 index 0000000000000..e9472b5194384 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +fn _f0(_a: &u32) {} //~ ERROR mismatched types +fn _f1(_a: &mut u32) {} //~ ERROR mismatched types +fn _f2(&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut _a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&_a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + + let _ = |_a: &u32| (); //~ ERROR mismatched types + let _ = |_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types +} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs new file mode 100644 index 0000000000000..49d88d13e01b3 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs @@ -0,0 +1,24 @@ +// run-rustfix + +fn _f0(&_a: u32) {} //~ ERROR mismatched types +fn _f1(&mut _a: u32) {} //~ ERROR mismatched types +fn _f2(&&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut &_a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&&mut _a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut &mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types + + let _ = |&_a: u32| (); //~ ERROR mismatched types + let _ = |&mut _a: u32| (); //~ ERROR mismatched types + let _ = |&&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types +} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr new file mode 100644 index 0000000000000..6ce1f9602ddb3 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -0,0 +1,297 @@ +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:3:8 + | +LL | fn _f0(&_a: u32) {} + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - fn _f0(&_a: u32) {} +LL + fn _f0(_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:4:8 + | +LL | fn _f1(&mut _a: u32) {} + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: to take parameter by ref, move `&mut` to the type + | +LL - fn _f1(&mut _a: u32) {} +LL + fn _f1(_a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:5:9 + | +LL | fn _f2(&&_a: &u32) {} + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f2(&&_a: &u32) {} +LL + fn _f2(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:6:13 + | +LL | fn _f3(&mut &_a: &mut u32) {} + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f3(&mut &_a: &mut u32) {} +LL + fn _f3(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:7:9 + | +LL | fn _f4(&&mut _a: &u32) {} + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f4(&&mut _a: &u32) {} +LL + fn _f4(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:8:13 + | +LL | fn _f5(&mut &mut _a: &mut u32) {} + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f5(&mut &mut _a: &mut u32) {} +LL + fn _f5(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:11:23 + | +LL | let _: fn(u32) = |&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(u32) = |&_a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:12:23 + | +LL | let _: fn(u32) = |&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(u32) = |&mut _a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:13:25 + | +LL | let _: fn(&u32) = |&&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&u32) = |&&_a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:14:33 + | +LL | let _: fn(&mut u32) = |&mut &_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &_a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:15:25 + | +LL | let _: fn(&u32) = |&&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&u32) = |&&mut _a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:16:33 + | +LL | let _: fn(&mut u32) = |&mut &mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &mut _a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:18:14 + | +LL | let _ = |&_a: u32| (); + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - let _ = |&_a: u32| (); +LL + let _ = |_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:19:14 + | +LL | let _ = |&mut _a: u32| (); + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: to take parameter by ref, move `&mut` to the type + | +LL - let _ = |&mut _a: u32| (); +LL + let _ = |_a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:20:15 + | +LL | let _ = |&&_a: &u32| (); + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&&_a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:21:19 + | +LL | let _ = |&mut &_a: &mut u32| (); + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&mut &_a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:22:15 + | +LL | let _ = |&&mut _a: &u32| (); + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&&mut _a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:23:19 + | +LL | let _ = |&mut &mut _a: &mut u32| (); + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&mut &mut _a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr index 9410e4da8d2af..886d815d70bea 100644 --- a/src/test/ui/pattern/for-loop-bad-item.stderr +++ b/src/test/ui/pattern/for-loop-bad-item.stderr @@ -5,10 +5,14 @@ LL | for ((_, _), (&mut c, _)) in &mut map { | ^^^^^^ -------- this is an iterator with items of type `(&(char, char), &mut (char, char))` | | | expected `char`, found `&mut _` - | help: you can probably remove the explicit borrow: `c` | = note: expected type `char` found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - for ((_, _), (&mut c, _)) in &mut map { +LL + for ((_, _), (c, _)) in &mut map { + | error[E0308]: mismatched types --> $DIR/for-loop-bad-item.rs:14:14 diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr index 4eab2df30801e..a9342f9fc309d 100644 --- a/src/test/ui/suggestions/match-ergonomics.stderr +++ b/src/test/ui/suggestions/match-ergonomics.stderr @@ -4,13 +4,15 @@ error[E0308]: mismatched types LL | match &x[..] { | ------ this expression has type `&[i32]` LL | [&v] => {}, - | ^^ - | | - | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` + | ^^ expected `i32`, found reference | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - [&v] => {}, +LL + [v] => {}, + | error[E0529]: expected an array or slice, found `Vec` --> $DIR/match-ergonomics.rs:8:9 @@ -34,13 +36,15 @@ error[E0308]: mismatched types LL | match y { | - this expression has type `i32` LL | &v => {}, - | ^^ - | | - | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` + | ^^ expected `i32`, found reference | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - &v => {}, +LL + v => {}, + | error[E0308]: mismatched types --> $DIR/match-ergonomics.rs:40:13 @@ -49,10 +53,14 @@ LL | if let [&v] = &x[..] {} | ^^ ------ this expression has type `&[i32]` | | | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let [&v] = &x[..] {} +LL + if let [v] = &x[..] {} + | error: aborting due to 5 previous errors From 2411692ab69922f16f24657b8c2e4f49e7a2932a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:03:46 +0400 Subject: [PATCH 02/13] Make preconditions of `check_pat_ref` & `borrow_pat_suggestion` clearer --- compiler/rustc_typeck/src/check/pat.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 8727ae4ea51ae..836cdb4206a60 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -649,9 +649,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>, inner: &Pat<'_>) { + // Precondition: pat is a Ref(_) pattern + fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) { let tcx = self.tcx; - if let PatKind::Ref(_, mutbl) = pat.kind + if let PatKind::Ref(inner, mutbl) = pat.kind && let PatKind::Binding(_, _, binding, ..) = inner.kind { let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); let binding_parent = tcx.hir().get(binding_parent_id); @@ -1835,6 +1836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { box_ty } + // Precondition: Pat is Ref(inner) fn check_pat_ref( &self, pat: &'tcx Pat<'tcx>, @@ -1868,7 +1870,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, pat, inner); + self.borrow_pat_suggestion(&mut err, pat); err.emit(); } (rptr_ty, inner_ty) From 451e0301d88feb3836177217c8d103d197b2b774 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:31:47 +0400 Subject: [PATCH 03/13] Improve suggestion wording --- compiler/rustc_typeck/src/check/pat.rs | 2 +- src/test/ui/mismatched_types/issue-38371.stderr | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.stderr | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 836cdb4206a60..5ecdbdadefd09 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -666,7 +666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match binding_parent { hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { err.multipart_suggestion_verbose( - format!("to take parameter by ref, move `&{mutability}` to the type"), + format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 5a0146dfd210b..003f17cda1553 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -8,7 +8,7 @@ LL | fn foo(&_a: Foo) {} | = note: expected struct `Foo` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - fn foo(&_a: Foo) {} LL + fn foo(_a: &Foo) {} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr index 6ce1f9602ddb3..0516bad49abf3 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -8,7 +8,7 @@ LL | fn _f0(&_a: u32) {} | = note: expected type `u32` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - fn _f0(&_a: u32) {} LL + fn _f0(_a: &u32) {} @@ -24,7 +24,7 @@ LL | fn _f1(&mut _a: u32) {} | = note: expected type `u32` found mutable reference `&mut _` -help: to take parameter by ref, move `&mut` to the type +help: to take parameter `_a` by reference, move `&mut` to the type | LL - fn _f1(&mut _a: u32) {} LL + fn _f1(_a: &mut u32) {} @@ -206,7 +206,7 @@ LL | let _ = |&_a: u32| (); | = note: expected type `u32` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - let _ = |&_a: u32| (); LL + let _ = |_a: &u32| (); @@ -222,7 +222,7 @@ LL | let _ = |&mut _a: u32| (); | = note: expected type `u32` found mutable reference `&mut _` -help: to take parameter by ref, move `&mut` to the type +help: to take parameter `_a` by reference, move `&mut` to the type | LL - let _ = |&mut _a: u32| (); LL + let _ = |_a: &mut u32| (); From dc2977e630c233866459399f0ff773505372803d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:49:53 +0400 Subject: [PATCH 04/13] check for inferred params in a clearer way --- compiler/rustc_typeck/src/check/pat.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5ecdbdadefd09..2fadf9c893804 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -664,7 +664,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match binding_parent { - hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { + // Check that there is explicit type (ie this is not a closure param with inferred type) + // so we don't suggest moving something to the type that does not exist + hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => { err.multipart_suggestion_verbose( format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ From 33ccd76562fe549e147bfccd0f5666505401ae0d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:51:03 +0400 Subject: [PATCH 05/13] Remove trailing whitespace --- compiler/rustc_typeck/src/check/pat.rs | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.fixed | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 2fadf9c893804..59d8776ca23a5 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we don't suggest moving something to the type that does not exist hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => { err.multipart_suggestion_verbose( - format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), + format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed index e9472b5194384..ab8483eef49fa 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed @@ -13,7 +13,7 @@ fn main() { let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types - let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types let _ = |_a: &u32| (); //~ ERROR mismatched types let _ = |_a: &mut u32| (); //~ ERROR mismatched types diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs index 49d88d13e01b3..7e55539aa3d1b 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.rs +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs @@ -13,7 +13,7 @@ fn main() { let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types - let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types let _ = |&_a: u32| (); //~ ERROR mismatched types let _ = |&mut _a: u32| (); //~ ERROR mismatched types From a752f82f19c167e86708157704342bf94a47a6ec Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 15:03:00 +0200 Subject: [PATCH 06/13] Ignore impl items because they can be duplicated in case of generic impl --- src/librustdoc/json/mod.rs | 53 +++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index f338050bee0f9..0964b757e74f5 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -181,15 +181,44 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let name = item.name; let item_id = item.item_id; if let Some(mut new_item) = self.convert_item(item) { - if let types::ItemEnum::Trait(ref mut t) = new_item.inner { - t.implementations = self.get_trait_implementors(item_id.expect_def_id()) - } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner { - s.impls = self.get_impls(item_id.expect_def_id()) - } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner { - e.impls = self.get_impls(item_id.expect_def_id()) - } else if let types::ItemEnum::Union(ref mut u) = new_item.inner { - u.impls = self.get_impls(item_id.expect_def_id()) - } + let can_be_ignored = match new_item.inner { + types::ItemEnum::Trait(ref mut t) => { + t.implementations = self.get_trait_implementors(item_id.expect_def_id()); + false + } + types::ItemEnum::Struct(ref mut s) => { + s.impls = self.get_impls(item_id.expect_def_id()); + false + } + types::ItemEnum::Enum(ref mut e) => { + e.impls = self.get_impls(item_id.expect_def_id()); + false + } + types::ItemEnum::Union(ref mut u) => { + u.impls = self.get_impls(item_id.expect_def_id()); + false + } + + types::ItemEnum::Method(_) + | types::ItemEnum::AssocConst { .. } + | types::ItemEnum::AssocType { .. } => true, + types::ItemEnum::Module(_) + | types::ItemEnum::ExternCrate { .. } + | types::ItemEnum::Import(_) + | types::ItemEnum::StructField(_) + | types::ItemEnum::Variant(_) + | types::ItemEnum::Function(_) + | types::ItemEnum::TraitAlias(_) + | types::ItemEnum::Impl(_) + | types::ItemEnum::Typedef(_) + | types::ItemEnum::OpaqueTy(_) + | types::ItemEnum::Constant(_) + | types::ItemEnum::Static(_) + | types::ItemEnum::ForeignType + | types::ItemEnum::Macro(_) + | types::ItemEnum::ProcMacro(_) + | types::ItemEnum::PrimitiveType(_) => false, + }; let removed = self .index .borrow_mut() @@ -199,7 +228,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { // to make sure the items are unique. The main place this happens is when an item, is // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod` if let Some(old_item) = removed { - assert_eq!(old_item, new_item); + // In case of generic implementations (like `impl Trait for T {}`), all the + // inner items will be duplicated so we can ignore if they are slightly different. + if !can_be_ignored { + assert_eq!(old_item, new_item); + } } } From 99cd9cae10fd7c9db35f3047a7f376bdb2d13f66 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Jun 2022 15:05:21 +0200 Subject: [PATCH 07/13] Add regression test for #97986 --- src/test/rustdoc-json/generic_impl.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/rustdoc-json/generic_impl.rs diff --git a/src/test/rustdoc-json/generic_impl.rs b/src/test/rustdoc-json/generic_impl.rs new file mode 100644 index 0000000000000..ac68ba578b6fb --- /dev/null +++ b/src/test/rustdoc-json/generic_impl.rs @@ -0,0 +1,24 @@ +// Regression test for . + +// @has generic_impl.json +// @has - "$.index[*][?(@.name=='f')]" +// @has - "$.index[*][?(@.name=='AssocTy')]" +// @has - "$.index[*][?(@.name=='AssocConst')]" + +pub mod m { + pub struct S; +} + +pub trait F { + type AssocTy; + const AssocConst: usize; + fn f() -> m::S; +} + +impl F for T { + type AssocTy = u32; + const AssocConst: usize = 0; + fn f() -> m::S { + m::S + } +} From 8a8404bc2b62299f085cd22bc1e0863eca3065fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 13 Jun 2022 00:00:00 +0000 Subject: [PATCH 08/13] Inline `const_eval_select` To avoid circular link time dependency between core and compiler builtins when building with `-Zshare-generics`. --- library/core/src/intrinsics.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 7c10ed65c4c4c..43ba2dc287490 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2363,6 +2363,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select"] #[rustc_do_not_const_check] +#[inline] pub const unsafe fn const_eval_select( arg: ARG, _called_in_const: F, From df9fea24a58eba9476aaeccc350441634eaf5eae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Jun 2022 10:59:01 +0200 Subject: [PATCH 09/13] Fix expand/collapse on source viewer sidebar folders --- src/librustdoc/html/static/js/source-script.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 58c036e0b3ca3..14d8a942977d6 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -32,10 +32,10 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { fullPath += elem["name"] + "/"; name.onclick = () => { - if (hasClass(this, "expand")) { - removeClass(this, "expand"); + if (hasClass(name, "expand")) { + removeClass(name, "expand"); } else { - addClass(this, "expand"); + addClass(name, "expand"); } }; name.innerText = elem["name"]; From a70c14aecca90e29417ab3c9b9dcbf0631efae79 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 Jun 2022 11:21:28 +0200 Subject: [PATCH 10/13] Add GUI test for sidebar items expand/collapse --- src/test/rustdoc-gui/source-code-page.goml | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 509739c9f2951..188b2605f0f13 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -1,4 +1,4 @@ -// Checks that the interactions with the source code pages are workined as expected. +// Checks that the interactions with the source code pages are working as expected. goto: file://|DOC_PATH|/src/test_docs/lib.rs.html // Check that we can click on the line number. click: ".line-numbers > span:nth-child(4)" // This is the span for line 4. @@ -27,3 +27,26 @@ assert-position: ("//*[@id='1']", {"x": 104, "y": 103}) // We click on the left of the "1" span but still in the "line-number" `
`.
 click: (103, 103)
 assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
+
+// Checking the source code sidebar.
+
+// First we "open" it.
+click: "#sidebar-toggle"
+assert: ".sidebar.expanded"
+
+// We check that the first entry of the sidebar is collapsed (which, for whatever reason,
+// is number 2 and not 1...).
+assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"})
+assert-text: ("#source-sidebar .name:nth-child(2)", "implementors")
+// We also check its children are hidden too.
+assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"})
+// We now click on it.
+click: "#source-sidebar .name:nth-child(2)"
+assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name expand"})
+// Checking that its children are displayed as well.
+assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "block"})
+
+// And now we collapse it again.
+click: "#source-sidebar .name:nth-child(2)"
+assert-attribute: ("#source-sidebar .name:nth-child(2)", {"class": "name"})
+assert-css: ("#source-sidebar .name:nth-child(2) + .children", {"display": "none"})

From 5028d20589c3f7c5d7bd4704b9d3bc6ec42e1767 Mon Sep 17 00:00:00 2001
From: Yuki Okushi 
Date: Wed, 15 Jun 2022 21:31:47 +0900
Subject: [PATCH 11/13] Add regression test for #93775

Signed-off-by: Yuki Okushi 
---
 src/test/ui/associated-consts/issue-93775.rs | 29 ++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 src/test/ui/associated-consts/issue-93775.rs

diff --git a/src/test/ui/associated-consts/issue-93775.rs b/src/test/ui/associated-consts/issue-93775.rs
new file mode 100644
index 0000000000000..7a007b732de8e
--- /dev/null
+++ b/src/test/ui/associated-consts/issue-93775.rs
@@ -0,0 +1,29 @@
+// build-pass
+// ignore-tidy-linelength
+
+// Regression for #93775, needs build-pass to test it.
+
+#![recursion_limit = "1000"]
+
+use std::marker::PhantomData;
+
+struct Z;
+struct S(PhantomData);
+
+type Nested = S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
+
+trait AsNum {
+    const NUM: u32;
+}
+
+impl AsNum for Z {
+    const NUM: u32 = 0;
+}
+
+impl AsNum for S {
+    const NUM: u32 = T::NUM + 1;
+}
+
+fn main() {
+    let _ = Nested::NUM;
+}

From 9aa1ccdae85b9d5b1575f7a2e48cf31196462e0f Mon Sep 17 00:00:00 2001
From: Sprite 
Date: Wed, 15 Jun 2022 03:06:28 +0800
Subject: [PATCH 12/13] Fix `cfg(not)` and `cfg(all)` causing Rustdoc stab to
 disappear

---
 src/librustdoc/clean/cfg.rs       | 14 +++++++++-----
 src/librustdoc/clean/cfg/tests.rs |  2 +-
 src/test/rustdoc/doc-auto-cfg.rs  | 18 +++++++++++++++++-
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index deac1723b2620..f33f5d27d1a9f 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -87,15 +87,20 @@ impl Cfg {
                 }),
             },
             MetaItemKind::List(ref items) => {
+                let orig_len = items.len();
                 let sub_cfgs =
                     items.iter().filter_map(|i| Cfg::parse_nested(i, exclude).transpose());
                 let ret = match name {
                     sym::all => sub_cfgs.fold(Ok(Cfg::True), |x, y| Ok(x? & y?)),
                     sym::any => sub_cfgs.fold(Ok(Cfg::False), |x, y| Ok(x? | y?)),
                     sym::not => {
-                        let mut sub_cfgs = sub_cfgs.collect::>();
-                        if sub_cfgs.len() == 1 {
-                            Ok(!sub_cfgs.pop().unwrap()?)
+                        if orig_len == 1 {
+                            let mut sub_cfgs = sub_cfgs.collect::>();
+                            if sub_cfgs.len() == 1 {
+                                Ok(!sub_cfgs.pop().unwrap()?)
+                            } else {
+                                return Ok(None);
+                            }
                         } else {
                             Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span })
                         }
@@ -304,8 +309,7 @@ impl ops::BitAnd for Cfg {
 impl ops::BitOrAssign for Cfg {
     fn bitor_assign(&mut self, other: Cfg) {
         match (self, other) {
-            (&mut Cfg::True, _) | (_, Cfg::False) => {}
-            (s, Cfg::True) => *s = Cfg::True,
+            (Cfg::True, _) | (_, Cfg::False) | (_, Cfg::True) => {}
             (s @ &mut Cfg::False, b) => *s = b,
             (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => {
                 for c in b.drain(..) {
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index ece3fcb18b6f3..7f72d5d39a752 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -161,7 +161,7 @@ fn test_cfg_or() {
 
         x = word_cfg("test");
         x |= Cfg::True;
-        assert_eq!(x, Cfg::True);
+        assert_eq!(x, word_cfg("test"));
 
         x = word_cfg("test2");
         x |= Cfg::False;
diff --git a/src/test/rustdoc/doc-auto-cfg.rs b/src/test/rustdoc/doc-auto-cfg.rs
index 57dd0529535f6..d73718762a7ae 100644
--- a/src/test/rustdoc/doc-auto-cfg.rs
+++ b/src/test/rustdoc/doc-auto-cfg.rs
@@ -1,5 +1,4 @@
 #![feature(doc_auto_cfg)]
-
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
@@ -12,3 +11,20 @@ pub fn foo() {}
 // @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
 #[cfg(any(test, doc))]
 pub fn bar() {}
+
+// @has foo/fn.appear_1.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
+#[cfg(any(doc, not(test)))]
+pub fn appear_1() {} // issue #98065
+
+// @has foo/fn.appear_2.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
+#[cfg(any(doc, all(test)))]
+pub fn appear_2() {} // issue #98065
+
+// @has foo/fn.appear_3.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+#[cfg(any(doc, all()))]
+pub fn appear_3() {} // issue #98065

From 713578b82791523afa62803f02a9fc7eef2c3368 Mon Sep 17 00:00:00 2001
From: Sprite 
Date: Wed, 15 Jun 2022 03:34:00 +0800
Subject: [PATCH 13/13] Exclude cfg "doc" and "doctest" from feature
 `doc_auto_cfg`

---
 src/librustdoc/visit_ast.rs      |  5 ++++-
 src/test/rustdoc/doc-auto-cfg.rs | 25 +++++++++++++++----------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 00553d3f007ff..ac934f6925d0b 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -141,7 +141,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     })
                     .collect::>()
             })
-            .chain([Cfg::Cfg(sym::test, None)].into_iter())
+            .chain(
+                [Cfg::Cfg(sym::test, None), Cfg::Cfg(sym::doc, None), Cfg::Cfg(sym::doctest, None)]
+                    .into_iter(),
+            )
             .collect();
 
         self.cx.cache.exact_paths = self.exact_paths;
diff --git a/src/test/rustdoc/doc-auto-cfg.rs b/src/test/rustdoc/doc-auto-cfg.rs
index d73718762a7ae..7842ee69c9f67 100644
--- a/src/test/rustdoc/doc-auto-cfg.rs
+++ b/src/test/rustdoc/doc-auto-cfg.rs
@@ -2,29 +2,34 @@
 #![crate_name = "foo"]
 
 // @has foo/fn.foo.html
-// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-doctest'
-#[cfg(not(doctest))]
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-meowmeow'
+#[cfg(not(meowmeow))]
 pub fn foo() {}
 
 // @has foo/fn.bar.html
-// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
 // @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
-#[cfg(any(test, doc))]
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doctest'
+#[cfg(any(meowmeow, test, doc, doctest))]
 pub fn bar() {}
 
 // @has foo/fn.appear_1.html
-// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
 // @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
-#[cfg(any(doc, not(test)))]
+#[cfg(any(meowmeow, doc, not(test)))]
 pub fn appear_1() {} // issue #98065
 
 // @has foo/fn.appear_2.html
-// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
 // @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'test'
-#[cfg(any(doc, all(test)))]
+#[cfg(any(meowmeow, doc, all(test)))]
 pub fn appear_2() {} // issue #98065
 
 // @has foo/fn.appear_3.html
-// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
-#[cfg(any(doc, all()))]
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'meowmeow'
+// @!has - '//*[@class="item-info"]/*[@class="stab portability"]' 'doc'
+#[cfg(any(meowmeow, doc, all()))]
 pub fn appear_3() {} // issue #98065