From 5216ea6493bc716c15b298acc65d182bfff2a159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 03:26:09 +0100 Subject: [PATCH 01/22] ExprUseVisitor: properly report discriminant reads This solves the "can't find the upvar" ICEs that resulted from `maybe_read_scrutinee` being unfit for purpose. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 102 +++++++++-- tests/crashes/137467-1.rs | 17 -- tests/crashes/137467-2.rs | 18 -- tests/crashes/137467-3.rs | 8 - .../2229_closure_analysis/capture-enums.rs | 2 + .../capture-enums.stderr | 26 ++- .../match/patterns-capture-analysis.rs | 5 + .../match/patterns-capture-analysis.stderr | 79 +++++--- .../only-inhabited-variant-stable.rs | 23 +++ .../only-inhabited-variant-stable.stderr | 20 +++ ...habited-variant.exhaustive_patterns.stderr | 20 +++ .../only-inhabited-variant.normal.stderr | 20 +++ ...tivariant.rs => only-inhabited-variant.rs} | 8 +- tests/ui/closures/or-patterns-issue-137467.rs | 170 ++++++++++++++++++ 14 files changed, 426 insertions(+), 92 deletions(-) delete mode 100644 tests/crashes/137467-1.rs delete mode 100644 tests/crashes/137467-2.rs delete mode 100644 tests/crashes/137467-3.rs create mode 100644 tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs create mode 100644 tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr rename tests/ui/closures/2229_closure_analysis/{run_pass/multivariant.rs => only-inhabited-variant.rs} (55%) create mode 100644 tests/ui/closures/or-patterns-issue-137467.rs diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 561230c193ce2..2df58a2164d62 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -943,6 +943,19 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// The core driver for walking a pattern + /// + /// This should mirror how pattern-matching gets lowered to MIR, as + /// otherwise lowering will ICE when trying to resolve the upvars. + /// + /// However, it is okay to approximate it here by doing *more* accesses than + /// the actual MIR builder will, which is useful when some checks are too + /// cumbersome to perform here. For example, if after typeck it becomes + /// clear that only one variant of an enum is inhabited, and therefore a + /// read of the discriminant is not necessary, `walk_pat` will have + /// over-approximated the necessary upvar capture granularity. + /// + /// Do note that discrepancies like these do still create obscure corners + /// in the semantics of the language, and should be avoided if possible. #[instrument(skip(self), level = "debug")] fn walk_pat( &self, @@ -952,6 +965,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx ) -> Result<(), Cx::Error> { let tcx = self.cx.tcx(); self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { + debug!("walk_pat: pat.kind={:?}", pat.kind); + let read_discriminant = || { + self.delegate.borrow_mut().borrow(place, discr_place.hir_id, BorrowKind::Immutable); + }; + match pat.kind { PatKind::Binding(_, canonical_id, ..) => { debug!("walk_pat: binding place={:?} pat={:?}", place, pat); @@ -974,11 +992,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // binding when lowering pattern guards to ensure that the guard does not // modify the scrutinee. if has_guard { - self.delegate.borrow_mut().borrow( - place, - discr_place.hir_id, - BorrowKind::Immutable, - ); + read_discriminant(); } // It is also a borrow or copy/move of the value being matched. @@ -1014,13 +1028,71 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx PatKind::Never => { // A `!` pattern always counts as an immutable read of the discriminant, // even in an irrefutable pattern. - self.delegate.borrow_mut().borrow( - place, - discr_place.hir_id, - BorrowKind::Immutable, - ); + read_discriminant(); + } + PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { + // A `Path` pattern is just a name like `Foo`. This is either a + // named constant or else it refers to an ADT variant + + let res = self.cx.typeck_results().qpath_res(qpath, *hir_id); + match res { + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { + // Named constants have to be equated with the value + // being matched, so that's a read of the value being matched. + // + // FIXME: Does the MIR code skip this read when matching on a ZST? + // If so, we can also skip it here. + read_discriminant(); + } + _ => { + // Otherwise, this is a struct/enum variant, and so it's + // only a read if we need to read the discriminant. + if self.is_multivariant_adt(place.place.ty(), *span) { + read_discriminant(); + } + } + } + } + PatKind::Expr(_) | PatKind::Range(..) => { + // When matching against a literal or range, we need to + // borrow the place to compare it against the pattern. + // + // FIXME: What if the type being matched only has one + // possible value? + // FIXME: What if the range is the full range of the type + // and doesn't actually require a discriminant read? + read_discriminant(); + } + PatKind::Struct(..) | PatKind::TupleStruct(..) => { + if self.is_multivariant_adt(place.place.ty(), pat.span) { + read_discriminant(); + } + } + PatKind::Slice(lhs, wild, rhs) => { + // We don't need to test the length if the pattern is `[..]` + if matches!((lhs, wild, rhs), (&[], Some(_), &[])) + // Arrays have a statically known size, so + // there is no need to read their length + || place.place.ty().peel_refs().is_array() + { + // No read necessary + } else { + read_discriminant(); + } + } + PatKind::Or(_) + | PatKind::Box(_) + | PatKind::Ref(..) + | PatKind::Guard(..) + | PatKind::Tuple(..) + | PatKind::Wild + | PatKind::Missing + | PatKind::Err(_) => { + // If the PatKind is Or, Box, Ref, Guard, or Tuple, the relevant accesses + // are made later as these patterns contains subpatterns. + // If the PatKind is Missing, Wild or Err, any relevant accesses are made when processing + // the other patterns that are part of the match } - _ => {} } Ok(()) @@ -1908,6 +1980,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } + /// Checks whether a type has multiple variants, and therefore, whether a + /// read of the discriminant might be necessary. Note that the actual MIR + /// builder code does a more specific check, filtering out variants that + /// happen to be uninhabited. + /// + /// Here, we cannot perform such an accurate checks, because querying + /// whether a type is inhabited requires that it has been fully inferred, + /// which cannot be guaranteed at this point. fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need diff --git a/tests/crashes/137467-1.rs b/tests/crashes/137467-1.rs deleted file mode 100644 index b6bff2bdc4e86..0000000000000 --- a/tests/crashes/137467-1.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 -enum Camera { - Normal { base_transform: i32 }, - Volume { transform: i32 }, -} - -fn draw_ui(camera: &mut Camera) { - || { - let (Camera::Normal { - base_transform: _transform, - } - | Camera::Volume { - transform: _transform, - }) = camera; - }; -} diff --git a/tests/crashes/137467-2.rs b/tests/crashes/137467-2.rs deleted file mode 100644 index a70ea92b22dc2..0000000000000 --- a/tests/crashes/137467-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 - -enum Camera { - Normal { base_transform: i32 }, - Volume { transform: i32 }, -} - -fn draw_ui(camera: &mut Camera) { - || { - let (Camera::Normal { - base_transform: _, - } - | Camera::Volume { - transform: _, - }) = camera; - }; -} diff --git a/tests/crashes/137467-3.rs b/tests/crashes/137467-3.rs deleted file mode 100644 index cb81a9a912e7c..0000000000000 --- a/tests/crashes/137467-3.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #137467 -//@ edition: 2021 - -fn meow(x: (u32, u32, u32)) { - let f = || { - let ((0, a, _) | (_, _, a)) = x; - }; -} diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs index d9c06a68c95b9..4c600ccdaa438 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs @@ -22,6 +22,7 @@ fn multi_variant_enum() { //~| ERROR Min Capture analysis includes: if let Info::Point(_, _, str) = point { //~^ NOTE: Capturing point[] -> Immutable + //~| NOTE: Capturing point[] -> Immutable //~| NOTE: Capturing point[(2, 0)] -> ByValue //~| NOTE: Min Capture point[] -> ByValue println!("{}", str); @@ -29,6 +30,7 @@ fn multi_variant_enum() { if let Info::Meta(_, v) = meta { //~^ NOTE: Capturing meta[] -> Immutable + //~| NOTE: Capturing meta[] -> Immutable //~| NOTE: Capturing meta[(1, 1)] -> ByValue //~| NOTE: Min Capture meta[] -> ByValue println!("{:?}", v); diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr index 89a879cec468b..b62384ffe12e0 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -9,7 +9,7 @@ LL | let c = #[rustc_capture_analysis] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: attributes on expressions are experimental - --> $DIR/capture-enums.rs:48:13 + --> $DIR/capture-enums.rs:50:13 | LL | let c = #[rustc_capture_analysis] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,18 +34,28 @@ note: Capturing point[] -> Immutable | LL | if let Info::Point(_, _, str) = point { | ^^^^^ +note: Capturing point[] -> Immutable + --> $DIR/capture-enums.rs:23:41 + | +LL | if let Info::Point(_, _, str) = point { + | ^^^^^ note: Capturing point[(2, 0)] -> ByValue --> $DIR/capture-enums.rs:23:41 | LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Capturing meta[] -> Immutable - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 + | +LL | if let Info::Meta(_, v) = meta { + | ^^^^ +note: Capturing meta[] -> Immutable + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ note: Capturing meta[(1, 1)] -> ByValue - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ @@ -67,13 +77,13 @@ note: Min Capture point[] -> ByValue LL | if let Info::Point(_, _, str) = point { | ^^^^^ note: Min Capture meta[] -> ByValue - --> $DIR/capture-enums.rs:30:35 + --> $DIR/capture-enums.rs:31:35 | LL | if let Info::Meta(_, v) = meta { | ^^^^ error: First Pass analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:54:5 | LL | / || { LL | | @@ -85,13 +95,13 @@ LL | | }; | |_____^ | note: Capturing point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:57:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-enums.rs:52:5 + --> $DIR/capture-enums.rs:54:5 | LL | / || { LL | | @@ -103,7 +113,7 @@ LL | | }; | |_____^ | note: Min Capture point[(2, 0)] -> ByValue - --> $DIR/capture-enums.rs:55:47 + --> $DIR/capture-enums.rs:57:47 | LL | let SingleVariant::Point(_, _, str) = point; | ^^^^^ diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index 40330af4088c2..a9d2777d93f13 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -14,6 +14,7 @@ fn test_1_should_capture() { //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable + //~| NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable Some(_) => {} _ => {} @@ -132,6 +133,7 @@ fn test_5_should_capture_multi_variant() { //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable + //~| NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable MVariant::A => {} _ => {} @@ -150,6 +152,7 @@ fn test_7_should_capture_slice_len() { //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Capturing slice[Deref] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable [_,_,_] => {}, _ => {} @@ -162,6 +165,7 @@ fn test_7_should_capture_slice_len() { //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Capturing slice[Deref] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable [] => {}, _ => {} @@ -174,6 +178,7 @@ fn test_7_should_capture_slice_len() { //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable + //~| NOTE: Capturing slice[Deref] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable [_, .. ,_] => {}, _ => {} diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index e7e5e7f7fa1bf..4b9d6fad0e504 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -14,6 +14,11 @@ note: Capturing variant[] -> Immutable | LL | match variant { | ^^^^^^^ +note: Capturing variant[] -> Immutable + --> $DIR/patterns-capture-analysis.rs:15:15 + | +LL | match variant { + | ^^^^^^^ error: Min Capture analysis includes: --> $DIR/patterns-capture-analysis.rs:12:5 @@ -33,7 +38,7 @@ LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:30:5 + --> $DIR/patterns-capture-analysis.rs:31:5 | LL | / || { LL | | @@ -44,7 +49,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:49:5 + --> $DIR/patterns-capture-analysis.rs:50:5 | LL | / || { LL | | @@ -55,7 +60,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:63:5 + --> $DIR/patterns-capture-analysis.rs:64:5 | LL | / || { LL | | @@ -66,18 +71,18 @@ LL | | }; | |_____^ | note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:66:15 + --> $DIR/patterns-capture-analysis.rs:67:15 | LL | match variant { | ^^^^^^^ note: Capturing variant[(0, 0)] -> Immutable - --> $DIR/patterns-capture-analysis.rs:66:15 + --> $DIR/patterns-capture-analysis.rs:67:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:63:5 + --> $DIR/patterns-capture-analysis.rs:64:5 | LL | / || { LL | | @@ -88,13 +93,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:66:15 + --> $DIR/patterns-capture-analysis.rs:67:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:83:5 + --> $DIR/patterns-capture-analysis.rs:84:5 | LL | / || { LL | | @@ -105,7 +110,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:95:5 + --> $DIR/patterns-capture-analysis.rs:96:5 | LL | / || { LL | | @@ -116,7 +121,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:108:5 + --> $DIR/patterns-capture-analysis.rs:109:5 | LL | / || { LL | | @@ -127,7 +132,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:130:5 + --> $DIR/patterns-capture-analysis.rs:131:5 | LL | / || { LL | | @@ -138,13 +143,18 @@ LL | | }; | |_____^ | note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:133:15 + --> $DIR/patterns-capture-analysis.rs:134:15 + | +LL | match variant { + | ^^^^^^^ +note: Capturing variant[] -> Immutable + --> $DIR/patterns-capture-analysis.rs:134:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:130:5 + --> $DIR/patterns-capture-analysis.rs:131:5 | LL | / || { LL | | @@ -155,13 +165,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:133:15 + --> $DIR/patterns-capture-analysis.rs:134:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:148:5 + --> $DIR/patterns-capture-analysis.rs:150:5 | LL | / || { LL | | @@ -172,13 +182,18 @@ LL | | }; | |_____^ | note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:151:15 + --> $DIR/patterns-capture-analysis.rs:153:15 + | +LL | match slice { + | ^^^^^ +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:153:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:148:5 + --> $DIR/patterns-capture-analysis.rs:150:5 | LL | / || { LL | | @@ -189,13 +204,13 @@ LL | | }; | |_____^ | note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:151:15 + --> $DIR/patterns-capture-analysis.rs:153:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:160:5 + --> $DIR/patterns-capture-analysis.rs:163:5 | LL | / || { LL | | @@ -206,13 +221,18 @@ LL | | }; | |_____^ | note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:163:15 + --> $DIR/patterns-capture-analysis.rs:166:15 + | +LL | match slice { + | ^^^^^ +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:166:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:160:5 + --> $DIR/patterns-capture-analysis.rs:163:5 | LL | / || { LL | | @@ -223,13 +243,13 @@ LL | | }; | |_____^ | note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:163:15 + --> $DIR/patterns-capture-analysis.rs:166:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:172:5 + --> $DIR/patterns-capture-analysis.rs:176:5 | LL | / || { LL | | @@ -240,13 +260,18 @@ LL | | }; | |_____^ | note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:175:15 + --> $DIR/patterns-capture-analysis.rs:179:15 + | +LL | match slice { + | ^^^^^ +note: Capturing slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:179:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:172:5 + --> $DIR/patterns-capture-analysis.rs:176:5 | LL | / || { LL | | @@ -257,13 +282,13 @@ LL | | }; | |_____^ | note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:175:15 + --> $DIR/patterns-capture-analysis.rs:179:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:189:5 + --> $DIR/patterns-capture-analysis.rs:194:5 | LL | / || { LL | | diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs new file mode 100644 index 0000000000000..a8e4b9cd18235 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs @@ -0,0 +1,23 @@ +// This example used to compile, but the fact that it should was never properly +// discussed. With further experience, we concluded that capture precision +// depending on whether some types are inhabited goes too far, introducing a +// bunch of headaches without much benefit. +//@ edition:2021 +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Void {} + +pub fn main() { + let mut r = Result::::Err((0, 0)); + let mut f = || { + let Err((ref mut a, _)) = r; + *a = 1; + }; + let mut g = || { + //~^ ERROR: cannot borrow `r` as mutable more than once at a time + let Err((_, ref mut b)) = r; + *b = 2; + }; + f(); + g(); + assert_eq!(r, Err((1, 2))); +} diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr new file mode 100644 index 0000000000000..dea85ff947ced --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant-stable.rs:15:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr new file mode 100644 index 0000000000000..58a5348aa391a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.exhaustive_patterns.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant.rs:16:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr new file mode 100644 index 0000000000000..58a5348aa391a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.normal.stderr @@ -0,0 +1,20 @@ +error[E0499]: cannot borrow `r` as mutable more than once at a time + --> $DIR/only-inhabited-variant.rs:16:17 + | +LL | let mut f = || { + | -- first mutable borrow occurs here +LL | let Err((ref mut a, _)) = r; + | - first borrow occurs due to use of `r` in closure +... +LL | let mut g = || { + | ^^ second mutable borrow occurs here +LL | +LL | let Err((_, ref mut b)) = r; + | - second borrow occurs due to use of `r` in closure +... +LL | f(); + | - first borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs similarity index 55% rename from tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs rename to tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs index 74f37b514e4a4..4638387347269 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant.rs @@ -1,8 +1,9 @@ -// Test precise capture of a multi-variant enum (when remaining variants are -// visibly uninhabited). +// This example used to compile, but the fact that it should was never properly +// discussed. With further experience, we concluded that capture precision +// depending on whether some types are inhabited goes too far, introducing a +// bunch of headaches without much benefit. //@ revisions: normal exhaustive_patterns //@ edition:2021 -//@ run-pass #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![feature(never_type)] @@ -13,6 +14,7 @@ pub fn main() { *a = 1; }; let mut g = || { + //~^ ERROR: cannot borrow `r` as mutable more than once at a time let Err((_, ref mut b)) = r; *b = 2; }; diff --git a/tests/ui/closures/or-patterns-issue-137467.rs b/tests/ui/closures/or-patterns-issue-137467.rs new file mode 100644 index 0000000000000..38144aa1e8162 --- /dev/null +++ b/tests/ui/closures/or-patterns-issue-137467.rs @@ -0,0 +1,170 @@ +//@ edition:2024 +//@ check-pass + +const X: u32 = 0; + +fn match_literal(x: (u32, u32, u32)) { + let _ = || { + let ((0, a, _) | (_, _, a)) = x; + a + }; +} + +fn match_range(x: (u32, u32, u32)) { + let _ = || { + let ((0..5, a, _) | (_, _, a)) = x; + a + }; +} + +fn match_const(x: (u32, u32, u32)) { + let _ = || { + let ((X, a, _) | (_, _, a)) = x; + a + }; +} + +enum Choice { A, B } + +fn match_unit_variant(x: (Choice, u32, u32)) { + let _ = || { + let ((Choice::A, a, _) | (Choice::B, _, a)) = x; + a + }; +} + +struct Unit; + +fn match_unit_struct(mut x: (Unit, u32)) { + let r = &mut x.0; + let _ = || { + let (Unit, a) = x; + a + }; + + let _ = *r; +} + +enum Also { Unit } + +fn match_unit_enum(mut x: (Also, u32)) { + let r = &mut x.0; + let _ = || { + let (Also::Unit, a) = x; + a + }; + + let _ = *r; +} + +enum TEnum { + A(u32), + B(u32), +} + +enum SEnum { + A { a: u32 }, + B { a: u32 }, +} + +fn match_tuple_enum(x: TEnum) { + let _ = || { + let (TEnum::A(a) | TEnum::B(a)) = x; + a + }; +} + +fn match_struct_enum(x: SEnum) { + let _ = || { + let (SEnum::A { a } | SEnum::B { a }) = x; + a + }; +} + +enum TSingle { + A(u32, u32), +} + +enum SSingle { + A { a: u32, b: u32 }, +} + +struct TStruct(u32, u32); +struct SStruct { a: u32, b: u32 } + +fn match_struct(mut x: SStruct) { + let r = &mut x.a; + let _ = || { + let SStruct { b, .. } = x; + b + }; + + let _ = *r; +} + +fn match_tuple_struct(mut x: TStruct) { + let r = &mut x.0; + let _ = || { + let TStruct(_, a) = x; + a + }; + + let _ = *r; +} + +fn match_singleton(mut x: SSingle) { + let SSingle::A { a: ref mut r, .. } = x; + let _ = || { + let SSingle::A { b, .. } = x; + b + }; + + let _ = *r; +} + +fn match_tuple_singleton(mut x: TSingle) { + let TSingle::A(ref mut r, _) = x; + let _ = || { + let TSingle::A(_, a) = x; + a + }; + + let _ = *r; +} + +fn match_slice(x: (&[u32], u32, u32)) { + let _ = || { + let (([], a, _) | ([_, ..], _, a)) = x; + a + }; +} + +// Original testcase, for completeness +enum Camera { + Normal { base_transform: i32 }, + Volume { transform: i32 }, +} + +fn draw_ui(camera: &mut Camera) { + || { + let (Camera::Normal { + base_transform: _transform, + } + | Camera::Volume { + transform: _transform, + }) = camera; + }; +} + +fn draw_ui2(camera: &mut Camera) { + || { + let (Camera::Normal { + base_transform: _, + } + | Camera::Volume { + transform: _, + }) = camera; + }; +} + +fn main() {} From e0c6949eef73d5765c2925610689b791bb52dd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 20:59:50 +0100 Subject: [PATCH 02/22] ExprUseVisitor: remove maybe_read_scrutinee The split between walk_pat and maybe_read_scrutinee has now become redundant. Due to this change, one testcase within the testsuite has become similar enough to a known ICE to also break. I am leaving this as future work, as it requires feature(type_alias_impl_trait) --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 167 +++--------------- tests/crashes/{119786.rs => 119786-1.rs} | 0 tests/crashes/119786-2.rs | 15 ++ tests/crashes/119786-3.rs | 15 ++ ...oo-{closure#0}-{closure#0}.built.after.mir | 29 ++- ...-{closure#0}-{synthetic#0}.built.after.mir | 24 ++- .../match/match-edge-cases_2.stderr | 2 +- .../match/patterns-capture-analysis.rs | 22 +-- .../match/patterns-capture-analysis.stderr | 90 ++++------ .../at-pattern-weirdness-issue-137553.rs | 41 +++++ .../issue-96572-unconstrained.rs | 9 - 11 files changed, 152 insertions(+), 262 deletions(-) rename tests/crashes/{119786.rs => 119786-1.rs} (100%) create mode 100644 tests/crashes/119786-2.rs create mode 100644 tests/crashes/119786-3.rs create mode 100644 tests/ui/closures/at-pattern-weirdness-issue-137553.rs diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 2df58a2164d62..9dc7901236b56 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -7,9 +7,7 @@ use std::cell::{Ref, RefCell}; use std::ops::Deref; -use std::slice::from_ref; -use hir::Expr; use hir::def::DefKind; use hir::pat_util::EnumerateAndAdjustIterator as _; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; @@ -313,7 +311,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let param_place = self.cat_rvalue(param.hir_id, param_ty); - self.walk_irrefutable_pat(¶m_place, param.pat)?; + self.fake_read_scrutinee(¶m_place, false)?; + self.walk_pat(¶m_place, param.pat, false)?; } self.consume_expr(body.value)?; @@ -455,13 +454,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx hir::ExprKind::Match(discr, arms, _) => { let discr_place = self.cat_expr(discr)?; - self.maybe_read_scrutinee( - discr, - discr_place.clone(), - arms.iter().map(|arm| arm.pat), - )?; + self.fake_read_scrutinee(&discr_place, true)?; + self.walk_expr(discr)?; - // treatment of the discriminant is handled while walking the arms. for arm in arms { self.walk_arm(&discr_place, arm)?; } @@ -598,116 +593,25 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } - fn maybe_read_scrutinee<'t>( + #[instrument(skip(self), level = "debug")] + fn fake_read_scrutinee( &self, - discr: &Expr<'_>, - discr_place: PlaceWithHirId<'tcx>, - pats: impl Iterator>, + discr_place: &PlaceWithHirId<'tcx>, + refutable: bool, ) -> Result<(), Cx::Error> { - // Matching should not always be considered a use of the place, hence - // discr does not necessarily need to be borrowed. - // We only want to borrow discr if the pattern contain something other - // than wildcards. - let mut needs_to_be_read = false; - for pat in pats { - self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { - match &pat.kind { - PatKind::Missing => unreachable!(), - PatKind::Binding(.., opt_sub_pat) => { - // If the opt_sub_pat is None, then the binding does not count as - // a wildcard for the purpose of borrowing discr. - if opt_sub_pat.is_none() { - needs_to_be_read = true; - } - } - PatKind::Never => { - // A never pattern reads the value. - // FIXME(never_patterns): does this do what I expect? - needs_to_be_read = true; - } - PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - // A `Path` pattern is just a name like `Foo`. This is either a - // named constant or else it refers to an ADT variant - - let res = self.cx.typeck_results().qpath_res(qpath, *hir_id); - match res { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { - // Named constants have to be equated with the value - // being matched, so that's a read of the value being matched. - // - // FIXME: We don't actually reads for ZSTs. - needs_to_be_read = true; - } - _ => { - // Otherwise, this is a struct/enum variant, and so it's - // only a read if we need to read the discriminant. - needs_to_be_read |= - self.is_multivariant_adt(place.place.ty(), *span); - } - } - } - PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::Tuple(..) => { - // For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching - // against a multivariant enum or struct. In that case, we have to read - // the discriminant. Otherwise this kind of pattern doesn't actually - // read anything (we'll get invoked for the `...`, which may indeed - // perform some reads). - - let place_ty = place.place.ty(); - needs_to_be_read |= self.is_multivariant_adt(place_ty, pat.span); - } - PatKind::Expr(_) | PatKind::Range(..) => { - // If the PatKind is a Lit or a Range then we want - // to borrow discr. - needs_to_be_read = true; - } - PatKind::Slice(lhs, wild, rhs) => { - // We don't need to test the length if the pattern is `[..]` - if matches!((lhs, wild, rhs), (&[], Some(_), &[])) - // Arrays have a statically known size, so - // there is no need to read their length - || place.place.ty().peel_refs().is_array() - { - } else { - needs_to_be_read = true; - } - } - PatKind::Or(_) - | PatKind::Box(_) - | PatKind::Deref(_) - | PatKind::Ref(..) - | PatKind::Guard(..) - | PatKind::Wild - | PatKind::Err(_) => { - // If the PatKind is Or, Box, or Ref, the decision is made later - // as these patterns contains subpatterns - // If the PatKind is Wild or Err, the decision is made based on the other patterns - // being examined - } - } - - Ok(()) - })? - } + let closure_def_id = match discr_place.place.base { + PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), + _ => None, + }; - if needs_to_be_read { - self.borrow_expr(discr, BorrowKind::Immutable)?; + let cause = if refutable { + FakeReadCause::ForMatchedPlace(closure_def_id) } else { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; + FakeReadCause::ForLet(closure_def_id) + }; - self.delegate.borrow_mut().fake_read( - &discr_place, - FakeReadCause::ForMatchedPlace(closure_def_id), - discr_place.hir_id, - ); + self.delegate.borrow_mut().fake_read(discr_place, cause, discr_place.hir_id); - // We always want to walk the discriminant. We want to make sure, for instance, - // that the discriminant has been initialized. - self.walk_expr(discr)?; - } Ok(()) } @@ -724,12 +628,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.walk_expr(expr)?; let expr_place = self.cat_expr(expr)?; f()?; + self.fake_read_scrutinee(&expr_place, els.is_some())?; + self.walk_pat(&expr_place, pat, false)?; if let Some(els) = els { - // borrowing because we need to test the discriminant - self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter())?; self.walk_block(els)?; } - self.walk_irrefutable_pat(&expr_place, pat)?; Ok(()) } @@ -901,16 +804,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>, ) -> Result<(), Cx::Error> { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; - - self.delegate.borrow_mut().fake_read( - discr_place, - FakeReadCause::ForMatchedPlace(closure_def_id), - discr_place.hir_id, - ); self.walk_pat(discr_place, arm.pat, arm.guard.is_some())?; if let Some(ref e) = arm.guard { @@ -921,27 +814,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } - /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or - /// let binding, and *not* a match arm or nested pat.) - fn walk_irrefutable_pat( - &self, - discr_place: &PlaceWithHirId<'tcx>, - pat: &hir::Pat<'_>, - ) -> Result<(), Cx::Error> { - let closure_def_id = match discr_place.place.base { - PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id), - _ => None, - }; - - self.delegate.borrow_mut().fake_read( - discr_place, - FakeReadCause::ForLet(closure_def_id), - discr_place.hir_id, - ); - self.walk_pat(discr_place, pat, false)?; - Ok(()) - } - /// The core driver for walking a pattern /// /// This should mirror how pattern-matching gets lowered to MIR, as @@ -1988,6 +1860,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// Here, we cannot perform such an accurate checks, because querying /// whether a type is inhabited requires that it has been fully inferred, /// which cannot be guaranteed at this point. + #[instrument(skip(self, span), level = "debug")] fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need diff --git a/tests/crashes/119786.rs b/tests/crashes/119786-1.rs similarity index 100% rename from tests/crashes/119786.rs rename to tests/crashes/119786-1.rs diff --git a/tests/crashes/119786-2.rs b/tests/crashes/119786-2.rs new file mode 100644 index 0000000000000..76c5deb4605ae --- /dev/null +++ b/tests/crashes/119786-2.rs @@ -0,0 +1,15 @@ +//@ known-bug: #119786 +//@ edition:2021 + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some(_) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/crashes/119786-3.rs b/tests/crashes/119786-3.rs new file mode 100644 index 0000000000000..34bb90fd0fae3 --- /dev/null +++ b/tests/crashes/119786-3.rs @@ -0,0 +1,15 @@ +//@ known-bug: #119786 +//@ edition:2021 + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some((a, b)) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir index b43af549b232c..9ff1a90ab820b 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir @@ -4,18 +4,16 @@ fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake yields () { debug _task_context => _2; - debug f => (*(_1.0: &&Foo)); + debug f => (*(_1.0: &Foo)); let mut _0: (); let mut _3: &Foo; let mut _4: &&Foo; - let mut _5: &&&Foo; - let mut _6: isize; - let mut _7: bool; + let mut _5: isize; + let mut _6: bool; bb0: { - PlaceMention((*(_1.0: &&Foo))); - _6 = discriminant((*(*(_1.0: &&Foo)))); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + _5 = discriminant((*(_1.0: &Foo))); + switchInt(move _5) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -32,17 +30,15 @@ yields () } bb4: { - FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo))); unreachable; } bb5: { - _3 = &fake shallow (*(*(_1.0: &&Foo))); - _4 = &fake shallow (*(_1.0: &&Foo)); - _5 = &fake shallow (_1.0: &&Foo); - StorageLive(_7); - _7 = const true; - switchInt(move _7) -> [0: bb8, otherwise: bb7]; + _3 = &fake shallow (*(_1.0: &Foo)); + _4 = &fake shallow (_1.0: &Foo); + StorageLive(_6); + _6 = const true; + switchInt(move _6) -> [0: bb8, otherwise: bb7]; } bb6: { @@ -50,10 +46,9 @@ yields () } bb7: { - StorageDead(_7); + StorageDead(_6); FakeRead(ForMatchGuard, _3); FakeRead(ForMatchGuard, _4); - FakeRead(ForMatchGuard, _5); _0 = const (); goto -> bb10; } @@ -63,7 +58,7 @@ yields () } bb9: { - StorageDead(_7); + StorageDead(_6); goto -> bb6; } diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index 5623b6d64e973..4b745caf48c5a 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -4,18 +4,16 @@ fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fa yields () { debug _task_context => _2; - debug f => (_1.0: &Foo); + debug f => (*(_1.0: &Foo)); let mut _0: (); let mut _3: &Foo; let mut _4: &&Foo; - let mut _5: &&&Foo; - let mut _6: isize; - let mut _7: bool; + let mut _5: isize; + let mut _6: bool; bb0: { - PlaceMention((_1.0: &Foo)); - _6 = discriminant((*(_1.0: &Foo))); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + _5 = discriminant((*(_1.0: &Foo))); + switchInt(move _5) -> [0: bb2, otherwise: bb1]; } bb1: { @@ -29,24 +27,22 @@ yields () bb3: { _3 = &fake shallow (*(_1.0: &Foo)); - _4 = &fake shallow (_1.0: &Foo); nop; - StorageLive(_7); - _7 = const true; - switchInt(move _7) -> [0: bb5, otherwise: bb4]; + StorageLive(_6); + _6 = const true; + switchInt(move _6) -> [0: bb5, otherwise: bb4]; } bb4: { - StorageDead(_7); + StorageDead(_6); FakeRead(ForMatchGuard, _3); FakeRead(ForMatchGuard, _4); - FakeRead(ForMatchGuard, _5); _0 = const (); goto -> bb6; } bb5: { - StorageDead(_7); + StorageDead(_6); falseEdge -> [real: bb1, imaginary: bb1]; } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr index d82db0481a06f..3f5fe9eda423f 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr @@ -4,7 +4,7 @@ error[E0505]: cannot move out of `ts` because it is borrowed LL | let _b = || { match ts { | -- -- borrow occurs due to use in closure | | - | borrow of `ts` occurs here + | borrow of `ts.x` occurs here ... LL | let mut mut_ts = ts; | ^^ move out of `ts` occurs here diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index a9d2777d93f13..16cb9d7355da5 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -14,7 +14,6 @@ fn test_1_should_capture() { //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable - //~| NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable Some(_) => {} _ => {} @@ -65,9 +64,8 @@ fn test_6_should_capture_single_variant() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match variant { - //~^ NOTE: Capturing variant[] -> Immutable - //~| NOTE: Capturing variant[(0, 0)] -> Immutable - //~| NOTE: Min Capture variant[] -> Immutable + //~^ NOTE: Capturing variant[(0, 0)] -> Immutable + //~| NOTE: Min Capture variant[(0, 0)] -> Immutable SingleVariant::Points(a) => { println!("{:?}", a); } @@ -133,7 +131,6 @@ fn test_5_should_capture_multi_variant() { //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable - //~| NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable MVariant::A => {} _ => {} @@ -151,9 +148,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Capturing slice[Deref] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [_,_,_] => {}, _ => {} } @@ -164,9 +160,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Capturing slice[Deref] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [] => {}, _ => {} } @@ -177,9 +172,8 @@ fn test_7_should_capture_slice_len() { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: match slice { - //~^ NOTE: Capturing slice[] -> Immutable - //~| NOTE: Capturing slice[Deref] -> Immutable - //~| NOTE: Min Capture slice[] -> Immutable + //~^ NOTE: Capturing slice[Deref] -> Immutable + //~| NOTE: Min Capture slice[Deref] -> Immutable [_, .. ,_] => {}, _ => {} } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr index 4b9d6fad0e504..73c685e152765 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -14,11 +14,6 @@ note: Capturing variant[] -> Immutable | LL | match variant { | ^^^^^^^ -note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:15:15 - | -LL | match variant { - | ^^^^^^^ error: Min Capture analysis includes: --> $DIR/patterns-capture-analysis.rs:12:5 @@ -38,7 +33,7 @@ LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:31:5 + --> $DIR/patterns-capture-analysis.rs:30:5 | LL | / || { LL | | @@ -49,7 +44,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:50:5 + --> $DIR/patterns-capture-analysis.rs:49:5 | LL | / || { LL | | @@ -60,7 +55,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:64:5 + --> $DIR/patterns-capture-analysis.rs:63:5 | LL | / || { LL | | @@ -70,19 +65,14 @@ LL | | match variant { LL | | }; | |_____^ | -note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:67:15 - | -LL | match variant { - | ^^^^^^^ note: Capturing variant[(0, 0)] -> Immutable - --> $DIR/patterns-capture-analysis.rs:67:15 + --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:64:5 + --> $DIR/patterns-capture-analysis.rs:63:5 | LL | / || { LL | | @@ -92,14 +82,14 @@ LL | | match variant { LL | | }; | |_____^ | -note: Min Capture variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:67:15 +note: Min Capture variant[(0, 0)] -> Immutable + --> $DIR/patterns-capture-analysis.rs:66:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:84:5 + --> $DIR/patterns-capture-analysis.rs:82:5 | LL | / || { LL | | @@ -110,7 +100,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:96:5 + --> $DIR/patterns-capture-analysis.rs:94:5 | LL | / || { LL | | @@ -121,7 +111,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:109:5 + --> $DIR/patterns-capture-analysis.rs:107:5 | LL | / || { LL | | @@ -132,7 +122,7 @@ LL | | }; | |_____^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:131:5 + --> $DIR/patterns-capture-analysis.rs:129:5 | LL | / || { LL | | @@ -143,18 +133,13 @@ LL | | }; | |_____^ | note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:134:15 - | -LL | match variant { - | ^^^^^^^ -note: Capturing variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:134:15 + --> $DIR/patterns-capture-analysis.rs:132:15 | LL | match variant { | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:131:5 + --> $DIR/patterns-capture-analysis.rs:129:5 | LL | / || { LL | | @@ -165,13 +150,13 @@ LL | | }; | |_____^ | note: Min Capture variant[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:134:15 + --> $DIR/patterns-capture-analysis.rs:132:15 | LL | match variant { | ^^^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:150:5 + --> $DIR/patterns-capture-analysis.rs:147:5 | LL | / || { LL | | @@ -181,19 +166,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:153:15 - | -LL | match slice { - | ^^^^^ note: Capturing slice[Deref] -> Immutable - --> $DIR/patterns-capture-analysis.rs:153:15 + --> $DIR/patterns-capture-analysis.rs:150:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:150:5 + --> $DIR/patterns-capture-analysis.rs:147:5 | LL | / || { LL | | @@ -203,14 +183,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:153:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:150:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:163:5 + --> $DIR/patterns-capture-analysis.rs:159:5 | LL | / || { LL | | @@ -220,19 +200,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:166:15 - | -LL | match slice { - | ^^^^^ note: Capturing slice[Deref] -> Immutable - --> $DIR/patterns-capture-analysis.rs:166:15 + --> $DIR/patterns-capture-analysis.rs:162:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:163:5 + --> $DIR/patterns-capture-analysis.rs:159:5 | LL | / || { LL | | @@ -242,14 +217,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:166:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:162:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:176:5 + --> $DIR/patterns-capture-analysis.rs:171:5 | LL | / || { LL | | @@ -259,19 +234,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Capturing slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:179:15 - | -LL | match slice { - | ^^^^^ note: Capturing slice[Deref] -> Immutable - --> $DIR/patterns-capture-analysis.rs:179:15 + --> $DIR/patterns-capture-analysis.rs:174:15 | LL | match slice { | ^^^^^ error: Min Capture analysis includes: - --> $DIR/patterns-capture-analysis.rs:176:5 + --> $DIR/patterns-capture-analysis.rs:171:5 | LL | / || { LL | | @@ -281,14 +251,14 @@ LL | | match slice { LL | | }; | |_____^ | -note: Min Capture slice[] -> Immutable - --> $DIR/patterns-capture-analysis.rs:179:15 +note: Min Capture slice[Deref] -> Immutable + --> $DIR/patterns-capture-analysis.rs:174:15 | LL | match slice { | ^^^^^ error: First Pass analysis includes: - --> $DIR/patterns-capture-analysis.rs:194:5 + --> $DIR/patterns-capture-analysis.rs:188:5 | LL | / || { LL | | diff --git a/tests/ui/closures/at-pattern-weirdness-issue-137553.rs b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs new file mode 100644 index 0000000000000..7c934d4a14339 --- /dev/null +++ b/tests/ui/closures/at-pattern-weirdness-issue-137553.rs @@ -0,0 +1,41 @@ +//@ edition:2024 +//@ check-pass + +// Background: +fn f1() { + let mut a = (21, 37); + // only captures a.0, example compiles fine + let mut f = || { + let (ref mut x, _) = a; + *x = 42; + }; + a.1 = 69; + f(); +} + +// This used to error out: +fn f2() { + let mut a = (21, 37); + // used to capture all of a, now captures only a.0 + let mut f = || { + match a { + (ref mut x, _) => *x = 42, + } + }; + a.1 = 69; + f(); +} + +// This was inconsistent with the following: +fn main() { + let mut a = (21, 37); + // the useless @-pattern would cause it to capture only a.0. now the + // behavior is consistent with the case that doesn't use the @-pattern + let mut f = || { + match a { + (ref mut x @ _, _) => *x = 42, + } + }; + a.1 = 69; + f(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index 7f0f6a214aae9..383d9108eb908 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -23,15 +23,6 @@ fn upvar() { }; } -fn enum_upvar() { - type T = impl Copy; - let foo: T = Some((1u32, 2u32)); - let x = move || match foo { - None => (), - Some((a, b)) => (), - }; -} - fn r#struct() { #[derive(Copy, Clone)] struct Foo((u32, u32)); From 213fa596f2dd54e639f2e88ad964eeac49d443ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Thu, 27 Mar 2025 16:50:11 +0100 Subject: [PATCH 03/22] Add test case for issue 138973 --- tests/ui/closures/or-patterns-issue-137467.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ui/closures/or-patterns-issue-137467.rs b/tests/ui/closures/or-patterns-issue-137467.rs index 38144aa1e8162..5a1e84e1c9a0d 100644 --- a/tests/ui/closures/or-patterns-issue-137467.rs +++ b/tests/ui/closures/or-patterns-issue-137467.rs @@ -24,6 +24,13 @@ fn match_const(x: (u32, u32, u32)) { }; } +// related testcase reported in #138973 +fn without_bindings(x: u32) { + let _ = || { + let (0 | _) = x; + }; +} + enum Choice { A, B } fn match_unit_variant(x: (Choice, u32, u32)) { From 2d6503c60079deedd828e0f1e5f3c7493966a9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 1 Apr 2025 20:32:13 +0200 Subject: [PATCH 04/22] Avoid using #[derive] in test As per code review, it is preferred to not use derives in tests that aren't about them. --- .../2229_closure_analysis/only-inhabited-variant-stable.rs | 3 +-- .../2229_closure_analysis/only-inhabited-variant-stable.stderr | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs index a8e4b9cd18235..c7f367cc48ab9 100644 --- a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.rs @@ -3,7 +3,6 @@ // depending on whether some types are inhabited goes too far, introducing a // bunch of headaches without much benefit. //@ edition:2021 -#[derive(Clone, Copy, PartialEq, Eq, Debug)] enum Void {} pub fn main() { @@ -19,5 +18,5 @@ pub fn main() { }; f(); g(); - assert_eq!(r, Err((1, 2))); + assert!(matches!(r, Err((1, 2)))); } diff --git a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr index dea85ff947ced..7f4c8942b0d91 100644 --- a/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr +++ b/tests/ui/closures/2229_closure_analysis/only-inhabited-variant-stable.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `r` as mutable more than once at a time - --> $DIR/only-inhabited-variant-stable.rs:15:17 + --> $DIR/only-inhabited-variant-stable.rs:14:17 | LL | let mut f = || { | -- first mutable borrow occurs here From 2b16835a5d901a0d74e57a829159343fb68a7638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 22 Apr 2025 01:02:48 +0200 Subject: [PATCH 05/22] Add debug logging in hir_typeck::upvar This aims to make each major part responsible for modifying the precision be visible in the logs. --- compiler/rustc_hir_typeck/src/upvar.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 0a7b458f3fb35..a4fa5677cf196 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -761,6 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ], /// } /// ``` + #[instrument(level = "debug", skip(self))] fn compute_min_captures( &self, closure_def_id: LocalDefId, @@ -2030,6 +2031,7 @@ struct InferBorrowKind<'tcx> { } impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { + #[instrument(skip(self), level = "debug")] fn fake_read( &mut self, place_with_id: &PlaceWithHirId<'tcx>, @@ -2120,6 +2122,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> { } /// Rust doesn't permit moving fields out of a type that implements drop +#[instrument(skip(fcx), ret, level = "debug")] fn restrict_precision_for_drop_types<'a, 'tcx>( fcx: &'a FnCtxt<'a, 'tcx>, mut place: Place<'tcx>, @@ -2180,6 +2183,7 @@ fn restrict_precision_for_unsafe( /// - No unsafe block is required to capture `place`. /// /// Returns the truncated place and updated capture mode. +#[instrument(ret, level = "debug")] fn restrict_capture_precision( place: Place<'_>, curr_mode: ty::UpvarCapture, @@ -2209,6 +2213,7 @@ fn restrict_capture_precision( } /// Truncate deref of any reference. +#[instrument(ret, level = "debug")] fn adjust_for_move_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2223,6 +2228,7 @@ fn adjust_for_move_closure( } /// Truncate deref of any reference. +#[instrument(ret, level = "debug")] fn adjust_for_use_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2238,6 +2244,7 @@ fn adjust_for_use_closure( /// Adjust closure capture just that if taking ownership of data, only move data /// from enclosing stack frame. +#[instrument(ret, level = "debug")] fn adjust_for_non_move_closure( mut place: Place<'_>, mut kind: ty::UpvarCapture, @@ -2560,6 +2567,7 @@ fn determine_place_ancestry_relation<'tcx>( /// // it is constrained to `'a` /// } /// ``` +#[instrument(ret, level = "debug")] fn truncate_capture_for_optimization( mut place: Place<'_>, mut curr_mode: ty::UpvarCapture, From 6890336e5b1fbd72557bec565cc31d19e3a88e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 22 Apr 2025 02:51:46 +0200 Subject: [PATCH 06/22] Add miri tests for new closure capture behavior --- .../tests/fail/closures/deref-in-pattern.rs | 20 ++++++++++++ .../fail/closures/deref-in-pattern.stderr | 20 ++++++++++++ .../tests/fail/closures/partial-pattern.rs | 28 +++++++++++++++++ .../fail/closures/partial-pattern.stderr | 20 ++++++++++++ .../fail/closures/uninhabited-variant.rs | 31 +++++++++++++++++++ .../fail/closures/uninhabited-variant.stderr | 20 ++++++++++++ 6 files changed, 139 insertions(+) create mode 100644 src/tools/miri/tests/fail/closures/deref-in-pattern.rs create mode 100644 src/tools/miri/tests/fail/closures/deref-in-pattern.stderr create mode 100644 src/tools/miri/tests/fail/closures/partial-pattern.rs create mode 100644 src/tools/miri/tests/fail/closures/partial-pattern.stderr create mode 100644 src/tools/miri/tests/fail/closures/uninhabited-variant.rs create mode 100644 src/tools/miri/tests/fail/closures/uninhabited-variant.stderr diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.rs b/src/tools/miri/tests/fail/closures/deref-in-pattern.rs new file mode 100644 index 0000000000000..c729469c78b0e --- /dev/null +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.rs @@ -0,0 +1,20 @@ +// This test serves to document the change in semantics introduced by +// rust-lang/rust#138961. +// +// A corollary of partial-pattern.rs: while the tuple access testcase makes +// it clear why these semantics are useful, it is actually the dereference +// being performed by the pattern that matters. + +fn main() { + // the inner reference is dangling + let x: &&u32 = unsafe { + let x: u32 = 42; + &&* &raw const x + }; + + let _ = || { //~ ERROR: encountered a dangling reference + match x { + &&_y => {}, + } + }; +} diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr new file mode 100644 index 0000000000000..aa97fd4b7ac26 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) + --> tests/fail/closures/deref-in-pattern.rs:LL:CC + | +LL | let _ = || { + | _____________^ +LL | | match x { +LL | | &&_y => {}, +LL | | } +LL | | }; + | |_____^ constructing invalid value: encountered a dangling reference (use-after-free) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/closures/deref-in-pattern.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.rs b/src/tools/miri/tests/fail/closures/partial-pattern.rs new file mode 100644 index 0000000000000..cb64462081802 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/partial-pattern.rs @@ -0,0 +1,28 @@ +// This test serves to document the change in semantics introduced by +// rust-lang/rust#138961. +// +// Previously, the closure would capture the entirety of x, and access *(*x).0 +// when called. Now, the closure only captures *(*x).0, which means that +// a &*(*x).0 reborrow happens when the closure is constructed. +// +// Hence, if one of the references is dangling, this constitutes newly introduced UB +// in the case where the closure doesn't get called. This isn't a big deal, +// because while opsem only now considers this to be UB, the unsafe code +// guidelines have long recommended against any handling of dangling references. + +fn main() { + // the inner references are dangling + let x: &(&u32, &u32) = unsafe { + let a = 21; + let b = 37; + let ra = &* &raw const a; + let rb = &* &raw const b; + &(ra, rb) + }; + + let _ = || { //~ ERROR: encountered a dangling reference + match x { + (&_y, _) => {}, + } + }; +} diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/closures/partial-pattern.stderr new file mode 100644 index 0000000000000..67b26709eb0d7 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/partial-pattern.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) + --> tests/fail/closures/partial-pattern.rs:LL:CC + | +LL | let _ = || { + | _____________^ +LL | | match x { +LL | | (&_y, _) => {}, +LL | | } +LL | | }; + | |_____^ constructing invalid value: encountered a dangling reference (use-after-free) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/closures/partial-pattern.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.rs b/src/tools/miri/tests/fail/closures/uninhabited-variant.rs new file mode 100644 index 0000000000000..9c50fdc13a35f --- /dev/null +++ b/src/tools/miri/tests/fail/closures/uninhabited-variant.rs @@ -0,0 +1,31 @@ +// Motivated by rust-lang/rust#138961, this shows how invalid discriminants interact with +// closure captures. +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1, // 1 + V2(!), // 2 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 2u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + let f = || { + // After rust-lang/rust#138961, constructing the closure performs a reborrow of r. + // Nevertheless, the discriminant is only actually inspected when the closure + // is called. + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1 => {} + E::V2(_) => {} + } + }; + + f(); +} diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr new file mode 100644 index 0000000000000..0c374804b9702 --- /dev/null +++ b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/closures/uninhabited-variant.rs:LL:CC + | +LL | match r { + | ^ read discriminant of an uninhabited enum variant + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside closure at tests/fail/closures/uninhabited-variant.rs:LL:CC +note: inside `main` + --> tests/fail/closures/uninhabited-variant.rs:LL:CC + | +LL | f(); + | ^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From bddc1e28f01c9805d5259d8dca94335a9c48f4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 22 Apr 2025 03:32:20 +0200 Subject: [PATCH 07/22] add a comment: MatchPair and ExprUseVisitor must stay in sync --- compiler/rustc_mir_build/src/builder/matches/match_pair.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index a0d54354a9c63..67c12bfa7790d 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -339,6 +339,12 @@ impl<'tcx> MatchPairTree<'tcx> { if let Some(test_case) = test_case { // This pattern is refutable, so push a new match-pair node. + // + // Note: unless test_case is TestCase::Or, place must not be None. + // This means that the closure capture analysis in + // rustc_hir_typeck::upvar, and in particular the pattern handling + // code of ExprUseVisitor, must capture all of the places we'll use. + // Make sure to keep these two parts in sync! match_pairs.push(MatchPairTree { place, test_case, From ca47a9196ae8b67c6ebe5afe37d95db7855b4e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sat, 31 May 2025 00:07:16 +0200 Subject: [PATCH 08/22] Mark crash 140011 as fixed --- tests/crashes/140011.rs | 11 ------ .../malformed-pattern-issue-140011.rs | 13 +++++++ .../malformed-pattern-issue-140011.stderr | 36 +++++++++++++++++++ 3 files changed, 49 insertions(+), 11 deletions(-) delete mode 100644 tests/crashes/140011.rs create mode 100644 tests/ui/closures/malformed-pattern-issue-140011.rs create mode 100644 tests/ui/closures/malformed-pattern-issue-140011.stderr diff --git a/tests/crashes/140011.rs b/tests/crashes/140011.rs deleted file mode 100644 index b9d57a2822d21..0000000000000 --- a/tests/crashes/140011.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #140011 -//@compile-flags: -Wrust-2021-incompatible-closure-captures -enum b { - c(d), - e(f), -} -struct f; -fn g() { - let h; - || b::e(a) = h; -} diff --git a/tests/ui/closures/malformed-pattern-issue-140011.rs b/tests/ui/closures/malformed-pattern-issue-140011.rs new file mode 100644 index 0000000000000..18061613e9880 --- /dev/null +++ b/tests/ui/closures/malformed-pattern-issue-140011.rs @@ -0,0 +1,13 @@ +//@compile-flags: -Wrust-2021-incompatible-closure-captures +enum B { + C(D), //~ ERROR: cannot find type `D` in this scope + E(F), +} +struct F; +fn f(h: B) { + || { + let B::E(a) = h; //~ ERROR: refutable pattern in local binding + }; +} + +fn main() {} diff --git a/tests/ui/closures/malformed-pattern-issue-140011.stderr b/tests/ui/closures/malformed-pattern-issue-140011.stderr new file mode 100644 index 0000000000000..08122b8a7d2e5 --- /dev/null +++ b/tests/ui/closures/malformed-pattern-issue-140011.stderr @@ -0,0 +1,36 @@ +error[E0412]: cannot find type `D` in this scope + --> $DIR/malformed-pattern-issue-140011.rs:3:7 + | +LL | C(D), + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | enum B { + | +++ + +error[E0005]: refutable pattern in local binding + --> $DIR/malformed-pattern-issue-140011.rs:9:13 + | +LL | let B::E(a) = h; + | ^^^^^^^ pattern `B::C(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html +note: `B` defined here + --> $DIR/malformed-pattern-issue-140011.rs:2:6 + | +LL | enum B { + | ^ +LL | C(D), + | - not covered + = note: the matched value is of type `B` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let B::E(a) = h else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0005, E0412. +For more information about an error, try `rustc --explain E0005`. From 21da351cff5ac1c89009f9323b7e70a8cd0b8575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sat, 31 May 2025 00:13:46 +0200 Subject: [PATCH 09/22] =?UTF-8?q?ExprUseVisitor:=20resolve=20a=20FIXME=20?= =?UTF-8?q?=E2=80=93=20it's=20fine=20as=20is?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 9dc7901236b56..772ce2d4627af 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -929,10 +929,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // When matching against a literal or range, we need to // borrow the place to compare it against the pattern. // + // Note that we do this read even if the range matches all + // possible values, such as 0..=u8::MAX. This is because + // we don't want to depend on consteval here. + // // FIXME: What if the type being matched only has one // possible value? - // FIXME: What if the range is the full range of the type - // and doesn't actually require a discriminant read? read_discriminant(); } PatKind::Struct(..) | PatKind::TupleStruct(..) => { From 0bc7f13ba72f7a08e867e278a6cb4e5c90926fe6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 15 Oct 2025 07:27:39 +0000 Subject: [PATCH 10/22] Bless miri tests --- src/tools/miri/tests/fail/closures/deref-in-pattern.stderr | 2 +- src/tools/miri/tests/fail/closures/partial-pattern.stderr | 2 +- src/tools/miri/tests/fail/closures/uninhabited-variant.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr index aa97fd4b7ac26..ccdfad5773151 100644 --- a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr @@ -7,7 +7,7 @@ LL | | match x { LL | | &&_y => {}, LL | | } LL | | }; - | |_____^ constructing invalid value: encountered a dangling reference (use-after-free) + | |_____^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/closures/partial-pattern.stderr index 67b26709eb0d7..f26d6ffed54b0 100644 --- a/src/tools/miri/tests/fail/closures/partial-pattern.stderr +++ b/src/tools/miri/tests/fail/closures/partial-pattern.stderr @@ -7,7 +7,7 @@ LL | | match x { LL | | (&_y, _) => {}, LL | | } LL | | }; - | |_____^ constructing invalid value: encountered a dangling reference (use-after-free) + | |_____^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr index 0c374804b9702..995a5e3eac146 100644 --- a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr +++ b/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr @@ -2,7 +2,7 @@ error: Undefined Behavior: read discriminant of an uninhabited enum variant --> tests/fail/closures/uninhabited-variant.rs:LL:CC | LL | match r { - | ^ read discriminant of an uninhabited enum variant + | ^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information From a625b7794ee0116fd8cb3cdc411d43102f7892b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 19 Oct 2025 00:38:31 +0200 Subject: [PATCH 11/22] Add a test for deref projections in new pattern capture behavior --- .../deref-mut-in-pattern.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs diff --git a/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs new file mode 100644 index 0000000000000..4839fc7d91926 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs @@ -0,0 +1,35 @@ +// Newly accepted examples as a result of the changes introduced in #138961. +// +//@ edition:2024 +//@ check-pass +#![allow(unused_assignments)] + +fn f() { + let mut x: &mut [u8] = &mut [1, 2, 3]; + let c = || { + match x { + [] => (), + _ => (), + } + }; + x = &mut []; + c(); +} + +fn g() { + let mut x: &mut bool = &mut false; + let mut t = true; + let c = || { + match x { + true => (), + false => (), + } + }; + x = &mut t; + c(); +} + +fn main() { + f(); + g(); +} From 39d09eb3f2f5151fa4ccbe8d0ab600eae44c669b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 19 Oct 2025 00:49:56 +0200 Subject: [PATCH 12/22] Rewrite the comment on is_multivariant_adt As Nadrieril remarked, the previous comment was misleadingly framed. --- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 772ce2d4627af..ab937d4a012c8 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1859,9 +1859,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// builder code does a more specific check, filtering out variants that /// happen to be uninhabited. /// - /// Here, we cannot perform such an accurate checks, because querying - /// whether a type is inhabited requires that it has been fully inferred, - /// which cannot be guaranteed at this point. + /// Here, it is not practical to perform such a check, because inhabitedness + /// queries require typeck results, and typeck requires closure capture analysis. + /// + /// Moreover, the language is moving towards uninhabited variants still semantically + /// causing a discriminant read, so we *shouldn't* perform any such check. + /// + /// FIXME(never_patterns): update this comment once the aforementioned MIR builder + /// code is changed to be insensitive to inhhabitedness. #[instrument(skip(self, span), level = "debug")] fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { From 736e322f6425ec633edcce0bb20b9fe2b69e8db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 19 Oct 2025 16:13:50 +0200 Subject: [PATCH 13/22] Add more variations from the PR thread --- .../deref-mut-in-pattern.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs index 4839fc7d91926..b2c0eac9efa27 100644 --- a/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs +++ b/tests/ui/closures/2229_closure_analysis/deref-mut-in-pattern.rs @@ -4,6 +4,7 @@ //@ check-pass #![allow(unused_assignments)] +// Reading the length as part of a pattern captures the pointee. fn f() { let mut x: &mut [u8] = &mut [1, 2, 3]; let c = || { @@ -16,6 +17,7 @@ fn f() { c(); } +// Plain old deref as part of pattern behaves similarly fn g() { let mut x: &mut bool = &mut false; let mut t = true; @@ -29,6 +31,23 @@ fn g() { c(); } +// Like f, but the lifetime implications are expressed in terms of +// returning a closure. +fn f2<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l { + || match *x { + &[] => (), + _ => (), + } +} + +// Related testcase that was already accepted before +fn f3<'l: 's, 's>(x: &'s mut &'l [u8]) -> impl Fn() + 'l { + || match **x { + [] => (), + _ => (), + } +} + fn main() { f(); g(); From 4e72c4d4b2bcc702140e9ad99f64b43f07b7526a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Fri, 14 Nov 2025 23:53:46 +0100 Subject: [PATCH 14/22] re-bless miri tests --- src/tools/miri/tests/fail/closures/deref-in-pattern.stderr | 2 -- src/tools/miri/tests/fail/closures/partial-pattern.stderr | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr index ccdfad5773151..1264f4e3fb95a 100644 --- a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr +++ b/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr @@ -11,8 +11,6 @@ LL | | }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: - = note: inside `main` at tests/fail/closures/deref-in-pattern.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/closures/partial-pattern.stderr index f26d6ffed54b0..5b7ee35ecc736 100644 --- a/src/tools/miri/tests/fail/closures/partial-pattern.stderr +++ b/src/tools/miri/tests/fail/closures/partial-pattern.stderr @@ -11,8 +11,6 @@ LL | | }; | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: - = note: inside `main` at tests/fail/closures/partial-pattern.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace From 9d031bcd1e5a15d28db6ac8fe161ed3ceaf64cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Fri, 14 Nov 2025 23:53:58 +0100 Subject: [PATCH 15/22] `search_is_some`: move to nursery See clippy issue 16086 for context --- .../clippy/clippy_lints/src/methods/mod.rs | 2 +- src/tools/clippy/tests/ui/crashes/ice-9041.rs | 1 + .../clippy/tests/ui/crashes/ice-9041.stderr | 2 +- .../ui/search_is_some_fixable_some.fixed | 14 +++++---- .../tests/ui/search_is_some_fixable_some.rs | 7 +++-- .../ui/search_is_some_fixable_some.stderr | 29 +------------------ 6 files changed, 18 insertions(+), 37 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 20dfce914838f..ffe59037bee95 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -889,7 +889,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "pre 1.29.0"] pub SEARCH_IS_SOME, - complexity, + nursery, "using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)" } diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.rs b/src/tools/clippy/tests/ui/crashes/ice-9041.rs index 4b2a0f9531148..fae3233ba2f51 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9041.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-9041.rs @@ -1,3 +1,4 @@ +#![warn(clippy::search_is_some)] pub struct Thing; //@no-rustfix pub fn has_thing(things: &[Thing]) -> bool { diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr index dd9db71c5de83..256c8b8330344 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr @@ -1,5 +1,5 @@ error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/crashes/ice-9041.rs:5:19 + --> tests/ui/crashes/ice-9041.rs:6:19 | LL | things.iter().find(|p| is_thing_ready(p)).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))` diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed index 1213fdcf61197..daae41c0c891b 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed @@ -311,19 +311,23 @@ mod issue9120 { } } +// skip this test due to rust-lang/rust-clippy#16086 +/* #[allow(clippy::match_like_matches_macro)] fn issue15102() { let values = [None, Some(3)]; - let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0)); - //~^ search_is_some + let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); + ~^ search_is_some println!("{has_even}"); let has_even = values .iter() - .any(|v| match &v { - //~^ search_is_some + .find(|v| match v { + ~^ search_is_some Some(x) if x % 2 == 0 => true, _ => false, - }); + }) + .is_some(); println!("{has_even}"); } +*/ diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs index 4294a39333f20..ead101a491a6a 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.rs @@ -322,20 +322,23 @@ mod issue9120 { } } +// skip this test due to rust-lang/rust-clippy#16086 +/* #[allow(clippy::match_like_matches_macro)] fn issue15102() { let values = [None, Some(3)]; let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); - //~^ search_is_some + ~^ search_is_some println!("{has_even}"); let has_even = values .iter() .find(|v| match v { - //~^ search_is_some + ~^ search_is_some Some(x) if x % 2 == 0 => true, _ => false, }) .is_some(); println!("{has_even}"); } +*/ diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr index cee1eb08876ba..c56fe859aac09 100644 --- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr +++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr @@ -346,32 +346,5 @@ error: called `is_some()` after searching an `Iterator` with `find` LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))` -error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:328:34 - | -LL | let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))` - -error: called `is_some()` after searching an `Iterator` with `find` - --> tests/ui/search_is_some_fixable_some.rs:334:10 - | -LL | .find(|v| match v { - | __________^ -LL | | -LL | | Some(x) if x % 2 == 0 => true, -LL | | _ => false, -LL | | }) -LL | | .is_some(); - | |__________________^ - | -help: consider using - | -LL ~ .any(|v| match &v { -LL + -LL + Some(x) if x % 2 == 0 => true, -LL + _ => false, -LL ~ }); - | - -error: aborting due to 51 previous errors +error: aborting due to 49 previous errors From 04fedf71738c44e716b01480550787d99c47a254 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 12 Dec 2025 09:12:31 +0100 Subject: [PATCH 16/22] Remove unused code in `cfg_old` --- compiler/rustc_attr_parsing/messages.ftl | 10 - .../rustc_attr_parsing/src/attributes/cfg.rs | 22 +- .../src/attributes/cfg_old.rs | 210 ------------------ .../rustc_attr_parsing/src/attributes/mod.rs | 1 - .../src/attributes/stability.rs | 4 +- compiler/rustc_attr_parsing/src/lib.rs | 1 - .../src/session_diagnostics.rs | 37 +-- 7 files changed, 22 insertions(+), 263 deletions(-) delete mode 100644 compiler/rustc_attr_parsing/src/attributes/cfg_old.rs diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index f2642838b3c8c..deebc25c8259e 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -6,9 +6,6 @@ attr_parsing_bundle_needs_static = attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters -attr_parsing_cfg_predicate_identifier = - `cfg` predicate key must be an identifier - attr_parsing_deprecated_item_suggestion = suggestions on deprecated items are unstable .help = add `#![feature(deprecated_suggestion)]` to the crate root @@ -41,9 +38,6 @@ attr_parsing_empty_link_name = link name must not be empty .label = empty link name -attr_parsing_expected_one_cfg_pattern = - expected 1 cfg-pattern - attr_parsing_expected_single_version_literal = expected single version literal @@ -241,10 +235,6 @@ attr_parsing_unstable_cfg_target_compact = attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable .help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]` -attr_parsing_unsupported_literal_cfg_boolean = - literal in `cfg` predicate value must be a boolean -attr_parsing_unsupported_literal_cfg_string = - literal in `cfg` predicate value must be a string attr_parsing_unsupported_literal_generic = unsupported literal attr_parsing_unsupported_literal_suggestion = diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 6ffe25098308a..93f4255309411 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -4,7 +4,9 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token}; use rustc_errors::{Applicability, PResult}; -use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template}; +use rustc_feature::{ + AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template, +}; use rustc_hir::attrs::CfgEntry; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, RustcVersion}; @@ -23,7 +25,7 @@ use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, ParsedDescription, }; -use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics, try_gate_cfg}; +use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics}; pub const CFG_TEMPLATE: AttributeTemplate = template!( List: &["predicate"], @@ -410,3 +412,19 @@ fn parse_cfg_attr_internal<'a>( Ok((cfg_predicate, expanded_attrs)) } + +fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) { + let gate = find_gated_cfg(|sym| sym == name); + if let (Some(feats), Some(gated_cfg)) = (features, gate) { + gate_cfg(gated_cfg, span, sess, feats); + } +} + +#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable +fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) { + let (cfg, feature, has_feature) = gated_cfg; + if !has_feature(features) && !cfg_span.allows_unstable(*feature) { + let explain = format!("`cfg({cfg})` is experimental and subject to change"); + feature_err(sess, *feature, cfg_span, explain).emit(); + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_old.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_old.rs deleted file mode 100644 index acb234480d5dd..0000000000000 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_old.rs +++ /dev/null @@ -1,210 +0,0 @@ -use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId}; -use rustc_ast_pretty::pprust; -use rustc_feature::{Features, GatedCfg, find_gated_cfg}; -use rustc_hir::RustcVersion; -use rustc_session::Session; -use rustc_session::lint::{BuiltinLintDiag, Lint}; -use rustc_session::parse::feature_err; -use rustc_span::{Span, Symbol, sym}; - -use crate::session_diagnostics::{self, UnsupportedLiteralReason}; -use crate::{fluent_generated, parse_version}; - -/// Emitter of a builtin lint from `cfg_matches`. -/// -/// Used to support emitting a lint (currently on check-cfg), either: -/// - as an early buffered lint (in `rustc`) -/// - or has a "normal" lint from HIR (in `rustdoc`) -pub trait CfgMatchesLintEmitter { - fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag); -} - -impl CfgMatchesLintEmitter for NodeId { - fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) { - sess.psess.buffer_lint(lint, sp, *self, diag); - } -} - -#[derive(Clone, Debug)] -pub struct Condition { - pub name: Symbol, - pub name_span: Span, - pub value: Option, - pub value_span: Option, - pub span: Span, -} - -pub fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) { - let gate = find_gated_cfg(|sym| sym == name); - if let (Some(feats), Some(gated_cfg)) = (features, gate) { - gate_cfg(gated_cfg, span, sess, feats); - } -} - -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) { - let (cfg, feature, has_feature) = gated_cfg; - if !has_feature(features) && !cfg_span.allows_unstable(*feature) { - let explain = format!("`cfg({cfg})` is experimental and subject to change"); - feature_err(sess, *feature, cfg_span, explain).emit(); - } -} - -/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to -/// evaluate individual items. -pub fn eval_condition( - cfg: &MetaItemInner, - sess: &Session, - features: Option<&Features>, - eval: &mut impl FnMut(Condition) -> bool, -) -> bool { - let dcx = sess.dcx(); - - let cfg = match cfg { - MetaItemInner::MetaItem(meta_item) => meta_item, - MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { - return *b; - } - _ => { - dcx.emit_err(session_diagnostics::UnsupportedLiteral { - span: cfg.span(), - reason: UnsupportedLiteralReason::CfgBoolean, - is_bytestr: false, - start_point_span: sess.source_map().start_point(cfg.span()), - }); - return false; - } - }; - - match &cfg.kind { - MetaItemKind::List(mis) if cfg.has_name(sym::version) => { - try_gate_cfg(sym::version, cfg.span, sess, features); - let (min_version, span) = match &mis[..] { - [MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => { - (sym, span) - } - [ - MetaItemInner::Lit(MetaItemLit { span, .. }) - | MetaItemInner::MetaItem(MetaItem { span, .. }), - ] => { - dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span }); - return false; - } - [..] => { - dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { - span: cfg.span, - }); - return false; - } - }; - let Some(min_version) = parse_version(*min_version) else { - dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span }); - return false; - }; - - // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details - if sess.psess.assume_incomplete_release { - RustcVersion::current_overridable() > min_version - } else { - RustcVersion::current_overridable() >= min_version - } - } - MetaItemKind::List(mis) => { - for mi in mis.iter() { - if mi.meta_item_or_bool().is_none() { - dcx.emit_err(session_diagnostics::UnsupportedLiteral { - span: mi.span(), - reason: UnsupportedLiteralReason::Generic, - is_bytestr: false, - start_point_span: sess.source_map().start_point(mi.span()), - }); - return false; - } - } - - // The unwraps below may look dangerous, but we've already asserted - // that they won't fail with the loop above. - match cfg.name() { - Some(sym::any) => mis - .iter() - // We don't use any() here, because we want to evaluate all cfg condition - // as eval_condition can (and does) extra checks - .fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)), - Some(sym::all) => mis - .iter() - // We don't use all() here, because we want to evaluate all cfg condition - // as eval_condition can (and does) extra checks - .fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)), - Some(sym::not) => { - let [mi] = mis.as_slice() else { - dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span }); - return false; - }; - - !eval_condition(mi, sess, features, eval) - } - Some(sym::target) => { - if let Some(features) = features - && !features.cfg_target_compact() - { - feature_err( - sess, - sym::cfg_target_compact, - cfg.span, - fluent_generated::attr_parsing_unstable_cfg_target_compact, - ) - .emit(); - } - - mis.iter().fold(true, |res, mi| { - let Some(mut mi) = mi.meta_item().cloned() else { - dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { - span: mi.span(), - }); - return false; - }; - - if let [seg, ..] = &mut mi.path.segments[..] { - seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name)); - } - - res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval) - }) - } - _ => { - dcx.emit_err(session_diagnostics::InvalidPredicate { - span: cfg.span, - predicate: pprust::path_to_string(&cfg.path), - }); - false - } - } - } - MetaItemKind::Word | MetaItemKind::NameValue(..) - if cfg.path.segments.len() != 1 - || cfg.path.segments[0].ident.is_path_segment_keyword() => - { - dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span }); - true - } - MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { - dcx.emit_err(session_diagnostics::UnsupportedLiteral { - span: lit.span, - reason: UnsupportedLiteralReason::CfgString, - is_bytestr: lit.kind.is_bytestr(), - start_point_span: sess.source_map().start_point(lit.span), - }); - true - } - MetaItemKind::Word | MetaItemKind::NameValue(..) => { - let ident = cfg.ident().expect("multi-segment cfg predicate"); - eval(Condition { - name: ident.name, - name_span: ident.span, - value: cfg.value_str(), - value_span: cfg.name_value_literal_span(), - span: cfg.span, - }) - } - } -} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 64bcb02b0b745..385003a359275 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -32,7 +32,6 @@ mod prelude; pub(crate) mod allow_unstable; pub(crate) mod body; pub(crate) mod cfg; -pub(crate) mod cfg_old; pub(crate) mod cfg_select; pub(crate) mod codegen_attrs; pub(crate) mod confusables; diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b94e23477ffeb..b97095893b8e2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -8,7 +8,7 @@ use rustc_hir::{ use super::prelude::*; use super::util::parse_version; -use crate::session_diagnostics::{self, UnsupportedLiteralReason}; +use crate::session_diagnostics::{self}; macro_rules! reject_outside_std { ($cx: ident) => { @@ -304,7 +304,6 @@ pub(crate) fn parse_stability( let Some(param) = param.meta_item() else { cx.emit_err(session_diagnostics::UnsupportedLiteral { span: param_span, - reason: UnsupportedLiteralReason::Generic, is_bytestr: false, start_point_span: cx.sess().source_map().start_point(param_span), }); @@ -384,7 +383,6 @@ pub(crate) fn parse_unstability( let Some(param) = param.meta_item() else { cx.emit_err(session_diagnostics::UnsupportedLiteral { span: param.span(), - reason: UnsupportedLiteralReason::Generic, is_bytestr: false, start_point_span: cx.sess().source_map().start_point(param.span()), }); diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index cb02bb9d501fc..411b4dd75e661 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -107,7 +107,6 @@ pub mod validate_attr; pub use attributes::cfg::{ CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; -pub use attributes::cfg_old::*; pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 7bb55d2a6de5b..df555a33f816b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -12,19 +12,6 @@ use rustc_span::{Span, Symbol}; use crate::fluent_generated as fluent; -pub(crate) enum UnsupportedLiteralReason { - Generic, - CfgString, - CfgBoolean, -} - -#[derive(Diagnostic)] -#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)] -pub(crate) struct ExpectedOneCfgPattern { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(attr_parsing_invalid_predicate, code = E0537)] pub(crate) struct InvalidPredicate { @@ -234,28 +221,13 @@ pub(crate) struct InvalidReprHintNoValue { // FIXME(jdonszelmann): slowly phased out pub(crate) struct UnsupportedLiteral { pub span: Span, - pub reason: UnsupportedLiteralReason, pub is_bytestr: bool, pub start_point_span: Span, } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new( - dcx, - level, - match self.reason { - UnsupportedLiteralReason::Generic => { - fluent::attr_parsing_unsupported_literal_generic - } - UnsupportedLiteralReason::CfgString => { - fluent::attr_parsing_unsupported_literal_cfg_string - } - UnsupportedLiteralReason::CfgBoolean => { - fluent::attr_parsing_unsupported_literal_cfg_boolean - } - }, - ); + let mut diag = Diag::new(dcx, level, fluent::attr_parsing_unsupported_literal_generic); diag.span(self.span); diag.code(E0565); if self.is_bytestr { @@ -375,13 +347,6 @@ pub(crate) struct RustcAllowedUnstablePairing { pub span: Span, } -#[derive(Diagnostic)] -#[diag(attr_parsing_cfg_predicate_identifier)] -pub(crate) struct CfgPredicateIdentifier { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(attr_parsing_deprecated_item_suggestion)] pub(crate) struct DeprecatedItemSuggestion { From acea7df0b4fdba04f94528f19ea1333cd68d2670 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 12 Dec 2025 09:24:49 +0100 Subject: [PATCH 17/22] Remove last remaining usages of `UnsupportedLiteral` --- compiler/rustc_attr_parsing/messages.ftl | 2 -- .../src/attributes/stability.rs | 12 ++------- .../src/session_diagnostics.rs | 25 ------------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index deebc25c8259e..61f816f0baf8f 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -235,8 +235,6 @@ attr_parsing_unstable_cfg_target_compact = attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable .help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]` -attr_parsing_unsupported_literal_generic = - unsupported literal attr_parsing_unsupported_literal_suggestion = consider removing the prefix diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b97095893b8e2..fede424c3af7d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -302,11 +302,7 @@ pub(crate) fn parse_stability( for param in list.mixed() { let param_span = param.span(); let Some(param) = param.meta_item() else { - cx.emit_err(session_diagnostics::UnsupportedLiteral { - span: param_span, - is_bytestr: false, - start_point_span: cx.sess().source_map().start_point(param_span), - }); + cx.unexpected_literal(param.span()); return None; }; @@ -381,11 +377,7 @@ pub(crate) fn parse_unstability( for param in list.mixed() { let Some(param) = param.meta_item() else { - cx.emit_err(session_diagnostics::UnsupportedLiteral { - span: param.span(), - is_bytestr: false, - start_point_span: cx.sess().source_map().start_point(param.span()), - }); + cx.unexpected_literal(param.span()); return None; }; diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index df555a33f816b..3adbe115b23b5 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -217,31 +217,6 @@ pub(crate) struct InvalidReprHintNoValue { pub name: Symbol, } -/// Error code: E0565 -// FIXME(jdonszelmann): slowly phased out -pub(crate) struct UnsupportedLiteral { - pub span: Span, - pub is_bytestr: bool, - pub start_point_span: Span, -} - -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, fluent::attr_parsing_unsupported_literal_generic); - diag.span(self.span); - diag.code(E0565); - if self.is_bytestr { - diag.span_suggestion( - self.start_point_span, - fluent::attr_parsing_unsupported_literal_suggestion, - "", - Applicability::MaybeIncorrect, - ); - } - diag - } -} - #[derive(Diagnostic)] #[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)] pub(crate) struct InvalidReprAlignNeedArg { From 3f63f521c1f611c2d68eaaf1fe5f9a3f08be3ed5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 12 Dec 2025 22:06:07 +1100 Subject: [PATCH 18/22] Don't pass an unused `--color` to compiletest This flag was an artifact of compiletest's old libtest-based test executor, and currently doesn't influence compiletest's output at all. --- src/bootstrap/src/core/build_steps/test.rs | 1 - src/tools/compiletest/src/lib.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index a699cd23fb607..f30641d71e839 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2401,7 +2401,6 @@ Please disable assertions with `rust.debug-assertions = false`. let git_config = builder.config.git_config(); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email); - cmd.force_coloring_in_ci(); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 1fa818df62dea..71dad36337932 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -136,8 +136,6 @@ fn parse_config(args: Vec) -> Config { ) .optflag("", "fail-fast", "stop as soon as possible after any test fails") .optopt("", "target", "the target to build for", "TARGET") - // FIXME: Should be removed once `bootstrap` will be updated to not use this option. - .optopt("", "color", "coloring: auto, always, never", "WHEN") .optopt("", "host", "the host to build for", "HOST") .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH") .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH") From ac5c70ad4d5d8f767237f5b3d28719fbc5d72bc8 Mon Sep 17 00:00:00 2001 From: Clara Engler Date: Tue, 11 Nov 2025 11:46:11 +0100 Subject: [PATCH 19/22] time: Implement SystemTime::{MIN, MAX} This commit introduces two new constants to SystemTime: `MIN` and `MAX`, whose value represent the maximum values for the respective data type, depending upon the platform. Technically, this value is already obtainable during runtime with the following algorithm: Use `SystemTime::UNIX_EPOCH` and call `checked_add` (or `checked_sub`) repeatedly with `Duration::new(0, 1)` on it, until it returns None. Mathematically speaking, this algorithm will terminate after a finite amount of steps, yet it is impractical to run it, as it takes practically forever. Besides, this commit also adds a unit test. Concrete implementation depending upon the platform is done in later commits. In the future, the hope of the authors lies within the creation of a `SystemTime::saturating_add` and `SystemTime::saturating_sub`, similar to the functions already present in `std::time::Duration`. However, for those, these constants are crucially required, thereby this should be seen as the initial step towards this direction. Below are platform specifc notes: # Hermit The HermitOS implementation is more or less identitcal to the Unix one. # sgx The implementation uses a `Duration` to store the Unix time, thereby implying `Duration::ZERO` and `Duration::MAX` as the limits. # solid The implementation uses a `time_t` to store the system time within a single value (i.e. no dual secs/nanosecs handling), thereby implying its `::MIN` and `::MAX` values as the respective boundaries. # UEFI UEFI has a weird way to store times, i.e. a very complicated struct. The standard proclaims "1900-01-01T00:00:00+0000" to be the lowest possible value and `MAX_UEFI_TIME` is already present for the upper limit. # Windows Windows is weird. The Win32 documentation makes no statement on a maximum value here. Next to this, there are two conflicting types: `SYSTEMTIME` and `FILETIME`. Rust's Standard Library uses `FILETIME`, whose limit will (probably) be `i64::MAX` packed into two integers. However, `SYSTEMTIME` has a lower-limit. # xous It is similar to sgx in the sense of using a `Duration`. # unsupported Unsupported platforms store a `SystemTime` in a `Duration`, just like sgx, thereby implying `Duration::ZERO` and `Duration::MAX` as the respective limits. --- library/std/src/sys/pal/hermit/time.rs | 8 +++ library/std/src/sys/pal/sgx/time.rs | 4 ++ library/std/src/sys/pal/solid/time.rs | 4 ++ library/std/src/sys/pal/uefi/time.rs | 17 ++++++ library/std/src/sys/pal/unix/time.rs | 11 ++++ library/std/src/sys/pal/unsupported/time.rs | 4 ++ library/std/src/sys/pal/windows/time.rs | 10 ++++ library/std/src/sys/pal/xous/time.rs | 4 ++ library/std/src/time.rs | 63 +++++++++++++++++++++ library/std/tests/time.rs | 19 +++++++ 10 files changed, 144 insertions(+) diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index bd6fd5a3de428..53b1f9292b3d4 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -15,6 +15,10 @@ struct Timespec { } impl Timespec { + const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1); + + const MIN: Timespec = Self::new(i64::MIN, 0); + const fn zero() -> Timespec { Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } } } @@ -209,6 +213,10 @@ pub struct SystemTime(Timespec); pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); impl SystemTime { + pub const MAX: SystemTime = SystemTime { t: Timespec::MAX }; + + pub const MIN: SystemTime = SystemTime { t: Timespec::MIN }; + pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime { SystemTime(Timespec::new(tv_sec, tv_nsec)) } diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/pal/sgx/time.rs index db4cf2804bf13..a9a448226619e 100644 --- a/library/std/src/sys/pal/sgx/time.rs +++ b/library/std/src/sys/pal/sgx/time.rs @@ -28,6 +28,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { SystemTime(usercalls::insecure_time()) } diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs index c39d715c6a6f6..d5cf70f94c987 100644 --- a/library/std/src/sys/pal/solid/time.rs +++ b/library/std/src/sys/pal/solid/time.rs @@ -10,6 +10,10 @@ pub struct SystemTime(abi::time_t); pub const UNIX_EPOCH: SystemTime = SystemTime(0); impl SystemTime { + pub const MAX: SystemTime = SystemTime(abi::time_t::MAX); + + pub const MIN: SystemTime = SystemTime(abi::time_t::MIN); + pub fn now() -> SystemTime { let rtc = unsafe { let mut out = MaybeUninit::zeroed(); diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index 28dacbe3068a7..30df6d93d0eed 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -70,6 +70,23 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = MAX_UEFI_TIME; + + pub const MIN: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1900, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: -1440, + daylight: 0, + pad1: 0, + pad2: 0, + }) + .unwrap(); + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Option { match system_time_internal::from_uefi(&t) { Some(x) => Some(Self(x)), diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index 24f13853b96b3..1b3fbeee4d900 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -30,6 +30,10 @@ pub(crate) struct Timespec { } impl SystemTime { + pub const MAX: SystemTime = SystemTime { t: Timespec::MAX }; + + pub const MIN: SystemTime = SystemTime { t: Timespec::MIN }; + #[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))] pub fn new(tv_sec: i64, tv_nsec: i64) -> Result { Ok(SystemTime { t: Timespec::new(tv_sec, tv_nsec)? }) @@ -62,6 +66,13 @@ impl fmt::Debug for SystemTime { } impl Timespec { + const MAX: Timespec = unsafe { Self::new_unchecked(i64::MAX, 1_000_000_000 - 1) }; + + // As described below, on Apple OS, dates before epoch are represented differently. + // This is not an issue here however, because we are using tv_sec = i64::MIN, + // which will cause the compatibility wrapper to not be executed at all. + const MIN: Timespec = unsafe { Self::new_unchecked(i64::MIN, 0) }; + const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec { Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } } } diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/pal/unsupported/time.rs index 6d67b538a96bf..9bdd57268fd5b 100644 --- a/library/std/src/sys/pal/unsupported/time.rs +++ b/library/std/src/sys/pal/unsupported/time.rs @@ -27,6 +27,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { panic!("time not implemented on this platform") } diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index 0d31b80e56afc..88f4d4cdbd615 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -64,6 +64,16 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime { + t: c::FILETIME { + dwLowDateTime: (i64::MAX & 0xFFFFFFFF) as u32, + dwHighDateTime: (i64::MAX >> 32) as u32, + }, + }; + + pub const MIN: SystemTime = + SystemTime { t: c::FILETIME { dwLowDateTime: 0, dwHighDateTime: 0 } }; + pub fn now() -> SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs index ae8be81c0b7c5..1e7e48183e982 100644 --- a/library/std/src/sys/pal/xous/time.rs +++ b/library/std/src/sys/pal/xous/time.rs @@ -35,6 +35,10 @@ impl Instant { } impl SystemTime { + pub const MAX: SystemTime = SystemTime(Duration::MAX); + + pub const MIN: SystemTime = SystemTime(Duration::ZERO); + pub fn now() -> SystemTime { let result = blocking_scalar(systime_server(), GetUtcTimeMs.into()) .expect("failed to request utc time in ms"); diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 87aaf9091f1bc..0bda83af4dfb6 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -511,6 +511,69 @@ impl SystemTime { #[stable(feature = "assoc_unix_epoch", since = "1.28.0")] pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH; + /// Represents the maximum value representable by [`SystemTime`] on this platform. + /// + /// This value differs a lot between platforms, but it is always the case + /// that any positive addition to [`SystemTime::MAX`] will fail. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(time_systemtime_limits)] + /// use std::time::{Duration, SystemTime}; + /// + /// // Adding zero will change nothing. + /// assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX)); + /// + /// // But adding just 1ns will already fail. + /// assert_eq!(SystemTime::MAX.checked_add(Duration::new(0, 1)), None); + /// + /// // Utilize this for saturating arithmetic to improve error handling. + /// // In this case, we will use a certificate with a timestamp in the + /// // future as a practical example. + /// let configured_offset = Duration::from_secs(60 * 60 * 24); + /// let valid_after = + /// SystemTime::now() + /// .checked_add(configured_offset) + /// .unwrap_or(SystemTime::MAX); + /// ``` + #[unstable(feature = "time_systemtime_limits", issue = "149067")] + pub const MAX: SystemTime = SystemTime(time::SystemTime::MAX); + + /// Represents the minimum value representable by [`SystemTime`] on this platform. + /// + /// This value differs a lot between platforms, but it is always the case + /// that any positive subtraction from [`SystemTime::MIN`] will fail. + /// + /// Depending on the platform, this may be either less than or equal to + /// [`SystemTime::UNIX_EPOCH`], depending on whether the operating system + /// supports the representation of timestamps before the Unix epoch or not. + /// However, it is always guaranteed that a [`SystemTime::UNIX_EPOCH`] fits + /// between a [`SystemTime::MIN`] and [`SystemTime::MAX`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(time_systemtime_limits)] + /// use std::time::{Duration, SystemTime}; + /// + /// // Subtracting zero will change nothing. + /// assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN)); + /// + /// // But subtracting just 1ns will already fail. + /// assert_eq!(SystemTime::MIN.checked_sub(Duration::new(0, 1)), None); + /// + /// // Utilize this for saturating arithmetic to improve error handling. + /// // In this case, we will use a cache expiry as a practical example. + /// let configured_expiry = Duration::from_secs(60 * 3); + /// let expiry_threshold = + /// SystemTime::now() + /// .checked_sub(configured_expiry) + /// .unwrap_or(SystemTime::MIN); + /// ``` + #[unstable(feature = "time_systemtime_limits", issue = "149067")] + pub const MIN: SystemTime = SystemTime(time::SystemTime::MIN); + /// Returns the system time corresponding to "now". /// /// # Examples diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs index be1948af91564..31cc7171fe52e 100644 --- a/library/std/tests/time.rs +++ b/library/std/tests/time.rs @@ -1,4 +1,5 @@ #![feature(duration_constants)] +#![feature(time_systemtime_limits)] use std::fmt::Debug; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -237,9 +238,27 @@ fn system_time_duration_since_max_range_on_unix() { let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0)); let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999)); + assert_eq!(min, SystemTime::MIN); + assert_eq!(max, SystemTime::MAX); + let delta_a = max.duration_since(min).expect("duration_since overflow"); let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration(); assert_eq!(Duration::MAX, delta_a); assert_eq!(Duration::MAX, delta_b); } + +#[test] +fn system_time_max_min() { + // First, test everything with checked_* and Duration::ZERO. + assert_eq!(SystemTime::MAX.checked_add(Duration::ZERO), Some(SystemTime::MAX)); + assert_eq!(SystemTime::MAX.checked_sub(Duration::ZERO), Some(SystemTime::MAX)); + assert_eq!(SystemTime::MIN.checked_add(Duration::ZERO), Some(SystemTime::MIN)); + assert_eq!(SystemTime::MIN.checked_sub(Duration::ZERO), Some(SystemTime::MIN)); + + // Now do the same again with checked_* but try by ± a single nanosecond. + assert!(SystemTime::MAX.checked_add(Duration::new(0, 1)).is_none()); + assert!(SystemTime::MAX.checked_sub(Duration::new(0, 1)).is_some()); + assert!(SystemTime::MIN.checked_add(Duration::new(0, 1)).is_some()); + assert!(SystemTime::MIN.checked_sub(Duration::new(0, 1)).is_none()); +} From 0e7dc328942c05a98f2e49b65692d7e7e70ea9d7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 12 Dec 2025 22:26:31 +1100 Subject: [PATCH 20/22] Inline `BootstrapCommand::force_coloring_in_ci` into its only call site This logic is cargo-specific anyway, so there is no need for it to be a generally-available helper method. --- src/bootstrap/src/core/builder/cargo.rs | 10 +++++++++- src/bootstrap/src/utils/exec.rs | 13 ------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 2ca52c72e5ec7..5a6bade59a6a3 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -2,6 +2,8 @@ use std::env; use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; +use build_helper::ci::CiEnv; + use super::{Builder, Kind}; use crate::core::build_steps::test; use crate::core::build_steps::tool::SourceType; @@ -1334,7 +1336,13 @@ impl Builder<'_> { // Try to use a sysroot-relative bindir, in case it was configured absolutely. cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative()); - cargo.force_coloring_in_ci(); + if CiEnv::is_ci() { + // Tell cargo to use colored output for nicer logs in CI, even + // though CI isn't printing to a terminal. + // Also set an explicit `TERM=xterm` so that cargo doesn't warn + // about TERM not being set. + cargo.env("TERM", "xterm").args(["--color=always"]); + }; // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index f875e6e1af75c..61b8b26dceaf4 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -21,7 +21,6 @@ use std::process::{ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; -use build_helper::ci::CiEnv; use build_helper::drop_bomb::DropBomb; use build_helper::exit; @@ -390,18 +389,6 @@ impl<'a> BootstrapCommand { self.drop_bomb.get_created_location() } - /// If in a CI environment, forces the command to run with colors. - pub fn force_coloring_in_ci(&mut self) { - if CiEnv::is_ci() { - // Due to use of stamp/docker, the output stream of bootstrap is not - // a TTY in CI, so coloring is by-default turned off. - // The explicit `TERM=xterm` environment is needed for - // `--color always` to actually work. This env var was lost when - // compiling through the Makefile. Very strange. - self.env("TERM", "xterm").args(["--color", "always"]); - } - } - pub fn fingerprint(&self) -> CommandFingerprint { let command = &self.command; CommandFingerprint { From 0ab4b8b9e0257a15fdf791950f48fa77dc0019b0 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 12 Dec 2025 12:21:15 +0100 Subject: [PATCH 21/22] Remove the E0536 error code --- compiler/rustc_error_codes/src/error_codes/E0536.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_error_codes/src/error_codes/E0536.md b/compiler/rustc_error_codes/src/error_codes/E0536.md index c1f43fa741cfa..7603be4fcc935 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0536.md +++ b/compiler/rustc_error_codes/src/error_codes/E0536.md @@ -1,3 +1,5 @@ +#### Note: this error code is no longer emitted by the compiler. + The `not` cfg-predicate was malformed. Erroneous code example (using `cargo doc`): From d025cdef7d9f5214dfffc4425eb1dd2228f8dc6c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 12 Dec 2025 14:47:28 +0100 Subject: [PATCH 22/22] If there are too many suggestions for malformed attribute, do not suggest them --- .../src/session_diagnostics.rs | 24 +- .../rustc_attr_parsing/src/validate_attr.rs | 5 + tests/rustdoc-ui/bad-render-options.stderr | 144 --------- tests/rustdoc-ui/check-doc-alias-attr.stderr | 32 -- tests/rustdoc-ui/doc-cfg.stderr | 80 ----- tests/rustdoc-ui/invalid-cfg.stderr | 128 -------- tests/rustdoc-ui/lints/doc-attr.stderr | 48 --- .../ui/attributes/crate-type-delimited.stderr | 14 - tests/ui/attributes/crate-type-empty.stderr | 10 - .../attributes/crate-type-macro-call.stderr | 14 - tests/ui/attributes/doc-attr.stderr | 48 --- tests/ui/attributes/doc-test-literal.stderr | 16 - tests/ui/attributes/malformed-attrs.stderr | 62 ---- tests/ui/attributes/malformed-reprs.stderr | 11 - .../ui/deprecation/deprecation-sanity.stderr | 96 ------ tests/ui/error-codes/E0458.stderr | 15 - tests/ui/error-codes/E0565-1.stderr | 16 - tests/ui/issues/issue-43988.stderr | 22 -- tests/ui/link-native-libs/issue-43925.stderr | 15 - tests/ui/link-native-libs/issue-43926.stderr | 15 - .../link-attr-validation-early.stderr | 26 -- .../link-attr-validation-late.stderr | 279 ------------------ .../modifiers-override-4.stderr | 43 --- tests/ui/linkage-attr/linkage3.stderr | 16 - .../import-name-type-invalid-format.stderr | 15 - .../windows/import-name-type-multiple.stderr | 15 - .../import-name-type-unknown-value.stderr | 15 - .../ui/malformed/malformed-regressions.stderr | 26 -- tests/ui/repr/repr.stderr | 41 --- tests/ui/rustdoc/check-doc-alias-attr.stderr | 32 -- .../ui/sanitize-attr/invalid-sanitize.stderr | 76 ----- tests/ui/wasm/wasm-import-module.stderr | 45 --- 32 files changed, 19 insertions(+), 1425 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 7bb55d2a6de5b..2bbdb5c2590bf 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -769,16 +769,20 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.note(format!("for more information, visit <{link}>")); } - diag.span_suggestions( - self.attr_span, - if self.suggestions.len() == 1 { - "must be of the form".to_string() - } else { - format!("try changing it to one of the following valid forms of the {description}") - }, - self.suggestions, - Applicability::HasPlaceholders, - ); + if self.suggestions.len() < 4 { + diag.span_suggestions( + self.attr_span, + if self.suggestions.len() == 1 { + "must be of the form".to_string() + } else { + format!( + "try changing it to one of the following valid forms of the {description}" + ) + }, + self.suggestions, + Applicability::HasPlaceholders, + ); + } diag } diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index cd28677b6a8fd..e69ed0eea6b01 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -198,6 +198,11 @@ fn emit_malformed_attribute( suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); } } + // If there are too many suggestions, better remove all of them as it's just noise at this + // point. + if suggestions.len() > 3 { + suggestions.clear(); + } if should_warn(name) { psess.buffer_lint( ILL_FORMED_ATTRIBUTE_INPUT, diff --git a/tests/rustdoc-ui/bad-render-options.stderr b/tests/rustdoc-ui/bad-render-options.stderr index 296a41337f336..28d4533a6edba 100644 --- a/tests/rustdoc-ui/bad-render-options.stderr +++ b/tests/rustdoc-ui/bad-render-options.stderr @@ -5,22 +5,6 @@ LL | #![doc(html_favicon_url)] | ^^^^^^^----------------^^ | | | expected this to be of the form `html_favicon_url = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_favicon_url)] -LL + #![doc = "string"] - | -LL - #![doc(html_favicon_url)] -LL + #![doc(alias)] - | -LL - #![doc(html_favicon_url)] -LL + #![doc(attribute)] - | -LL - #![doc(html_favicon_url)] -LL + #![doc(auto_cfg)] - | - = and 21 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:6:1 @@ -29,22 +13,6 @@ LL | #![doc(html_logo_url)] | ^^^^^^^-------------^^ | | | expected this to be of the form `html_logo_url = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_logo_url)] -LL + #![doc = "string"] - | -LL - #![doc(html_logo_url)] -LL + #![doc(alias)] - | -LL - #![doc(html_logo_url)] -LL + #![doc(attribute)] - | -LL - #![doc(html_logo_url)] -LL + #![doc(auto_cfg)] - | - = and 21 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:9:1 @@ -53,22 +21,6 @@ LL | #![doc(html_playground_url)] | ^^^^^^^-------------------^^ | | | expected this to be of the form `html_playground_url = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_playground_url)] -LL + #![doc = "string"] - | -LL - #![doc(html_playground_url)] -LL + #![doc(alias)] - | -LL - #![doc(html_playground_url)] -LL + #![doc(attribute)] - | -LL - #![doc(html_playground_url)] -LL + #![doc(auto_cfg)] - | - = and 21 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:12:1 @@ -77,22 +29,6 @@ LL | #![doc(issue_tracker_base_url)] | ^^^^^^^----------------------^^ | | | expected this to be of the form `issue_tracker_base_url = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(issue_tracker_base_url)] -LL + #![doc = "string"] - | -LL - #![doc(issue_tracker_base_url)] -LL + #![doc(alias)] - | -LL - #![doc(issue_tracker_base_url)] -LL + #![doc(attribute)] - | -LL - #![doc(issue_tracker_base_url)] -LL + #![doc(auto_cfg)] - | - = and 21 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:15:1 @@ -101,22 +37,6 @@ LL | #![doc(html_favicon_url = 1)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_favicon_url = 1)] -LL + #![doc = "string"] - | -LL - #![doc(html_favicon_url = 1)] -LL + #![doc(alias)] - | -LL - #![doc(html_favicon_url = 1)] -LL + #![doc(attribute)] - | -LL - #![doc(html_favicon_url = 1)] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:18:1 @@ -125,22 +45,6 @@ LL | #![doc(html_logo_url = 2)] | ^^^^^^^^^^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_logo_url = 2)] -LL + #![doc = "string"] - | -LL - #![doc(html_logo_url = 2)] -LL + #![doc(alias)] - | -LL - #![doc(html_logo_url = 2)] -LL + #![doc(attribute)] - | -LL - #![doc(html_logo_url = 2)] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:21:1 @@ -149,22 +53,6 @@ LL | #![doc(html_playground_url = 3)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_playground_url = 3)] -LL + #![doc = "string"] - | -LL - #![doc(html_playground_url = 3)] -LL + #![doc(alias)] - | -LL - #![doc(html_playground_url = 3)] -LL + #![doc(attribute)] - | -LL - #![doc(html_playground_url = 3)] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:24:1 @@ -173,22 +61,6 @@ LL | #![doc(issue_tracker_base_url = 4)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(issue_tracker_base_url = 4)] -LL + #![doc = "string"] - | -LL - #![doc(issue_tracker_base_url = 4)] -LL + #![doc(alias)] - | -LL - #![doc(issue_tracker_base_url = 4)] -LL + #![doc(attribute)] - | -LL - #![doc(issue_tracker_base_url = 4)] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error[E0565]: malformed `doc` attribute input --> $DIR/bad-render-options.rs:27:1 @@ -197,22 +69,6 @@ LL | #![doc(html_no_source = "asdf")] | ^^^^^^^^^^^^^^^^^^^^^^--------^^ | | | didn't expect any arguments here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(html_no_source = "asdf")] -LL + #![doc = "string"] - | -LL - #![doc(html_no_source = "asdf")] -LL + #![doc(alias)] - | -LL - #![doc(html_no_source = "asdf")] -LL + #![doc(attribute)] - | -LL - #![doc(html_no_source = "asdf")] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error: aborting due to 9 previous errors diff --git a/tests/rustdoc-ui/check-doc-alias-attr.stderr b/tests/rustdoc-ui/check-doc-alias-attr.stderr index 6c33f10e87851..d9e785ee0f1fe 100644 --- a/tests/rustdoc-ui/check-doc-alias-attr.stderr +++ b/tests/rustdoc-ui/check-doc-alias-attr.stderr @@ -11,22 +11,6 @@ LL | #[doc(alias = 0)] | ^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(alias = 0)] -LL + #[doc = "string"] - | -LL - #[doc(alias = 0)] -LL + #[doc(alias)] - | -LL - #[doc(alias = 0)] -LL + #[doc(attribute)] - | -LL - #[doc(alias = 0)] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:9:15 @@ -79,22 +63,6 @@ LL | #[doc(alias(0))] | ^^^^^^^^^^^^-^^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(alias(0))] -LL + #[doc = "string"] - | -LL - #[doc(alias(0))] -LL + #[doc(alias)] - | -LL - #[doc(alias(0))] -LL + #[doc(attribute)] - | -LL - #[doc(alias(0))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:20:13 diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr index 0efeac66554c8..ce16ec31d8754 100644 --- a/tests/rustdoc-ui/doc-cfg.stderr +++ b/tests/rustdoc-ui/doc-cfg.stderr @@ -5,22 +5,6 @@ LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^--^^^^^^^^^^^^^^^^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:3:1 @@ -29,22 +13,6 @@ LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^^^^^^^^----------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(), cfg(foo, bar))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:6:1 @@ -53,22 +21,6 @@ LL | #[doc(cfg())] | ^^^^^^^^^--^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg())] -LL + #[doc = "string"] - | -LL - #[doc(cfg())] -LL + #[doc(alias)] - | -LL - #[doc(cfg())] -LL + #[doc(attribute)] - | -LL - #[doc(cfg())] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:7:1 @@ -77,22 +29,6 @@ LL | #[doc(cfg(foo, bar))] | ^^^^^^^^^----------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(foo, bar))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(foo, bar))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(foo, bar))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(foo, bar))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/doc-cfg.rs:8:1 @@ -101,22 +37,6 @@ LL | #[doc(auto_cfg(hide(foo::bar)))] | ^^^^^^^^^^^^^^^^^^^^--------^^^^ | | | expected a valid identifier here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(auto_cfg(hide(foo::bar)))] -LL + #[doc = "string"] - | -LL - #[doc(auto_cfg(hide(foo::bar)))] -LL + #[doc(alias)] - | -LL - #[doc(auto_cfg(hide(foo::bar)))] -LL + #[doc(attribute)] - | -LL - #[doc(auto_cfg(hide(foo::bar)))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: aborting due to 5 previous errors diff --git a/tests/rustdoc-ui/invalid-cfg.stderr b/tests/rustdoc-ui/invalid-cfg.stderr index 3363dbb56fb4f..84f8cea543145 100644 --- a/tests/rustdoc-ui/invalid-cfg.stderr +++ b/tests/rustdoc-ui/invalid-cfg.stderr @@ -3,22 +3,6 @@ error[E0539]: malformed `doc` attribute input | LL | #[doc(cfg = "x")] | ^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg = "x")] -LL + #[doc = "string"] - | -LL - #[doc(cfg = "x")] -LL + #[doc(alias)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(attribute)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:3:1 @@ -27,44 +11,12 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(x, y))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:7:1 | LL | #[doc(cfg = "x")] | ^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg = "x")] -LL + #[doc = "string"] - | -LL - #[doc(cfg = "x")] -LL + #[doc(alias)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(attribute)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:8:1 @@ -73,44 +25,12 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(x, y))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:12:1 | LL | #[doc(cfg = "x")] | ^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg = "x")] -LL + #[doc = "string"] - | -LL - #[doc(cfg = "x")] -LL + #[doc(alias)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(attribute)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:13:1 @@ -119,44 +39,12 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(x, y))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:18:1 | LL | #[doc(cfg = "x")] | ^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg = "x")] -LL + #[doc = "string"] - | -LL - #[doc(cfg = "x")] -LL + #[doc(alias)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(attribute)] - | -LL - #[doc(cfg = "x")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0805]: malformed `doc` attribute input --> $DIR/invalid-cfg.rs:19:1 @@ -165,22 +53,6 @@ LL | #[doc(cfg(x, y))] | ^^^^^^^^^------^^ | | | expected a single argument here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(cfg(x, y))] -LL + #[doc = "string"] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(alias)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(attribute)] - | -LL - #[doc(cfg(x, y))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: aborting due to 8 previous errors diff --git a/tests/rustdoc-ui/lints/doc-attr.stderr b/tests/rustdoc-ui/lints/doc-attr.stderr index 1201bd5c71f18..8f8c6000b3640 100644 --- a/tests/rustdoc-ui/lints/doc-attr.stderr +++ b/tests/rustdoc-ui/lints/doc-attr.stderr @@ -5,22 +5,6 @@ LL | #[doc(123)] | ^^^^^^---^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(123)] -LL + #[doc = "string"] - | -LL - #[doc(123)] -LL + #[doc(alias)] - | -LL - #[doc(123)] -LL + #[doc(attribute)] - | -LL - #[doc(123)] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/doc-attr.rs:5:1 @@ -29,22 +13,6 @@ LL | #[doc("hello", "bar")] | ^^^^^^-------^^^^^^^^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc("hello", "bar")] -LL + #[doc = "string"] - | -LL - #[doc("hello", "bar")] -LL + #[doc(alias)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(attribute)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/doc-attr.rs:5:1 @@ -53,22 +21,6 @@ LL | #[doc("hello", "bar")] | ^^^^^^^^^^^^^^^-----^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc("hello", "bar")] -LL + #[doc = "string"] - | -LL - #[doc("hello", "bar")] -LL + #[doc(alias)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(attribute)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/crate-type-delimited.stderr b/tests/ui/attributes/crate-type-delimited.stderr index 7f080f7483869..23234efe169f1 100644 --- a/tests/ui/attributes/crate-type-delimited.stderr +++ b/tests/ui/attributes/crate-type-delimited.stderr @@ -5,21 +5,7 @@ LL | #![crate_type(lib)] | ^^^^^^^^^^^^^^^^^^^ | = note: for more information, visit -help: the following are the possible correct uses | -LL - #![crate_type(lib)] -LL + #![crate_type = "bin"] - | -LL - #![crate_type(lib)] -LL + #![crate_type = "cdylib"] - | -LL - #![crate_type(lib)] -LL + #![crate_type = "dylib"] - | -LL - #![crate_type(lib)] -LL + #![crate_type = "lib"] - | - = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/crate-type-empty.stderr b/tests/ui/attributes/crate-type-empty.stderr index f50bb33d6bb01..c1d474d9f17ff 100644 --- a/tests/ui/attributes/crate-type-empty.stderr +++ b/tests/ui/attributes/crate-type-empty.stderr @@ -5,17 +5,7 @@ LL | #![crate_type] | ^^^^^^^^^^^^^^ | = note: for more information, visit -help: the following are the possible correct uses | -LL | #![crate_type = "bin"] - | +++++++ -LL | #![crate_type = "cdylib"] - | ++++++++++ -LL | #![crate_type = "dylib"] - | +++++++++ -LL | #![crate_type = "lib"] - | +++++++ - = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/crate-type-macro-call.stderr b/tests/ui/attributes/crate-type-macro-call.stderr index 97938f7af24e7..cd17b324041bd 100644 --- a/tests/ui/attributes/crate-type-macro-call.stderr +++ b/tests/ui/attributes/crate-type-macro-call.stderr @@ -5,21 +5,7 @@ LL | #![crate_type = foo!()] | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, visit -help: the following are the possible correct uses | -LL - #![crate_type = foo!()] -LL + #![crate_type = "bin"] - | -LL - #![crate_type = foo!()] -LL + #![crate_type = "cdylib"] - | -LL - #![crate_type = foo!()] -LL + #![crate_type = "dylib"] - | -LL - #![crate_type = foo!()] -LL + #![crate_type = "lib"] - | - = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/doc-attr.stderr b/tests/ui/attributes/doc-attr.stderr index 9234c1a0719b6..dfc0e8ad5b6f1 100644 --- a/tests/ui/attributes/doc-attr.stderr +++ b/tests/ui/attributes/doc-attr.stderr @@ -5,22 +5,6 @@ LL | #[doc(123)] | ^^^^^^---^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(123)] -LL + #[doc = "string"] - | -LL - #[doc(123)] -LL + #[doc(alias)] - | -LL - #[doc(123)] -LL + #[doc(attribute)] - | -LL - #[doc(123)] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/doc-attr.rs:11:1 @@ -29,22 +13,6 @@ LL | #[doc("hello", "bar")] | ^^^^^^-------^^^^^^^^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc("hello", "bar")] -LL + #[doc = "string"] - | -LL - #[doc("hello", "bar")] -LL + #[doc(alias)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(attribute)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error[E0539]: malformed `doc` attribute input --> $DIR/doc-attr.rs:11:1 @@ -53,22 +21,6 @@ LL | #[doc("hello", "bar")] | ^^^^^^^^^^^^^^^-----^^ | | | expected this to be of the form `... = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc("hello", "bar")] -LL + #[doc = "string"] - | -LL - #[doc("hello", "bar")] -LL + #[doc(alias)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(attribute)] - | -LL - #[doc("hello", "bar")] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:5:7 diff --git a/tests/ui/attributes/doc-test-literal.stderr b/tests/ui/attributes/doc-test-literal.stderr index 3ffbdcbb9fee7..2d70d5d206f07 100644 --- a/tests/ui/attributes/doc-test-literal.stderr +++ b/tests/ui/attributes/doc-test-literal.stderr @@ -5,22 +5,6 @@ LL | #![doc(test(""))] | ^^^^^^^^^^^^--^^^ | | | didn't expect a literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #![doc(test(""))] -LL + #![doc = "string"] - | -LL - #![doc(test(""))] -LL + #![doc(alias)] - | -LL - #![doc(test(""))] -LL + #![doc(attribute)] - | -LL - #![doc(test(""))] -LL + #![doc(auto_cfg)] - | - = and 22 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index a6bd62fa1214e..e1ebe4ac9eab4 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -240,22 +240,6 @@ LL | #[deprecated = 5] | ^^^^^^^^^^^^^^^-^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated = 5] -LL + #[deprecated = "reason"] - | -LL - #[deprecated = 5] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated = 5] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated = 5] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error[E0539]: malformed `rustc_macro_transparency` attribute input --> $DIR/malformed-attrs.rs:44:1 @@ -287,17 +271,6 @@ LL | #[repr] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[repr()] - | ++++++++++++++++ -LL | #[repr(C)] - | +++ -LL | #[repr(Rust)] - | ++++++ -LL | #[repr(align(...))] - | ++++++++++++ - = and 2 other candidates error[E0565]: malformed `rustc_as_ptr` attribute input --> $DIR/malformed-attrs.rs:50:1 @@ -437,17 +410,6 @@ LL | #[link] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[link(name = "...")] - | ++++++++++++++ -LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...")] - | +++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - = and 1 other candidate error[E0539]: malformed `link_name` attribute input --> $DIR/malformed-attrs.rs:88:1 @@ -483,18 +445,6 @@ error[E0539]: malformed `sanitize` attribute input | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL | #[sanitize(address = "on|off")] - | ++++++++++++++++++++ -LL | #[sanitize(cfi = "on|off")] - | ++++++++++++++++ -LL | #[sanitize(hwaddress = "on|off")] - | ++++++++++++++++++++++ -LL | #[sanitize(kcfi = "on|off")] - | +++++++++++++++++ - = and 6 other candidates error[E0565]: malformed `no_implicit_prelude` attribute input --> $DIR/malformed-attrs.rs:101:1 @@ -634,18 +584,6 @@ error[E0539]: malformed `linkage` attribute input | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL | #[linkage = "available_externally"] - | ++++++++++++++++++++++++ -LL | #[linkage = "common"] - | ++++++++++ -LL | #[linkage = "extern_weak"] - | +++++++++++++++ -LL | #[linkage = "external"] - | ++++++++++++ - = and 5 other candidates error[E0539]: malformed `debugger_visualizer` attribute input --> $DIR/malformed-attrs.rs:194:1 diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr index 3a788999542b4..504ba91aac5f5 100644 --- a/tests/ui/attributes/malformed-reprs.stderr +++ b/tests/ui/attributes/malformed-reprs.stderr @@ -5,17 +5,6 @@ LL | #![repr] | ^^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #![repr()] - | ++++++++++++++++ -LL | #![repr(C)] - | +++ -LL | #![repr(Rust)] - | ++++++ -LL | #![repr(align(...))] - | ++++++++++++ - = and 2 other candidates error[E0589]: invalid `repr(align)` attribute: not a power of two --> $DIR/malformed-reprs.rs:9:14 diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index 48d08b18f8bda..a96d4a0bdea88 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -11,22 +11,6 @@ LL | #[deprecated(since = "a", note)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^^ | | | expected this to be of the form `note = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated(since = "a", note)] -LL + #[deprecated = "reason"] - | -LL - #[deprecated(since = "a", note)] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated(since = "a", note)] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated(since = "a", note)] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:12:5 @@ -35,22 +19,6 @@ LL | #[deprecated(since, note = "a")] | ^^^^^^^^^^^^^-----^^^^^^^^^^^^^^ | | | expected this to be of the form `since = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated(since, note = "a")] -LL + #[deprecated = "reason"] - | -LL - #[deprecated(since, note = "a")] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated(since, note = "a")] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated(since, note = "a")] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:15:5 @@ -59,22 +27,6 @@ LL | #[deprecated(since = "a", note(b))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ | | | expected this to be of the form `note = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated = "reason"] - | -LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:18:5 @@ -83,22 +35,6 @@ LL | #[deprecated(since(b), note = "a")] | ^^^^^^^^^^^^^--------^^^^^^^^^^^^^^ | | | expected this to be of the form `since = "..."` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated = "reason"] - | -LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:21:5 @@ -117,22 +53,6 @@ LL | #[deprecated("test")] | ^^^^^^^^^^^^^------^^ | | | didn't expect a literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated("test")] -LL + #[deprecated = "reason"] - | -LL - #[deprecated("test")] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated("test")] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated("test")] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error: multiple `deprecated` attributes --> $DIR/deprecation-sanity.rs:29:1 @@ -153,22 +73,6 @@ LL | #[deprecated(since = "a", since = "b", note = "c")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^ | | | found `since` used as a key more than once - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated = "reason"] - | -LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error: `#[deprecated]` attribute cannot be used on trait impl blocks --> $DIR/deprecation-sanity.rs:37:1 diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr index 524765ea12a1f..e56c9473d287e 100644 --- a/tests/ui/error-codes/E0458.stderr +++ b/tests/ui/error-codes/E0458.stderr @@ -7,21 +7,6 @@ LL | #[link(kind = "wonderful_unicorn")] extern "C" {} | valid arguments are "static", "dylib", "framework", "raw-dylib" or "link-arg" | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(kind = "wonderful_unicorn")] extern "C" {} -LL + #[link(name = "...")] extern "C" {} - | -LL - #[link(kind = "wonderful_unicorn")] extern "C" {} -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {} - | -LL - #[link(kind = "wonderful_unicorn")] extern "C" {} -LL + #[link(name = "...", kind = "dylib|static|...")] extern "C" {} - | -LL - #[link(kind = "wonderful_unicorn")] extern "C" {} -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {} - | - = and 1 other candidate error[E0459]: `#[link]` attribute requires a `name = "string"` argument --> $DIR/E0458.rs:1:1 diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr index 52daf2a62fcd5..d1aff042e8fb6 100644 --- a/tests/ui/error-codes/E0565-1.stderr +++ b/tests/ui/error-codes/E0565-1.stderr @@ -5,22 +5,6 @@ LL | #[deprecated("since")] | ^^^^^^^^^^^^^-------^^ | | | didn't expect a literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[deprecated("since")] -LL + #[deprecated = "reason"] - | -LL - #[deprecated("since")] -LL + #[deprecated(note = "reason")] - | -LL - #[deprecated("since")] -LL + #[deprecated(since = "version")] - | -LL - #[deprecated("since")] -LL + #[deprecated(since = "version", note = "reason")] - | - = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index 0219eeb693e73..d393255e0ee1d 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -60,17 +60,6 @@ LL | #[repr] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[repr()] - | ++++++++++++++++ -LL | #[repr(C)] - | +++ -LL | #[repr(Rust)] - | ++++++ -LL | #[repr(align(...))] - | ++++++++++++ - = and 2 other candidates error[E0539]: malformed `inline` attribute input --> $DIR/issue-43988.rs:31:5 @@ -108,17 +97,6 @@ LL | let _z = #[repr] 1; | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | let _z = #[repr()] 1; - | ++++++++++++++++ -LL | let _z = #[repr(C)] 1; - | +++ -LL | let _z = #[repr(Rust)] 1; - | ++++++ -LL | let _z = #[repr(align(...))] 1; - | ++++++++++++ - = and 2 other candidates error: aborting due to 9 previous errors diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr index 68a020546c14e..fdc644ed6469c 100644 --- a/tests/ui/link-native-libs/issue-43925.stderr +++ b/tests/ui/link-native-libs/issue-43925.stderr @@ -16,21 +16,6 @@ LL | #[link(name = "foo", cfg("rlib"))] | expected a valid identifier here | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", cfg("rlib"))] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", cfg("rlib"))] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", cfg("rlib"))] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", cfg("rlib"))] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 2 previous errors diff --git a/tests/ui/link-native-libs/issue-43926.stderr b/tests/ui/link-native-libs/issue-43926.stderr index 9e3ec21cc9454..f7b85788a2a30 100644 --- a/tests/ui/link-native-libs/issue-43926.stderr +++ b/tests/ui/link-native-libs/issue-43926.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "foo", cfg())] | expected a single argument here | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", cfg())] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", cfg())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", cfg())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", cfg())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr index e4799b1a16180..101df0371b542 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr @@ -5,17 +5,6 @@ LL | #[link] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[link(name = "...")] - | ++++++++++++++ -LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...")] - | +++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-early.rs:3:1 @@ -24,21 +13,6 @@ LL | #[link = "foo"] | ^^^^^^^^^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link = "foo"] -LL + #[link(name = "...")] - | -LL - #[link = "foo"] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link = "foo"] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link = "foo"] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 2 previous errors diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index 106b7cebc99f7..a5f654ca0aeb5 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "...", "literal")] | didn't expect a literal here | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", "literal")] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", "literal")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", "literal")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", "literal")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:5:1 @@ -32,21 +17,6 @@ LL | #[link(name = "...", unknown)] | valid arguments are "name", "kind", "modifiers", "cfg", "wasm_import_module" or "import_name_type" | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", unknown)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", unknown)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", unknown)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", unknown)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0538]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:9:1 @@ -57,21 +27,6 @@ LL | #[link(name = "foo", name = "bar")] | found `name` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", name = "bar")] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", name = "bar")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", name = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", name = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0538]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:10:1 @@ -82,21 +37,6 @@ LL | #[link(name = "...", kind = "dylib", kind = "bar")] | found `kind` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", kind = "dylib", kind = "bar")] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", kind = "dylib", kind = "bar")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", kind = "dylib", kind = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", kind = "dylib", kind = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0538]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:11:1 @@ -107,21 +47,6 @@ LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] | found `modifiers` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0538]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:12:1 @@ -132,21 +57,6 @@ LL | #[link(name = "...", cfg(false), cfg(false))] | found `cfg` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", cfg(false), cfg(false))] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", cfg(false), cfg(false))] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", cfg(false), cfg(false))] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", cfg(false), cfg(false))] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0538]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:13:1 @@ -157,21 +67,6 @@ LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")] | found `wasm_import_module` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] -LL + #[link(name = "...")] - | -LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:17:1 @@ -182,17 +77,6 @@ LL | #[link(name)] | expected this to be of the form `name = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[link(name = "...")] - | +++++++ -LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...")] - | ++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:18:1 @@ -203,21 +87,6 @@ LL | #[link(name())] | expected this to be of the form `name = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name())] -LL + #[link(name = "...")] - | -LL - #[link(name())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:19:1 @@ -228,19 +97,6 @@ LL | #[link(name = "...", kind)] | expected this to be of the form `kind = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", kind)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", kind)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL | #[link(name = "...", kind = "dylib|static|...")] - | ++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:20:1 @@ -251,21 +107,6 @@ LL | #[link(name = "...", kind())] | expected this to be of the form `kind = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", kind())] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", kind())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", kind())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", kind())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:21:1 @@ -276,21 +117,6 @@ LL | #[link(name = "...", modifiers)] | expected this to be of the form `modifiers = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", modifiers)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", modifiers)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", modifiers)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", modifiers)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:22:1 @@ -301,21 +127,6 @@ LL | #[link(name = "...", modifiers())] | expected this to be of the form `modifiers = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", modifiers())] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", modifiers())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", modifiers())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", modifiers())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:23:1 @@ -326,21 +137,6 @@ LL | #[link(name = "...", cfg)] | expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", cfg)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", cfg)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", cfg)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", cfg)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:24:1 @@ -351,21 +147,6 @@ LL | #[link(name = "...", cfg = "literal")] | expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", cfg = "literal")] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", cfg = "literal")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", cfg = "literal")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", cfg = "literal")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:25:1 @@ -376,21 +157,6 @@ LL | #[link(name = "...", cfg("literal"))] | expected a valid identifier here | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", cfg("literal"))] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", cfg("literal"))] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", cfg("literal"))] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", cfg("literal"))] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:26:1 @@ -401,21 +167,6 @@ LL | #[link(name = "...", wasm_import_module)] | expected this to be of the form `wasm_import_module = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:27:1 @@ -426,21 +177,6 @@ LL | #[link(name = "...", wasm_import_module())] | expected this to be of the form `wasm_import_module = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed --> $DIR/link-attr-validation-late.rs:31:34 @@ -463,21 +199,6 @@ LL | #[link(name = "...", modifiers = "+unknown")] | valid arguments are "bundle", "verbatim", "whole-archive" or "as-needed" | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", modifiers = "+unknown")] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", modifiers = "+unknown")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", modifiers = "+unknown")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", modifiers = "+unknown")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: multiple `verbatim` modifiers in a single `modifiers` argument --> $DIR/link-attr-validation-late.rs:34:34 diff --git a/tests/ui/link-native-libs/modifiers-override-4.stderr b/tests/ui/link-native-libs/modifiers-override-4.stderr index 317e89cb39cc8..12b0d89c79a7f 100644 --- a/tests/ui/link-native-libs/modifiers-override-4.stderr +++ b/tests/ui/link-native-libs/modifiers-override-4.stderr @@ -12,49 +12,6 @@ LL | | )] | |__^ | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link( -LL - -LL - name = "bar", -LL - kind = "static", -LL - modifiers = "+whole-archive,-whole-archive", -LL - -LL - modifiers = "+bundle" -LL - )] -LL + #[link(name = "...")] - | -LL - #[link( -LL - -LL - name = "bar", -LL - kind = "static", -LL - modifiers = "+whole-archive,-whole-archive", -LL - -LL - modifiers = "+bundle" -LL - )] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link( -LL - -LL - name = "bar", -LL - kind = "static", -LL - modifiers = "+whole-archive,-whole-archive", -LL - -LL - modifiers = "+bundle" -LL - )] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link( -LL - -LL - name = "bar", -LL - kind = "static", -LL - modifiers = "+whole-archive,-whole-archive", -LL - -LL - modifiers = "+bundle" -LL - )] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: multiple `whole-archive` modifiers in a single `modifiers` argument --> $DIR/modifiers-override-4.rs:6:17 diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index f1215f09aeafc..564090e9538f0 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -5,22 +5,6 @@ LL | #[linkage = "foo"] | ^^^^^^^^^^^^-----^ | | | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[linkage = "foo"] -LL + #[linkage = "available_externally"] - | -LL - #[linkage = "foo"] -LL + #[linkage = "common"] - | -LL - #[linkage = "foo"] -LL + #[linkage = "extern_weak"] - | -LL - #[linkage = "foo"] -LL + #[linkage = "external"] - | - = and 5 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr index 6b54f3b247d1c..86a53a030f50c 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] | expected this to be of the form `import_name_type = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr index 35ddb2a7e3d36..ef909ad7278b7 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", im | found `import_name_type` used as a key more than once | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr index b0099675dd23d..577ec8e7764c3 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] | valid arguments are "decorated", "noprefix" or "undecorated" | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] -LL + #[link(name = "...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 29734fd84e6ba..f46afda1e4772 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -5,17 +5,6 @@ LL | #[link] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[link(name = "...")] - | ++++++++++++++ -LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...")] - | +++++++++++++++++++++++++++++++++++++++++ -LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/malformed-regressions.rs:10:1 @@ -24,21 +13,6 @@ LL | #[link = ""] | ^^^^^^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link = ""] -LL + #[link(name = "...")] - | -LL - #[link = ""] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link = ""] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link = ""] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/malformed-regressions.rs:7:1 diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr index d4faea1251762..e8168f8f9a582 100644 --- a/tests/ui/repr/repr.stderr +++ b/tests/ui/repr/repr.stderr @@ -5,17 +5,6 @@ LL | #[repr] | ^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL | #[repr()] - | ++++++++++++++++ -LL | #[repr(C)] - | +++ -LL | #[repr(Rust)] - | ++++++ -LL | #[repr(align(...))] - | ++++++++++++ - = and 2 other candidates error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:4:1 @@ -24,21 +13,6 @@ LL | #[repr = "B"] | ^^^^^^^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[repr = "B"] -LL + #[repr()] - | -LL - #[repr = "B"] -LL + #[repr(C)] - | -LL - #[repr = "B"] -LL + #[repr(Rust)] - | -LL - #[repr = "B"] -LL + #[repr(align(...))] - | - = and 2 other candidates error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:7:1 @@ -47,21 +21,6 @@ LL | #[repr = "C"] | ^^^^^^^^^^^^^ expected this to be a list | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[repr = "C"] -LL + #[repr()] - | -LL - #[repr = "C"] -LL + #[repr(C)] - | -LL - #[repr = "C"] -LL + #[repr(Rust)] - | -LL - #[repr = "C"] -LL + #[repr(align(...))] - | - = and 2 other candidates error: aborting due to 3 previous errors diff --git a/tests/ui/rustdoc/check-doc-alias-attr.stderr b/tests/ui/rustdoc/check-doc-alias-attr.stderr index 6c33f10e87851..d9e785ee0f1fe 100644 --- a/tests/ui/rustdoc/check-doc-alias-attr.stderr +++ b/tests/ui/rustdoc/check-doc-alias-attr.stderr @@ -11,22 +11,6 @@ LL | #[doc(alias = 0)] | ^^^^^^^^^^^^^^-^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(alias = 0)] -LL + #[doc = "string"] - | -LL - #[doc(alias = 0)] -LL + #[doc(alias)] - | -LL - #[doc(alias = 0)] -LL + #[doc(attribute)] - | -LL - #[doc(alias = 0)] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:9:15 @@ -79,22 +63,6 @@ LL | #[doc(alias(0))] | ^^^^^^^^^^^^-^^^ | | | expected a string literal here - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[doc(alias(0))] -LL + #[doc = "string"] - | -LL - #[doc(alias(0))] -LL + #[doc(alias)] - | -LL - #[doc(alias(0))] -LL + #[doc(attribute)] - | -LL - #[doc(alias(0))] -LL + #[doc(auto_cfg)] - | - = and 22 other candidates error: '"' character isn't allowed in `#[doc(alias = "...")]` --> $DIR/check-doc-alias-attr.rs:20:13 diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr index 9c1a6e5c45285..2a3497678bdca 100644 --- a/tests/ui/sanitize-attr/invalid-sanitize.stderr +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -5,22 +5,6 @@ LL | #[sanitize(brontosaurus = "off")] | ^^^^^^^^^^^------------^^^^^^^^^^ | | | valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime" - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[sanitize(brontosaurus = "off")] -LL + #[sanitize(address = "on|off")] - | -LL - #[sanitize(brontosaurus = "off")] -LL + #[sanitize(cfi = "on|off")] - | -LL - #[sanitize(brontosaurus = "off")] -LL + #[sanitize(hwaddress = "on|off")] - | -LL - #[sanitize(brontosaurus = "off")] -LL + #[sanitize(kcfi = "on|off")] - | - = and 6 other candidates error: multiple `sanitize` attributes --> $DIR/invalid-sanitize.rs:7:1 @@ -53,62 +37,18 @@ LL | #[sanitize(address = "bogus")] | ^^^^^^^^^^^^^^^^^^^^^-------^^ | | | valid arguments are "on" or "off" - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[sanitize(address = "bogus")] -LL + #[sanitize(address = "on|off")] - | -LL - #[sanitize(address = "bogus")] -LL + #[sanitize(cfi = "on|off")] - | -LL - #[sanitize(address = "bogus")] -LL + #[sanitize(hwaddress = "on|off")] - | -LL - #[sanitize(address = "bogus")] -LL + #[sanitize(kcfi = "on|off")] - | - = and 6 other candidates error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:18:1 | LL | #[sanitize = "off"] | ^^^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[sanitize = "off"] -LL + #[sanitize(address = "on|off")] - | -LL - #[sanitize = "off"] -LL + #[sanitize(cfi = "on|off")] - | -LL - #[sanitize = "off"] -LL + #[sanitize(hwaddress = "on|off")] - | -LL - #[sanitize = "off"] -LL + #[sanitize(kcfi = "on|off")] - | - = and 6 other candidates error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:21:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list - | -help: try changing it to one of the following valid forms of the attribute - | -LL | #[sanitize(address = "on|off")] - | ++++++++++++++++++++ -LL | #[sanitize(cfi = "on|off")] - | ++++++++++++++++ -LL | #[sanitize(hwaddress = "on|off")] - | ++++++++++++++++++++++ -LL | #[sanitize(kcfi = "on|off")] - | +++++++++++++++++ - = and 6 other candidates error[E0539]: malformed `sanitize` attribute input --> $DIR/invalid-sanitize.rs:24:1 @@ -117,22 +57,6 @@ LL | #[sanitize(realtime = "on")] | ^^^^^^^^^^^^^^^^^^^^^^----^^ | | | valid arguments are "nonblocking", "blocking" or "caller" - | -help: try changing it to one of the following valid forms of the attribute - | -LL - #[sanitize(realtime = "on")] -LL + #[sanitize(address = "on|off")] - | -LL - #[sanitize(realtime = "on")] -LL + #[sanitize(cfi = "on|off")] - | -LL - #[sanitize(realtime = "on")] -LL + #[sanitize(hwaddress = "on|off")] - | -LL - #[sanitize(realtime = "on")] -LL + #[sanitize(kcfi = "on|off")] - | - = and 6 other candidates warning: the async executor can run blocking code, without realtime sanitizer catching it --> $DIR/invalid-sanitize.rs:27:1 diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr index f5ea449839bb6..6171f04f862cc 100644 --- a/tests/ui/wasm/wasm-import-module.stderr +++ b/tests/ui/wasm/wasm-import-module.stderr @@ -7,21 +7,6 @@ LL | #[link(name = "...", wasm_import_module)] | expected this to be of the form `wasm_import_module = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", wasm_import_module)] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/wasm-import-module.rs:6:1 @@ -32,21 +17,6 @@ LL | #[link(name = "...", wasm_import_module(x))] | expected this to be of the form `wasm_import_module = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", wasm_import_module(x))] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", wasm_import_module(x))] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", wasm_import_module(x))] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", wasm_import_module(x))] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/wasm-import-module.rs:9:1 @@ -57,21 +27,6 @@ LL | #[link(name = "...", wasm_import_module())] | expected this to be of the form `wasm_import_module = "..."` | = note: for more information, visit -help: try changing it to one of the following valid forms of the attribute - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", kind = "dylib|static|...")] - | -LL - #[link(name = "...", wasm_import_module())] -LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] - | - = and 1 other candidate error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes --> $DIR/wasm-import-module.rs:12:8