From a264bff9d557e9fc468c9fefeabc0c09d4eeea6f Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 18 Jun 2024 15:56:34 +0800 Subject: [PATCH 01/53] Mark assoc tys live only if the trait is live --- compiler/rustc_passes/src/dead.rs | 41 +++++++++++-------- .../ui/const-generics/cross_crate_complex.rs | 1 + .../missing-bounds.fixed | 4 ++ .../missing-bounds.rs | 4 ++ .../missing-bounds.stderr | 18 ++++---- .../dead-code/unused-trait-with-assoc-ty.rs | 11 +++++ .../unused-trait-with-assoc-ty.stderr | 20 +++++++++ tests/ui/pattern/issue-22546.rs | 2 +- tests/ui/pattern/issue-22546.stderr | 10 ----- 9 files changed, 75 insertions(+), 36 deletions(-) create mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs create mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr delete mode 100644 tests/ui/pattern/issue-22546.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 6a74ddc5508a..7c8c1d251ae0 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -156,7 +156,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { + Res::Def( + DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias, + def_id, + ) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -442,7 +445,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} - hir::ItemKind::Trait(..) => { + hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => { for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { if let Some(local_def_id) = impl_def_id.as_local() && let ItemKind::Impl(impl_ref) = @@ -455,7 +458,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); } } - + // mark assoc ty live if the trait is live + for trait_item in trait_item_refs { + if let hir::AssocItemKind::Type = trait_item.kind { + self.check_def_id(trait_item.id.owner_id.to_def_id()); + } + } intravisit::walk_item(self, item) } _ => intravisit::walk_item(self, item), @@ -472,9 +480,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let ItemKind::Impl(impl_ref) = self.tcx.hir().expect_item(local_impl_id).kind { - if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) - && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - .ty_and_all_fields_are_public + if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) + .ty_and_all_fields_are_public { // skip impl-items of non pure pub ty, // cause we don't know the ty is constructed or not, @@ -813,9 +820,8 @@ fn check_item<'tcx>( // for trait impl blocks, // mark the method live if the self_ty is public, // or the method is public and may construct self - if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy) - || tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + if tcx.visibility(local_def_id).is_public() + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, @@ -852,10 +858,13 @@ fn check_trait_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::TraitItemId, ) { - use hir::TraitItemKind::{Const, Fn}; - if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { + use hir::TraitItemKind::{Const, Fn, Type}; + if matches!( + tcx.def_kind(id.owner_id), + DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn + ) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) + if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -897,7 +906,7 @@ fn create_and_seed_worklist( // checks impls, impl-items and pub structs with all public fields later match tcx.def_kind(id) { DefKind::Impl { .. } => false, - DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), + DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) @@ -1132,6 +1141,7 @@ impl<'tcx> DeadVisitor<'tcx> { } match self.tcx.def_kind(def_id) { DefKind::AssocConst + | DefKind::AssocTy | DefKind::AssocFn | DefKind::Fn | DefKind::Static { .. } @@ -1173,15 +1183,14 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused assoc consts and fns in traits + // We have diagnosed unused assocs in traits if matches!(def_kind, DefKind::Impl { of_trait: true }) - && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn) + && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn) // skip unused public inherent methods, // cause we have diagnosed unconstructed struct || matches!(def_kind, DefKind::Impl { of_trait: false }) && tcx.visibility(def_id).is_public() && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public - || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy { continue; } diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs index d13b69aa0cfb..b44d889f5e99 100644 --- a/tests/ui/const-generics/cross_crate_complex.rs +++ b/tests/ui/const-generics/cross_crate_complex.rs @@ -11,6 +11,7 @@ async fn foo() { async_in_foo(async_out_foo::<4>().await).await; } +#[allow(dead_code)] struct Faz; impl Foo for Faz {} diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed index 703d3c1e0fb1..ff69016d8626 100644 --- a/tests/ui/generic-associated-types/missing-bounds.fixed +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -2,6 +2,7 @@ use std::ops::Add; +#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -12,6 +13,7 @@ impl Add for A where B: Add { } } +#[allow(dead_code)] struct C(B); impl> Add for C { @@ -22,6 +24,7 @@ impl> Add for C { } } +#[allow(dead_code)] struct D(B); impl> Add for D { @@ -32,6 +35,7 @@ impl> Add for D { } } +#[allow(dead_code)] struct E(B); impl> Add for E where B: Add { diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs index f40b42288731..1f83356c2fa6 100644 --- a/tests/ui/generic-associated-types/missing-bounds.rs +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -2,6 +2,7 @@ use std::ops::Add; +#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -12,6 +13,7 @@ impl Add for A where B: Add { } } +#[allow(dead_code)] struct C(B); impl Add for C { @@ -22,6 +24,7 @@ impl Add for C { } } +#[allow(dead_code)] struct D(B); impl Add for D { @@ -32,6 +35,7 @@ impl Add for D { } } +#[allow(dead_code)] struct E(B); impl Add for E where ::Output = B { diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 1d7d80d1b076..0f0dc24c06c0 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -1,5 +1,5 @@ error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:37:33 + --> $DIR/missing-bounds.rs:41:33 | LL | impl Add for E where ::Output = B { | ^^^^^^^^^^^^^^^^^^^^^^ not supported @@ -11,7 +11,7 @@ LL | impl Add for E where B: Add { | ~~~~~~~~~~~~~~~~~~ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:11:11 + --> $DIR/missing-bounds.rs:12:11 | LL | impl Add for A where B: Add { | - expected this type parameter @@ -24,14 +24,14 @@ LL | A(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` help: the type constructed contains `::Output` due to the type of the argument passed - --> $DIR/missing-bounds.rs:11:9 + --> $DIR/missing-bounds.rs:12:9 | LL | A(self.0 + rhs.0) | ^^--------------^ | | | this argument influences the type of `A` note: tuple struct defined here - --> $DIR/missing-bounds.rs:5:8 + --> $DIR/missing-bounds.rs:6:8 | LL | struct A(B); | ^ @@ -41,7 +41,7 @@ LL | impl Add for A where B: Add { | ++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:21:14 + --> $DIR/missing-bounds.rs:23:14 | LL | impl Add for C { | - expected this type parameter @@ -54,7 +54,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:15:8 + --> $DIR/missing-bounds.rs:17:8 | LL | struct C(B); | ^ @@ -64,7 +64,7 @@ LL | impl> Add for C { | ++++++++++++ error[E0369]: cannot add `B` to `B` - --> $DIR/missing-bounds.rs:31:21 + --> $DIR/missing-bounds.rs:34:21 | LL | Self(self.0 + rhs.0) | ------ ^ ----- B @@ -77,7 +77,7 @@ LL | impl> Add for D { | +++++++++++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:42:14 + --> $DIR/missing-bounds.rs:46:14 | LL | impl Add for E where ::Output = B { | - expected this type parameter @@ -90,7 +90,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:35:8 + --> $DIR/missing-bounds.rs:39:8 | LL | struct E(B); | ^ diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs new file mode 100644 index 000000000000..e8116d83ebf1 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs @@ -0,0 +1,11 @@ +#![deny(dead_code)] + +struct T1; //~ ERROR struct `T1` is never constructed + +trait Foo { type Unused; } //~ ERROR trait `Foo` is never used +impl Foo for T1 { type Unused = Self; } + +pub trait Bar { type Used; } +impl Bar for T1 { type Used = Self; } + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr new file mode 100644 index 000000000000..ab73c6406343 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr @@ -0,0 +1,20 @@ +error: struct `T1` is never constructed + --> $DIR/unused-trait-with-assoc-ty.rs:3:8 + | +LL | struct T1; + | ^^ + | +note: the lint level is defined here + --> $DIR/unused-trait-with-assoc-ty.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: trait `Foo` is never used + --> $DIR/unused-trait-with-assoc-ty.rs:5:7 + | +LL | trait Foo { type Unused; } + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index fd1d5fb6c477..d5c5b68be78d 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl Foo { } } -trait Tr { //~ WARN trait `Tr` is never used +trait Tr { type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr deleted file mode 100644 index e067a95e4226..000000000000 --- a/tests/ui/pattern/issue-22546.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: trait `Tr` is never used - --> $DIR/issue-22546.rs:18:7 - | -LL | trait Tr { - | ^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - From dd557d8c3720c82c488d6e2af3b7e19025f2473a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Jun 2024 12:04:59 -0400 Subject: [PATCH 02/53] Add a test demonstrating that RPITITs cant use precise capturing --- .../ui/impl-trait/precise-capturing/rpitit.rs | 21 ++++++++++ .../precise-capturing/rpitit.stderr | 42 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit.rs create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit.stderr diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs new file mode 100644 index 000000000000..4eb053573e1f --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -0,0 +1,21 @@ +//@ known-bug: unknown + +// RPITITs don't have variances in their GATs, so they always relate invariantly +// and act as if they capture all their args. +// To fix this soundly, we need to make sure that all the trait header args +// remain captured, since they affect trait selection. + +#![feature(precise_capturing)] + +trait Foo<'a> { + fn hello() -> impl PartialEq + use; +} + +fn test<'a, 'b, T: for<'r> Foo<'r>>() { + PartialEq::eq( + &>::hello(), + &>::hello(), + ); +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr new file mode 100644 index 000000000000..202eeb39385d --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -0,0 +1,42 @@ +error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + --> $DIR/rpitit.rs:11:19 + | +LL | trait Foo<'a> { + | -- this lifetime parameter is captured +LL | fn hello() -> impl PartialEq + use; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` + +error: lifetime may not live long enough + --> $DIR/rpitit.rs:15:5 + | +LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / PartialEq::eq( +LL | | &>::hello(), +LL | | &>::hello(), +LL | | ); + | |_____^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/rpitit.rs:15:5 + | +LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / PartialEq::eq( +LL | | &>::hello(), +LL | | &>::hello(), +LL | | ); + | |_____^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 3 previous errors + From 594fa01aba7aa48990ffb673eb6d46be239f0193 Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 23 Jun 2024 23:44:22 +0800 Subject: [PATCH 03/53] not use offset when there is not ends with brace --- compiler/rustc_hir_analysis/src/check/mod.rs | 17 +++++++--- .../missing-impl-trait-block-but-not-ascii.rs | 13 ++++++++ ...sing-impl-trait-block-but-not-ascii.stderr | 31 +++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.rs create mode 100644 tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.stderr diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 4d1b96d9c1ba..8469cbbbc7d6 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -211,11 +211,18 @@ fn missing_items_err( .collect::>() .join("`, `"); - // `Span` before impl block closing brace. - let hi = full_impl_span.hi() - BytePos(1); - // Point at the place right before the closing brace of the relevant `impl` to suggest - // adding the associated item at the end of its body. - let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi); + let sugg_sp = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(full_impl_span) + && snippet.ends_with("}") + { + // `Span` before impl block closing brace. + let hi = full_impl_span.hi() - BytePos(1); + // Point at the place right before the closing brace of the relevant `impl` to suggest + // adding the associated item at the end of its body. + full_impl_span.with_lo(hi).with_hi(hi) + } else { + full_impl_span.shrink_to_hi() + }; + // Obtain the level of indentation ending in `sugg_sp`. let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new()); diff --git a/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.rs b/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.rs new file mode 100644 index 000000000000..ddb6bd1e9020 --- /dev/null +++ b/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.rs @@ -0,0 +1,13 @@ +// issue#126764 + +struct S; + +trait T { + fn f(); +} +impl T for S; +//~^ ERROR: unknown start of token +//~| ERROR: expected `{}` +//~| ERROR: not all trait items implemented, missing: `f` + +fn main() {} diff --git a/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.stderr b/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.stderr new file mode 100644 index 000000000000..56cdc11b62e6 --- /dev/null +++ b/tests/ui/suggestions/missing-impl-trait-block-but-not-ascii.stderr @@ -0,0 +1,31 @@ +error: unknown start of token: \u{ff1b} + --> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:13 + | +LL | impl T for S; + | ^^ + | +help: Unicode character ';' (Fullwidth Semicolon) looks like ';' (Semicolon), but it is not + | +LL | impl T for S; + | ~ + +error: expected `{}`, found `;` + --> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:13 + | +LL | impl T for S; + | ^^ + | + = help: try using `{}` instead + +error[E0046]: not all trait items implemented, missing: `f` + --> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:1 + | +LL | fn f(); + | ------- `f` from trait +LL | } +LL | impl T for S; + | ^^^^^^^^^^^^ missing `f` in implementation + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0046`. From 8cfd4b180b33695a2e24e74ce4864b3b4bf6a302 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 23 Jun 2024 18:29:51 -0700 Subject: [PATCH 04/53] Unify the precedence level for PREC_POSTFIX and PREC_PAREN --- compiler/rustc_ast/src/util/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 373c0ebcc5cb..900040b8bd92 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -234,7 +234,7 @@ pub const PREC_RANGE: i8 = -10; // The range 2..=14 is reserved for AssocOp binary operator precedences. pub const PREC_PREFIX: i8 = 50; pub const PREC_POSTFIX: i8 = 60; -pub const PREC_PAREN: i8 = 99; +pub const PREC_PAREN: i8 = 60; pub const PREC_FORCE_PAREN: i8 = 100; #[derive(Debug, Clone, Copy)] From 273447cec7a5b27febf82be7a9889c7f5de2411b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 23 Jun 2024 18:30:13 -0700 Subject: [PATCH 05/53] Rename the 2 unambiguous precedence levels to PREC_UNAMBIGUOUS --- compiler/rustc_ast/src/util/parser.rs | 53 +++++++++---------- .../rustc_ast_pretty/src/pprust/state/expr.rs | 14 ++--- compiler/rustc_hir_pretty/src/lib.rs | 8 +-- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/cast.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 8 +-- .../clippy/clippy_lints/src/dereference.rs | 6 +-- .../clippy_lints/src/matches/manual_utils.rs | 4 +- 8 files changed, 48 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 900040b8bd92..ad92bf2cd407 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -233,8 +233,7 @@ pub const PREC_JUMP: i8 = -30; pub const PREC_RANGE: i8 = -10; // The range 2..=14 is reserved for AssocOp binary operator precedences. pub const PREC_PREFIX: i8 = 50; -pub const PREC_POSTFIX: i8 = 60; -pub const PREC_PAREN: i8 = 60; +pub const PREC_UNAMBIGUOUS: i8 = 60; pub const PREC_FORCE_PAREN: i8 = 100; #[derive(Debug, Clone, Copy)] @@ -325,37 +324,35 @@ impl ExprPrecedence { | ExprPrecedence::Let | ExprPrecedence::Unary => PREC_PREFIX, - // Unary, postfix - ExprPrecedence::Await - | ExprPrecedence::Call - | ExprPrecedence::MethodCall - | ExprPrecedence::Field - | ExprPrecedence::Index - | ExprPrecedence::Try - | ExprPrecedence::InlineAsm - | ExprPrecedence::Mac - | ExprPrecedence::FormatArgs - | ExprPrecedence::OffsetOf - | ExprPrecedence::PostfixMatch => PREC_POSTFIX, - // Never need parens ExprPrecedence::Array - | ExprPrecedence::Repeat - | ExprPrecedence::Tup - | ExprPrecedence::Lit - | ExprPrecedence::Path - | ExprPrecedence::Paren - | ExprPrecedence::If - | ExprPrecedence::While - | ExprPrecedence::ForLoop - | ExprPrecedence::Loop - | ExprPrecedence::Match - | ExprPrecedence::ConstBlock + | ExprPrecedence::Await | ExprPrecedence::Block - | ExprPrecedence::TryBlock + | ExprPrecedence::Call + | ExprPrecedence::ConstBlock + | ExprPrecedence::Field + | ExprPrecedence::ForLoop + | ExprPrecedence::FormatArgs | ExprPrecedence::Gen + | ExprPrecedence::If + | ExprPrecedence::Index + | ExprPrecedence::InlineAsm + | ExprPrecedence::Lit + | ExprPrecedence::Loop + | ExprPrecedence::Mac + | ExprPrecedence::Match + | ExprPrecedence::MethodCall + | ExprPrecedence::OffsetOf + | ExprPrecedence::Paren + | ExprPrecedence::Path + | ExprPrecedence::PostfixMatch + | ExprPrecedence::Repeat | ExprPrecedence::Struct - | ExprPrecedence::Err => PREC_PAREN, + | ExprPrecedence::Try + | ExprPrecedence::TryBlock + | ExprPrecedence::Tup + | ExprPrecedence::While + | ExprPrecedence::Err => PREC_UNAMBIGUOUS, } } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 1e117c46b6e2..f2f6594e6869 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -217,7 +217,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { let prec = match func.kind { ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_POSTFIX, + _ => parser::PREC_UNAMBIGUOUS, }; // Independent of parenthesization related to precedence, we must @@ -257,7 +257,7 @@ impl<'a> State<'a> { // boundaries, `$receiver.method()` can be parsed back as a statement // containing an expression if and only if `$receiver` can be parsed as // a statement containing an expression. - self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup); + self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS, fixup); self.word("."); self.print_ident(segment.ident); @@ -489,7 +489,7 @@ impl<'a> State<'a> { self.space(); } MatchKind::Postfix => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); + self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); self.word_nbsp(".match"); } } @@ -549,7 +549,7 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Await(expr, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); + self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { @@ -568,14 +568,14 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression()); } ast::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup); + self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); self.word("."); self.print_ident(*ident); } ast::ExprKind::Index(expr, index, _) => { self.print_expr_maybe_paren( expr, - parser::PREC_POSTFIX, + parser::PREC_UNAMBIGUOUS, fixup.leftmost_subexpression(), ); self.word("["); @@ -713,7 +713,7 @@ impl<'a> State<'a> { } } ast::ExprKind::Try(e) => { - self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup); + self.print_expr_maybe_paren(e, parser::PREC_UNAMBIGUOUS, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b21f1eadfb7a..25b0cbdc026a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1120,7 +1120,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let prec = match func.kind { hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_POSTFIX, + _ => parser::PREC_UNAMBIGUOUS, }; self.print_expr_maybe_paren(func, prec); @@ -1134,7 +1134,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS); self.word("."); self.print_ident(segment.ident); @@ -1478,12 +1478,12 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(rhs, prec); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); + self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); self.word("["); self.print_expr(index); self.word("]"); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 46c855155753..3b199b7e3c26 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -3,7 +3,7 @@ use super::method::MethodCallee; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; use crate::errors; -use rustc_ast::util::parser::PREC_POSTFIX; +use rustc_ast::util::parser::PREC_UNAMBIGUOUS; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; @@ -656,7 +656,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Ok(rest_snippet) = rest_snippet { - let sugg = if callee_expr.precedence().order() >= PREC_POSTFIX { + let sugg = if callee_expr.precedence().order() >= PREC_UNAMBIGUOUS { vec![ (up_to_rcvr_span, "".to_string()), (rest_span, format!(".{}({rest_snippet}", segment.ident)), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 587085102821..92f2d3254bb2 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -946,7 +946,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { let expr_prec = self.expr.precedence().order(); - let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX; + let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS; let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9dd82868adc5..32369b2f720d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -9,7 +9,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use core::cmp::min; use core::iter; use hir::def_id::LocalDefId; -use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; +use rustc_ast::util::parser::{ExprPrecedence, PREC_UNAMBIGUOUS}; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir as hir; @@ -1287,7 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); - let mut sugg = if expr.precedence().order() >= PREC_POSTFIX { + let mut sugg = if expr.precedence().order() >= PREC_UNAMBIGUOUS { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -2826,7 +2826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); - let close_paren = if expr.precedence().order() < PREC_POSTFIX { + let close_paren = if expr.precedence().order() < PREC_UNAMBIGUOUS { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); ")" } else { @@ -2851,7 +2851,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = src.trim_end_matches(&checked_ty.to_string()).len(); expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) }, - if expr.precedence().order() < PREC_POSTFIX { + if expr.precedence().order() < PREC_UNAMBIGUOUS { // Readd `)` format!("{expected_ty})") } else { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index d60320d82825..f451758c3350 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -6,7 +6,7 @@ use clippy_utils::{ expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode, }; use core::mem; -use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; +use rustc_ast::util::parser::{PREC_UNAMBIGUOUS, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_ty, Visitor}; @@ -1013,7 +1013,7 @@ fn report<'tcx>( let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { Node::Expr(e) => match e.kind { ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), - ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))), + ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))), _ => (e.precedence().order(), false), }, _ => (0, false), @@ -1160,7 +1160,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence().order() == PREC_POSTFIX { + if parent.precedence().order() == PREC_UNAMBIGUOUS { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 183caab56c59..be80aebed6df 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -7,7 +7,7 @@ use clippy_utils::{ can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind, }; -use rustc_ast::util::parser::PREC_POSTFIX; +use rustc_ast::util::parser::PREC_UNAMBIGUOUS; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{OptionNone, OptionSome}; @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_UNAMBIGUOUS { format!("({scrutinee_str})") } else { scrutinee_str.into() From a2298a6f190a020da69860433b4031775ea82cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Jun 2024 01:11:56 +0000 Subject: [PATCH 06/53] Do not ICE when suggesting dereferencing closure arg Account for `for` lifetimes when constructing closure to see if dereferencing the return value would be valid. Fix #125634, fix #124563. --- .../src/diagnostics/region_errors.rs | 6 ++- ...unt-for-lifetimes-in-closure-suggestion.rs | 19 +++++++ ...for-lifetimes-in-closure-suggestion.stderr | 17 +++++++ ...ough-suggestion-regression-test-124563.rs} | 11 +++-- ...h-suggestion-regression-test-124563.stderr | 49 +++++++++++++++++++ tests/ui/regions/regions-escape-method.fixed | 17 +++++++ tests/ui/regions/regions-escape-method.rs | 1 + tests/ui/regions/regions-escape-method.stderr | 7 ++- 8 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 tests/ui/regions/account-for-lifetimes-in-closure-suggestion.rs create mode 100644 tests/ui/regions/account-for-lifetimes-in-closure-suggestion.stderr rename tests/{crashes/124563.rs => ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.rs} (72%) create mode 100644 tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr create mode 100644 tests/ui/regions/regions-escape-method.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 67c11ff4a5bd..d0cdf2baf993 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1152,7 +1152,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Get the arguments for the found method, only specifying that `Self` is the receiver type. let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return }; let args = GenericArgs::for_item(tcx, method_def_id, |param, _| { - if param.index == 0 { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else if param.index == 0 && param.name == kw::SelfUpper { possible_rcvr_ty.into() } else if param.index == closure_param.index { closure_ty.into() @@ -1169,7 +1171,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred) })); - if ocx.select_all_or_error().is_empty() { + if ocx.select_all_or_error().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), "dereference the return value", diff --git a/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.rs b/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.rs new file mode 100644 index 000000000000..2de92cf62da1 --- /dev/null +++ b/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.rs @@ -0,0 +1,19 @@ +// #125634 +struct Thing; + +// Invariant in 'a, Covariant in 'b +struct TwoThings<'a, 'b>(*mut &'a (), &'b mut ()); + +impl Thing { + fn enter_scope<'a>(self, _scope: impl for<'b> FnOnce(TwoThings<'a, 'b>)) {} +} + +fn foo() { + Thing.enter_scope(|ctx| { + SameLifetime(ctx); //~ ERROR lifetime may not live long enough + }); +} + +struct SameLifetime<'a>(TwoThings<'a, 'a>); + +fn main() {} diff --git a/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.stderr b/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.stderr new file mode 100644 index 000000000000..5e158f59cdc6 --- /dev/null +++ b/tests/ui/regions/account-for-lifetimes-in-closure-suggestion.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/account-for-lifetimes-in-closure-suggestion.rs:13:22 + | +LL | Thing.enter_scope(|ctx| { + | --- + | | + | has type `TwoThings<'_, '1>` + | has type `TwoThings<'2, '_>` +LL | SameLifetime(ctx); + | ^^^ this usage requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `TwoThings<'_, '_>`, which makes the generic argument `'_` invariant + = note: the struct `TwoThings<'a, 'b>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to 1 previous error + diff --git a/tests/crashes/124563.rs b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.rs similarity index 72% rename from tests/crashes/124563.rs rename to tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.rs index b082739af53d..23427838ceb7 100644 --- a/tests/crashes/124563.rs +++ b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.rs @@ -1,5 +1,4 @@ -//@ known-bug: rust-lang/rust#124563 - +// #124563 use std::marker::PhantomData; pub trait Trait {} @@ -17,11 +16,11 @@ where T: Trait, { type Trait = T; - type Bar = BarImpl<'a, 'b, T>; + type Bar = BarImpl<'a, 'b, T>; //~ ERROR lifetime bound not satisfied fn foo(&mut self) { - self.enter_scope(|ctx| { - BarImpl(ctx); + self.enter_scope(|ctx| { //~ ERROR lifetime may not live long enough + BarImpl(ctx); //~ ERROR lifetime may not live long enough }); } } @@ -44,3 +43,5 @@ where { type Foo = FooImpl<'a, 'b, T>; } + +fn main() {} diff --git a/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr new file mode 100644 index 000000000000..fcd0a232a7bd --- /dev/null +++ b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr @@ -0,0 +1,49 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:19:16 + | +LL | type Bar = BarImpl<'a, 'b, T>; + | ^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:14:6 + | +LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T> + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here + --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:14:10 + | +LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T> + | ^^ + +error: lifetime may not live long enough + --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:23:21 + | +LL | self.enter_scope(|ctx| { + | --- + | | + | has type `&'1 mut FooImpl<'_, '_, T>` + | has type `&mut FooImpl<'2, '_, T>` +LL | BarImpl(ctx); + | ^^^ this usage requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9 + | +LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T> + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | / self.enter_scope(|ctx| { +LL | | BarImpl(ctx); +LL | | }); + | |__________^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `FooImpl<'_, '_, T>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/regions/regions-escape-method.fixed b/tests/ui/regions/regions-escape-method.fixed new file mode 100644 index 000000000000..f192dca1e25f --- /dev/null +++ b/tests/ui/regions/regions-escape-method.fixed @@ -0,0 +1,17 @@ +// Test a method call where the parameter `B` would (illegally) be +// inferred to a region bound in the method argument. If this program +// were accepted, then the closure passed to `s.f` could escape its +// argument. +//@ run-rustfix + +struct S; + +impl S { + fn f(&self, _: F) where F: FnOnce(&i32) -> B { + } +} + +fn main() { + let s = S; + s.f(|p| *p) //~ ERROR lifetime may not live long enough +} diff --git a/tests/ui/regions/regions-escape-method.rs b/tests/ui/regions/regions-escape-method.rs index 69c01ae6906c..82bf86c79b23 100644 --- a/tests/ui/regions/regions-escape-method.rs +++ b/tests/ui/regions/regions-escape-method.rs @@ -2,6 +2,7 @@ // inferred to a region bound in the method argument. If this program // were accepted, then the closure passed to `s.f` could escape its // argument. +//@ run-rustfix struct S; diff --git a/tests/ui/regions/regions-escape-method.stderr b/tests/ui/regions/regions-escape-method.stderr index aeda923b0ba9..687b91bb7b47 100644 --- a/tests/ui/regions/regions-escape-method.stderr +++ b/tests/ui/regions/regions-escape-method.stderr @@ -1,11 +1,16 @@ error: lifetime may not live long enough - --> $DIR/regions-escape-method.rs:15:13 + --> $DIR/regions-escape-method.rs:16:13 | LL | s.f(|p| p) | -- ^ returning this value requires that `'1` must outlive `'2` | || | |return type of closure is &'2 i32 | has type `&'1 i32` + | +help: dereference the return value + | +LL | s.f(|p| *p) + | + error: aborting due to 1 previous error From fce07a82c632ec28ac02361b786e64bf56ec1739 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 16 Jun 2024 03:09:58 -0500 Subject: [PATCH 07/53] Extract repeated constants from `f32` and `f64` source This will make it easier to keep `f16` and `f128` consistent as their implementations get added. --- library/core/src/num/f32.rs | 45 ++++++++++--------- library/core/src/num/f64.rs | 51 +++++++++++----------- library/std/src/f32/tests.rs | 82 +++++++++++++++++++++++------------ library/std/src/f64/tests.rs | 83 ++++++++++++++++++++++++------------ 4 files changed, 160 insertions(+), 101 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 9d34d3da9e95..271965c28840 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -490,6 +490,21 @@ impl f32 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; + /// Sign bit + const SIGN_MASK: u32 = 0x8000_0000; + + /// Exponent mask + const EXP_MASK: u32 = 0x7f80_0000; + + /// Mantissa mask + const MAN_MASK: u32 = 0x007f_ffff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u32 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u32 = Self::TINY_BITS | Self::SIGN_MASK; + /// Returns `true` if this value is NaN. /// /// ``` @@ -515,7 +530,7 @@ impl f32 { #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f32 { // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. - unsafe { mem::transmute::(mem::transmute::(self) & 0x7fff_ffff) } + unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } } /// Returns `true` if this value is positive infinity or negative infinity, and @@ -682,12 +697,9 @@ impl f32 { // runtime-deviating logic which may or may not be acceptable. #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] const unsafe fn partial_classify(self) -> FpCategory { - const EXP_MASK: u32 = 0x7f800000; - const MAN_MASK: u32 = 0x007fffff; - // SAFETY: The caller is not asking questions for which this will tell lies. let b = unsafe { mem::transmute::(self) }; - match (b & MAN_MASK, b & EXP_MASK) { + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { (0, 0) => FpCategory::Zero, (_, 0) => FpCategory::Subnormal, _ => FpCategory::Normal, @@ -699,12 +711,9 @@ impl f32 { // plus a transmute. We do not live in a just world, but we can make it more so. #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] const fn classify_bits(b: u32) -> FpCategory { - const EXP_MASK: u32 = 0x7f800000; - const MAN_MASK: u32 = 0x007fffff; - - match (b & MAN_MASK, b & EXP_MASK) { - (0, EXP_MASK) => FpCategory::Infinite, - (_, EXP_MASK) => FpCategory::Nan, + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, (0, 0) => FpCategory::Zero, (_, 0) => FpCategory::Subnormal, _ => FpCategory::Normal, @@ -789,17 +798,14 @@ impl f32 { pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. - const TINY_BITS: u32 = 0x1; // Smallest positive f32. - const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; - let bits = self.to_bits(); if self.is_nan() || bits == Self::INFINITY.to_bits() { return self; } - let abs = bits & CLEAR_SIGN_MASK; + let abs = bits & !Self::SIGN_MASK; let next_bits = if abs == 0 { - TINY_BITS + Self::TINY_BITS } else if bits == abs { bits + 1 } else { @@ -839,17 +845,14 @@ impl f32 { pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. - const NEG_TINY_BITS: u32 = 0x8000_0001; // Smallest (in magnitude) negative f32. - const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; - let bits = self.to_bits(); if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { return self; } - let abs = bits & CLEAR_SIGN_MASK; + let abs = bits & !Self::SIGN_MASK; let next_bits = if abs == 0 { - NEG_TINY_BITS + Self::NEG_TINY_BITS } else if bits == abs { bits - 1 } else { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 95f021b2541a..bccd39f60594 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -489,6 +489,21 @@ impl f64 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; + /// Sign bit + const SIGN_MASK: u64 = 0x8000_0000_0000_0000; + + /// Exponent mask + const EXP_MASK: u64 = 0x7ff0_0000_0000_0000; + + /// Mantissa mask + const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff; + + /// Minimum representable positive value (min subnormal) + const TINY_BITS: u64 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + const NEG_TINY_BITS: u64 = Self::TINY_BITS | Self::SIGN_MASK; + /// Returns `true` if this value is NaN. /// /// ``` @@ -514,9 +529,7 @@ impl f64 { #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] pub(crate) const fn abs_private(self) -> f64 { // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. - unsafe { - mem::transmute::(mem::transmute::(self) & 0x7fff_ffff_ffff_ffff) - } + unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } } /// Returns `true` if this value is positive infinity or negative infinity, and @@ -673,13 +686,10 @@ impl f64 { // and some normal floating point numbers truncated from an x87 FPU. #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] const unsafe fn partial_classify(self) -> FpCategory { - const EXP_MASK: u64 = 0x7ff0000000000000; - const MAN_MASK: u64 = 0x000fffffffffffff; - // SAFETY: The caller is not asking questions for which this will tell lies. let b = unsafe { mem::transmute::(self) }; - match (b & MAN_MASK, b & EXP_MASK) { - (0, EXP_MASK) => FpCategory::Infinite, + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, (0, 0) => FpCategory::Zero, (_, 0) => FpCategory::Subnormal, _ => FpCategory::Normal, @@ -691,12 +701,9 @@ impl f64 { // plus a transmute. We do not live in a just world, but we can make it more so. #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] const fn classify_bits(b: u64) -> FpCategory { - const EXP_MASK: u64 = 0x7ff0000000000000; - const MAN_MASK: u64 = 0x000fffffffffffff; - - match (b & MAN_MASK, b & EXP_MASK) { - (0, EXP_MASK) => FpCategory::Infinite, - (_, EXP_MASK) => FpCategory::Nan, + match (b & Self::MAN_MASK, b & Self::EXP_MASK) { + (0, Self::EXP_MASK) => FpCategory::Infinite, + (_, Self::EXP_MASK) => FpCategory::Nan, (0, 0) => FpCategory::Zero, (_, 0) => FpCategory::Subnormal, _ => FpCategory::Normal, @@ -756,7 +763,7 @@ impl f64 { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. // SAFETY: This is just transmuting to get the sign bit, it's fine. - unsafe { mem::transmute::(self) & 0x8000_0000_0000_0000 != 0 } + unsafe { mem::transmute::(self) & Self::SIGN_MASK != 0 } } #[must_use] @@ -799,17 +806,14 @@ impl f64 { pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. - const TINY_BITS: u64 = 0x1; // Smallest positive f64. - const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; - let bits = self.to_bits(); if self.is_nan() || bits == Self::INFINITY.to_bits() { return self; } - let abs = bits & CLEAR_SIGN_MASK; + let abs = bits & !Self::SIGN_MASK; let next_bits = if abs == 0 { - TINY_BITS + Self::TINY_BITS } else if bits == abs { bits + 1 } else { @@ -849,17 +853,14 @@ impl f64 { pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. - const NEG_TINY_BITS: u64 = 0x8000_0000_0000_0001; // Smallest (in magnitude) negative f64. - const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; - let bits = self.to_bits(); if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { return self; } - let abs = bits & CLEAR_SIGN_MASK; + let abs = bits & !Self::SIGN_MASK; let next_bits = if abs == 0 { - NEG_TINY_BITS + Self::NEG_TINY_BITS } else if bits == abs { bits - 1 } else { diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 9ca4e8f2f45f..63e65698374c 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -2,6 +2,45 @@ use crate::f32::consts; use crate::num::FpCategory as Fp; use crate::num::*; +/// Smallest number +#[allow(dead_code)] // unused on x86 +const TINY_BITS: u32 = 0x1; + +/// Next smallest number +#[allow(dead_code)] // unused on x86 +const TINY_UP_BITS: u32 = 0x2; + +/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 +#[allow(dead_code)] // unused on x86 +const MAX_DOWN_BITS: u32 = 0x7f7f_fffe; + +/// Zeroed exponent, full significant +#[allow(dead_code)] // unused on x86 +const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff; + +/// Exponent = 0b1, zeroed significand +#[allow(dead_code)] // unused on x86 +const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000; + +/// First pattern over the mantissa +#[allow(dead_code)] // unused on x86 +const NAN_MASK1: u32 = 0x002a_aaaa; + +/// Second pattern over the mantissa +#[allow(dead_code)] // unused on x86 +const NAN_MASK2: u32 = 0x0055_5555; + +#[allow(unused_macros)] +macro_rules! assert_f32_biteq { + ($left : expr, $right : expr) => { + let l: &f32 = &$left; + let r: &f32 = &$right; + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})"); + }; +} + #[test] fn test_num_f32() { test_num(10f32, 2f32); @@ -315,27 +354,16 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } -#[allow(unused_macros)] -macro_rules! assert_f32_biteq { - ($left : expr, $right : expr) => { - let l: &f32 = &$left; - let r: &f32 = &$right; - let lb = l.to_bits(); - let rb = r.to_bits(); - assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); - }; -} - // Ignore test on x87 floating point, these platforms do not guarantee NaN // payloads are preserved and flush denormals to zero, failing the tests. #[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { - let tiny = f32::from_bits(1); - let tiny_up = f32::from_bits(2); - let max_down = f32::from_bits(0x7f7f_fffe); - let largest_subnormal = f32::from_bits(0x007f_ffff); - let smallest_normal = f32::from_bits(0x0080_0000); + let tiny = f32::from_bits(TINY_BITS); + let tiny_up = f32::from_bits(TINY_UP_BITS); + let max_down = f32::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS); assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_f32_biteq!(f32::MIN.next_up(), -max_down); assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0); @@ -352,8 +380,8 @@ fn test_next_up() { // Check that NaNs roundtrip. let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2); assert_f32_biteq!(nan0.next_up(), nan0); assert_f32_biteq!(nan1.next_up(), nan1); assert_f32_biteq!(nan2.next_up(), nan2); @@ -364,11 +392,11 @@ fn test_next_up() { #[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { - let tiny = f32::from_bits(1); - let tiny_up = f32::from_bits(2); - let max_down = f32::from_bits(0x7f7f_fffe); - let largest_subnormal = f32::from_bits(0x007f_ffff); - let smallest_normal = f32::from_bits(0x0080_0000); + let tiny = f32::from_bits(TINY_BITS); + let tiny_up = f32::from_bits(TINY_UP_BITS); + let max_down = f32::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS); assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY); assert_f32_biteq!((-max_down).next_down(), f32::MIN); @@ -386,8 +414,8 @@ fn test_next_down() { // Check that NaNs roundtrip. let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2); assert_f32_biteq!(nan0.next_down(), nan0); assert_f32_biteq!(nan1.next_down(), nan1); assert_f32_biteq!(nan2.next_down(), nan2); @@ -734,8 +762,8 @@ fn test_float_bits_conv() { // Check that NaNs roundtrip their bits regardless of signaling-ness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits - let masked_nan1 = f32::NAN.to_bits() ^ 0x002A_AAAA; - let masked_nan2 = f32::NAN.to_bits() ^ 0x0055_5555; + let masked_nan1 = f32::NAN.to_bits() ^ NAN_MASK1; + let masked_nan2 = f32::NAN.to_bits() ^ NAN_MASK2; assert!(f32::from_bits(masked_nan1).is_nan()); assert!(f32::from_bits(masked_nan2).is_nan()); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index f88d01593b5e..d9e17fd601d2 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -2,6 +2,45 @@ use crate::f64::consts; use crate::num::FpCategory as Fp; use crate::num::*; +/// Smallest number +#[allow(dead_code)] // unused on x86 +const TINY_BITS: u64 = 0x1; + +/// Next smallest number +#[allow(dead_code)] // unused on x86 +const TINY_UP_BITS: u64 = 0x2; + +/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 +#[allow(dead_code)] // unused on x86 +const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe; + +/// Zeroed exponent, full significant +#[allow(dead_code)] // unused on x86 +const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff; + +/// Exponent = 0b1, zeroed significand +#[allow(dead_code)] // unused on x86 +const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000; + +/// First pattern over the mantissa +#[allow(dead_code)] // unused on x86 +const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa; + +/// Second pattern over the mantissa +#[allow(dead_code)] // unused on x86 +const NAN_MASK2: u64 = 0x0005_5555_5555_5555; + +#[allow(unused_macros)] +macro_rules! assert_f64_biteq { + ($left : expr, $right : expr) => { + let l: &f64 = &$left; + let r: &f64 = &$right; + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})"); + }; +} + #[test] fn test_num_f64() { test_num(10f64, 2f64); @@ -305,27 +344,16 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } -#[allow(unused_macros)] -macro_rules! assert_f64_biteq { - ($left : expr, $right : expr) => { - let l: &f64 = &$left; - let r: &f64 = &$right; - let lb = l.to_bits(); - let rb = r.to_bits(); - assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); - }; -} - // Ignore test on x87 floating point, these platforms do not guarantee NaN // payloads are preserved and flush denormals to zero, failing the tests. #[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { - let tiny = f64::from_bits(1); - let tiny_up = f64::from_bits(2); - let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); - let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); - let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + let tiny = f64::from_bits(TINY_BITS); + let tiny_up = f64::from_bits(TINY_UP_BITS); + let max_down = f64::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS); assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_f64_biteq!(f64::MIN.next_up(), -max_down); assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0); @@ -341,8 +369,8 @@ fn test_next_up() { assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY); let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2); assert_f64_biteq!(nan0.next_up(), nan0); assert_f64_biteq!(nan1.next_up(), nan1); assert_f64_biteq!(nan2.next_up(), nan2); @@ -353,11 +381,11 @@ fn test_next_up() { #[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { - let tiny = f64::from_bits(1); - let tiny_up = f64::from_bits(2); - let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); - let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); - let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + let tiny = f64::from_bits(TINY_BITS); + let tiny_up = f64::from_bits(TINY_UP_BITS); + let max_down = f64::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS); assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY); assert_f64_biteq!((-max_down).next_down(), f64::MIN); @@ -374,8 +402,8 @@ fn test_next_down() { assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX); let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2); assert_f64_biteq!(nan0.next_down(), nan0); assert_f64_biteq!(nan1.next_down(), nan1); assert_f64_biteq!(nan2.next_down(), nan2); @@ -715,9 +743,8 @@ fn test_float_bits_conv() { assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25); // Check that NaNs roundtrip their bits regardless of signaling-ness - // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits - let masked_nan1 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; - let masked_nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1; + let masked_nan2 = f64::NAN.to_bits() ^ NAN_MASK2; assert!(f64::from_bits(masked_nan1).is_nan()); assert!(f64::from_bits(masked_nan2).is_nan()); From 0314fe62bd178200a620b90b59becd735d6c2e66 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 21 Jun 2024 03:30:15 -0400 Subject: [PATCH 08/53] Reword docs for `f32` and `f64` Better explain the reasoning for the `next_up`/`next_down` integer implementation, as requested by Ralf. --- library/core/src/num/f32.rs | 10 ++++++---- library/core/src/num/f64.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 271965c28840..b9c84a66ed13 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -796,8 +796,9 @@ impl f32 { #[unstable(feature = "float_next_up_down", issue = "91399")] #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { - // We must use strictly integer arithmetic to prevent denormals from - // flushing to zero after an arithmetic operation on some platforms. + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. let bits = self.to_bits(); if self.is_nan() || bits == Self::INFINITY.to_bits() { return self; @@ -843,8 +844,9 @@ impl f32 { #[unstable(feature = "float_next_up_down", issue = "91399")] #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { - // We must use strictly integer arithmetic to prevent denormals from - // flushing to zero after an arithmetic operation on some platforms. + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. let bits = self.to_bits(); if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { return self; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index bccd39f60594..f8e4555fc44f 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -804,8 +804,9 @@ impl f64 { #[unstable(feature = "float_next_up_down", issue = "91399")] #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { - // We must use strictly integer arithmetic to prevent denormals from - // flushing to zero after an arithmetic operation on some platforms. + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. let bits = self.to_bits(); if self.is_nan() || bits == Self::INFINITY.to_bits() { return self; @@ -851,8 +852,9 @@ impl f64 { #[unstable(feature = "float_next_up_down", issue = "91399")] #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { - // We must use strictly integer arithmetic to prevent denormals from - // flushing to zero after an arithmetic operation on some platforms. + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. let bits = self.to_bits(); if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { return self; From 6521c3971d0818ab37f27f36f2eb99de420c780f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Jun 2024 12:17:42 -0400 Subject: [PATCH 09/53] Deny use<> for RPITITs --- compiler/rustc_ast_lowering/messages.ftl | 3 ++ compiler/rustc_ast_lowering/src/errors.rs | 8 +++++ compiler/rustc_ast_lowering/src/lib.rs | 20 +++++++++++ .../forgot-to-capture-type.rs | 1 + .../forgot-to-capture-type.stderr | 10 +++++- .../precise-capturing/redundant.normal.stderr | 20 +++++++++++ .../precise-capturing/redundant.rpitit.stderr | 18 ++++++++++ .../impl-trait/precise-capturing/redundant.rs | 13 ++++--- .../precise-capturing/redundant.stderr | 36 ------------------- .../precise-capturing/rpitit.stderr | 10 +++++- .../precise-capturing/self-capture.rs | 3 +- .../precise-capturing/self-capture.stderr | 10 ++++++ 12 files changed, 107 insertions(+), 45 deletions(-) create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.normal.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 7d81e45d314d..57b9d904dc2f 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -130,6 +130,9 @@ ast_lowering_never_pattern_with_guard = ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` +ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + .note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + ast_lowering_previously_used_here = previously used here ast_lowering_register1 = register `{$reg1_name}` diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 02744d16b422..3d4b6a1f033f 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -424,6 +424,14 @@ pub(crate) struct NoPreciseCapturesOnApit { pub span: Span, } +#[derive(Diagnostic)] +#[diag(ast_lowering_no_precise_captures_on_rpitit)] +#[note] +pub(crate) struct NoPreciseCapturesOnRpitit { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(ast_lowering_yield_in_closure)] pub(crate) struct YieldInClosure { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index da8682d3d095..0a06304fcecf 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1594,6 +1594,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; debug!(?captured_lifetimes_to_duplicate); + match fn_kind { + // Deny `use<>` on RPITIT in trait/trait-impl for now. + Some(FnDeclKind::Trait | FnDeclKind::Impl) => { + if let Some(span) = bounds.iter().find_map(|bound| match *bound { + ast::GenericBound::Use(_, span) => Some(span), + _ => None, + }) { + self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span }); + } + } + None + | Some( + FnDeclKind::Fn + | FnDeclKind::Inherent + | FnDeclKind::ExternFn + | FnDeclKind::Closure + | FnDeclKind::Pointer, + ) => {} + } + self.lower_opaque_inner( opaque_ty_node_id, origin, diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 080149857839..0028a45cbf3f 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -6,6 +6,7 @@ fn type_param() -> impl Sized + use<> {} trait Foo { fn bar() -> impl Sized + use<>; //~^ ERROR `impl Trait` must mention the `Self` type of the trait + //~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 93b44a0c18c2..89bd4df44310 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,3 +1,11 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/forgot-to-capture-type.rs:7:30 + | +LL | fn bar() -> impl Sized + use<>; + | ^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:3:23 | @@ -18,5 +26,5 @@ LL | fn bar() -> impl Sized + use<>; | = note: currently, all type parameters are required to be mentioned in the precise captures list -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr new file mode 100644 index 000000000000..44bc9f7daad8 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr @@ -0,0 +1,20 @@ +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:7:19 + | +LL | fn hello<'a>() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + | + = note: `#[warn(impl_trait_redundant_captures)]` on by default + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:12:27 + | +LL | fn inherent(&self) -> impl Sized + use<'_> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: 2 warnings emitted + diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr new file mode 100644 index 000000000000..9aa73353126c --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr @@ -0,0 +1,18 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/redundant.rs:18:35 + | +LL | fn in_trait() -> impl Sized + use<'a, Self>; + | ^^^^^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/redundant.rs:23:35 + | +LL | fn in_trait() -> impl Sized + use<'a> {} + | ^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 99c128fdc482..ef4f05bd7e45 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -1,24 +1,27 @@ //@ compile-flags: -Zunstable-options --edition=2024 -//@ check-pass +//@ revisions: normal rpitit +//@[normal] check-pass #![feature(precise_capturing)] fn hello<'a>() -> impl Sized + use<'a> {} -//~^ WARN all possible in-scope parameters are already captured +//[normal]~^ WARN all possible in-scope parameters are already captured struct Inherent; impl Inherent { fn inherent(&self) -> impl Sized + use<'_> {} - //~^ WARN all possible in-scope parameters are already captured + //[normal]~^ WARN all possible in-scope parameters are already captured } +#[cfg(rpitit)] trait Test<'a> { fn in_trait() -> impl Sized + use<'a, Self>; - //~^ WARN all possible in-scope parameters are already captured + //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } +#[cfg(rpitit)] impl<'a> Test<'a> for () { fn in_trait() -> impl Sized + use<'a> {} - //~^ WARN all possible in-scope parameters are already captured + //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr deleted file mode 100644 index 274d9d2375f7..000000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.stderr +++ /dev/null @@ -1,36 +0,0 @@ -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:6:19 - | -LL | fn hello<'a>() -> impl Sized + use<'a> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - | - = note: `#[warn(impl_trait_redundant_captures)]` on by default - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:11:27 - | -LL | fn inherent(&self) -> impl Sized + use<'_> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:16:22 - | -LL | fn in_trait() -> impl Sized + use<'a, Self>; - | ^^^^^^^^^^^^^------------- - | | - | help: remove the `use<...>` syntax - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:20:22 - | -LL | fn in_trait() -> impl Sized + use<'a> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - -warning: 4 warnings emitted - diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 202eeb39385d..45eceef2f494 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,3 +1,11 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/rpitit.rs:11:36 + | +LL | fn hello() -> impl PartialEq + use; + | ^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list --> $DIR/rpitit.rs:11:19 | @@ -38,5 +46,5 @@ LL | | ); help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index e0a4a8b658c5..07bb417f9f7f 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,9 +1,8 @@ -//@ check-pass - #![feature(precise_capturing)] trait Foo { fn bar<'a>() -> impl Sized + use; + //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr new file mode 100644 index 000000000000..351de86dd5fa --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -0,0 +1,10 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/self-capture.rs:4:34 + | +LL | fn bar<'a>() -> impl Sized + use; + | ^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + +error: aborting due to 1 previous error + From 26677eb06efbd976e2a3b1c30eacf8e22c8c831c Mon Sep 17 00:00:00 2001 From: SparkyPotato Date: Mon, 24 Jun 2024 16:20:22 -0500 Subject: [PATCH 10/53] don't suggest awaiting type expr patterns --- .../src/infer/error_reporting/suggest.rs | 6 ++++-- tests/ui/async-await/suggest-missing-await.rs | 7 +++++++ tests/ui/async-await/suggest-missing-await.stderr | 14 +++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 74c65e93616e..13b145296a7c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -209,8 +209,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() { - ObligationCauseCode::Pattern { span: Some(then_span), .. } => { - Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() }) + ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => { + origin_expr.then_some(ConsiderAddingAwait::FutureSugg { + span: then_span.shrink_to_hi(), + }) } ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { let then_span = self.find_block_span_from_hir_id(*then_id); diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs index 96996af0bd2d..0bd67cec335b 100644 --- a/tests/ui/async-await/suggest-missing-await.rs +++ b/tests/ui/async-await/suggest-missing-await.rs @@ -71,4 +71,11 @@ async fn suggest_await_in_generic_pattern() { } } +// Issue #126903 +async fn do_async() {} +fn dont_suggest_awaiting_closure_patterns() { + Some(do_async()).map(|()| {}); + //~^ ERROR mismatched types [E0308] +} + fn main() {} diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr index f0ec34a6a555..f9db86ea40a9 100644 --- a/tests/ui/async-await/suggest-missing-await.stderr +++ b/tests/ui/async-await/suggest-missing-await.stderr @@ -133,6 +133,18 @@ help: consider `await`ing on the `Future` LL | match dummy_result().await { | ++++++ -error: aborting due to 7 previous errors +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:77:27 + | +LL | Some(do_async()).map(|()| {}); + | ^^ + | | + | expected future, found `()` + | expected due to this + | + = note: expected opaque type `impl Future` + found unit type `()` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`. From 8016940ef41b1245aecf9eb19c02b85f45dcd133 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 24 Jun 2024 12:50:04 +1000 Subject: [PATCH 11/53] Tweak a confusing comment in `create_match_candidates` --- compiler/rustc_mir_build/src/build/matches/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 68244136d1ad..350b00db7fdd 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -358,8 +358,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { where 'a: 'pat, { - // Assemble a list of candidates: there is one candidate per pattern, - // which means there may be more than one candidate *per arm*. + // Assemble the initial list of candidates. These top-level candidates + // are 1:1 with the original match arms, but other parts of match + // lowering also introduce subcandidates (for subpatterns), and will + // also flatten candidates in some cases. So in general a list of + // candidates does _not_ necessarily correspond to a list of arms. arms.iter() .copied() .map(|arm| { From 050595a82619515614674b6e5dfe16a123dab9c2 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 24 Jun 2024 20:24:10 -0700 Subject: [PATCH 12/53] core: VaArgSafe is an unsafe trait `T: VaArgSafe` is relied on for soundness. Safe impls promise nothing. Therefore this must be an unsafe trait. Slightly pedantic, as only core can impl this, but we could choose to unseal the trait. That would allow soundly (but unsafely) implementing this for e.g. a `#[repr(C)] struct` that should be passable by varargs. --- library/core/src/ffi/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 618897b3abab..6d1f10f52117 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -484,7 +484,7 @@ mod sealed_trait { all supported platforms", issue = "44930" )] - pub trait VaArgSafe {} + pub unsafe trait VaArgSafe {} } macro_rules! impl_va_arg_safe { @@ -494,7 +494,7 @@ macro_rules! impl_va_arg_safe { reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] - impl sealed_trait::VaArgSafe for $t {} + unsafe impl sealed_trait::VaArgSafe for $t {} )+ } } @@ -509,14 +509,15 @@ impl_va_arg_safe! {f64} all supported platforms", issue = "44930" )] -impl sealed_trait::VaArgSafe for *mut T {} +unsafe impl sealed_trait::VaArgSafe for *mut T {} + #[unstable( feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930" )] -impl sealed_trait::VaArgSafe for *const T {} +unsafe impl sealed_trait::VaArgSafe for *const T {} #[unstable( feature = "c_variadic", From 99ed3d3e99da5bf7c1fc0df49425e2dc4d0ca2a9 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Jun 2024 22:05:07 -0400 Subject: [PATCH 13/53] Add build.rs config for reliable `f16` and `f128` There are some complexities about what platforms we can test f16 and f128 on. Put this in build.rs so we have an easy way to configure tests with a single attribute, and keep it up to date. --- library/std/build.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/library/std/build.rs b/library/std/build.rs index 7d975df545ec..55388648a14b 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -7,6 +7,10 @@ fn main() { let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); + let target_pointer_width: u32 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH") + .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set") + .parse() + .unwrap(); println!("cargo:rustc-check-cfg=cfg(netbsd10)"); if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() { @@ -70,4 +74,62 @@ fn main() { println!("cargo:rustc-cfg=backtrace_in_libstd"); println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap()); + + // Emit these on platforms that have no known ABI bugs, LLVM selection bugs, lowering bugs, + // missing symbols, or other problems, to determine when tests get run. + // If more broken platforms are found, please update the tracking issue at + // + // + // Some of these match arms are redundant; the goal is to separate reasons that the type is + // unreliable, even when multiple reasons might fail the same platform. + println!("cargo:rustc-check-cfg=cfg(reliable_f16)"); + println!("cargo:rustc-check-cfg=cfg(reliable_f128)"); + + let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) { + // Selection failure until recent LLVM + // FIXME(llvm19): can probably be removed at the version bump + ("loongarch64", _) => false, + // Selection failure + ("s390x", _) => false, + // Unsupported + ("arm64ec", _) => false, + // MinGW ABI bugs + ("x86", "windows") => false, + // x86 has ABI bugs that show up with optimizations. This should be partially fixed with + // the compiler-builtins update. + ("x86" | "x86_64", _) => false, + // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` + ("powerpc" | "powerpc64" | "powerpc64le", _) => false, + // Missing `__extendhfsf` and `__truncsfhf` + ("riscv32" | "riscv64", _) => false, + // Most OSs are missing `__extendhfsf` and `__truncsfhf` + (_, "linux" | "macos") => true, + // Almost all OSs besides Linux and MacOS are missing symbols until compiler-builtins can + // be updated. will get some of these, the + // next CB update should get the rest. + _ => false, + }; + + let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) { + // Unsupported + ("arm64ec", _) => false, + // ABI and precision bugs + // + ("powerpc" | "powerpc64", _) => false, + // Selection bug + ("nvptx64", _) => false, + // ABI unsupported + ("sparc", _) => false, + // 64-bit Linux is about the only platform to have f128 symbols by default + (_, "linux") if target_pointer_width == 64 => true, + // Same as for f16, except MacOS is also missing f128 symbols. + _ => false, + }; + + if has_reliable_f16 { + println!("cargo:rustc-cfg=reliable_f16"); + } + if has_reliable_f128 { + println!("cargo:rustc-cfg=reliable_f128"); + } } From 0eee0557d076e24c716740c168428f6d12cdf566 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 18 Jun 2024 18:22:14 -0500 Subject: [PATCH 14/53] Add doctests to existing `f16` and `f128` functions The symbols that these tests rely on are not available on all platforms and some ABIs are buggy, tests that rely on external functions are configured to only run on x86 (`f128`) or aarch64 (`f16`). --- library/core/src/num/f128.rs | 36 ++++++++++++++++++++++++++++++++++-- library/core/src/num/f16.rs | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 129f62fb43d1..490d7bd504df 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -221,8 +221,22 @@ impl f128 { pub const MAX_10_EXP: i32 = 4_932; /// Returns `true` if this value is NaN. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `unordtf2` is available + /// # #[cfg(target_arch = "x86_64", target_os = "linux")] { + /// + /// let nan = f128::NAN; + /// let f = 7.0_f128; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// # } + /// ``` #[inline] #[must_use] + #[cfg(not(bootstrap))] #[unstable(feature = "f128", issue = "116909")] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -234,7 +248,7 @@ impl f128 { /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f32) for more info. + /// See [explanation of NaN as a special value](f128) for more info. /// /// ``` /// #![feature(f128)] @@ -257,7 +271,7 @@ impl f128 { /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f32) for more info. + /// See [explanation of NaN as a special value](f128) for more info. /// /// ``` /// #![feature(f128)] @@ -287,6 +301,14 @@ impl f128 { /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f128)] + /// + /// # // FIXME(f16_f128): enable this once const casting works + /// # // assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting! + /// assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] @@ -326,6 +348,16 @@ impl f128 { /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let v = f128::from_bits(0x40029000000000000000000000000000); + /// assert_eq!(v, 12.5); + /// # } + /// ``` #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 7a488cd6bf6f..4b0c25fcce96 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -216,8 +216,21 @@ impl f16 { pub const MAX_10_EXP: i32 = 4; /// Returns `true` if this value is NaN. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "x86_64")] { // FIXME(f16_f128): remove when ABI bugs are fixed + /// + /// let nan = f16::NAN; + /// let f = 7.0_f16; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// # } + /// ``` #[inline] #[must_use] + #[cfg(not(bootstrap))] #[unstable(feature = "f16", issue = "116909")] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -229,7 +242,7 @@ impl f16 { /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_positive` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f32) for more info. + /// See [explanation of NaN as a special value](f16) for more info. /// /// ``` /// #![feature(f16)] @@ -252,7 +265,7 @@ impl f16 { /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that /// the bit pattern of NaNs are conserved over arithmetic operations, the result of /// `is_sign_negative` on a NaN might produce an unexpected result in some cases. - /// See [explanation of NaN as a special value](f32) for more info. + /// See [explanation of NaN as a special value](f16) for more info. /// /// ``` /// #![feature(f16)] @@ -282,6 +295,16 @@ impl f16 { /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// # // FIXME(f16_f128): enable this once const casting works + /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! + /// assert_eq!((12.5f16).to_bits(), 0x4a40); + /// # } + /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] @@ -321,6 +344,15 @@ impl f16 { /// /// Note that this function is distinct from `as` casting, which attempts to /// preserve the *numeric* value, and not the bitwise value. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let v = f16::from_bits(0x4a40); + /// assert_eq!(v, 12.5); + /// # } + /// ``` #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] From 6e2d934a881cc79c14cf7b92e7f57a13426b7c26 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 18 Jun 2024 18:25:07 -0500 Subject: [PATCH 15/53] Add more `f16` and `f128` library functions and constants This adds everything that was directly or transitively blocked on const arithmetic for these types, which was recently merged. Since const arithmetic is recent, most of these need to be gated by `bootstrap`. Anything that relies on intrinsics that are still missing is excluded. --- library/core/src/num/f128.rs | 640 ++++++++++++++++++++++++++++++++++- library/core/src/num/f16.rs | 612 ++++++++++++++++++++++++++++++++- library/std/src/f128.rs | 30 ++ library/std/src/f16.rs | 29 ++ 4 files changed, 1309 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 490d7bd504df..58ed98c888cc 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -11,6 +11,7 @@ #![unstable(feature = "f128", issue = "116909")] +use crate::convert::FloatToInt; use crate::mem; /// Basic mathematical constants. @@ -220,12 +221,50 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] pub const MAX_10_EXP: i32 = 4_932; + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[cfg(not(bootstrap))] + #[allow(clippy::eq_op)] + #[rustc_diagnostic_item = "f128_nan"] + #[unstable(feature = "f128", issue = "116909")] + pub const NAN: f128 = 0.0_f128 / 0.0_f128; + + /// Infinity (∞). + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + pub const INFINITY: f128 = 1.0_f128 / 0.0_f128; + + /// Negative infinity (−∞). + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128; + + /// Sign bit + #[cfg(not(bootstrap))] + pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + + /// Minimum representable positive value (min subnormal) + #[cfg(not(bootstrap))] + const TINY_BITS: u128 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + #[cfg(not(bootstrap))] + const NEG_TINY_BITS: u128 = Self::TINY_BITS | Self::SIGN_MASK; + /// Returns `true` if this value is NaN. /// /// ``` /// #![feature(f128)] /// # // FIXME(f16_f128): remove when `unordtf2` is available - /// # #[cfg(target_arch = "x86_64", target_os = "linux")] { + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// /// let nan = f128::NAN; /// let f = 7.0_f128; @@ -243,6 +282,78 @@ impl f128 { self != self } + // FIXME(#50145): `abs` is publicly unavailable in core due to + // concerns about portability, so this implementation is for + // private use internally. + #[inline] + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub(crate) const fn abs_private(self) -> f128 { + // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + unsafe { + mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) + } + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f128; + /// let inf = f128::INFINITY; + /// let neg_inf = f128::NEG_INFINITY; + /// let nan = f128::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn is_infinite(self) -> bool { + (self == f128::INFINITY) | (self == f128::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `lttf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let f = 7.0f128; + /// let inf: f128 = f128::INFINITY; + /// let neg_inf: f128 = f128::NEG_INFINITY; + /// let nan: f128 = f128::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs_private() < Self::INFINITY + } + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that @@ -292,6 +403,222 @@ impl f128 { (self.to_bits() & (1 << 127)) != 0 } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f128`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(f128)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// // f128::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f128.next_up() < 0.1 + f128::EPSILON); + /// assert_eq!(4611686018427387904f128.next_up(), 4611686018427387904.000000000000001); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f128`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(f128)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 1.0f128; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f128.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 2.0_f128; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference <= f128::EPSILON); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn recip(self) -> Self { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = std::f128::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// assert!(abs_difference <= f128::EPSILON); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_degrees(self) -> Self { + // Use a literal for better precision. + const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128; + self * PIS_IN_180 + } + + /// Converts degrees to radians. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let angle = 180.0f128; + /// + /// let abs_difference = (angle.to_radians() - std::f128::consts::PI).abs(); + /// + /// assert!(abs_difference <= 1e-30); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_radians(self) -> f128 { + // Use a literal for better precision. + const RADS_PER_DEG: f128 = + 0.0174532925199432957692369076848861271344287188854172545609719_f128; + self * RADS_PER_DEG + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `float*itf` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = 4.6_f128; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f128; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// # } + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + /// Raw transmutation to `u128`. /// /// This is currently identical to `transmute::(self)` on all platforms. @@ -367,4 +694,315 @@ impl f128 { // Stability concerns. unsafe { mem::transmute(v) } } + + /// Return the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_be_bytes(); + /// assert_eq!( + /// bytes, + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_be_bytes(self) -> [u8; 16] { + self.to_bits().to_be_bytes() + } + + /// Return the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_le_bytes(); + /// assert_eq!( + /// bytes, + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_le_bytes(self) -> [u8; 16] { + self.to_bits().to_le_bytes() + } + + /// Return the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f128::to_be_bytes + /// [`to_le_bytes`]: f128::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// + /// let bytes = 12.5f128.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// } + /// ); + /// ``` + #[inline] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_ne_bytes(self) -> [u8; 16] { + self.to_bits().to_ne_bytes() + } + + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_be_bytes( + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// ); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub fn from_be_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_be_bytes(bytes)) + } + + /// Create a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_le_bytes( + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// ); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub fn from_le_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_le_bytes(bytes)) + } + + /// Create a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f128::from_be_bytes + /// [`from_le_bytes`]: f128::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `eqtf2` is available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + /// } else { + /// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /// 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x02, 0x40] + /// }); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f128", issue = "116909")] + pub fn from_ne_bytes(bytes: [u8; 16]) -> Self { + Self::from_bits(u128::from_ne_bytes(bytes)) + } + + /// Return the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f128`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// #![feature(f128)] + /// + /// struct GoodBoy { + /// name: &'static str, + /// weight: f128, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci", weight: 0.1 }, + /// GoodBoy { name: "Woofer", weight: 99.0 }, + /// GoodBoy { name: "Yapper", weight: 10.0 }, + /// GoodBoy { name: "Chonk", weight: f128::INFINITY }, + /// GoodBoy { name: "Abs. Unit", weight: f128::NAN }, + /// GoodBoy { name: "Floaty", weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f128::NAN` could be positive or negative, which will affect the sort order. + /// if f128::NAN.is_sign_negative() { + /// bois.into_iter().map(|b| b.weight) + /// .zip([f128::NAN, -5.0, 0.1, 10.0, 99.0, f128::INFINITY].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } else { + /// bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f128::INFINITY, f128::NAN].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i128; + let mut right = other.to_bits() as i128; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 127) as u128) >> 1) as i128; + right ^= (((right >> 127) as u128) >> 1) as i128; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f128).clamp(-2.0, 1.0) == 1.0); + /// assert!((f128::NAN).clamp(-2.0, 1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn clamp(mut self, min: f128, max: f128) -> f128 { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 4b0c25fcce96..3c58b0af9c27 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -11,6 +11,7 @@ #![unstable(feature = "f16", issue = "116909")] +use crate::convert::FloatToInt; use crate::mem; /// Basic mathematical constants. @@ -215,11 +216,49 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] pub const MAX_10_EXP: i32 = 4; + /// Not a Number (NaN). + /// + /// Note that IEEE 754 doesn't define just a single NaN value; + /// a plethora of bit patterns are considered to be NaN. + /// Furthermore, the standard makes a difference + /// between a "signaling" and a "quiet" NaN, + /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). + /// This constant isn't guaranteed to equal to any specific NaN bitpattern, + /// and the stability of its representation over Rust versions + /// and target platforms isn't guaranteed. + #[cfg(not(bootstrap))] + #[allow(clippy::eq_op)] + #[rustc_diagnostic_item = "f16_nan"] + #[unstable(feature = "f16", issue = "116909")] + pub const NAN: f16 = 0.0_f16 / 0.0_f16; + + /// Infinity (∞). + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + pub const INFINITY: f16 = 1.0_f16 / 0.0_f16; + + /// Negative infinity (−∞). + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16; + + /// Sign bit + #[cfg(not(bootstrap))] + const SIGN_MASK: u16 = 0x8000; + + /// Minimum representable positive value (min subnormal) + #[cfg(not(bootstrap))] + const TINY_BITS: u16 = 0x1; + + /// Minimum representable negative value (min negative subnormal) + #[cfg(not(bootstrap))] + const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK; + /// Returns `true` if this value is NaN. /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "x86_64")] { // FIXME(f16_f128): remove when ABI bugs are fixed + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 /// /// let nan = f16::NAN; /// let f = 7.0_f16; @@ -237,6 +276,74 @@ impl f16 { self != self } + // FIXMxE(#50145): `abs` is publicly unavailable in core due to + // concerns about portability, so this implementation is for + // private use internally. + #[inline] + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub(crate) const fn abs_private(self) -> f16 { + // SAFETY: This transmutation is fine. Probably. For the reasons std is using it. + unsafe { mem::transmute::(mem::transmute::(self) & !Self::SIGN_MASK) } + } + + /// Returns `true` if this value is positive infinity or negative infinity, and + /// `false` otherwise. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let f = 7.0f16; + /// let inf = f16::INFINITY; + /// let neg_inf = f16::NEG_INFINITY; + /// let nan = f16::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn is_infinite(self) -> bool { + (self == f16::INFINITY) | (self == f16::NEG_INFINITY) + } + + /// Returns `true` if this number is neither infinite nor NaN. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let f = 7.0f16; + /// let inf: f16 = f16::INFINITY; + /// let neg_inf: f16 = f16::NEG_INFINITY; + /// let nan: f16 = f16::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// # } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn is_finite(self) -> bool { + // There's no need to handle NaN separately: if self is NaN, + // the comparison is not true, exactly as desired. + self.abs_private() < Self::INFINITY + } + /// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that @@ -286,6 +393,220 @@ impl f16 { (self.to_bits() & (1 << 15)) != 0 } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f16`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(f16)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): ABI issues on MSVC + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// // f16::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f16.next_up(), 1.0 + f16::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f16.next_up() < 0.1 + f16::EPSILON); + /// assert_eq!(4356f16.next_up(), 4360.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub fn next_up(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f16`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(f16)] + /// #![feature(float_next_up_down)] + /// # // FIXME(f16_f128): ABI issues on MSVC + /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + /// let x = 1.0f16; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f16.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// # } + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + // #[unstable(feature = "float_next_up_down", issue = "91399")] + pub fn next_down(self) -> Self { + // Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing + // denormals to zero. This is in general unsound and unsupported, but here + // we do our best to still produce the correct result on such targets. + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & !Self::SIGN_MASK; + let next_bits = if abs == 0 { + Self::NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + + /// Takes the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): remove when `extendhfsf2` and `truncsfhf2` are available + /// # #[cfg(target_os = "linux")] { + /// + /// let x = 2.0_f16; + /// let abs_difference = (x.recip() - (1.0 / x)).abs(); + /// + /// assert!(abs_difference <= f16::EPSILON); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn recip(self) -> Self { + 1.0 / self + } + + /// Converts radians to degrees. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): remove when `extendhfsf2` and `truncsfhf2` are available + /// # #[cfg(target_os = "linux")] { + /// + /// let angle = std::f16::consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// assert!(abs_difference <= 0.5); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_degrees(self) -> Self { + // Use a literal for better precision. + const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16; + self * PIS_IN_180 + } + + /// Converts degrees to radians. + /// + /// ``` + /// #![feature(f16)] + /// # // FIXME(f16_f128): remove when `extendhfsf2` and `truncsfhf2` are available + /// # #[cfg(target_os = "linux")] { + /// + /// let angle = 180.0f16; + /// + /// let abs_difference = (angle.to_radians() - std::f16::consts::PI).abs(); + /// + /// assert!(abs_difference <= 0.01); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_radians(self) -> f16 { + // Use a literal for better precision. + const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16; + self * RADS_PER_DEG + } + + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let value = 4.6_f16; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f16; + /// let rounded = unsafe { value.to_int_unchecked::() }; + /// assert_eq!(rounded, i8::MIN); + /// # } + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub unsafe fn to_int_unchecked(self) -> Int + where + Self: FloatToInt, + { + // SAFETY: the caller must uphold the safety contract for + // `FloatToInt::to_int_unchecked`. + unsafe { FloatToInt::::to_int_unchecked(self) } + } + /// Raw transmutation to `u16`. /// /// This is currently identical to `transmute::(self)` on all platforms. @@ -362,4 +683,293 @@ impl f16 { // Stability concerns. unsafe { mem::transmute(v) } } + + /// Return the memory representation of this floating point number as a byte array in + /// big-endian (network) byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// + /// let bytes = 12.5f16.to_be_bytes(); + /// assert_eq!(bytes, [0x4a, 0x40]); + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_be_bytes(self) -> [u8; 2] { + self.to_bits().to_be_bytes() + } + + /// Return the memory representation of this floating point number as a byte array in + /// little-endian byte order. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// + /// let bytes = 12.5f16.to_le_bytes(); + /// assert_eq!(bytes, [0x40, 0x4a]); + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_le_bytes(self) -> [u8; 2] { + self.to_bits().to_le_bytes() + } + + /// Return the memory representation of this floating point number as a byte array in + /// native byte order. + /// + /// As the target platform's native endianness is used, portable code + /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead. + /// + /// [`to_be_bytes`]: f16::to_be_bytes + /// [`to_le_bytes`]: f16::to_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// + /// let bytes = 12.5f16.to_ne_bytes(); + /// assert_eq!( + /// bytes, + /// if cfg!(target_endian = "big") { + /// [0x4a, 0x40] + /// } else { + /// [0x40, 0x4a] + /// } + /// ); + /// ``` + #[inline] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub fn to_ne_bytes(self) -> [u8; 2] { + self.to_bits().to_ne_bytes() + } + + /// Create a floating point value from its representation as a byte array in big endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let value = f16::from_be_bytes([0x4a, 0x40]); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub fn from_be_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_be_bytes(bytes)) + } + + /// Create a floating point value from its representation as a byte array in little endian. + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let value = f16::from_le_bytes([0x40, 0x4a]); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub fn from_le_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_le_bytes(bytes)) + } + + /// Create a floating point value from its representation as a byte array in native endian. + /// + /// As the target platform's native endianness is used, portable code + /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as + /// appropriate instead. + /// + /// [`from_be_bytes`]: f16::from_be_bytes + /// [`from_le_bytes`]: f16::from_le_bytes + /// + /// See [`from_bits`](Self::from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") { + /// [0x4a, 0x40] + /// } else { + /// [0x40, 0x4a] + /// }); + /// assert_eq!(value, 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16", issue = "116909")] + pub fn from_ne_bytes(bytes: [u8; 2]) -> Self { + Self::from_bits(u16::from_ne_bytes(bytes)) + } + + /// Return the ordering between `self` and `other`. + /// + /// Unlike the standard partial comparison between floating point numbers, + /// this comparison always produces an ordering in accordance to + /// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision) + /// floating point standard. The values are ordered in the following sequence: + /// + /// - negative quiet NaN + /// - negative signaling NaN + /// - negative infinity + /// - negative numbers + /// - negative subnormal numbers + /// - negative zero + /// - positive zero + /// - positive subnormal numbers + /// - positive numbers + /// - positive infinity + /// - positive signaling NaN + /// - positive quiet NaN. + /// + /// The ordering established by this function does not always agree with the + /// [`PartialOrd`] and [`PartialEq`] implementations of `f16`. For example, + /// they consider negative and positive zero equal, while `total_cmp` + /// doesn't. + /// + /// The interpretation of the signaling NaN bit follows the definition in + /// the IEEE 754 standard, which may not match the interpretation by some of + /// the older, non-conformant (e.g. MIPS) hardware implementations. + /// + /// # Example + /// + /// ``` + /// #![feature(f16)] + /// + /// struct GoodBoy { + /// name: &'static str, + /// weight: f16, + /// } + /// + /// let mut bois = vec![ + /// GoodBoy { name: "Pucci", weight: 0.1 }, + /// GoodBoy { name: "Woofer", weight: 99.0 }, + /// GoodBoy { name: "Yapper", weight: 10.0 }, + /// GoodBoy { name: "Chonk", weight: f16::INFINITY }, + /// GoodBoy { name: "Abs. Unit", weight: f16::NAN }, + /// GoodBoy { name: "Floaty", weight: -5.0 }, + /// ]; + /// + /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight)); + /// + /// // `f16::NAN` could be positive or negative, which will affect the sort order. + /// if f16::NAN.is_sign_negative() { + /// bois.into_iter().map(|b| b.weight) + /// .zip([f16::NAN, -5.0, 0.1, 10.0, 99.0, f16::INFINITY].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } else { + /// bois.into_iter().map(|b| b.weight) + /// .zip([-5.0, 0.1, 10.0, 99.0, f16::INFINITY, f16::NAN].iter()) + /// .for_each(|(a, b)| assert_eq!(a.to_bits(), b.to_bits())) + /// } + /// ``` + #[inline] + #[must_use] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { + let mut left = self.to_bits() as i16; + let mut right = other.to_bits() as i16; + + // In case of negatives, flip all the bits except the sign + // to achieve a similar layout as two's complement integers + // + // Why does this work? IEEE 754 floats consist of three fields: + // Sign bit, exponent and mantissa. The set of exponent and mantissa + // fields as a whole have the property that their bitwise order is + // equal to the numeric magnitude where the magnitude is defined. + // The magnitude is not normally defined on NaN values, but + // IEEE 754 totalOrder defines the NaN values also to follow the + // bitwise order. This leads to order explained in the doc comment. + // However, the representation of magnitude is the same for negative + // and positive numbers – only the sign bit is different. + // To easily compare the floats as signed integers, we need to + // flip the exponent and mantissa bits in case of negative numbers. + // We effectively convert the numbers to "two's complement" form. + // + // To do the flipping, we construct a mask and XOR against it. + // We branchlessly calculate an "all-ones except for the sign bit" + // mask from negative-signed values: right shifting sign-extends + // the integer, so we "fill" the mask with sign bits, and then + // convert to unsigned to push one more zero bit. + // On positive values, the mask is all zeros, so it's a no-op. + left ^= (((left >> 15) as u16) >> 1) as i16; + right ^= (((right >> 15) as u16) >> 1) as i16; + + left.cmp(&right) + } + + /// Restrict a value to a certain interval unless it is NaN. + /// + /// Returns `max` if `self` is greater than `max`, and `min` if `self` is + /// less than `min`. Otherwise this returns `self`. + /// + /// Note that this function returns NaN if the initial value was NaN as + /// well. + /// + /// # Panics + /// + /// Panics if `min > max`, `min` is NaN, or `max` is NaN. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// + /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0); + /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0); + /// assert!((2.0f16).clamp(-2.0, 1.0) == 1.0); + /// assert!((f16::NAN).clamp(-2.0, 1.0).is_nan()); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn clamp(mut self, min: f16, max: f16) -> f16 { + assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}"); + if self < min { + self = min; + } + if self > max { + self = max; + } + self + } } diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 491235a872ea..0591c6f517b4 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -32,4 +32,34 @@ impl f128 { pub fn powi(self, n: i32) -> f128 { unsafe { intrinsics::powif128(self, n) } } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128)] { // FIXME(f16_f128): reliable_f128 + /// + /// let x = 3.5_f128; + /// let y = -3.5_f128; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f128::NAN.abs().is_nan()); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn abs(self) -> Self { + // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available + // We don't do this now because LLVM has lowering bugs for f128 math. + Self::from_bits(self.to_bits() & !(1 << 127)) + } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 1cb655ffabd8..d48518622999 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -32,4 +32,33 @@ impl f16 { pub fn powi(self, n: i32) -> f16 { unsafe { intrinsics::powif16(self, n) } } + + /// Computes the absolute value of `self`. + /// + /// This function always returns the precise result. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16)] { + /// + /// let x = 3.5_f16; + /// let y = -3.5_f16; + /// + /// assert_eq!(x.abs(), x); + /// assert_eq!(y.abs(), -y); + /// + /// assert!(f16::NAN.abs().is_nan()); + /// # } + /// ``` + #[inline] + #[cfg(not(bootstrap))] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn abs(self) -> Self { + // FIXME(f16_f128): replace with `intrinsics::fabsf16` when available + Self::from_bits(self.to_bits() & !(1 << 15)) + } } From e181297c8cc814b2d3873b3a3b9d9d0182c660f1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 18 Jun 2024 18:27:28 -0500 Subject: [PATCH 16/53] Add tests for `f16` and `f128` This suite tests all library functions that are now available for the types. Tests are only run on certain platforms where `f16` and `f128` are known to work (have symbols available and don't crash LLVM). --- library/std/src/f128/tests.rs | 527 ++++++++++++++++++++++++++++++++-- library/std/src/f16/tests.rs | 526 +++++++++++++++++++++++++++++++-- library/std/src/macros.rs | 11 +- 3 files changed, 1029 insertions(+), 35 deletions(-) diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs index b64c7f856a15..bd7a921c502a 100644 --- a/library/std/src/f128/tests.rs +++ b/library/std/src/f128/tests.rs @@ -1,29 +1,31 @@ -#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used +#![cfg(not(bootstrap))] +// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy +#![cfg(reliable_f128)] + +use crate::f128::consts; +use crate::num::*; /// Smallest number const TINY_BITS: u128 = 0x1; + /// Next smallest number const TINY_UP_BITS: u128 = 0x2; + /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 -const MAX_DOWN_BITS: u128 = 0x7ffeffffffffffffffffffffffffffff; +const MAX_DOWN_BITS: u128 = 0x7ffefffffffffffffffffffffffffffe; + /// Zeroed exponent, full significant const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff; + /// Exponent = 0b1, zeroed significand const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000; + /// First pattern over the mantissa const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa; + /// Second pattern over the mantissa const NAN_MASK2: u128 = 0x00005555555555555555555555555555; -/// Compare by value -#[allow(unused_macros)] -macro_rules! assert_f128_eq { - ($a:expr, $b:expr) => { - let (l, r): (&f128, &f128) = (&$a, &$b); - assert_eq!(*l, *r, "\na: {:#0130x}\nb: {:#0130x}", l.to_bits(), r.to_bits()) - }; -} - /// Compare by representation #[allow(unused_macros)] macro_rules! assert_f128_biteq { @@ -31,10 +33,503 @@ macro_rules! assert_f128_biteq { let (l, r): (&f128, &f128) = (&$a, &$b); let lb = l.to_bits(); let rb = r.to_bits(); - assert_eq!( - lb, rb, - "float {:?} is not bitequal to {:?}.\na: {:#0130x}\nb: {:#0130x}", - *l, *r, lb, rb - ); + assert_eq!(lb, rb, "float {l:?} is not bitequal to {r:?}.\na: {lb:#034x}\nb: {rb:#034x}"); }; } + +#[test] +fn test_num_f128() { + test_num(10f128, 2f128); +} + +// FIXME(f16_f128): add min and max tests when available + +#[test] +fn test_nan() { + let nan: f128 = f128::NAN; + assert!(nan.is_nan()); + assert!(!nan.is_infinite()); + assert!(!nan.is_finite()); + assert!(nan.is_sign_positive()); + assert!(!nan.is_sign_negative()); + // FIXME(f16_f128): classify + // assert!(!nan.is_normal()); + // assert_eq!(Fp::Nan, nan.classify()); +} + +#[test] +fn test_infinity() { + let inf: f128 = f128::INFINITY; + assert!(inf.is_infinite()); + assert!(!inf.is_finite()); + assert!(inf.is_sign_positive()); + assert!(!inf.is_sign_negative()); + assert!(!inf.is_nan()); + // FIXME(f16_f128): classify + // assert!(!inf.is_normal()); + // assert_eq!(Fp::Infinite, inf.classify()); +} + +#[test] +fn test_neg_infinity() { + let neg_inf: f128 = f128::NEG_INFINITY; + assert!(neg_inf.is_infinite()); + assert!(!neg_inf.is_finite()); + assert!(!neg_inf.is_sign_positive()); + assert!(neg_inf.is_sign_negative()); + assert!(!neg_inf.is_nan()); + // FIXME(f16_f128): classify + // assert!(!neg_inf.is_normal()); + // assert_eq!(Fp::Infinite, neg_inf.classify()); +} + +#[test] +fn test_zero() { + let zero: f128 = 0.0f128; + assert_eq!(0.0, zero); + assert!(!zero.is_infinite()); + assert!(zero.is_finite()); + assert!(zero.is_sign_positive()); + assert!(!zero.is_sign_negative()); + assert!(!zero.is_nan()); + // FIXME(f16_f128): classify + // assert!(!zero.is_normal()); + // assert_eq!(Fp::Zero, zero.classify()); +} + +#[test] +fn test_neg_zero() { + let neg_zero: f128 = -0.0; + assert_eq!(0.0, neg_zero); + assert!(!neg_zero.is_infinite()); + assert!(neg_zero.is_finite()); + assert!(!neg_zero.is_sign_positive()); + assert!(neg_zero.is_sign_negative()); + assert!(!neg_zero.is_nan()); + // FIXME(f16_f128): classify + // assert!(!neg_zero.is_normal()); + // assert_eq!(Fp::Zero, neg_zero.classify()); +} + +#[test] +fn test_one() { + let one: f128 = 1.0f128; + assert_eq!(1.0, one); + assert!(!one.is_infinite()); + assert!(one.is_finite()); + assert!(one.is_sign_positive()); + assert!(!one.is_sign_negative()); + assert!(!one.is_nan()); + // FIXME(f16_f128): classify + // assert!(one.is_normal()); + // assert_eq!(Fp::Normal, one.classify()); +} + +#[test] +fn test_is_nan() { + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert!(nan.is_nan()); + assert!(!0.0f128.is_nan()); + assert!(!5.3f128.is_nan()); + assert!(!(-10.732f128).is_nan()); + assert!(!inf.is_nan()); + assert!(!neg_inf.is_nan()); +} + +#[test] +fn test_is_infinite() { + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert!(!nan.is_infinite()); + assert!(inf.is_infinite()); + assert!(neg_inf.is_infinite()); + assert!(!0.0f128.is_infinite()); + assert!(!42.8f128.is_infinite()); + assert!(!(-109.2f128).is_infinite()); +} + +#[test] +fn test_is_finite() { + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert!(!nan.is_finite()); + assert!(!inf.is_finite()); + assert!(!neg_inf.is_finite()); + assert!(0.0f128.is_finite()); + assert!(42.8f128.is_finite()); + assert!((-109.2f128).is_finite()); +} + +// FIXME(f16_f128): add `test_is_normal` and `test_classify` when classify is working +// FIXME(f16_f128): add missing math functions when available + +#[test] +fn test_abs() { + assert_eq!(f128::INFINITY.abs(), f128::INFINITY); + assert_eq!(1f128.abs(), 1f128); + assert_eq!(0f128.abs(), 0f128); + assert_eq!((-0f128).abs(), 0f128); + assert_eq!((-1f128).abs(), 1f128); + assert_eq!(f128::NEG_INFINITY.abs(), f128::INFINITY); + assert_eq!((1f128 / f128::NEG_INFINITY).abs(), 0f128); + assert!(f128::NAN.abs().is_nan()); +} + +#[test] +fn test_is_sign_positive() { + assert!(f128::INFINITY.is_sign_positive()); + assert!(1f128.is_sign_positive()); + assert!(0f128.is_sign_positive()); + assert!(!(-0f128).is_sign_positive()); + assert!(!(-1f128).is_sign_positive()); + assert!(!f128::NEG_INFINITY.is_sign_positive()); + assert!(!(1f128 / f128::NEG_INFINITY).is_sign_positive()); + assert!(f128::NAN.is_sign_positive()); + assert!(!(-f128::NAN).is_sign_positive()); +} + +#[test] +fn test_is_sign_negative() { + assert!(!f128::INFINITY.is_sign_negative()); + assert!(!1f128.is_sign_negative()); + assert!(!0f128.is_sign_negative()); + assert!((-0f128).is_sign_negative()); + assert!((-1f128).is_sign_negative()); + assert!(f128::NEG_INFINITY.is_sign_negative()); + assert!((1f128 / f128::NEG_INFINITY).is_sign_negative()); + assert!(!f128::NAN.is_sign_negative()); + assert!((-f128::NAN).is_sign_negative()); +} + +#[test] +fn test_next_up() { + let tiny = f128::from_bits(TINY_BITS); + let tiny_up = f128::from_bits(TINY_UP_BITS); + let max_down = f128::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS); + assert_f128_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN); + assert_f128_biteq!(f128::MIN.next_up(), -max_down); + assert_f128_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0); + assert_f128_biteq!((-smallest_normal).next_up(), -largest_subnormal); + assert_f128_biteq!((-tiny_up).next_up(), -tiny); + assert_f128_biteq!((-tiny).next_up(), -0.0f128); + assert_f128_biteq!((-0.0f128).next_up(), tiny); + assert_f128_biteq!(0.0f128.next_up(), tiny); + assert_f128_biteq!(tiny.next_up(), tiny_up); + assert_f128_biteq!(largest_subnormal.next_up(), smallest_normal); + assert_f128_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON); + assert_f128_biteq!(f128::MAX.next_up(), f128::INFINITY); + assert_f128_biteq!(f128::INFINITY.next_up(), f128::INFINITY); + + // Check that NaNs roundtrip. + let nan0 = f128::NAN; + let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555); + assert_f128_biteq!(nan0.next_up(), nan0); + assert_f128_biteq!(nan1.next_up(), nan1); + assert_f128_biteq!(nan2.next_up(), nan2); +} + +#[test] +fn test_next_down() { + let tiny = f128::from_bits(TINY_BITS); + let tiny_up = f128::from_bits(TINY_UP_BITS); + let max_down = f128::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS); + assert_f128_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY); + assert_f128_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY); + assert_f128_biteq!((-max_down).next_down(), f128::MIN); + assert_f128_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON); + assert_f128_biteq!((-largest_subnormal).next_down(), -smallest_normal); + assert_f128_biteq!((-tiny).next_down(), -tiny_up); + assert_f128_biteq!((-0.0f128).next_down(), -tiny); + assert_f128_biteq!((0.0f128).next_down(), -tiny); + assert_f128_biteq!(tiny.next_down(), 0.0f128); + assert_f128_biteq!(tiny_up.next_down(), tiny); + assert_f128_biteq!(smallest_normal.next_down(), largest_subnormal); + assert_f128_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128); + assert_f128_biteq!(f128::MAX.next_down(), max_down); + assert_f128_biteq!(f128::INFINITY.next_down(), f128::MAX); + + // Check that NaNs roundtrip. + let nan0 = f128::NAN; + let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555); + assert_f128_biteq!(nan0.next_down(), nan0); + assert_f128_biteq!(nan1.next_down(), nan1); + assert_f128_biteq!(nan2.next_down(), nan2); +} + +#[test] +fn test_recip() { + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert_eq!(1.0f128.recip(), 1.0); + assert_eq!(2.0f128.recip(), 0.5); + assert_eq!((-0.4f128).recip(), -2.5); + assert_eq!(0.0f128.recip(), inf); + assert!(nan.recip().is_nan()); + assert_eq!(inf.recip(), 0.0); + assert_eq!(neg_inf.recip(), 0.0); +} + +#[test] +fn test_to_degrees() { + let pi: f128 = consts::PI; + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert_eq!(0.0f128.to_degrees(), 0.0); + assert_approx_eq!((-5.8f128).to_degrees(), -332.315521); + assert_eq!(pi.to_degrees(), 180.0); + assert!(nan.to_degrees().is_nan()); + assert_eq!(inf.to_degrees(), inf); + assert_eq!(neg_inf.to_degrees(), neg_inf); + assert_eq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703); +} + +#[test] +fn test_to_radians() { + let pi: f128 = consts::PI; + let nan: f128 = f128::NAN; + let inf: f128 = f128::INFINITY; + let neg_inf: f128 = f128::NEG_INFINITY; + assert_eq!(0.0f128.to_radians(), 0.0); + assert_approx_eq!(154.6f128.to_radians(), 2.698279); + assert_approx_eq!((-332.31f128).to_radians(), -5.799903); + // check approx rather than exact because round trip for pi doesn't fall on an exactly + // representable value (unlike `f32` and `f64`). + assert_approx_eq!(180.0f128.to_radians(), pi); + assert!(nan.to_radians().is_nan()); + assert_eq!(inf.to_radians(), inf); + assert_eq!(neg_inf.to_radians(), neg_inf); +} + +#[test] +fn test_real_consts() { + // FIXME(f16_f128): add math tests when available + use super::consts; + + let pi: f128 = consts::PI; + let frac_pi_2: f128 = consts::FRAC_PI_2; + let frac_pi_3: f128 = consts::FRAC_PI_3; + let frac_pi_4: f128 = consts::FRAC_PI_4; + let frac_pi_6: f128 = consts::FRAC_PI_6; + let frac_pi_8: f128 = consts::FRAC_PI_8; + let frac_1_pi: f128 = consts::FRAC_1_PI; + let frac_2_pi: f128 = consts::FRAC_2_PI; + // let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI; + // let sqrt2: f128 = consts::SQRT_2; + // let frac_1_sqrt2: f128 = consts::FRAC_1_SQRT_2; + // let e: f128 = consts::E; + // let log2_e: f128 = consts::LOG2_E; + // let log10_e: f128 = consts::LOG10_E; + // let ln_2: f128 = consts::LN_2; + // let ln_10: f128 = consts::LN_10; + + assert_approx_eq!(frac_pi_2, pi / 2f128); + assert_approx_eq!(frac_pi_3, pi / 3f128); + assert_approx_eq!(frac_pi_4, pi / 4f128); + assert_approx_eq!(frac_pi_6, pi / 6f128); + assert_approx_eq!(frac_pi_8, pi / 8f128); + assert_approx_eq!(frac_1_pi, 1f128 / pi); + assert_approx_eq!(frac_2_pi, 2f128 / pi); + // assert_approx_eq!(frac_2_sqrtpi, 2f128 / pi.sqrt()); + // assert_approx_eq!(sqrt2, 2f128.sqrt()); + // assert_approx_eq!(frac_1_sqrt2, 1f128 / 2f128.sqrt()); + // assert_approx_eq!(log2_e, e.log2()); + // assert_approx_eq!(log10_e, e.log10()); + // assert_approx_eq!(ln_2, 2f128.ln()); + // assert_approx_eq!(ln_10, 10f128.ln()); +} + +#[test] +fn test_float_bits_conv() { + assert_eq!((1f128).to_bits(), 0x3fff0000000000000000000000000000); + assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000); + assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); + assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); + assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5); + assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); + assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signaling-ness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + let masked_nan1 = f128::NAN.to_bits() ^ NAN_MASK1; + let masked_nan2 = f128::NAN.to_bits() ^ NAN_MASK2; + assert!(f128::from_bits(masked_nan1).is_nan()); + assert!(f128::from_bits(masked_nan2).is_nan()); + + assert_eq!(f128::from_bits(masked_nan1).to_bits(), masked_nan1); + assert_eq!(f128::from_bits(masked_nan2).to_bits(), masked_nan2); +} + +#[test] +#[should_panic] +fn test_clamp_min_greater_than_max() { + let _ = 1.0f128.clamp(3.0, 1.0); +} + +#[test] +#[should_panic] +fn test_clamp_min_is_nan() { + let _ = 1.0f128.clamp(f128::NAN, 1.0); +} + +#[test] +#[should_panic] +fn test_clamp_max_is_nan() { + let _ = 1.0f128.clamp(3.0, f128::NAN); +} + +#[test] +fn test_total_cmp() { + use core::cmp::Ordering; + + fn quiet_bit_mask() -> u128 { + 1 << (f128::MANTISSA_DIGITS - 2) + } + + // FIXME(f16_f128): test subnormals when powf is available + // fn min_subnorm() -> f128 { + // f128::MIN_POSITIVE / f128::powf(2.0, f128::MANTISSA_DIGITS as f128 - 1.0) + // } + + // fn max_subnorm() -> f128 { + // f128::MIN_POSITIVE - min_subnorm() + // } + + fn q_nan() -> f128 { + f128::from_bits(f128::NAN.to_bits() | quiet_bit_mask()) + } + + fn s_nan() -> f128 { + f128::from_bits((f128::NAN.to_bits() & !quiet_bit_mask()) + 42) + } + + assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan())); + assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Equal, (-f128::INFINITY).total_cmp(&-f128::INFINITY)); + assert_eq!(Ordering::Equal, (-f128::MAX).total_cmp(&-f128::MAX)); + assert_eq!(Ordering::Equal, (-2.5_f128).total_cmp(&-2.5)); + assert_eq!(Ordering::Equal, (-1.0_f128).total_cmp(&-1.0)); + assert_eq!(Ordering::Equal, (-1.5_f128).total_cmp(&-1.5)); + assert_eq!(Ordering::Equal, (-0.5_f128).total_cmp(&-0.5)); + assert_eq!(Ordering::Equal, (-f128::MIN_POSITIVE).total_cmp(&-f128::MIN_POSITIVE)); + // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Equal, (-0.0_f128).total_cmp(&-0.0)); + assert_eq!(Ordering::Equal, 0.0_f128.total_cmp(&0.0)); + // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm())); + assert_eq!(Ordering::Equal, f128::MIN_POSITIVE.total_cmp(&f128::MIN_POSITIVE)); + assert_eq!(Ordering::Equal, 0.5_f128.total_cmp(&0.5)); + assert_eq!(Ordering::Equal, 1.0_f128.total_cmp(&1.0)); + assert_eq!(Ordering::Equal, 1.5_f128.total_cmp(&1.5)); + assert_eq!(Ordering::Equal, 2.5_f128.total_cmp(&2.5)); + assert_eq!(Ordering::Equal, f128::MAX.total_cmp(&f128::MAX)); + assert_eq!(Ordering::Equal, f128::INFINITY.total_cmp(&f128::INFINITY)); + assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan())); + assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan())); + + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY)); + assert_eq!(Ordering::Less, (-f128::INFINITY).total_cmp(&-f128::MAX)); + assert_eq!(Ordering::Less, (-f128::MAX).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-2.5_f128).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-1.5_f128).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-1.0_f128).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-0.5_f128).total_cmp(&-f128::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-f128::MIN_POSITIVE).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm())); + // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-0.0_f128).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, 0.0_f128.total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm())); + // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f128::MIN_POSITIVE)); + assert_eq!(Ordering::Less, f128::MIN_POSITIVE.total_cmp(&0.5)); + assert_eq!(Ordering::Less, 0.5_f128.total_cmp(&1.0)); + assert_eq!(Ordering::Less, 1.0_f128.total_cmp(&1.5)); + assert_eq!(Ordering::Less, 1.5_f128.total_cmp(&2.5)); + assert_eq!(Ordering::Less, 2.5_f128.total_cmp(&f128::MAX)); + assert_eq!(Ordering::Less, f128::MAX.total_cmp(&f128::INFINITY)); + assert_eq!(Ordering::Less, f128::INFINITY.total_cmp(&s_nan())); + assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan())); + + assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan())); + assert_eq!(Ordering::Greater, (-f128::INFINITY).total_cmp(&-s_nan())); + assert_eq!(Ordering::Greater, (-f128::MAX).total_cmp(&-f128::INFINITY)); + assert_eq!(Ordering::Greater, (-2.5_f128).total_cmp(&-f128::MAX)); + assert_eq!(Ordering::Greater, (-1.5_f128).total_cmp(&-2.5)); + assert_eq!(Ordering::Greater, (-1.0_f128).total_cmp(&-1.5)); + assert_eq!(Ordering::Greater, (-0.5_f128).total_cmp(&-1.0)); + assert_eq!(Ordering::Greater, (-f128::MIN_POSITIVE).total_cmp(&-0.5)); + // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f128::MIN_POSITIVE)); + // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Greater, (-0.0_f128).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Greater, 0.0_f128.total_cmp(&-0.0)); + // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0)); + // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Greater, f128::MIN_POSITIVE.total_cmp(&max_subnorm())); + assert_eq!(Ordering::Greater, 0.5_f128.total_cmp(&f128::MIN_POSITIVE)); + assert_eq!(Ordering::Greater, 1.0_f128.total_cmp(&0.5)); + assert_eq!(Ordering::Greater, 1.5_f128.total_cmp(&1.0)); + assert_eq!(Ordering::Greater, 2.5_f128.total_cmp(&1.5)); + assert_eq!(Ordering::Greater, f128::MAX.total_cmp(&2.5)); + assert_eq!(Ordering::Greater, f128::INFINITY.total_cmp(&f128::MAX)); + assert_eq!(Ordering::Greater, s_nan().total_cmp(&f128::INFINITY)); + assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan())); + + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::INFINITY)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MAX)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MIN_POSITIVE)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MAX)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::INFINITY)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan())); + + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MAX)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MIN_POSITIVE)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MAX)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); +} diff --git a/library/std/src/f16/tests.rs b/library/std/src/f16/tests.rs index d65c43eca4bb..bb6a811529e1 100644 --- a/library/std/src/f16/tests.rs +++ b/library/std/src/f16/tests.rs @@ -1,35 +1,37 @@ -#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used +#![cfg(not(bootstrap))] +// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy +#![cfg(reliable_f16)] + +use crate::f16::consts; +use crate::num::*; // We run out of precision pretty quickly with f16 -const F16_APPROX_L1: f16 = 0.001; +// const F16_APPROX_L1: f16 = 0.001; const F16_APPROX_L2: f16 = 0.01; -const F16_APPROX_L3: f16 = 0.1; +// const F16_APPROX_L3: f16 = 0.1; const F16_APPROX_L4: f16 = 0.5; /// Smallest number const TINY_BITS: u16 = 0x1; + /// Next smallest number const TINY_UP_BITS: u16 = 0x2; + /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 const MAX_DOWN_BITS: u16 = 0x7bfe; + /// Zeroed exponent, full significant const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff; + /// Exponent = 0b1, zeroed significand const SMALLEST_NORMAL_BITS: u16 = 0x0400; + /// First pattern over the mantissa const NAN_MASK1: u16 = 0x02aa; + /// Second pattern over the mantissa const NAN_MASK2: u16 = 0x0155; -/// Compare by value -#[allow(unused_macros)] -macro_rules! assert_f16_eq { - ($a:expr, $b:expr) => { - let (l, r): (&f16, &f16) = (&$a, &$b); - assert_eq!(*l, *r, "\na: {:#018x}\nb: {:#018x}", l.to_bits(), r.to_bits()) - }; -} - /// Compare by representation #[allow(unused_macros)] macro_rules! assert_f16_biteq { @@ -37,10 +39,500 @@ macro_rules! assert_f16_biteq { let (l, r): (&f16, &f16) = (&$a, &$b); let lb = l.to_bits(); let rb = r.to_bits(); - assert_eq!( - lb, rb, - "float {:?} is not bitequal to {:?}.\na: {:#018x}\nb: {:#018x}", - *l, *r, lb, rb - ); + assert_eq!(lb, rb, "float {l:?} ({lb:#04x}) is not bitequal to {r:?} ({rb:#04x})"); }; } + +#[test] +fn test_num_f16() { + test_num(10f16, 2f16); +} + +// FIXME(f16_f128): add min and max tests when available + +#[test] +fn test_nan() { + let nan: f16 = f16::NAN; + assert!(nan.is_nan()); + assert!(!nan.is_infinite()); + assert!(!nan.is_finite()); + assert!(nan.is_sign_positive()); + assert!(!nan.is_sign_negative()); + // FIXME(f16_f128): classify + // assert!(!nan.is_normal()); + // assert_eq!(Fp::Nan, nan.classify()); +} + +#[test] +fn test_infinity() { + let inf: f16 = f16::INFINITY; + assert!(inf.is_infinite()); + assert!(!inf.is_finite()); + assert!(inf.is_sign_positive()); + assert!(!inf.is_sign_negative()); + assert!(!inf.is_nan()); + // FIXME(f16_f128): classify + // assert!(!inf.is_normal()); + // assert_eq!(Fp::Infinite, inf.classify()); +} + +#[test] +fn test_neg_infinity() { + let neg_inf: f16 = f16::NEG_INFINITY; + assert!(neg_inf.is_infinite()); + assert!(!neg_inf.is_finite()); + assert!(!neg_inf.is_sign_positive()); + assert!(neg_inf.is_sign_negative()); + assert!(!neg_inf.is_nan()); + // FIXME(f16_f128): classify + // assert!(!neg_inf.is_normal()); + // assert_eq!(Fp::Infinite, neg_inf.classify()); +} + +#[test] +fn test_zero() { + let zero: f16 = 0.0f16; + assert_eq!(0.0, zero); + assert!(!zero.is_infinite()); + assert!(zero.is_finite()); + assert!(zero.is_sign_positive()); + assert!(!zero.is_sign_negative()); + assert!(!zero.is_nan()); + // FIXME(f16_f128): classify + // assert!(!zero.is_normal()); + // assert_eq!(Fp::Zero, zero.classify()); +} + +#[test] +fn test_neg_zero() { + let neg_zero: f16 = -0.0; + assert_eq!(0.0, neg_zero); + assert!(!neg_zero.is_infinite()); + assert!(neg_zero.is_finite()); + assert!(!neg_zero.is_sign_positive()); + assert!(neg_zero.is_sign_negative()); + assert!(!neg_zero.is_nan()); + // FIXME(f16_f128): classify + // assert!(!neg_zero.is_normal()); + // assert_eq!(Fp::Zero, neg_zero.classify()); +} + +#[test] +fn test_one() { + let one: f16 = 1.0f16; + assert_eq!(1.0, one); + assert!(!one.is_infinite()); + assert!(one.is_finite()); + assert!(one.is_sign_positive()); + assert!(!one.is_sign_negative()); + assert!(!one.is_nan()); + // FIXME(f16_f128): classify + // assert!(one.is_normal()); + // assert_eq!(Fp::Normal, one.classify()); +} + +#[test] +fn test_is_nan() { + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert!(nan.is_nan()); + assert!(!0.0f16.is_nan()); + assert!(!5.3f16.is_nan()); + assert!(!(-10.732f16).is_nan()); + assert!(!inf.is_nan()); + assert!(!neg_inf.is_nan()); +} + +#[test] +fn test_is_infinite() { + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert!(!nan.is_infinite()); + assert!(inf.is_infinite()); + assert!(neg_inf.is_infinite()); + assert!(!0.0f16.is_infinite()); + assert!(!42.8f16.is_infinite()); + assert!(!(-109.2f16).is_infinite()); +} + +#[test] +fn test_is_finite() { + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert!(!nan.is_finite()); + assert!(!inf.is_finite()); + assert!(!neg_inf.is_finite()); + assert!(0.0f16.is_finite()); + assert!(42.8f16.is_finite()); + assert!((-109.2f16).is_finite()); +} + +// FIXME(f16_f128): add `test_is_normal` and `test_classify` when classify is working +// FIXME(f16_f128): add missing math functions when available + +#[test] +fn test_abs() { + assert_eq!(f16::INFINITY.abs(), f16::INFINITY); + assert_eq!(1f16.abs(), 1f16); + assert_eq!(0f16.abs(), 0f16); + assert_eq!((-0f16).abs(), 0f16); + assert_eq!((-1f16).abs(), 1f16); + assert_eq!(f16::NEG_INFINITY.abs(), f16::INFINITY); + assert_eq!((1f16 / f16::NEG_INFINITY).abs(), 0f16); + assert!(f16::NAN.abs().is_nan()); +} + +#[test] +fn test_is_sign_positive() { + assert!(f16::INFINITY.is_sign_positive()); + assert!(1f16.is_sign_positive()); + assert!(0f16.is_sign_positive()); + assert!(!(-0f16).is_sign_positive()); + assert!(!(-1f16).is_sign_positive()); + assert!(!f16::NEG_INFINITY.is_sign_positive()); + assert!(!(1f16 / f16::NEG_INFINITY).is_sign_positive()); + assert!(f16::NAN.is_sign_positive()); + assert!(!(-f16::NAN).is_sign_positive()); +} + +#[test] +fn test_is_sign_negative() { + assert!(!f16::INFINITY.is_sign_negative()); + assert!(!1f16.is_sign_negative()); + assert!(!0f16.is_sign_negative()); + assert!((-0f16).is_sign_negative()); + assert!((-1f16).is_sign_negative()); + assert!(f16::NEG_INFINITY.is_sign_negative()); + assert!((1f16 / f16::NEG_INFINITY).is_sign_negative()); + assert!(!f16::NAN.is_sign_negative()); + assert!((-f16::NAN).is_sign_negative()); +} + +#[test] +fn test_next_up() { + let tiny = f16::from_bits(TINY_BITS); + let tiny_up = f16::from_bits(TINY_UP_BITS); + let max_down = f16::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS); + assert_f16_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN); + assert_f16_biteq!(f16::MIN.next_up(), -max_down); + assert_f16_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0); + assert_f16_biteq!((-smallest_normal).next_up(), -largest_subnormal); + assert_f16_biteq!((-tiny_up).next_up(), -tiny); + assert_f16_biteq!((-tiny).next_up(), -0.0f16); + assert_f16_biteq!((-0.0f16).next_up(), tiny); + assert_f16_biteq!(0.0f16.next_up(), tiny); + assert_f16_biteq!(tiny.next_up(), tiny_up); + assert_f16_biteq!(largest_subnormal.next_up(), smallest_normal); + assert_f16_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON); + assert_f16_biteq!(f16::MAX.next_up(), f16::INFINITY); + assert_f16_biteq!(f16::INFINITY.next_up(), f16::INFINITY); + + // Check that NaNs roundtrip. + let nan0 = f16::NAN; + let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2); + assert_f16_biteq!(nan0.next_up(), nan0); + assert_f16_biteq!(nan1.next_up(), nan1); + assert_f16_biteq!(nan2.next_up(), nan2); +} + +#[test] +fn test_next_down() { + let tiny = f16::from_bits(TINY_BITS); + let tiny_up = f16::from_bits(TINY_UP_BITS); + let max_down = f16::from_bits(MAX_DOWN_BITS); + let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS); + let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS); + assert_f16_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY); + assert_f16_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY); + assert_f16_biteq!((-max_down).next_down(), f16::MIN); + assert_f16_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON); + assert_f16_biteq!((-largest_subnormal).next_down(), -smallest_normal); + assert_f16_biteq!((-tiny).next_down(), -tiny_up); + assert_f16_biteq!((-0.0f16).next_down(), -tiny); + assert_f16_biteq!((0.0f16).next_down(), -tiny); + assert_f16_biteq!(tiny.next_down(), 0.0f16); + assert_f16_biteq!(tiny_up.next_down(), tiny); + assert_f16_biteq!(smallest_normal.next_down(), largest_subnormal); + assert_f16_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16); + assert_f16_biteq!(f16::MAX.next_down(), max_down); + assert_f16_biteq!(f16::INFINITY.next_down(), f16::MAX); + + // Check that NaNs roundtrip. + let nan0 = f16::NAN; + let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1); + let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2); + assert_f16_biteq!(nan0.next_down(), nan0); + assert_f16_biteq!(nan1.next_down(), nan1); + assert_f16_biteq!(nan2.next_down(), nan2); +} + +#[test] +fn test_recip() { + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert_eq!(1.0f16.recip(), 1.0); + assert_eq!(2.0f16.recip(), 0.5); + assert_eq!((-0.4f16).recip(), -2.5); + assert_eq!(0.0f16.recip(), inf); + assert!(nan.recip().is_nan()); + assert_eq!(inf.recip(), 0.0); + assert_eq!(neg_inf.recip(), 0.0); +} + +#[test] +fn test_to_degrees() { + let pi: f16 = consts::PI; + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert_eq!(0.0f16.to_degrees(), 0.0); + assert_approx_eq!((-5.8f16).to_degrees(), -332.315521); + assert_approx_eq!(pi.to_degrees(), 180.0, F16_APPROX_L4); + assert!(nan.to_degrees().is_nan()); + assert_eq!(inf.to_degrees(), inf); + assert_eq!(neg_inf.to_degrees(), neg_inf); + assert_eq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703); +} + +#[test] +fn test_to_radians() { + let pi: f16 = consts::PI; + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert_eq!(0.0f16.to_radians(), 0.0); + assert_approx_eq!(154.6f16.to_radians(), 2.698279); + assert_approx_eq!((-332.31f16).to_radians(), -5.799903); + assert_approx_eq!(180.0f16.to_radians(), pi, F16_APPROX_L2); + assert!(nan.to_radians().is_nan()); + assert_eq!(inf.to_radians(), inf); + assert_eq!(neg_inf.to_radians(), neg_inf); +} + +#[test] +fn test_real_consts() { + // FIXME(f16_f128): add math tests when available + use super::consts; + + let pi: f16 = consts::PI; + let frac_pi_2: f16 = consts::FRAC_PI_2; + let frac_pi_3: f16 = consts::FRAC_PI_3; + let frac_pi_4: f16 = consts::FRAC_PI_4; + let frac_pi_6: f16 = consts::FRAC_PI_6; + let frac_pi_8: f16 = consts::FRAC_PI_8; + let frac_1_pi: f16 = consts::FRAC_1_PI; + let frac_2_pi: f16 = consts::FRAC_2_PI; + // let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI; + // let sqrt2: f16 = consts::SQRT_2; + // let frac_1_sqrt2: f16 = consts::FRAC_1_SQRT_2; + // let e: f16 = consts::E; + // let log2_e: f16 = consts::LOG2_E; + // let log10_e: f16 = consts::LOG10_E; + // let ln_2: f16 = consts::LN_2; + // let ln_10: f16 = consts::LN_10; + + assert_approx_eq!(frac_pi_2, pi / 2f16); + assert_approx_eq!(frac_pi_3, pi / 3f16); + assert_approx_eq!(frac_pi_4, pi / 4f16); + assert_approx_eq!(frac_pi_6, pi / 6f16); + assert_approx_eq!(frac_pi_8, pi / 8f16); + assert_approx_eq!(frac_1_pi, 1f16 / pi); + assert_approx_eq!(frac_2_pi, 2f16 / pi); + // assert_approx_eq!(frac_2_sqrtpi, 2f16 / pi.sqrt()); + // assert_approx_eq!(sqrt2, 2f16.sqrt()); + // assert_approx_eq!(frac_1_sqrt2, 1f16 / 2f16.sqrt()); + // assert_approx_eq!(log2_e, e.log2()); + // assert_approx_eq!(log10_e, e.log10()); + // assert_approx_eq!(ln_2, 2f16.ln()); + // assert_approx_eq!(ln_10, 10f16.ln()); +} + +#[test] +fn test_float_bits_conv() { + assert_eq!((1f16).to_bits(), 0x3c00); + assert_eq!((12.5f16).to_bits(), 0x4a40); + assert_eq!((1337f16).to_bits(), 0x6539); + assert_eq!((-14.25f16).to_bits(), 0xcb20); + assert_approx_eq!(f16::from_bits(0x3c00), 1.0); + assert_approx_eq!(f16::from_bits(0x4a40), 12.5); + assert_approx_eq!(f16::from_bits(0x6539), 1337.0); + assert_approx_eq!(f16::from_bits(0xcb20), -14.25); + + // Check that NaNs roundtrip their bits regardless of signaling-ness + let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1; + let masked_nan2 = f16::NAN.to_bits() ^ NAN_MASK2; + assert!(f16::from_bits(masked_nan1).is_nan()); + assert!(f16::from_bits(masked_nan2).is_nan()); + + assert_eq!(f16::from_bits(masked_nan1).to_bits(), masked_nan1); + assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2); +} + +#[test] +#[should_panic] +fn test_clamp_min_greater_than_max() { + let _ = 1.0f16.clamp(3.0, 1.0); +} + +#[test] +#[should_panic] +fn test_clamp_min_is_nan() { + let _ = 1.0f16.clamp(f16::NAN, 1.0); +} + +#[test] +#[should_panic] +fn test_clamp_max_is_nan() { + let _ = 1.0f16.clamp(3.0, f16::NAN); +} + +#[test] +fn test_total_cmp() { + use core::cmp::Ordering; + + fn quiet_bit_mask() -> u16 { + 1 << (f16::MANTISSA_DIGITS - 2) + } + + // FIXME(f16_f128): test subnormals when powf is available + // fn min_subnorm() -> f16 { + // f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0) + // } + + // fn max_subnorm() -> f16 { + // f16::MIN_POSITIVE - min_subnorm() + // } + + fn q_nan() -> f16 { + f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask()) + } + + fn s_nan() -> f16 { + f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42) + } + + assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan())); + assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Equal, (-f16::INFINITY).total_cmp(&-f16::INFINITY)); + assert_eq!(Ordering::Equal, (-f16::MAX).total_cmp(&-f16::MAX)); + assert_eq!(Ordering::Equal, (-2.5_f16).total_cmp(&-2.5)); + assert_eq!(Ordering::Equal, (-1.0_f16).total_cmp(&-1.0)); + assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5)); + assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5)); + assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE)); + // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0)); + assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0)); + // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm())); + assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5)); + assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0)); + assert_eq!(Ordering::Equal, 1.5_f16.total_cmp(&1.5)); + assert_eq!(Ordering::Equal, 2.5_f16.total_cmp(&2.5)); + assert_eq!(Ordering::Equal, f16::MAX.total_cmp(&f16::MAX)); + assert_eq!(Ordering::Equal, f16::INFINITY.total_cmp(&f16::INFINITY)); + assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan())); + assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan())); + + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY)); + assert_eq!(Ordering::Less, (-f16::INFINITY).total_cmp(&-f16::MAX)); + assert_eq!(Ordering::Less, (-f16::MAX).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-2.5_f16).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm())); + // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm())); + // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5)); + assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0)); + assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5)); + assert_eq!(Ordering::Less, 1.5_f16.total_cmp(&2.5)); + assert_eq!(Ordering::Less, 2.5_f16.total_cmp(&f16::MAX)); + assert_eq!(Ordering::Less, f16::MAX.total_cmp(&f16::INFINITY)); + assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan())); + assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan())); + + assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan())); + assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan())); + assert_eq!(Ordering::Greater, (-f16::MAX).total_cmp(&-f16::INFINITY)); + assert_eq!(Ordering::Greater, (-2.5_f16).total_cmp(&-f16::MAX)); + assert_eq!(Ordering::Greater, (-1.5_f16).total_cmp(&-2.5)); + assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5)); + assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0)); + assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5)); + // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE)); + // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0)); + // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0)); + // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm())); + assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5)); + assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0)); + assert_eq!(Ordering::Greater, 2.5_f16.total_cmp(&1.5)); + assert_eq!(Ordering::Greater, f16::MAX.total_cmp(&2.5)); + assert_eq!(Ordering::Greater, f16::INFINITY.total_cmp(&f16::MAX)); + assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY)); + assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan())); + + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::INFINITY)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MAX)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MAX)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::INFINITY)); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan())); + + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE)); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm())); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0)); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm())); + // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY)); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); +} diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 58df83bd79d2..972b6015932d 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -373,10 +373,17 @@ macro_rules! dbg { }; } +/// Verify that floats are within a tolerance of each other, 1.0e-6 by default. #[cfg(test)] macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => {{ + ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; + ($a:expr, $b:expr, $lim:expr) => {{ let (a, b) = (&$a, &$b); - assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + let diff = (*a - *b).abs(); + assert!( + diff < $lim, + "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, actual {diff:?})", + lim = $lim + ); }}; } From c2f1072e013c3b58febab160b7f8759a21aaaf79 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 25 Jun 2024 16:33:51 +1000 Subject: [PATCH 17/53] Tweak `FlatPat::new` to avoid a temporarily-invalid state It was somewhat confusing that the old constructor would create a `FlatPat` in a (possibly) non-simplified state, and then simplify its contents in-place. So instead we now create its fields as local variables, perform simplification, and then create the struct afterwards. This doesn't affect correctness, but is less confusing. --- .../rustc_mir_build/src/build/matches/mod.rs | 33 ++++++++++++------- .../rustc_mir_build/src/build/matches/util.rs | 2 ++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 68244136d1ad..5ede0dc3ed0e 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1031,6 +1031,12 @@ impl<'tcx> PatternExtraData<'tcx> { } /// A pattern in a form suitable for generating code. +/// +/// Here, "flat" indicates that the pattern's match pairs have been recursively +/// simplified by [`Builder::simplify_match_pairs`]. They are not necessarily +/// flat in an absolute sense. +/// +/// Will typically be incorporated into a [`Candidate`]. #[derive(Debug, Clone)] struct FlatPat<'pat, 'tcx> { /// To match the pattern, all of these must be satisfied... @@ -1042,23 +1048,25 @@ struct FlatPat<'pat, 'tcx> { } impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { + /// Creates a `FlatPat` containing a simplified [`MatchPair`] list/forest + /// for the given pattern. fn new( place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, cx: &mut Builder<'_, 'tcx>, ) -> Self { - let is_never = pattern.is_never_pattern(); - let mut flat_pat = FlatPat { - match_pairs: vec![MatchPair::new(place, pattern, cx)], - extra_data: PatternExtraData { - span: pattern.span, - bindings: Vec::new(), - ascriptions: Vec::new(), - is_never, - }, + // First, recursively build a tree of match pairs for the given pattern. + let mut match_pairs = vec![MatchPair::new(place, pattern, cx)]; + let mut extra_data = PatternExtraData { + span: pattern.span, + bindings: Vec::new(), + ascriptions: Vec::new(), + is_never: pattern.is_never_pattern(), }; - cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data); - flat_pat + // Partly-flatten and sort the match pairs, while recording extra data. + cx.simplify_match_pairs(&mut match_pairs, &mut extra_data); + + Self { match_pairs, extra_data } } } @@ -1104,9 +1112,12 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { has_guard: bool, cx: &mut Builder<'_, 'tcx>, ) -> Self { + // Use `FlatPat` to build simplified match pairs, then immediately + // incorporate them into a new candidate. Self::from_flat_pat(FlatPat::new(place, pattern, cx), has_guard) } + /// Incorporates an already-simplified [`FlatPat`] into a new candidate. fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self { Candidate { match_pairs: flat_pat.match_pairs, diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 50f4ca2d819d..630d0b9438dc 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -95,6 +95,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { + /// Recursively builds a `MatchPair` tree for the given pattern and its + /// subpatterns. pub(in crate::build) fn new( mut place_builder: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, From 604caa09ed54ed313a512d5c61022625227a910d Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 25 Jun 2024 13:18:19 +0200 Subject: [PATCH 18/53] De-duplicate all consecutive native libs regardless of their options --- compiler/rustc_codegen_ssa/src/back/link.rs | 7 ++----- tests/run-make/print-native-static-libs/bar.rs | 6 ++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index bdb808b1d4ff..0f0058c1d17c 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1490,11 +1490,6 @@ fn print_native_static_libs( let mut lib_args: Vec<_> = all_native_libs .iter() .filter(|l| relevant_lib(sess, l)) - // Deduplication of successive repeated libraries, see rust-lang/rust#113209 - // - // note: we don't use PartialEq/Eq because NativeLib transitively depends on local - // elements like spans, which we don't care about and would make the deduplication impossible - .dedup_by(|l1, l2| l1.name == l2.name && l1.kind == l2.kind && l1.verbatim == l2.verbatim) .filter_map(|lib| { let name = lib.name; match lib.kind { @@ -1521,6 +1516,8 @@ fn print_native_static_libs( | NativeLibKind::RawDylib => None, } }) + // deduplication of consecutive repeated libraries, see rust-lang/rust#113209 + .dedup() .collect(); for path in all_rust_dylibs { // FIXME deduplicate with add_dynamic_crate diff --git a/tests/run-make/print-native-static-libs/bar.rs b/tests/run-make/print-native-static-libs/bar.rs index cd9c1c453e5f..74c76da6938f 100644 --- a/tests/run-make/print-native-static-libs/bar.rs +++ b/tests/run-make/print-native-static-libs/bar.rs @@ -17,3 +17,9 @@ extern "C" { extern "C" { fn g_free2(p: *mut ()); } + +#[cfg(windows)] +#[link(name = "glib-2.0", kind = "raw-dylib")] +extern "C" { + fn g_free3(p: *mut ()); +} From c7b579a7cb4109f8397a9700523e26269cf6a2ed Mon Sep 17 00:00:00 2001 From: cyrgani <85427285+cyrgani@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:37:22 +0200 Subject: [PATCH 19/53] Add missing slash in const_eval_select doc comment --- library/core/src/intrinsics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 6b5054a9f061..9ba1c6a41547 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2579,7 +2579,7 @@ extern "rust-intrinsic" { /// fn runtime() -> i32 { 1 } /// const fn compiletime() -> i32 { 2 } /// -// // ⚠ This code violates the required equivalence of `compiletime` +/// // ⚠ This code violates the required equivalence of `compiletime` /// // and `runtime`. /// const_eval_select((), compiletime, runtime) /// } From d9a34232888629efb8226a9c791b40a384986ef8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 25 Jun 2024 12:02:55 +0200 Subject: [PATCH 20/53] miri: make sure we can find link_section statics even for the local crate --- compiler/rustc_passes/src/reachable.rs | 12 ++---------- .../miri/tests/pass/tls/win_tls_callback.rs | 16 ++++++++++++++++ .../miri/tests/pass/tls/win_tls_callback.stderr | 1 + 3 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 src/tools/miri/tests/pass/tls/win_tls_callback.rs create mode 100644 src/tools/miri/tests/pass/tls/win_tls_callback.stderr diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 6dd8eaf7e673..da4435ebebe8 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -30,7 +30,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc}; use rustc_middle::query::Providers; @@ -178,15 +178,7 @@ impl<'tcx> ReachableContext<'tcx> { if !self.any_library { // If we are building an executable, only explicitly extern // types need to be exported. - let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() { - self.tcx.codegen_fn_attrs(search_item) - } else { - CodegenFnAttrs::EMPTY - }; - let is_extern = codegen_attrs.contains_extern_indicator(); - let std_internal = - codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); - if is_extern || std_internal { + if has_custom_linkage(self.tcx, search_item) { self.reachable_symbols.insert(search_item); } } else { diff --git a/src/tools/miri/tests/pass/tls/win_tls_callback.rs b/src/tools/miri/tests/pass/tls/win_tls_callback.rs new file mode 100644 index 000000000000..99a8de29e917 --- /dev/null +++ b/src/tools/miri/tests/pass/tls/win_tls_callback.rs @@ -0,0 +1,16 @@ +//! Ensure that we call Windows TLS callbacks in the local crate. +//@only-target-windows +// Calling eprintln in the callback seems to (re-)initialize some thread-local storage +// and then leak the memory allocated for that. Let's just ignore these leaks, +// that's not what this test is about. +//@compile-flags: -Zmiri-ignore-leaks + +#[link_section = ".CRT$XLB"] +#[used] // Miri only considers explicitly `#[used]` statics for `lookup_link_section` +pub static CALLBACK: unsafe extern "system" fn(*const (), u32, *const ()) = tls_callback; + +unsafe extern "system" fn tls_callback(_h: *const (), _dw_reason: u32, _pv: *const ()) { + eprintln!("in tls_callback"); +} + +fn main() {} diff --git a/src/tools/miri/tests/pass/tls/win_tls_callback.stderr b/src/tools/miri/tests/pass/tls/win_tls_callback.stderr new file mode 100644 index 000000000000..847955895445 --- /dev/null +++ b/src/tools/miri/tests/pass/tls/win_tls_callback.stderr @@ -0,0 +1 @@ +in tls_callback From 2155c6c47761391673a2794430dc78436c25bbf8 Mon Sep 17 00:00:00 2001 From: ash <97464181+Borgerr@users.noreply.github.com> Date: Sat, 22 Jun 2024 18:53:31 -0600 Subject: [PATCH 21/53] #126333 remove `PathBuf::as_mut_vec` reference at top of `PathBuf::_push` --- library/std/src/path.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 72073d132802..13947122dcad 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1290,7 +1290,8 @@ impl PathBuf { fn _push(&mut self, path: &Path) { // in general, a separator is needed if the rightmost byte is not a separator - let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false); + let buf = self.inner.as_encoded_bytes(); + let mut need_sep = buf.last().map(|c| !is_sep_byte(*c)).unwrap_or(false); // in the special case of `C:` on Windows, do *not* add a separator let comps = self.components(); From b08cd69684e4b121399b3ea0f9ee6cc4a51cad07 Mon Sep 17 00:00:00 2001 From: ash <97464181+Borgerr@users.noreply.github.com> Date: Sun, 23 Jun 2024 08:36:23 -0600 Subject: [PATCH 22/53] inner truncate methods for UEFI platforms --- library/std/src/ffi/os_str.rs | 5 +++++ library/std/src/path.rs | 6 +++--- library/std/src/sys/os_str/bytes.rs | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index f6b9de26c1c4..318fe205e0fa 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -557,6 +557,11 @@ impl OsString { pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { self.inner.as_mut_vec_for_path_buf() } + + #[inline] + pub(crate) fn truncate(&mut self, len: usize) { + self.inner.truncate(len); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 13947122dcad..fb7476a3b267 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1305,7 +1305,7 @@ impl PathBuf { // absolute `path` replaces `self` if path.is_absolute() || path.prefix().is_some() { - self.as_mut_vec().truncate(0); + self.inner.truncate(0); // verbatim paths need . and .. removed } else if comps.prefix_verbatim() && !path.inner.is_empty() { @@ -1350,7 +1350,7 @@ impl PathBuf { // `path` has a root but no prefix, e.g., `\windows` (Windows only) } else if path.has_root() { let prefix_len = self.components().prefix_remaining(); - self.as_mut_vec().truncate(prefix_len); + self.inner.truncate(prefix_len); // `path` is a pure relative path } else if need_sep { @@ -1383,7 +1383,7 @@ impl PathBuf { pub fn pop(&mut self) -> bool { match self.parent().map(|p| p.as_u8_slice().len()) { Some(len) => { - self.as_mut_vec().truncate(len); + self.inner.truncate(len); true } None => false, diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index f7c6b0877aa6..e494f7d1dea1 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -207,6 +207,11 @@ impl Buf { pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { &mut self.inner } + + #[inline] + pub(crate) fn truncate(&mut self, len: usize) { + self.inner.truncate(len); + } } impl Slice { From 7e187e8e4b0a12b9adc0d24dc30dffde6ceaba4a Mon Sep 17 00:00:00 2001 From: ash <97464181+Borgerr@users.noreply.github.com> Date: Sun, 23 Jun 2024 17:24:59 -0600 Subject: [PATCH 23/53] remove references to `PathBuf::as_mut_vec` in `PathBuf::_set_extension` --- library/std/src/path.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index fb7476a3b267..fb488ae94a1e 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1511,15 +1511,14 @@ impl PathBuf { // truncate until right after the file stem let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr(); let start = self.inner.as_encoded_bytes().as_ptr().addr(); - let v = self.as_mut_vec(); - v.truncate(end_file_stem.wrapping_sub(start)); + self.inner.truncate(end_file_stem.wrapping_sub(start)); // add the new extension, if any - let new = extension.as_encoded_bytes(); + let new = extension; if !new.is_empty() { - v.reserve_exact(new.len() + 1); - v.push(b'.'); - v.extend_from_slice(new); + self.inner.reserve_exact(new.len() + 1); + self.inner.push(OsStr::new(".")); + self.inner.push(new); } true From aa46a3368eb017eba41bfab956c7787d46c09935 Mon Sep 17 00:00:00 2001 From: ash <97464181+Borgerr@users.noreply.github.com> Date: Tue, 25 Jun 2024 07:34:35 -0600 Subject: [PATCH 24/53] `PathBuf::as_mut_vec` removed and verified for UEFI and Windows platforms #126333 --- library/std/src/ffi/os_str.rs | 17 +++++++++++------ library/std/src/path.rs | 11 +++-------- library/std/src/sys/os_str/bytes.rs | 17 +++++++++++------ library/std/src/sys/os_str/wtf8.rs | 16 +++++++++++++--- library/std/src/sys_common/wtf8.rs | 12 ++++++------ 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 318fe205e0fa..4a417c84a30a 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -552,16 +552,21 @@ impl OsString { OsStr::from_inner_mut(self.inner.leak()) } - /// Part of a hack to make PathBuf::push/pop more efficient. - #[inline] - pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { - self.inner.as_mut_vec_for_path_buf() - } - + /// Provides plumbing to core `Vec::truncate`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. #[inline] pub(crate) fn truncate(&mut self, len: usize) { self.inner.truncate(len); } + + /// Provides plumbing to core `Vec::extend_from_slice`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. + #[inline] + pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { + self.inner.extend_from_slice(other); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index fb488ae94a1e..caae8f924d2b 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1163,11 +1163,6 @@ pub struct PathBuf { } impl PathBuf { - #[inline] - fn as_mut_vec(&mut self) -> &mut Vec { - self.inner.as_mut_vec_for_path_buf() - } - /// Allocates an empty `PathBuf`. /// /// # Examples @@ -2645,18 +2640,18 @@ impl Path { None => { // Enough capacity for the extension and the dot let capacity = self_len + extension.len() + 1; - let whole_path = self_bytes.iter(); + let whole_path = self_bytes; (capacity, whole_path) } Some(previous_extension) => { let capacity = self_len + extension.len() - previous_extension.len(); - let path_till_dot = self_bytes[..self_len - previous_extension.len()].iter(); + let path_till_dot = &self_bytes[..self_len - previous_extension.len()]; (capacity, path_till_dot) } }; let mut new_path = PathBuf::with_capacity(new_capacity); - new_path.as_mut_vec().extend(slice_to_copy); + new_path.inner.extend_from_slice(slice_to_copy); new_path.set_extension(extension); new_path } diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index e494f7d1dea1..2a7477e3afc2 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -202,16 +202,21 @@ impl Buf { self.as_slice().into_rc() } - /// Part of a hack to make PathBuf::push/pop more efficient. - #[inline] - pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { - &mut self.inner - } - + /// Provides plumbing to core `Vec::truncate`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. #[inline] pub(crate) fn truncate(&mut self, len: usize) { self.inner.truncate(len); } + + /// Provides plumbing to core `Vec::extend_from_slice`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. + #[inline] + pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { + self.inner.extend_from_slice(other); + } } impl Slice { diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index 96690f8c44e9..edb923a47501 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -165,10 +165,20 @@ impl Buf { self.as_slice().into_rc() } - /// Part of a hack to make PathBuf::push/pop more efficient. + /// Provides plumbing to core `Vec::truncate`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. #[inline] - pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { - self.inner.as_mut_vec_for_path_buf() + pub(crate) fn truncate(&mut self, len: usize) { + self.inner.truncate(len); + } + + /// Provides plumbing to core `Vec::extend_from_slice`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. + #[inline] + pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { + self.inner.extend_from_slice(other); } } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 84128a4b595f..708f62f476e7 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -474,13 +474,13 @@ impl Wtf8Buf { Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false } } - /// Part of a hack to make PathBuf::push/pop more efficient. + /// Provides plumbing to core `Vec::extend_from_slice`. + /// More well behaving alternative to allowing outer types + /// full mutable access to the core `Vec`. #[inline] - pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { - // FIXME: this function should not even exist, as it implies violating Wtf8Buf invariants - // For now, simply assume that is about to happen. - self.is_known_utf8 = false; - &mut self.bytes + pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { + self.bytes.extend_from_slice(other); + self.is_known_utf8 = self.is_known_utf8 || self.next_surrogate(0).is_none(); } } From d30d85fd9e71e701e9179037d5100b6a04521c50 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Tue, 25 Jun 2024 16:32:00 +0300 Subject: [PATCH 25/53] Delegation: ast lowering refactor --- compiler/rustc_ast_lowering/src/delegation.rs | 107 ++++++++---------- tests/ui/delegation/explicit-paths.stderr | 8 +- 2 files changed, 53 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index d9dd0b3bca53..678cac210f41 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -66,14 +66,18 @@ impl<'hir> LoweringContext<'_, 'hir> { let Ok(sig_id) = sig_id else { return false; }; - if let Some(local_sig_id) = sig_id.as_local() { + self.has_self(sig_id, span) + } + + fn has_self(&self, def_id: DefId, span: Span) -> bool { + if let Some(local_sig_id) = def_id.as_local() { // The value may be missing due to recursive delegation. // Error will be emmited later during HIR ty lowering. self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self) } else { - match self.tcx.def_kind(sig_id) { + match self.tcx.def_kind(def_id) { DefKind::Fn => false, - DefKind::AssocFn => self.tcx.associated_item(sig_id).fn_has_self_parameter, + DefKind::AssocFn => self.tcx.associated_item(def_id).fn_has_self_parameter, _ => span_bug!(span, "unexpected DefKind for delegation item"), } } @@ -107,12 +111,17 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, ) -> Result { let sig_id = if self.is_in_trait_impl { item_id } else { path_id }; - let sig_id = - self.resolver.get_partial_res(sig_id).and_then(|r| r.expect_full_res().opt_def_id()); - sig_id.ok_or_else(|| { - self.tcx - .dcx() - .span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item") + self.get_resolution_id(sig_id, span) + } + + fn get_resolution_id(&self, node_id: NodeId, span: Span) -> Result { + let def_id = + self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id()); + def_id.ok_or_else(|| { + self.tcx.dcx().span_delayed_bug( + span, + format!("LoweringContext: couldn't resolve node {:?} in delegation item", node_id), + ) }) } @@ -122,7 +131,7 @@ impl<'hir> LoweringContext<'_, 'hir> { predicates: &[], has_where_clause_predicates: false, where_clause_span: span, - span: span, + span, }) } @@ -222,12 +231,7 @@ impl<'hir> LoweringContext<'_, 'hir> { })); let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments }); - - hir::Expr { - hir_id: self.next_id(), - kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), - span, - } + self.mk_expr(hir::ExprKind::Path(hir::QPath::Resolved(None, path)), span) } fn lower_delegation_body( @@ -236,19 +240,11 @@ impl<'hir> LoweringContext<'_, 'hir> { param_count: usize, span: Span, ) -> BodyId { - let path = self.lower_qpath( - delegation.id, - &delegation.qself, - &delegation.path, - ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, - ); let block = delegation.body.as_deref(); self.lower_body(|this| { - let mut parameters: Vec> = Vec::new(); - let mut args: Vec> = Vec::new(); + let mut parameters: Vec> = Vec::with_capacity(param_count); + let mut args: Vec> = Vec::with_capacity(param_count); for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(span); @@ -264,11 +260,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; self_resolver.visit_block(block); let block = this.lower_block(block, false); - hir::Expr { - hir_id: this.next_id(), - kind: hir::ExprKind::Block(block, None), - span: block.span, - } + this.mk_expr(hir::ExprKind::Block(block, None), block.span) } else { let pat_hir_id = this.lower_node_id(pat_node_id); this.generate_arg(pat_hir_id, span) @@ -276,43 +268,41 @@ impl<'hir> LoweringContext<'_, 'hir> { args.push(arg); } - let args = self.arena.alloc_from_iter(args); - let final_expr = this.generate_call(path, args); + let final_expr = this.finalize_body_lowering(delegation, args, span); (this.arena.alloc_from_iter(parameters), final_expr) }) } - fn generate_call( + // Generates fully qualified call for the resulting body. + fn finalize_body_lowering( &mut self, - path: hir::QPath<'hir>, - args: &'hir [hir::Expr<'hir>], + delegation: &Delegation, + args: Vec>, + span: Span, ) -> hir::Expr<'hir> { - let callee = self.arena.alloc(hir::Expr { - hir_id: self.next_id(), - kind: hir::ExprKind::Path(path), - span: path.span(), - }); + let path = self.lower_qpath( + delegation.id, + &delegation.qself, + &delegation.path, + ParamMode::Optional, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + ); - let expr = self.arena.alloc(hir::Expr { - hir_id: self.next_id(), - kind: hir::ExprKind::Call(callee, args), - span: path.span(), - }); + let args = self.arena.alloc_from_iter(args); + let path_expr = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span)); + let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(path_expr, args), span)); let block = self.arena.alloc(hir::Block { stmts: &[], - expr: Some(expr), + expr: Some(call), hir_id: self.next_id(), rules: hir::BlockCheckMode::DefaultBlock, - span: path.span(), + span, targeted_by_break: false, }); - hir::Expr { - hir_id: self.next_id(), - kind: hir::ExprKind::Block(block, None), - span: path.span(), - } + self.mk_expr(hir::ExprKind::Block(block, None), span) } fn generate_delegation_error( @@ -333,11 +323,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.generate_header_error(); let sig = hir::FnSig { decl, header, span }; - let body_id = self.lower_body(|this| { - let expr = - hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span }; - (&[], expr) - }); + let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span))); DelegationResults { generics, body_id, sig } } @@ -349,6 +335,11 @@ impl<'hir> LoweringContext<'_, 'hir> { abi: abi::Abi::Rust, } } + + #[inline] + fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir> { + hir::Expr { hir_id: self.next_id(), kind, span } + } } struct SelfResolver<'a> { diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr index 30891c94c0e9..d33c5da4377b 100644 --- a/tests/ui/delegation/explicit-paths.stderr +++ b/tests/ui/delegation/explicit-paths.stderr @@ -110,10 +110,10 @@ error[E0308]: mismatched types --> $DIR/explicit-paths.rs:78:30 | LL | reuse ::foo1; - | ---------------^^^^ - | | | - | | expected `&S2`, found `&S` - | arguments to this function are incorrect + | ^^^^ + | | + | expected `&S2`, found `&S` + | arguments to this function are incorrect | = note: expected reference `&S2` found reference `&S` From 8b14e23dce2d3cc7cb873609a22c727421d02d3b Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 10 Feb 2024 21:53:34 +0000 Subject: [PATCH 26/53] RFC 2383: Stabilize `lint_reasons` :tada: --- compiler/rustc_builtin_macros/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/builtin_attrs.rs | 6 ++--- compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_lint/src/expect.rs | 5 ---- compiler/rustc_lint/src/levels.rs | 10 ------- compiler/rustc_lint_defs/src/builtin.rs | 26 ++++++------------- .../crates/hir-expand/src/inert_attr_macro.rs | 6 ++--- .../lints/expect-tool-lint-rfc-2383.rs | 1 - .../in-trait/async-example-desugared-extra.rs | 2 -- tests/ui/cfg/diagnostics-not-a-def.rs | 2 -- tests/ui/cfg/diagnostics-not-a-def.stderr | 2 +- tests/ui/empty/empty-attributes.rs | 2 -- tests/ui/empty/empty-attributes.stderr | 18 ++++++------- tests/ui/error-codes/E0602.stderr | 7 ++++- .../feature-gate-lint-reasons.rs | 5 ---- .../feature-gate-lint-reasons.stderr | 24 ----------------- .../impl-trait/in-trait/auxiliary/rpitit.rs | 2 -- .../impl-trait/in-trait/deep-match-works.rs | 2 -- .../in-trait/foreign-dyn-error.stderr | 2 +- tests/ui/impl-trait/in-trait/foreign.rs | 2 -- tests/ui/impl-trait/in-trait/foreign.stderr | 8 +++--- tests/ui/impl-trait/in-trait/nested-rpitit.rs | 2 -- tests/ui/impl-trait/in-trait/reveal.rs | 2 -- .../rpitit-shadowed-by-missing-adt.rs | 2 -- .../rpitit-shadowed-by-missing-adt.stderr | 2 +- .../signature-mismatch.failure.stderr | 2 +- .../impl-trait/in-trait/signature-mismatch.rs | 2 -- .../in-trait/specialization-substs-remap.rs | 1 - tests/ui/impl-trait/in-trait/success.rs | 2 -- tests/ui/lint/cli-unknown-force-warn.stderr | 7 ++++- .../allow-or-expect-dead_code-114557-2.rs | 1 - .../allow-or-expect-dead_code-114557-2.stderr | 2 +- .../allow-or-expect-dead_code-114557-3.rs | 1 - .../allow-or-expect-dead_code-114557-3.stderr | 2 +- .../allow-or-expect-dead_code-114557.rs | 1 - tests/ui/lint/empty-lint-attributes.rs | 2 -- .../ui/lint/lint-removed-cmdline-deny.stderr | 7 ++++- tests/ui/lint/lint-removed-cmdline.stderr | 7 ++++- .../ui/lint/lint-renamed-cmdline-deny.stderr | 8 +++++- tests/ui/lint/lint-renamed-cmdline.stderr | 8 +++++- .../ui/lint/lint-unexported-no-mangle.stderr | 12 ++++++++- .../lint-unknown-lint-cmdline-deny.stderr | 13 +++++++++- .../ui/lint/lint-unknown-lint-cmdline.stderr | 13 +++++++++- tests/ui/lint/reasons-erroneous.rs | 2 -- tests/ui/lint/reasons-erroneous.stderr | 16 ++++++------ tests/ui/lint/reasons-forbidden.rs | 2 -- tests/ui/lint/reasons-forbidden.stderr | 6 ++--- tests/ui/lint/reasons.rs | 1 - tests/ui/lint/reasons.stderr | 8 +++--- .../avoid_delayed_good_path_ice.rs | 1 - .../catch_multiple_lint_triggers.rs | 2 -- .../crate_level_expect.rs | 2 -- .../crate_level_expect.stderr | 2 +- .../expect_inside_macro.rs | 2 -- .../expect_lint_from_macro.rs | 2 -- .../expect_lint_from_macro.stderr | 6 ++--- .../expect_missing_feature_gate.rs | 9 ------- .../expect_missing_feature_gate.stderr | 13 ---------- .../expect_multiple_lints.rs | 2 -- .../expect_multiple_lints.stderr | 16 ++++++------ .../expect_nested_lint_levels.rs | 1 - .../expect_nested_lint_levels.stderr | 14 +++++----- .../expect_on_fn_params.rs | 1 - .../expect_on_fn_params.stderr | 2 +- .../expect_tool_lint_rfc_2383.rs | 1 - .../expect_tool_lint_rfc_2383.stderr | 4 +-- .../expect_unfulfilled_expectation.rs | 1 - .../expect_unfulfilled_expectation.stderr | 8 +++--- .../expect_unused_inside_impl_block.rs | 1 - .../expect_with_forbid.rs | 2 -- .../expect_with_forbid.stderr | 8 +++--- .../expect_with_reason.rs | 1 - .../expect_with_reason.stderr | 2 +- .../force_warn_expected_lints_fulfilled.rs | 2 -- ...force_warn_expected_lints_fulfilled.stderr | 10 +++---- .../force_warn_expected_lints_unfulfilled.rs | 2 -- ...rce_warn_expected_lints_unfulfilled.stderr | 10 +++---- .../fulfilled_expectation_early_lints.rs | 2 -- .../fulfilled_expectation_late_lints.rs | 1 - .../lint-attribute-only-with-reason.rs | 2 -- .../lint-attribute-only-with-reason.stderr | 12 ++++----- .../multiple_expect_attrs.rs | 1 - .../multiple_expect_attrs.stderr | 2 +- .../no_ice_for_partial_compiler_runs.rs | 2 -- .../no_ice_for_partial_compiler_runs.stdout | 8 +++--- .../root-attribute-confusion.rs | 1 - tests/ui/target-feature/no-llvm-leaks.rs | 2 +- 89 files changed, 177 insertions(+), 257 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-lint-reasons.rs delete mode 100644 tests/ui/feature-gates/feature-gate-lint-reasons.stderr delete mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs delete mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 8ac59605bc10..b3ec9a577b5a 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -12,7 +12,7 @@ #![feature(decl_macro)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(lint_reasons)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index cddc67d1578e..356ddf014bee 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![cfg_attr(not(parallel_compiler), feature(cell_leak))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] @@ -24,7 +25,6 @@ #![feature(extend_one)] #![feature(hash_raw_entry)] #![feature(hasher_prefixfree_extras)] -#![feature(lint_reasons)] #![feature(macro_metavar_expr)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9beaa6b8d95f..f082cc2b5699 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -232,6 +232,8 @@ declare_features! ( (accepted, label_break_value, "1.65.0", Some(48594)), /// Allows `let...else` statements. (accepted, let_else, "1.65.0", Some(87335)), + /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. + (accepted, lint_reasons, "CURRENT_RUSTC_VERSION", Some(54503)), /// Allows `break {expr}` with a value inside `loop`s. (accepted, loop_break_value, "1.19.0", Some(37339)), /// Allows use of `?` as the Kleene "at most one" operator in macros. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c53bf9651395..32a047a9363e 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -369,9 +369,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk, EncodeCrossCrate::No, ), - gated!( - expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk, - EncodeCrossCrate::No, lint_reasons, experimental!(expect) + ungated!( + expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + DuplicatesOk, EncodeCrossCrate::No, ), ungated!( forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2dfaac8f6e73..f4e20328814d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -512,8 +512,6 @@ declare_features! ( /// Allows using `#[link(kind = "link-arg", name = "...")]` /// to pass custom arguments to the linker. (unstable, link_arg_attribute, "1.76.0", Some(99427)), - /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. - (unstable, lint_reasons, "1.31.0", Some(54503)), /// Give access to additional metadata about declarative macro meta-variables. (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 40db765da53a..04c2ebf189f9 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -3,7 +3,6 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; use rustc_session::lint::LintExpectationId; -use rustc_span::symbol::sym; use rustc_span::Symbol; pub(crate) fn provide(providers: &mut Providers) { @@ -11,10 +10,6 @@ pub(crate) fn provide(providers: &mut Providers) { } fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { - if !tcx.features().active(sym::lint_reasons) { - return; - } - let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids(); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 1317af50a4a8..0df34c32e385 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -37,7 +37,6 @@ use rustc_session::lint::{ }, Level, Lint, LintExpectationId, LintId, }; -use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -788,15 +787,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { ast::MetaItemKind::NameValue(ref name_value) => { if item.path == sym::reason { if let ast::LitKind::Str(rationale, _) = name_value.kind { - if !self.features.lint_reasons { - feature_err( - &self.sess, - sym::lint_reasons, - item.span, - "lint reasons are experimental", - ) - .emit(); - } reason = Some(rationale); } else { sess.dcx().emit_err(MalformedAttribute { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a023d6161df0..39066ddcf000 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -608,13 +608,13 @@ declare_lint! { } declare_lint! { - /// The `unfulfilled_lint_expectations` lint detects lint trigger expectations - /// that have not been fulfilled. + /// The `unfulfilled_lint_expectations` lint warns if a lint expectation is + /// unfulfilled. /// /// ### Example /// /// ```rust - /// #![feature(lint_reasons)] + /// #![cfg_attr(bootstrap, feature(lint_reasons))] /// /// #[expect(unused_variables)] /// let x = 10; @@ -625,24 +625,14 @@ declare_lint! { /// /// ### Explanation /// - /// It was expected that the marked code would emit a lint. This expectation - /// has not been fulfilled. + /// The `#[expect]` attribute can be used to create a lint expectation. The + /// expectation is fulfilled, if a `#[warn]` attribute at the same location + /// would result in a lint emission. If the expectation is unfulfilled, + /// because no lint was emitted, this lint will be emitted on the attribute. /// - /// The `expect` attribute can be removed if this is intended behavior otherwise - /// it should be investigated why the expected lint is no longer issued. - /// - /// In rare cases, the expectation might be emitted at a different location than - /// shown in the shown code snippet. In most cases, the `#[expect]` attribute - /// works when added to the outer scope. A few lints can only be expected - /// on a crate level. - /// - /// Part of RFC 2383. The progress is being tracked in [#54503] - /// - /// [#54503]: https://github.com/rust-lang/rust/issues/54503 pub UNFULFILLED_LINT_EXPECTATIONS, Warn, - "unfulfilled lint expectation", - @feature_gate = rustc_span::sym::lint_reasons; + "unfulfilled lint expectation" } declare_lint! { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 35fd85bf4518..7ead7e939015 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -142,9 +142,9 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk, @only_local: true, ), - gated!( - expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk, - lint_reasons, experimental!(expect) + ungated!( + expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + DuplicatesOk, @only_local: true, ), ungated!( forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs index 169505b04066..87e6aa0c256d 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(lint_reasons)] //! This file tests the `#[expect]` attribute implementation for tool lints. The same //! file is used to test clippy and rustdoc. Any changes to this file should be synced diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index b4fbcb78c134..d85ad869fd40 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition: 2021 -#![feature(lint_reasons)] - use std::future::Future; use std::pin::Pin; use std::task::Poll; diff --git a/tests/ui/cfg/diagnostics-not-a-def.rs b/tests/ui/cfg/diagnostics-not-a-def.rs index 1912cf9f6166..3a7ca6240b1a 100644 --- a/tests/ui/cfg/diagnostics-not-a-def.rs +++ b/tests/ui/cfg/diagnostics-not-a-def.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - pub mod inner { #[expect(unexpected_cfgs)] pub fn i_am_here() { diff --git a/tests/ui/cfg/diagnostics-not-a-def.stderr b/tests/ui/cfg/diagnostics-not-a-def.stderr index 89bbf574871b..51c1c03640f6 100644 --- a/tests/ui/cfg/diagnostics-not-a-def.stderr +++ b/tests/ui/cfg/diagnostics-not-a-def.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function `i_am_not` in module `inner` - --> $DIR/diagnostics-not-a-def.rs:14:12 + --> $DIR/diagnostics-not-a-def.rs:12:12 | LL | inner::i_am_not(); | ^^^^^^^^ not found in `inner` diff --git a/tests/ui/empty/empty-attributes.rs b/tests/ui/empty/empty-attributes.rs index d319227b217a..027d30cce17f 100644 --- a/tests/ui/empty/empty-attributes.rs +++ b/tests/ui/empty/empty-attributes.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - #![deny(unused_attributes)] #![allow()] //~ ERROR unused attribute #![expect()] //~ ERROR unused attribute diff --git a/tests/ui/empty/empty-attributes.stderr b/tests/ui/empty/empty-attributes.stderr index 01d0d5a6b48b..e86dea10c705 100644 --- a/tests/ui/empty/empty-attributes.stderr +++ b/tests/ui/empty/empty-attributes.stderr @@ -1,18 +1,18 @@ error: unused attribute - --> $DIR/empty-attributes.rs:11:1 + --> $DIR/empty-attributes.rs:9:1 | LL | #[repr()] | ^^^^^^^^^ help: remove this attribute | = note: attribute `repr` with an empty list has no effect note: the lint level is defined here - --> $DIR/empty-attributes.rs:3:9 + --> $DIR/empty-attributes.rs:1:9 | LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/empty-attributes.rs:14:1 + --> $DIR/empty-attributes.rs:12:1 | LL | #[target_feature()] | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -20,7 +20,7 @@ LL | #[target_feature()] = note: attribute `target_feature` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:4:1 + --> $DIR/empty-attributes.rs:2:1 | LL | #![allow()] | ^^^^^^^^^^^ help: remove this attribute @@ -28,7 +28,7 @@ LL | #![allow()] = note: attribute `allow` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:5:1 + --> $DIR/empty-attributes.rs:3:1 | LL | #![expect()] | ^^^^^^^^^^^^ help: remove this attribute @@ -36,7 +36,7 @@ LL | #![expect()] = note: attribute `expect` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:6:1 + --> $DIR/empty-attributes.rs:4:1 | LL | #![warn()] | ^^^^^^^^^^ help: remove this attribute @@ -44,7 +44,7 @@ LL | #![warn()] = note: attribute `warn` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:7:1 + --> $DIR/empty-attributes.rs:5:1 | LL | #![deny()] | ^^^^^^^^^^ help: remove this attribute @@ -52,7 +52,7 @@ LL | #![deny()] = note: attribute `deny` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:8:1 + --> $DIR/empty-attributes.rs:6:1 | LL | #![forbid()] | ^^^^^^^^^^^^ help: remove this attribute @@ -60,7 +60,7 @@ LL | #![forbid()] = note: attribute `forbid` with an empty list has no effect error: unused attribute - --> $DIR/empty-attributes.rs:9:1 + --> $DIR/empty-attributes.rs:7:1 | LL | #![feature()] | ^^^^^^^^^^^^^ help: remove this attribute diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr index b6b5cd5c3d3e..b0b6033aadd2 100644 --- a/tests/ui/error-codes/E0602.stderr +++ b/tests/ui/error-codes/E0602.stderr @@ -13,6 +13,11 @@ warning[E0602]: unknown lint: `bogus` = note: requested on the command line with `-D bogus` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning: 3 warnings emitted +warning[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 4 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.rs b/tests/ui/feature-gates/feature-gate-lint-reasons.rs deleted file mode 100644 index 7756074e235a..000000000000 --- a/tests/ui/feature-gates/feature-gate-lint-reasons.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![warn(nonstandard_style, reason = "the standard should be respected")] -//~^ ERROR lint reasons are experimental -//~| ERROR lint reasons are experimental - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr deleted file mode 100644 index efcb3a10f32d..000000000000 --- a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0658]: lint reasons are experimental - --> $DIR/feature-gate-lint-reasons.rs:1:28 - | -LL | #![warn(nonstandard_style, reason = "the standard should be respected")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #54503 for more information - = help: add `#![feature(lint_reasons)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: lint reasons are experimental - --> $DIR/feature-gate-lint-reasons.rs:1:28 - | -LL | #![warn(nonstandard_style, reason = "the standard should be respected")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #54503 for more information - = help: add `#![feature(lint_reasons)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs index a213994ff86c..f6120b3fc70e 100644 --- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs +++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - use std::ops::Deref; pub trait Foo { diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs index 02fe5b0e19bf..591429d60475 100644 --- a/tests/ui/impl-trait/in-trait/deep-match-works.rs +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - pub struct Wrapper(T); pub trait Foo { diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr index 9cc4c4b2f9e5..a0840699268a 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -5,7 +5,7 @@ LL | let _: &dyn rpitit::Foo = todo!(); | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/auxiliary/rpitit.rs:6:21 + --> $DIR/auxiliary/rpitit.rs:4:21 | LL | fn bar(self) -> impl Deref; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs index ca759afc2e6e..3b6f79a4f52d 100644 --- a/tests/ui/impl-trait/in-trait/foreign.rs +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -1,8 +1,6 @@ //@ check-pass //@ aux-build: rpitit.rs -#![feature(lint_reasons)] - extern crate rpitit; use rpitit::{Foo, Foreign}; diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr index 1a5a4f2432b1..36114dcf02b6 100644 --- a/tests/ui/impl-trait/in-trait/foreign.stderr +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -1,5 +1,5 @@ warning: impl trait in impl method signature does not match trait method signature - --> $DIR/foreign.rs:23:21 + --> $DIR/foreign.rs:21:21 | LL | fn bar(self) -> Arc { | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn bar(self) -> Arc { = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 for more information note: the lint level is defined here - --> $DIR/foreign.rs:22:12 + --> $DIR/foreign.rs:20:12 | LL | #[warn(refining_impl_trait)] | ^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | fn bar(self) -> impl Deref { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: impl trait in impl method signature does not match trait method signature - --> $DIR/foreign.rs:33:21 + --> $DIR/foreign.rs:31:21 | LL | fn bar(self) -> Arc { | ^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | fn bar(self) -> Arc { = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: we are soliciting feedback, see issue #121718 for more information note: the lint level is defined here - --> $DIR/foreign.rs:31:12 + --> $DIR/foreign.rs:29:12 | LL | #[warn(refining_impl_trait)] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs index 91fb5331f769..6e4954582281 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - use std::fmt::Display; use std::ops::Deref; diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs index f949077a1317..f6ce31e38379 100644 --- a/tests/ui/impl-trait/in-trait/reveal.rs +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - pub trait Foo { fn f() -> Box; } diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs index b9fe8d8bfc59..4e46b7114c1a 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.rs @@ -1,7 +1,5 @@ // issue: 113903 -#![feature(lint_reasons)] - use std::ops::Deref; pub trait Tr { diff --git a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr index 73ada8d70961..e7d38f224064 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-shadowed-by-missing-adt.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/rpitit-shadowed-by-missing-adt.rs:8:35 + --> $DIR/rpitit-shadowed-by-missing-adt.rs:6:35 | LL | fn w() -> impl Deref>; | ^^^^^^^ not found in this scope diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr index 0cd76815afa7..56b83cbca77a 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr @@ -1,5 +1,5 @@ error[E0623]: lifetime mismatch - --> $DIR/signature-mismatch.rs:79:10 + --> $DIR/signature-mismatch.rs:77:10 | LL | &'a self, | -------- this parameter and the return type are declared with different lifetimes... diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 7a74281b1f29..55b9a0de5ff0 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -2,8 +2,6 @@ //@ revisions: success failure //@[success] check-pass -#![feature(lint_reasons)] - use std::future::Future; pub trait Captures<'a> {} diff --git a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs index 3ef6735de804..50bb61c9f024 100644 --- a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs +++ b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(specialization)] -#![feature(lint_reasons)] #![allow(incomplete_features)] pub trait Foo { diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs index c99291def034..97a1ce809972 100644 --- a/tests/ui/impl-trait/in-trait/success.rs +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - use std::fmt::Display; pub trait Foo { diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr index 5084b4a40013..cfff190b54af 100644 --- a/tests/ui/lint/cli-unknown-force-warn.stderr +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -13,6 +13,11 @@ warning[E0602]: unknown lint: `foo_qux` = note: requested on the command line with `--force-warn foo_qux` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning: 3 warnings emitted +warning[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 4 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs index 37c78bc68ed0..20999df9844e 100644 --- a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.rs @@ -7,7 +7,6 @@ // it also checks that the `dead_code` lint is also *NOT* emited // for `bar` as it's suppresed by the `#[expect]` on `bar` -#![feature(lint_reasons)] #![warn(dead_code)] // to override compiletest fn bar() {} diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr index d5c4dabed015..a199859cb20b 100644 --- a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-2.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/allow-or-expect-dead_code-114557-2.rs:15:10 + --> $DIR/allow-or-expect-dead_code-114557-2.rs:14:10 | LL | #[expect(dead_code)] | ^^^^^^^^^ diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs index d2ead24b57ca..08103b233872 100644 --- a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.rs @@ -3,7 +3,6 @@ // this test makes sure that the `unfulfilled_lint_expectations` lint // is being emited for `foo` as foo is not dead code, it's pub -#![feature(lint_reasons)] #![warn(dead_code)] // to override compiletest #[expect(dead_code)] diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr index c954a75b3941..3169f0123e94 100644 --- a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557-3.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/allow-or-expect-dead_code-114557-3.rs:9:10 + --> $DIR/allow-or-expect-dead_code-114557-3.rs:8:10 | LL | #[expect(dead_code)] | ^^^^^^^^^ diff --git a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs index 323bb06b681c..f2625f0781f6 100644 --- a/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs +++ b/tests/ui/lint/dead-code/allow-or-expect-dead_code-114557.rs @@ -4,7 +4,6 @@ // this test checks that no matter if we put #[allow(dead_code)] // or #[expect(dead_code)], no warning is being emited -#![feature(lint_reasons)] #![warn(dead_code)] // to override compiletest fn f() {} diff --git a/tests/ui/lint/empty-lint-attributes.rs b/tests/ui/lint/empty-lint-attributes.rs index b12b4064990b..0193345e5c8c 100644 --- a/tests/ui/lint/empty-lint-attributes.rs +++ b/tests/ui/lint/empty-lint-attributes.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - //@ check-pass // Empty (and reason-only) lint attributes are legal—although we may want to diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 3321afa7fcd7..2a24e795f443 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -26,5 +26,10 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -error: aborting due to 4 previous errors +error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index fd63433c3086..78ae2fd8fbff 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -26,5 +26,10 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -error: aborting due to 1 previous error; 3 warnings emitted +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index 0e182a4e5dea..3c1a59ec1e1c 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -29,5 +29,11 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: aborting due to 4 previous errors +error: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = help: use the new name `bare_trait_objects` + = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index d6bb72f34dce..6544416f6114 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -29,5 +29,11 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: aborting due to 1 previous error; 3 warnings emitted +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = help: use the new name `bare_trait_objects` + = note: requested on the command line with `-D bare_trait_object` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr index 0efec51abaf6..39377b6fe846 100644 --- a/tests/ui/lint/lint-unexported-no-mangle.stderr +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -45,5 +45,15 @@ LL | pub const PUB_FOO: u64 = 1; | | | help: try a static value: `pub static` -error: aborting due to 2 previous errors; 6 warnings emitted +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors; 8 warnings emitted diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr index f12ce03ddfce..1ce55706d765 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr @@ -30,6 +30,17 @@ error[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr index f452fc9eb943..4e0c5dbcb073 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -30,6 +30,17 @@ warning[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning: 6 warnings emitted +warning[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 8 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs index 7366a03232f3..244b376b60d8 100644 --- a/tests/ui/lint/reasons-erroneous.rs +++ b/tests/ui/lint/reasons-erroneous.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes -#![feature(lint_reasons)] - #![warn(absolute_paths_not_starting_with_crate, reason = 0)] //~^ ERROR malformed lint attribute //~| NOTE reason must be a string literal diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr index 003da5673704..adc97174b99c 100644 --- a/tests/ui/lint/reasons-erroneous.stderr +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -1,47 +1,47 @@ error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:5:58 + --> $DIR/reasons-erroneous.rs:3:58 | LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:8:40 + --> $DIR/reasons-erroneous.rs:6:40 | LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:11:29 + --> $DIR/reasons-erroneous.rs:9:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:14:23 + --> $DIR/reasons-erroneous.rs:12:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:17:36 + --> $DIR/reasons-erroneous.rs:15:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:20:44 + --> $DIR/reasons-erroneous.rs:18:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last error[E0452]: malformed lint attribute input - --> $DIR/reasons-erroneous.rs:23:25 + --> $DIR/reasons-erroneous.rs:21:25 | LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last warning: unknown lint: `reason` - --> $DIR/reasons-erroneous.rs:26:39 + --> $DIR/reasons-erroneous.rs:24:39 | LL | #![warn(missing_copy_implementations, reason)] | ^^^^^^ diff --git a/tests/ui/lint/reasons-forbidden.rs b/tests/ui/lint/reasons-forbidden.rs index 0b08e7571db0..47a1454e7148 100644 --- a/tests/ui/lint/reasons-forbidden.rs +++ b/tests/ui/lint/reasons-forbidden.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - // If you turn off deduplicate diagnostics (which rustc turns on by default but // compiletest turns off when it runs ui tests), then the errors are // (unfortunately) repeated here because the checking is done as we read in the diff --git a/tests/ui/lint/reasons-forbidden.stderr b/tests/ui/lint/reasons-forbidden.stderr index ab6f19a019d4..cecc83450796 100644 --- a/tests/ui/lint/reasons-forbidden.stderr +++ b/tests/ui/lint/reasons-forbidden.stderr @@ -1,5 +1,5 @@ error[E0453]: allow(unsafe_code) incompatible with previous forbid - --> $DIR/reasons-forbidden.rs:25:13 + --> $DIR/reasons-forbidden.rs:23:13 | LL | unsafe_code, | ----------- `forbid` level set here @@ -10,7 +10,7 @@ LL | #[allow(unsafe_code)] = note: our errors & omissions insurance policy doesn't cover unsafe Rust error: usage of an `unsafe` block - --> $DIR/reasons-forbidden.rs:29:5 + --> $DIR/reasons-forbidden.rs:27:5 | LL | / unsafe { LL | | @@ -21,7 +21,7 @@ LL | | } | = note: our errors & omissions insurance policy doesn't cover unsafe Rust note: the lint level is defined here - --> $DIR/reasons-forbidden.rs:14:5 + --> $DIR/reasons-forbidden.rs:12:5 | LL | unsafe_code, | ^^^^^^^^^^^ diff --git a/tests/ui/lint/reasons.rs b/tests/ui/lint/reasons.rs index 4c2f92af1c70..917e7539aaed 100644 --- a/tests/ui/lint/reasons.rs +++ b/tests/ui/lint/reasons.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] #![warn(elided_lifetimes_in_paths, //~^ NOTE the lint level is defined here reason = "explicit anonymous lifetimes aid reasoning about ownership")] diff --git a/tests/ui/lint/reasons.stderr b/tests/ui/lint/reasons.stderr index cd8412153f10..8028785ab94b 100644 --- a/tests/ui/lint/reasons.stderr +++ b/tests/ui/lint/reasons.stderr @@ -1,5 +1,5 @@ warning: hidden lifetime parameters in types are deprecated - --> $DIR/reasons.rs:20:34 + --> $DIR/reasons.rs:19:34 | LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | -----^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | = note: explicit anonymous lifetimes aid reasoning about ownership note: the lint level is defined here - --> $DIR/reasons.rs:4:9 + --> $DIR/reasons.rs:3:9 | LL | #![warn(elided_lifetimes_in_paths, | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ++++ warning: variable `Social_exchange_psychology` should have a snake case name - --> $DIR/reasons.rs:30:9 + --> $DIR/reasons.rs:29:9 | LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology` @@ -26,7 +26,7 @@ LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; = note: people shouldn't have to change their usual style habits to contribute to our project note: the lint level is defined here - --> $DIR/reasons.rs:8:5 + --> $DIR/reasons.rs:7:5 | LL | nonstandard_style, | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs index e94755618cf4..1322d2d5e890 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(lint_reasons)] #[expect(drop_bounds)] fn trigger_rustc_lints() { diff --git a/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs index ce4b89f5d999..3b702dbd1cc5 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - #![warn(unused)] // This expect attribute should catch all lint triggers diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs index 8f2550651257..0a39674144c7 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - #![warn(unused)] #![expect(unused_mut)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr index 7237f6fb6bba..90a2c54b5822 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/crate_level_expect.rs:7:11 + --> $DIR/crate_level_expect.rs:5:11 | LL | #![expect(unused_mut)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs index 7bfb84c88269..3a3cef2d00de 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - #![warn(unused)] macro_rules! expect_inside_macro { diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs index e6f7471b93ce..549f031cbf6a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - #![warn(unused_variables)] macro_rules! trigger_unused_variables_macro { diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr index 817e16fdcaa0..49dba1c7ffe8 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr @@ -1,5 +1,5 @@ warning: unused variable: `x` - --> $DIR/expect_lint_from_macro.rs:9:13 + --> $DIR/expect_lint_from_macro.rs:7:13 | LL | let x = 0; | ^ help: if this is intentional, prefix it with an underscore: `_x` @@ -8,14 +8,14 @@ LL | trigger_unused_variables_macro!(); | --------------------------------- in this macro invocation | note: the lint level is defined here - --> $DIR/expect_lint_from_macro.rs:5:9 + --> $DIR/expect_lint_from_macro.rs:3:9 | LL | #![warn(unused_variables)] | ^^^^^^^^^^^^^^^^ = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unused variable: `x` - --> $DIR/expect_lint_from_macro.rs:9:13 + --> $DIR/expect_lint_from_macro.rs:7:13 | LL | let x = 0; | ^ help: if this is intentional, prefix it with an underscore: `_x` diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs deleted file mode 100644 index 928e16106143..000000000000 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs +++ /dev/null @@ -1,9 +0,0 @@ -// should error due to missing feature gate. - -#![warn(unused)] - -#[expect(unused)] -//~^ ERROR: the `#[expect]` attribute is an experimental feature [E0658] -fn main() { - let x = 1; -} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr deleted file mode 100644 index 5d252fdcf5da..000000000000 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[expect]` attribute is an experimental feature - --> $DIR/expect_missing_feature_gate.rs:5:1 - | -LL | #[expect(unused)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #54503 for more information - = help: add `#![feature(lint_reasons)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs index 1534d5f862cd..5d80a7ca0467 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - #![warn(unused)] // The warnings are not double triggers, they identify different unfulfilled lint diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr index 90ee744b26b0..c551c55fbeda 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:10:28 + --> $DIR/expect_multiple_lints.rs:8:28 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^ @@ -7,43 +7,43 @@ LL | #[expect(unused_variables, unused_mut, while_true)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:10:40 + --> $DIR/expect_multiple_lints.rs:8:40 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:19:10 + --> $DIR/expect_multiple_lints.rs:17:10 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:19:40 + --> $DIR/expect_multiple_lints.rs:17:40 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:28:10 + --> $DIR/expect_multiple_lints.rs:26:10 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:28:28 + --> $DIR/expect_multiple_lints.rs:26:28 | LL | #[expect(unused_variables, unused_mut, while_true)] | ^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:36:18 + --> $DIR/expect_multiple_lints.rs:34:18 | LL | #[expect(unused, while_true)] | ^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_multiple_lints.rs:45:10 + --> $DIR/expect_multiple_lints.rs:43:10 | LL | #[expect(unused, while_true)] | ^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs index 8f94bd6ec6cb..1d365363ceb6 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs @@ -1,6 +1,5 @@ // ignore-tidy-linelength -#![feature(lint_reasons)] #![warn(unused_mut)] #[expect( diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr index 0e445d2439b4..02710d9f2af2 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr @@ -1,5 +1,5 @@ warning: variable does not need to be mutable - --> $DIR/expect_nested_lint_levels.rs:36:13 + --> $DIR/expect_nested_lint_levels.rs:35:13 | LL | let mut v = 0; | ----^ @@ -8,25 +8,25 @@ LL | let mut v = 0; | = note: this overrides the previous `expect` lint level and warns about the `unused_mut` lint here note: the lint level is defined here - --> $DIR/expect_nested_lint_levels.rs:31:9 + --> $DIR/expect_nested_lint_levels.rs:30:9 | LL | unused_mut, | ^^^^^^^^^^ error: unused variable: `this_is_my_function` - --> $DIR/expect_nested_lint_levels.rs:48:9 + --> $DIR/expect_nested_lint_levels.rs:47:9 | LL | let this_is_my_function = 3; | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function` | note: the lint level is defined here - --> $DIR/expect_nested_lint_levels.rs:45:10 + --> $DIR/expect_nested_lint_levels.rs:44:10 | LL | #[forbid(unused_variables)] | ^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect_nested_lint_levels.rs:7:5 + --> $DIR/expect_nested_lint_levels.rs:6:5 | LL | unused_mut, | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | unused_mut, = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_nested_lint_levels.rs:24:5 + --> $DIR/expect_nested_lint_levels.rs:23:5 | LL | unused_mut, | ^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | unused_mut, = note: this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered warning: this lint expectation is unfulfilled - --> $DIR/expect_nested_lint_levels.rs:43:10 + --> $DIR/expect_nested_lint_levels.rs:42:10 | LL | #[expect(unused_variables)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs index d066a2b6ba6b..bdea0fa1ce05 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(lint_reasons)] #[warn(unused_variables)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr index 69f7cda08ef0..14e78ddd305e 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_on_fn_params.rs:9:43 + --> $DIR/expect_on_fn_params.rs:8:43 | LL | fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs index 7a57ab0f9818..c99317d6aa88 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(lint_reasons)] //! This file tests the `#[expect]` attribute implementation for tool lints. The same //! file is used to test clippy and rustdoc. Any changes to this file should be synced diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr index efe1aa04e5e2..cd6dae0d761f 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:33:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:32:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[expect(dead_code)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:38:18 | LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs index 577c6855fbe8..413833ba351b 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs @@ -1,7 +1,6 @@ //@ check-pass // ignore-tidy-linelength -#![feature(lint_reasons)] #![warn(unused_mut)] #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr index 9a1c3e442bb9..bd2df362a77a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_unfulfilled_expectation.rs:7:11 + --> $DIR/expect_unfulfilled_expectation.rs:6:11 | LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_unfulfilled_expectation.rs:13:10 + --> $DIR/expect_unfulfilled_expectation.rs:12:10 | LL | #[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | #[expect(unfulfilled_lint_expectations, reason = "a local: idk why you woul = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message warning: this lint expectation is unfulfilled - --> $DIR/expect_unfulfilled_expectation.rs:18:14 + --> $DIR/expect_unfulfilled_expectation.rs:17:14 | LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] | ^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | #[expect(unused_mut, reason = "this expectation will create a diagnosti = note: this expectation will create a diagnostic with the default lint level warning: this lint expectation is unfulfilled - --> $DIR/expect_unfulfilled_expectation.rs:25:22 + --> $DIR/expect_unfulfilled_expectation.rs:24:22 | LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs index 44a715e4cdca..0ba63aa7bf8c 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unused_inside_impl_block.rs @@ -1,7 +1,6 @@ //@ check-pass //@ incremental -#![feature(lint_reasons)] #![warn(unused)] struct OneUnused; diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs index 7c0ecd190101..9e06140f80c8 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs @@ -1,7 +1,5 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes -#![feature(lint_reasons)] - #[forbid(unused_variables)] //~^ NOTE `forbid` level set here #[expect(unused_variables)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr index 0f42ffbdea36..e6d7896ddd40 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr @@ -1,5 +1,5 @@ error[E0453]: expect(unused_variables) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:7:10 + --> $DIR/expect_with_forbid.rs:5:10 | LL | #[forbid(unused_variables)] | ---------------- `forbid` level set here @@ -8,7 +8,7 @@ LL | #[expect(unused_variables)] | ^^^^^^^^^^^^^^^^ overruled by previous forbid error[E0453]: expect(while_true) incompatible with previous forbid - --> $DIR/expect_with_forbid.rs:15:10 + --> $DIR/expect_with_forbid.rs:13:10 | LL | #[forbid(while_true)] | ---------- `forbid` level set here @@ -17,13 +17,13 @@ LL | #[expect(while_true)] | ^^^^^^^^^^ overruled by previous forbid error: denote infinite loops with `loop { ... }` - --> $DIR/expect_with_forbid.rs:22:5 + --> $DIR/expect_with_forbid.rs:20:5 | LL | while true {} | ^^^^^^^^^^ help: use `loop` | note: the lint level is defined here - --> $DIR/expect_with_forbid.rs:12:10 + --> $DIR/expect_with_forbid.rs:10:10 | LL | #[forbid(while_true)] | ^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs index 29e60a265da4..482c8134a83f 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] #![warn(unused)] #![expect(unused_variables, reason = "")] diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr index e349e4081f86..644f3fa7906e 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_with_reason.rs:6:11 + --> $DIR/expect_with_reason.rs:5:11 | LL | #![expect(unused_variables, reason = "")] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs index efe921b76af3..ad85a777ef9a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs @@ -3,8 +3,6 @@ //@ compile-flags: --force-warn unused_mut //@ check-pass -#![feature(lint_reasons)] - fn expect_early_pass_lint() { #[expect(while_true)] while true { diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr index 169f03aed941..29e579464c8d 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -1,5 +1,5 @@ warning: unused variable: `x` - --> $DIR/force_warn_expected_lints_fulfilled.rs:20:9 + --> $DIR/force_warn_expected_lints_fulfilled.rs:18:9 | LL | let x = 2; | ^ help: if this is intentional, prefix it with an underscore: `_x` @@ -7,13 +7,13 @@ LL | let x = 2; = note: requested on the command line with `--force-warn unused-variables` warning: unused variable: `fox_name` - --> $DIR/force_warn_expected_lints_fulfilled.rs:28:9 + --> $DIR/force_warn_expected_lints_fulfilled.rs:26:9 | LL | let fox_name = "Sir Nibbles"; | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_fox_name` warning: variable does not need to be mutable - --> $DIR/force_warn_expected_lints_fulfilled.rs:32:9 + --> $DIR/force_warn_expected_lints_fulfilled.rs:30:9 | LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; | ----^^^^^^^^^^^^^^^^^^^^^ @@ -23,13 +23,13 @@ LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; = note: requested on the command line with `--force-warn unused-mut` warning: unused variable: `this_should_fulfill_the_expectation` - --> $DIR/force_warn_expected_lints_fulfilled.rs:43:9 + --> $DIR/force_warn_expected_lints_fulfilled.rs:41:9 | LL | let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation` warning: denote infinite loops with `loop { ... }` - --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 + --> $DIR/force_warn_expected_lints_fulfilled.rs:8:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs index 2751f5d8303f..a43c75c3455e 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs @@ -3,8 +3,6 @@ //@ compile-flags: --force-warn unused_mut //@ check-pass -#![feature(lint_reasons)] - fn expect_early_pass_lint(terminate: bool) { #[expect(while_true)] //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr index c74fabe27dc8..f5e66694b8ea 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr @@ -1,5 +1,5 @@ warning: unused variable: `this_should_not_fulfill_the_expectation` - --> $DIR/force_warn_expected_lints_unfulfilled.rs:40:9 + --> $DIR/force_warn_expected_lints_unfulfilled.rs:38:9 | LL | let this_should_not_fulfill_the_expectation = "maybe"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_not_fulfill_the_expectation` @@ -7,7 +7,7 @@ LL | let this_should_not_fulfill_the_expectation = "maybe"; = note: requested on the command line with `--force-warn unused-variables` warning: this lint expectation is unfulfilled - --> $DIR/force_warn_expected_lints_unfulfilled.rs:9:14 + --> $DIR/force_warn_expected_lints_unfulfilled.rs:7:14 | LL | #[expect(while_true)] | ^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[expect(while_true)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/force_warn_expected_lints_unfulfilled.rs:17:10 + --> $DIR/force_warn_expected_lints_unfulfilled.rs:15:10 | LL | #[expect(unused_variables, reason="")] | ^^^^^^^^^^^^^^^^ @@ -23,13 +23,13 @@ LL | #[expect(unused_variables, reason=" warning: this lint expectation is unfulfilled - --> $DIR/force_warn_expected_lints_unfulfilled.rs:24:10 + --> $DIR/force_warn_expected_lints_unfulfilled.rs:22:10 | LL | #[expect(unused)] | ^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/force_warn_expected_lints_unfulfilled.rs:36:10 + --> $DIR/force_warn_expected_lints_unfulfilled.rs:34:10 | LL | #[expect(unused)] | ^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs index 545939b13698..078c3a59eb3e 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] - fn expect_early_pass_lints() { #[expect(while_true)] while true { diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs index 9431655c41d3..4e2377a2dc39 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] #![warn(unused)] #[expect(unused_variables)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs index bafdea96e08d..a7767769344a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs @@ -1,5 +1,3 @@ -#![feature(lint_reasons)] - #![deny(unused_attributes)] #[allow(reason = "I want to allow something")]//~ ERROR unused attribute diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr index 3e9d70821b57..7f01c2dc61be 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr @@ -1,18 +1,18 @@ error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:5:1 + --> $DIR/lint-attribute-only-with-reason.rs:3:1 | LL | #[allow(reason = "I want to allow something")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: attribute `allow` without any lints has no effect note: the lint level is defined here - --> $DIR/lint-attribute-only-with-reason.rs:3:9 + --> $DIR/lint-attribute-only-with-reason.rs:1:9 | LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:6:1 + --> $DIR/lint-attribute-only-with-reason.rs:4:1 | LL | #[expect(reason = "I don't know what I'm waiting for")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -20,7 +20,7 @@ LL | #[expect(reason = "I don't know what I'm waiting for")] = note: attribute `expect` without any lints has no effect error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:7:1 + --> $DIR/lint-attribute-only-with-reason.rs:5:1 | LL | #[warn(reason = "This should be warn by default")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -28,7 +28,7 @@ LL | #[warn(reason = "This should be warn by default")] = note: attribute `warn` without any lints has no effect error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:8:1 + --> $DIR/lint-attribute-only-with-reason.rs:6:1 | LL | #[deny(reason = "All listed lints are denied")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute @@ -36,7 +36,7 @@ LL | #[deny(reason = "All listed lints are denied")] = note: attribute `deny` without any lints has no effect error: unused attribute - --> $DIR/lint-attribute-only-with-reason.rs:9:1 + --> $DIR/lint-attribute-only-with-reason.rs:7:1 | LL | #[forbid(reason = "Just some reason")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs index f02dfdcea305..8930f1cd3b94 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(lint_reasons)] #![warn(unused)] #[warn(unused_variables)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr index df7d6584f99d..31042c4bb6dc 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/multiple_expect_attrs.rs:7:10 + --> $DIR/multiple_expect_attrs.rs:6:10 | LL | #[expect(unused_variables)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs index 613335193841..9e38b94b76ce 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs @@ -2,8 +2,6 @@ //@ check-pass //@ compile-flags: -Z unpretty=expanded -#![feature(lint_reasons)] - // This `expect` will create an expectation with an unstable expectation id #[expect(while_true)] fn create_early_lint_pass_expectation() { diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout index 6a6b4dcff92e..d804c1d2d200 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -1,14 +1,12 @@ #![feature(prelude_import)] #![no_std] -// This ensures that ICEs like rust#94953 don't happen -//@ check-pass -//@ compile-flags: -Z unpretty=expanded - -#![feature(lint_reasons)] #[prelude_import] use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; +// This ensures that ICEs like rust#94953 don't happen +//@ check-pass +//@ compile-flags: -Z unpretty=expanded // This `expect` will create an expectation with an unstable expectation id #[expect(while_true)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs index 7b60b55eb612..f83066c138fc 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/root-attribute-confusion.rs @@ -2,6 +2,5 @@ //@ compile-flags: -Dunused_attributes #![deny(unused_crate_dependencies)] -#![feature(lint_reasons)] fn main() {} diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs index 73cec0a4496a..9f5dec4447fb 100644 --- a/tests/ui/target-feature/no-llvm-leaks.rs +++ b/tests/ui/target-feature/no-llvm-leaks.rs @@ -6,7 +6,7 @@ //@ build-pass #![no_core] #![crate_type = "rlib"] -#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api, lint_reasons)] +#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] #![stable(feature = "test", since = "1.0.0")] // Supporting minimal rust core code From 6997b6876d62b7c42faf12af3164c87ab733be13 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 25 Jun 2024 23:29:44 +0800 Subject: [PATCH 27/53] Detect unused structs which derived Default --- compiler/rustc_passes/src/dead.rs | 25 +++++++++++++++++++ library/alloc/src/sync/tests.rs | 2 +- library/core/src/default.rs | 1 + tests/ui/deriving/deriving-default-enum.rs | 2 +- .../issues/issue-68696-catch-during-unwind.rs | 1 + .../dead-code/unused-struct-derive-default.rs | 25 +++++++++++++++++++ .../unused-struct-derive-default.stderr | 24 ++++++++++++++++++ 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/dead-code/unused-struct-derive-default.rs create mode 100644 tests/ui/lint/dead-code/unused-struct-derive-default.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2cb3c5d8965c..a188a1c25633 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -400,6 +400,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return false; } + // don't ignore impls for Enums and pub Structs whose methods don't have self receiver, + // cause external crate may call such methods to construct values of these types + if let Some(local_impl_of) = impl_of.as_local() + && let Some(local_def_id) = def_id.as_local() + && let Some(fn_sig) = + self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) + && let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind + && let Res::Def(def_kind, did) = path.res + { + match def_kind { + // for example, #[derive(Default)] pub struct T(i32); + // external crate can call T::default() to construct T, + // so that don't ignore impl Default for pub Enum and Structs + DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => { + return false; + } + // don't ignore impl Default for Enums, + // cause we don't know which variant is constructed + DefKind::Enum => return false, + _ => (), + }; + } + if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 49eae718c169..1b123aa58f20 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -396,7 +396,7 @@ fn show_arc() { // Make sure deriving works with Arc #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] -struct Foo { +struct _Foo { inner: Arc, } diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 4524b352ec81..5cacedcb241a 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar; /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/tests/ui/deriving/deriving-default-enum.rs b/tests/ui/deriving/deriving-default-enum.rs index 96eba258c97e..6b59f39a67d4 100644 --- a/tests/ui/deriving/deriving-default-enum.rs +++ b/tests/ui/deriving/deriving-default-enum.rs @@ -22,6 +22,6 @@ enum MyOption { } fn main() { - assert_eq!(Foo::default(), Foo::Alpha); + assert!(matches!(Foo::default(), Foo::Alpha)); assert!(matches!(MyOption::::default(), MyOption::None)); } diff --git a/tests/ui/issues/issue-68696-catch-during-unwind.rs b/tests/ui/issues/issue-68696-catch-during-unwind.rs index 2368cccef0d8..80d63b0cde70 100644 --- a/tests/ui/issues/issue-68696-catch-during-unwind.rs +++ b/tests/ui/issues/issue-68696-catch-during-unwind.rs @@ -7,6 +7,7 @@ use std::panic::catch_unwind; +#[allow(dead_code)] #[derive(Default)] struct Guard; diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs new file mode 100644 index 000000000000..330ad32dd570 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -0,0 +1,25 @@ +#![deny(dead_code)] + +#[derive(Default)] +struct T; //~ ERROR struct `T` is never constructed + +#[derive(Default)] +struct Used; + +#[derive(Default)] +enum E { + #[default] + A, + B, //~ ERROR variant `B` is never constructed +} + +// external crate can call T2::default() to construct T2, +// so that no warnings for pub adts +#[derive(Default)] +pub struct T2 { + _unread: i32, +} + +fn main() { + let _x: Used = Default::default(); +} diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr new file mode 100644 index 000000000000..bbb0bd7be706 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -0,0 +1,24 @@ +error: struct `T` is never constructed + --> $DIR/unused-struct-derive-default.rs:4:8 + | +LL | struct T; + | ^ + | + = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis +note: the lint level is defined here + --> $DIR/unused-struct-derive-default.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: variant `B` is never constructed + --> $DIR/unused-struct-derive-default.rs:13:5 + | +LL | enum E { + | - variant in this enum +... +LL | B, + | ^ + +error: aborting due to 2 previous errors + From 48310525bd79636964ff09bff63c89bf6c9c2dda Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 10 Feb 2024 22:31:36 +0000 Subject: [PATCH 28/53] RFC 2383: Stabilize `lint_reasons` in Clippy :paperclips: --- src/tools/clippy/CHANGELOG.md | 2 +- .../clippy/book/src/lint_configuration.md | 2 + src/tools/clippy/clippy_config/src/conf.rs | 2 +- src/tools/clippy/clippy_config/src/msrvs.rs | 1 + .../clippy_lints/src/allow_attributes.rs | 74 ------------ .../src/attrs/allow_attributes.rs | 26 +++++ .../attrs/allow_attributes_without_reason.rs | 5 - .../clippy/clippy_lints/src/attrs/mod.rs | 71 ++++++++++-- .../clippy/clippy_lints/src/declared_lints.rs | 2 +- src/tools/clippy/clippy_lints/src/lib.rs | 6 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- src/tools/clippy/src/driver.rs | 2 +- .../ui-cargo/duplicate_mod/fail/src/main.rs | 1 - .../default/test.stderr | 11 +- .../undocumented_unsafe_blocks.default.stderr | 74 ++++++------ ...undocumented_unsafe_blocks.disabled.stderr | 94 ++++++++-------- .../undocumented_unsafe_blocks.rs | 1 - .../clippy/tests/ui/allow_attributes.fixed | 13 ++- src/tools/clippy/tests/ui/allow_attributes.rs | 13 ++- .../clippy/tests/ui/allow_attributes.stderr | 20 +++- .../ui/allow_attributes_without_reason.rs | 13 ++- .../ui/allow_attributes_without_reason.stderr | 29 ++++- .../clippy/tests/ui/async_yields_async.fixed | 1 - .../clippy/tests/ui/async_yields_async.rs | 1 - .../clippy/tests/ui/async_yields_async.stderr | 12 +- src/tools/clippy/tests/ui/boxed_local.rs | 1 - src/tools/clippy/tests/ui/boxed_local.stderr | 8 +- .../ui/checked_unwrap/simple_conditionals.rs | 1 - .../checked_unwrap/simple_conditionals.stderr | 54 ++++----- .../ui/default_numeric_fallback_i32.fixed | 1 - .../tests/ui/default_numeric_fallback_i32.rs | 1 - .../ui/default_numeric_fallback_i32.stderr | 56 ++++----- .../ui/derive_partial_eq_without_eq.fixed | 1 - .../tests/ui/derive_partial_eq_without_eq.rs | 1 - .../ui/derive_partial_eq_without_eq.stderr | 26 ++--- .../tests/ui/expect_tool_lint_rfc_2383.rs | 1 - .../tests/ui/expect_tool_lint_rfc_2383.stderr | 12 +- .../clippy/tests/ui/implicit_return.fixed | 1 - src/tools/clippy/tests/ui/implicit_return.rs | 1 - .../clippy/tests/ui/implicit_return.stderr | 32 +++--- src/tools/clippy/tests/ui/let_unit.fixed | 1 - src/tools/clippy/tests/ui/let_unit.rs | 1 - src/tools/clippy/tests/ui/let_unit.stderr | 8 +- .../clippy/tests/ui/macro_use_imports.fixed | 1 - .../clippy/tests/ui/macro_use_imports.rs | 1 - .../clippy/tests/ui/macro_use_imports.stderr | 8 +- .../tests/ui/macro_use_imports_expect.rs | 1 - .../tests/ui/manual_non_exhaustive_enum.rs | 1 - .../ui/manual_non_exhaustive_enum.stderr | 8 +- .../clippy/tests/ui/needless_borrow.fixed | 1 - src/tools/clippy/tests/ui/needless_borrow.rs | 1 - .../clippy/tests/ui/needless_borrow.stderr | 56 ++++----- .../tests/ui/needless_pass_by_ref_mut.rs | 1 - .../tests/ui/needless_pass_by_ref_mut.stderr | 68 +++++------ .../clippy/tests/ui/needless_return.fixed | 1 - src/tools/clippy/tests/ui/needless_return.rs | 1 - .../clippy/tests/ui/needless_return.stderr | 106 +++++++++--------- src/tools/clippy/tests/ui/nonminimal_bool.rs | 2 - .../clippy/tests/ui/nonminimal_bool.stderr | 58 +++++----- .../tests/ui/overly_complex_bool_expr.fixed | 1 - .../tests/ui/overly_complex_bool_expr.rs | 1 - .../tests/ui/overly_complex_bool_expr.stderr | 20 ++-- src/tools/clippy/tests/ui/ptr_arg.rs | 1 - src/tools/clippy/tests/ui/ptr_arg.stderr | 48 ++++---- .../clippy/tests/ui/redundant_clone.fixed | 1 - src/tools/clippy/tests/ui/redundant_clone.rs | 1 - .../clippy/tests/ui/redundant_clone.stderr | 78 ++++++------- .../tests/ui/ref_binding_to_reference.rs | 1 - .../tests/ui/ref_binding_to_reference.stderr | 14 +-- src/tools/clippy/tests/ui/same_name_method.rs | 1 - .../clippy/tests/ui/same_name_method.stderr | 24 ++-- .../tests/ui/unsafe_derive_deserialize.rs | 1 - .../tests/ui/unsafe_derive_deserialize.stderr | 8 +- .../tests/ui/used_underscore_binding.rs | 2 +- 74 files changed, 620 insertions(+), 582 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/allow_attributes.rs create mode 100644 src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index d7bcd7a19687..d1cd87473cef 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -1943,7 +1943,7 @@ Released 2022-05-19 [#8218](https://github.com/rust-lang/rust-clippy/pull/8218) * [`needless_match`] [#8471](https://github.com/rust-lang/rust-clippy/pull/8471) -* [`allow_attributes_without_reason`] (Requires `#![feature(lint_reasons)]`) +* [`allow_attributes_without_reason`] [#8504](https://github.com/rust-lang/rust-clippy/pull/8504) * [`print_in_format_impl`] [#8253](https://github.com/rust-lang/rust-clippy/pull/8253) diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index c8223007df7b..6dad3463aa47 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -669,6 +669,8 @@ The minimum rust version that the project supports. Defaults to the `rust-versio --- **Affected lints:** +* [`allow_attributes`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes) +* [`allow_attributes_without_reason`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason) * [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) * [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) * [`assigning_clones`](https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones) diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index cfdf620b7d07..279193e516e9 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -265,7 +265,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index a3e7d0c3fa5f..8bdb5b317e5d 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -17,6 +17,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,81,0 { LINT_REASONS_STABILIZATION } 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } diff --git a/src/tools/clippy/clippy_lints/src/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/allow_attributes.rs deleted file mode 100644 index 123d0e51eeee..000000000000 --- a/src/tools/clippy/clippy_lints/src/allow_attributes.rs +++ /dev/null @@ -1,74 +0,0 @@ -use ast::{AttrStyle, Attribute}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_from_proc_macro; -use rustc_ast as ast; -use rustc_errors::Applicability; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_session::declare_lint_pass; - -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of the `#[allow]` attribute and suggests replacing it with - /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) - /// - /// The expect attribute is still unstable and requires the `lint_reasons` - /// on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to - /// the crate root. - /// - /// This lint only warns outer attributes (`#[allow]`), as inner attributes - /// (`#![allow]`) are usually used to enable or disable lints on a global scale. - /// - /// ### Why restrict this? - /// `#[allow]` attributes can linger after their reason for existence is gone. - /// `#[expect]` attributes suppress the lint emission, but emit a warning if - /// the expectation is unfulfilled. This can be useful to be notified when the - /// lint is no longer triggered, which may indicate the attribute can be removed. - /// - /// ### Example - /// ```rust,ignore - /// #[allow(unused_mut)] - /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() - /// } - /// ``` - /// Use instead: - /// ```rust,ignore - /// #![feature(lint_reasons)] - /// #[expect(unused_mut)] - /// fn foo() -> usize { - /// let mut a = Vec::new(); - /// a.len() - /// } - /// ``` - #[clippy::version = "1.70.0"] - pub ALLOW_ATTRIBUTES, - restriction, - "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings." -} - -declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]); - -impl LateLintPass<'_> for AllowAttribute { - // Separate each crate's features. - fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) { - if !in_external_macro(cx.sess(), attr.span) - && cx.tcx.features().lint_reasons - && let AttrStyle::Outer = attr.style - && let Some(ident) = attr.ident() - && ident.name == rustc_span::symbol::sym::allow - && !is_from_proc_macro(cx, &attr) - { - span_lint_and_sugg( - cx, - ALLOW_ATTRIBUTES, - ident.span, - "#[allow] attribute found", - "replace it with", - "expect".into(), - Applicability::MachineApplicable, - ); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs new file mode 100644 index 000000000000..c5b6980b0b90 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs @@ -0,0 +1,26 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_from_proc_macro; +use rustc_ast::{AttrStyle, Attribute}; +use rustc_errors::Applicability; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; +use super::ALLOW_ATTRIBUTES; + +// Separate each crate's features. +pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) { + if !in_external_macro(cx.sess(), attr.span) + && let AttrStyle::Outer = attr.style + && let Some(ident) = attr.ident() + && !is_from_proc_macro(cx, &attr) + { + span_lint_and_sugg( + cx, + ALLOW_ATTRIBUTES, + ident.span, + "#[allow] attribute found", + "replace it with", + "expect".into(), + Applicability::MachineApplicable, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs index 4a22e17463fc..8bf985a36c7a 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -8,11 +8,6 @@ use rustc_span::sym; use rustc_span::symbol::Symbol; pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { - // Check for the feature - if !cx.tcx.features().lint_reasons { - return; - } - // Check if the reason is present if let Some(item) = items.last().and_then(NestedMetaItem::meta_item) && let MetaItemKind::NameValue(_) = &item.kind diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index e4c98a32fd67..da19f17998af 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -1,6 +1,7 @@ //! checks for attributes mod allow_attributes_without_reason; +mod allow_attributes; mod blanket_clippy_restriction_lints; mod deprecated_cfg_attr; mod deprecated_semver; @@ -14,11 +15,11 @@ mod unnecessary_clippy_cfg; mod useless_attribute; mod utils; -use clippy_config::msrvs::Msrv; +use clippy_config::msrvs::{self, Msrv}; use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem}; use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, impl_lint_pass}; +use rustc_session::impl_lint_pass; use rustc_span::sym; use utils::{is_lint_level, is_relevant_impl, is_relevant_item, is_relevant_trait}; @@ -272,23 +273,17 @@ declare_clippy_lint! { /// ### What it does /// Checks for attributes that allow lints without a reason. /// - /// (This requires the `lint_reasons` feature) - /// /// ### Why restrict this? /// Justifying each `allow` helps readers understand the reasoning, /// and may allow removing `allow` attributes if their purpose is obsolete. /// /// ### Example /// ```no_run - /// #![feature(lint_reasons)] - /// /// #![allow(clippy::some_lint)] /// ``` /// /// Use instead: /// ```no_run - /// #![feature(lint_reasons)] - /// /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")] /// ``` #[clippy::version = "1.61.0"] @@ -297,6 +292,41 @@ declare_clippy_lint! { "ensures that all `allow` and `expect` attributes have a reason" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of the `#[allow]` attribute and suggests replacing it with + /// the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) + /// + /// This lint only warns outer attributes (`#[allow]`), as inner attributes + /// (`#![allow]`) are usually used to enable or disable lints on a global scale. + /// + /// ### Why is this bad? + /// `#[expect]` attributes suppress the lint emission, but emit a warning, if + /// the expectation is unfulfilled. This can be useful to be notified when the + /// lint is no longer triggered. + /// + /// ### Example + /// ```rust,ignore + /// #[allow(unused_mut)] + /// fn foo() -> usize { + /// let mut a = Vec::new(); + /// a.len() + /// } + /// ``` + /// Use instead: + /// ```rust,ignore + /// #[expect(unused_mut)] + /// fn foo() -> usize { + /// let mut a = Vec::new(); + /// a.len() + /// } + /// ``` + #[clippy::version = "1.70.0"] + pub ALLOW_ATTRIBUTES, + restriction, + "`#[allow]` will not trigger if a warning isn't found. `#[expect]` triggers if there are no warnings." +} + declare_clippy_lint! { /// ### What it does /// Checks for `#[should_panic]` attributes without specifying the expected panic message. @@ -469,7 +499,12 @@ declare_clippy_lint! { "duplicated attribute" } -declare_lint_pass!(Attributes => [ +#[derive(Clone)] +pub struct Attributes { + msrv: Msrv, +} + +impl_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, DEPRECATED_SEMVER, @@ -480,6 +515,13 @@ declare_lint_pass!(Attributes => [ DUPLICATED_ATTRIBUTES, ]); +impl Attributes { + #[must_use] + pub fn new(msrv: Msrv) -> Self { + Self { msrv } + } +} + impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_crate(&mut self, cx: &LateContext<'tcx>) { blanket_clippy_restriction_lints::check_command_line(cx); @@ -492,8 +534,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { if is_lint_level(ident.name, attr.id) { blanket_clippy_restriction_lints::check(cx, ident.name, items); } + if matches!(ident.name, sym::allow) { + if self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { + allow_attributes::check(cx, attr); + } + } if matches!(ident.name, sym::allow | sym::expect) { - allow_attributes_without_reason::check(cx, ident.name, items, attr); + if self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) { + allow_attributes_without_reason::check(cx, ident.name, items, attr); + } } if items.is_empty() || !attr.has_name(sym::deprecated) { return; @@ -537,6 +586,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id())); } } + + extract_msrv_attr!(LateContext); } pub struct EarlyAttributes { diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 7e43a99e9f24..76a0e450e59a 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -38,7 +38,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ #[cfg(feature = "internal")] crate::utils::internal_lints::unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS_INFO, crate::absolute_paths::ABSOLUTE_PATHS_INFO, - crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, crate::approx_const::APPROX_CONSTANT_INFO, crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, @@ -49,6 +48,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO, crate::assigning_clones::ASSIGNING_CLONES_INFO, crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO, + crate::attrs::ALLOW_ATTRIBUTES_INFO, crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO, crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO, crate::attrs::DEPRECATED_CFG_ATTR_INFO, diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index ef322786dbcd..63461c14d779 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -6,7 +6,7 @@ #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(lint_reasons)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![feature(never_type)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] @@ -73,7 +73,6 @@ mod renamed_lints; // begin lints modules, do not remove this comment, it’s used in `update_lints` mod absolute_paths; -mod allow_attributes; mod almost_complete_range; mod approx_const; mod arc_with_non_send_sync; @@ -699,7 +698,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed)); store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(len_zero::LenZero)); - store.register_late_pass(|_| Box::new(attrs::Attributes)); + store.register_late_pass(move |_| Box::new(attrs::Attributes::new(msrv()))); store.register_late_pass(|_| Box::new(blocks_in_conditions::BlocksInConditions)); store.register_late_pass(|_| Box::new(unicode::Unicode)); store.register_late_pass(|_| Box::new(uninit_vec::UninitVec)); @@ -1065,7 +1064,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(needless_maybe_sized::NeedlessMaybeSized)); store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock)); store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped)); - store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute)); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv()))); store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct)); store.register_late_pass(move |_| { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 6848e8e5c304..ee43d95272a0 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -5,7 +5,7 @@ #![feature(f16)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(lint_reasons)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![feature(never_type)] #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 6117e76897f2..9b1577f24b8e 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -2,7 +2,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(rustc_private)] #![feature(let_chains)] -#![feature(lint_reasons)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs index 6478e65ac81a..a99fe2e12bb2 100644 --- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs +++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] mod a; diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr index d6b97f6fde1e..138eb6029494 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr @@ -1,3 +1,12 @@ +error: the feature `lint_reasons` has been stable since 1.81.0-dev and no longer requires an attribute to enable + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:2:24 + | +LL | #![feature(decl_macro, lint_reasons)] + | ^^^^^^^^^^^^ + | + = note: `-D stable-features` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(stable_features)]` + error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9 | @@ -183,5 +192,5 @@ LL | | } = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 37d690557370..a44c810b1350 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:286:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:291:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:305:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:315:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:321:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:333:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:361:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:382:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:415:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:421:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:478:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:487:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -291,13 +291,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -305,7 +305,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 400fde997e9f..db5ea5b62890 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | /* Safety: */ unsafe {} = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:286:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:291:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +73,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +81,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:305:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +97,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:315:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:321:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +117,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:333:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +133,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +141,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:361:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:382:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:415:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +197,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:407:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:421:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +241,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant item has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:478:5 | LL | // SAFETY: | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:487:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +287,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 | LL | / let _ = { LL | | if unsafe { true } { @@ -299,13 +299,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -321,7 +321,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:532:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:531:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -329,7 +329,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:536:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:535:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:540:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -345,7 +345,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:546:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:5 | LL | unsafe {} | ^^^^^^^^^ @@ -353,7 +353,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:550:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:5 | LL | unsafe { | ^^^^^^^^ @@ -361,7 +361,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:557:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:556:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -369,7 +369,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:562:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:561:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -377,7 +377,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:567:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:572:5 | LL | unsafe {} | ^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index e5ef9d35fb6b..02170e1f7402 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -10,7 +10,6 @@ clippy::let_unit_value, clippy::missing_safety_doc )] -#![feature(lint_reasons)] extern crate proc_macro_unsafe; diff --git a/src/tools/clippy/tests/ui/allow_attributes.fixed b/src/tools/clippy/tests/ui/allow_attributes.fixed index b506a9890f5b..49ee3ee17c70 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.fixed +++ b/src/tools/clippy/tests/ui/allow_attributes.fixed @@ -1,7 +1,6 @@ //@aux-build:proc_macros.rs #![allow(unused)] #![warn(clippy::allow_attributes)] -#![feature(lint_reasons)] #![no_main] extern crate proc_macros; @@ -47,3 +46,15 @@ fn ignore_proc_macro() { fn ignore_inner_attr() { #![allow(unused)] // Should not lint } + +#[clippy::msrv = "1.81"] +fn msrv_1_81() { + #[expect(unused)] + let x = 1; +} + +#[clippy::msrv = "1.80"] +fn msrv_1_80() { + #[allow(unused)] + let x = 1; +} diff --git a/src/tools/clippy/tests/ui/allow_attributes.rs b/src/tools/clippy/tests/ui/allow_attributes.rs index c7daa7abd9d4..854acf8348dc 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.rs +++ b/src/tools/clippy/tests/ui/allow_attributes.rs @@ -1,7 +1,6 @@ //@aux-build:proc_macros.rs #![allow(unused)] #![warn(clippy::allow_attributes)] -#![feature(lint_reasons)] #![no_main] extern crate proc_macros; @@ -47,3 +46,15 @@ fn ignore_proc_macro() { fn ignore_inner_attr() { #![allow(unused)] // Should not lint } + +#[clippy::msrv = "1.81"] +fn msrv_1_81() { + #[allow(unused)] + let x = 1; +} + +#[clippy::msrv = "1.80"] +fn msrv_1_80() { + #[allow(unused)] + let x = 1; +} diff --git a/src/tools/clippy/tests/ui/allow_attributes.stderr b/src/tools/clippy/tests/ui/allow_attributes.stderr index 9c99e88c796a..10dac0bc8080 100644 --- a/src/tools/clippy/tests/ui/allow_attributes.stderr +++ b/src/tools/clippy/tests/ui/allow_attributes.stderr @@ -1,5 +1,5 @@ error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:13:3 + --> tests/ui/allow_attributes.rs:12:3 | LL | #[allow(dead_code)] | ^^^^^ help: replace it with: `expect` @@ -8,10 +8,24 @@ LL | #[allow(dead_code)] = help: to override `-D warnings` add `#[allow(clippy::allow_attributes)]` error: #[allow] attribute found - --> tests/ui/allow_attributes.rs:22:30 + --> tests/ui/allow_attributes.rs:21:30 | LL | #[cfg_attr(panic = "unwind", allow(dead_code))] | ^^^^^ help: replace it with: `expect` -error: aborting due to 2 previous errors +error: #[allow] attribute found + --> tests/ui/allow_attributes.rs:52:7 + | +LL | #[allow(unused)] + | ^^^^^ help: replace it with: `expect` + +error: #[allow] attribute found + --> tests/ui/allow_attributes.rs:52:7 + | +LL | #[allow(unused)] + | ^^^^^ help: replace it with: `expect` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs index 523148d65869..86f6b2c5742a 100644 --- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs +++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.rs @@ -1,5 +1,4 @@ //@aux-build:proc_macros.rs -#![feature(lint_reasons)] #![deny(clippy::allow_attributes_without_reason)] #![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)] @@ -42,3 +41,15 @@ pub fn trigger_fp_result() -> Result<(), &'static str> { Err("asdf")?; Ok(()) } + +#[clippy::msrv = "1.81"] +fn msrv_1_81() { + #[allow(unused)] + let _ = 1; +} + +#[clippy::msrv = "1.80"] +fn msrv_1_80() { + #[allow(unused)] + let _ = 1; +} diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr index 770a771ec3d1..9bc3ca0f2afd 100644 --- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr +++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr @@ -1,18 +1,18 @@ error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:4:1 + --> tests/ui/allow_attributes_without_reason.rs:3:1 | LL | #![allow(unfulfilled_lint_expectations, clippy::duplicated_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` note: the lint level is defined here - --> tests/ui/allow_attributes_without_reason.rs:3:9 + --> tests/ui/allow_attributes_without_reason.rs:2:9 | LL | #![deny(clippy::allow_attributes_without_reason)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:10:1 + --> tests/ui/allow_attributes_without_reason.rs:9:1 | LL | #[allow(dead_code)] | ^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #[allow(dead_code)] = help: try adding a reason at the end with `, reason = ".."` error: `allow` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:11:1 + --> tests/ui/allow_attributes_without_reason.rs:10:1 | LL | #[allow(dead_code, deprecated)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,12 +28,29 @@ LL | #[allow(dead_code, deprecated)] = help: try adding a reason at the end with `, reason = ".."` error: `expect` attribute without specifying a reason - --> tests/ui/allow_attributes_without_reason.rs:12:1 + --> tests/ui/allow_attributes_without_reason.rs:11:1 | LL | #[expect(dead_code)] | ^^^^^^^^^^^^^^^^^^^^ | = help: try adding a reason at the end with `, reason = ".."` -error: aborting due to 4 previous errors +error: `allow` attribute without specifying a reason + --> tests/ui/allow_attributes_without_reason.rs:47:5 + | +LL | #[allow(unused)] + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + +error: `allow` attribute without specifying a reason + --> tests/ui/allow_attributes_without_reason.rs:47:5 + | +LL | #[allow(unused)] + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a reason at the end with `, reason = ".."` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/async_yields_async.fixed b/src/tools/clippy/tests/ui/async_yields_async.fixed index cfad78138053..208651bab1fd 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.fixed +++ b/src/tools/clippy/tests/ui/async_yields_async.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![feature(async_closure)] #![warn(clippy::async_yields_async)] #![allow(clippy::redundant_async_block)] diff --git a/src/tools/clippy/tests/ui/async_yields_async.rs b/src/tools/clippy/tests/ui/async_yields_async.rs index 7bc26647943f..b124c994442b 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.rs +++ b/src/tools/clippy/tests/ui/async_yields_async.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![feature(async_closure)] #![warn(clippy::async_yields_async)] #![allow(clippy::redundant_async_block)] diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index 991ad7ae0ae2..861c3f2ce4a5 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -1,5 +1,5 @@ error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:39:9 + --> tests/ui/async_yields_async.rs:38:9 | LL | let _h = async { | _____________________- @@ -20,7 +20,7 @@ LL + }.await | error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:44:9 + --> tests/ui/async_yields_async.rs:43:9 | LL | let _i = async { | ____________________- @@ -33,7 +33,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:50:9 + --> tests/ui/async_yields_async.rs:49:9 | LL | let _j = async || { | ________________________- @@ -52,7 +52,7 @@ LL + }.await | error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:55:9 + --> tests/ui/async_yields_async.rs:54:9 | LL | let _k = async || { | _______________________- @@ -65,7 +65,7 @@ LL | | }; | |_____- outer async construct error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:57:23 + --> tests/ui/async_yields_async.rs:56:23 | LL | let _l = async || CustomFutureType; | ^^^^^^^^^^^^^^^^ @@ -75,7 +75,7 @@ LL | let _l = async || CustomFutureType; | help: consider awaiting this value: `CustomFutureType.await` error: an async construct yields a type which is itself awaitable - --> tests/ui/async_yields_async.rs:63:9 + --> tests/ui/async_yields_async.rs:62:9 | LL | let _m = async || { | _______________________- diff --git a/src/tools/clippy/tests/ui/boxed_local.rs b/src/tools/clippy/tests/ui/boxed_local.rs index e888154c46de..fbd9e12fc189 100644 --- a/src/tools/clippy/tests/ui/boxed_local.rs +++ b/src/tools/clippy/tests/ui/boxed_local.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow( clippy::borrowed_box, clippy::needless_pass_by_value, diff --git a/src/tools/clippy/tests/ui/boxed_local.stderr b/src/tools/clippy/tests/ui/boxed_local.stderr index d3156c820b2c..7710233fa4db 100644 --- a/src/tools/clippy/tests/ui/boxed_local.stderr +++ b/src/tools/clippy/tests/ui/boxed_local.stderr @@ -1,5 +1,5 @@ error: local variable doesn't need to be boxed here - --> tests/ui/boxed_local.rs:40:13 + --> tests/ui/boxed_local.rs:39:13 | LL | fn warn_arg(x: Box) { | ^ @@ -8,19 +8,19 @@ LL | fn warn_arg(x: Box) { = help: to override `-D warnings` add `#[allow(clippy::boxed_local)]` error: local variable doesn't need to be boxed here - --> tests/ui/boxed_local.rs:123:12 + --> tests/ui/boxed_local.rs:122:12 | LL | pub fn new(_needs_name: Box>) -> () {} | ^^^^^^^^^^^ error: local variable doesn't need to be boxed here - --> tests/ui/boxed_local.rs:188:44 + --> tests/ui/boxed_local.rs:187:44 | LL | fn default_impl_x(self: Box, x: Box) -> u32 { | ^ error: local variable doesn't need to be boxed here - --> tests/ui/boxed_local.rs:196:16 + --> tests/ui/boxed_local.rs:195:16 | LL | fn foo(x: Box) {} | ^ diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs index 02f80cc52ac7..c3c8562edffb 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs @@ -1,5 +1,4 @@ //@no-rustfix: overlapping suggestions -#![feature(lint_reasons)] #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow( clippy::if_same_then_else, diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index bae621337601..ddd600418afe 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: called `unwrap` on `x` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:47:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -8,13 +8,13 @@ LL | x.unwrap(); | ^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui/checked_unwrap/simple_conditionals.rs:3:35 + --> tests/ui/checked_unwrap/simple_conditionals.rs:2:35 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:50:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:49:9 | LL | if x.is_some() { | -------------- help: try: `if let Some(..) = x` @@ -23,7 +23,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:54:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:53:9 | LL | if x.is_some() { | ----------- because of this check @@ -32,13 +32,13 @@ LL | x.unwrap(); | ^^^^^^^^^^ | note: the lint level is defined here - --> tests/ui/checked_unwrap/simple_conditionals.rs:3:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:2:9 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `expect()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:57:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:56:9 | LL | if x.is_some() { | ----------- because of this check @@ -47,7 +47,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:62:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:61:9 | LL | if x.is_none() { | ----------- because of this check @@ -56,7 +56,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_none` - --> tests/ui/checked_unwrap/simple_conditionals.rs:66:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:65:9 | LL | if x.is_none() { | -------------- help: try: `if let Some(..) = x` @@ -65,7 +65,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:14:13 + --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13 | LL | if $a.is_some() { | --------------- help: try: `if let Some(..) = x` @@ -79,7 +79,7 @@ LL | m!(x); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:79:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:78:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -88,7 +88,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `expect` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:82:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:81:9 | LL | if x.is_ok() { | ------------ help: try: `if let Ok(..) = x` @@ -97,7 +97,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:85:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:84:9 | LL | if x.is_ok() { | --------- because of this check @@ -106,7 +106,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:89:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:88:9 | LL | if x.is_ok() { | --------- because of this check @@ -115,7 +115,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: this call to `expect()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:92:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:91:9 | LL | if x.is_ok() { | --------- because of this check @@ -124,7 +124,7 @@ LL | x.expect("an error message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:95:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:94:9 | LL | if x.is_ok() { | ------------ help: try: `if let Err(..) = x` @@ -133,7 +133,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:100:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:99:9 | LL | if x.is_err() { | ---------- because of this check @@ -142,7 +142,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: called `unwrap_err` on `x` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/simple_conditionals.rs:103:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:102:9 | LL | if x.is_err() { | ------------- help: try: `if let Err(..) = x` @@ -151,7 +151,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: called `unwrap` on `x` after checking its variant with `is_err` - --> tests/ui/checked_unwrap/simple_conditionals.rs:107:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:106:9 | LL | if x.is_err() { | ------------- help: try: `if let Ok(..) = x` @@ -160,7 +160,7 @@ LL | x.unwrap(); | ^^^^^^^^^^ error: this call to `unwrap_err()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:110:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:109:9 | LL | if x.is_err() { | ---------- because of this check @@ -169,7 +169,7 @@ LL | x.unwrap_err(); | ^^^^^^^^^^^^^^ error: called `unwrap` on `option` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:135:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:134:9 | LL | if option.is_some() { | ------------------- help: try: `if let Some(..) = &option` @@ -177,7 +177,7 @@ LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:138:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:137:9 | LL | if option.is_some() { | ---------------- because of this check @@ -186,7 +186,7 @@ LL | option.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `result` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:145:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:144:9 | LL | if result.is_ok() { | ----------------- help: try: `if let Ok(..) = &result` @@ -194,7 +194,7 @@ LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:148:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:147:9 | LL | if result.is_ok() { | -------------- because of this check @@ -203,7 +203,7 @@ LL | result.as_ref().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `option` after checking its variant with `is_some` - --> tests/ui/checked_unwrap/simple_conditionals.rs:154:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:153:9 | LL | if option.is_some() { | ------------------- help: try: `if let Some(..) = &mut option` @@ -211,7 +211,7 @@ LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:157:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:156:9 | LL | if option.is_some() { | ---------------- because of this check @@ -220,7 +220,7 @@ LL | option.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: called `unwrap` on `result` after checking its variant with `is_ok` - --> tests/ui/checked_unwrap/simple_conditionals.rs:163:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:162:9 | LL | if result.is_ok() { | ----------------- help: try: `if let Ok(..) = &mut result` @@ -228,7 +228,7 @@ LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this call to `unwrap()` will always panic - --> tests/ui/checked_unwrap/simple_conditionals.rs:166:9 + --> tests/ui/checked_unwrap/simple_conditionals.rs:165:9 | LL | if result.is_ok() { | -------------- because of this check diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed index e7038082c089..f28ae04fd0a4 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed @@ -1,6 +1,5 @@ //@aux-build:proc_macros.rs -#![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] #![allow( unused, diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs index d8eeda704919..78a5006444ee 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs @@ -1,6 +1,5 @@ //@aux-build:proc_macros.rs -#![feature(lint_reasons)] #![warn(clippy::default_numeric_fallback)] #![allow( unused, diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr index 9961a3669ef2..67ab923ecf5f 100644 --- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr +++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr @@ -1,5 +1,5 @@ error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:21:17 + --> tests/ui/default_numeric_fallback_i32.rs:20:17 | LL | let x = 22; | ^^ help: consider adding suffix: `22_i32` @@ -8,145 +8,145 @@ LL | let x = 22; = help: to override `-D warnings` add `#[allow(clippy::default_numeric_fallback)]` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:18 + --> tests/ui/default_numeric_fallback_i32.rs:21:18 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:21 + --> tests/ui/default_numeric_fallback_i32.rs:21:21 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:22:24 + --> tests/ui/default_numeric_fallback_i32.rs:21:24 | LL | let x = [1, 2, 3]; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:23:28 + --> tests/ui/default_numeric_fallback_i32.rs:22:28 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:23:31 + --> tests/ui/default_numeric_fallback_i32.rs:22:31 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:23:44 + --> tests/ui/default_numeric_fallback_i32.rs:22:44 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `3_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:23:47 + --> tests/ui/default_numeric_fallback_i32.rs:22:47 | LL | let x = if true { (1, 2) } else { (3, 4) }; | ^ help: consider adding suffix: `4_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:24:23 + --> tests/ui/default_numeric_fallback_i32.rs:23:23 | LL | let x = match 1 { | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:25:13 + --> tests/ui/default_numeric_fallback_i32.rs:24:13 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:25:18 + --> tests/ui/default_numeric_fallback_i32.rs:24:18 | LL | 1 => 1, | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:26:18 + --> tests/ui/default_numeric_fallback_i32.rs:25:18 | LL | _ => 2, | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:45:21 + --> tests/ui/default_numeric_fallback_i32.rs:44:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:53:21 + --> tests/ui/default_numeric_fallback_i32.rs:52:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:59:21 + --> tests/ui/default_numeric_fallback_i32.rs:58:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:67:21 + --> tests/ui/default_numeric_fallback_i32.rs:66:21 | LL | let y = 1; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:83:27 + --> tests/ui/default_numeric_fallback_i32.rs:82:27 | LL | let f = || -> _ { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:87:29 + --> tests/ui/default_numeric_fallback_i32.rs:86:29 | LL | let f = || -> i32 { 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:101:21 + --> tests/ui/default_numeric_fallback_i32.rs:100:21 | LL | generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:104:32 + --> tests/ui/default_numeric_fallback_i32.rs:103:32 | LL | let x: _ = generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:122:28 + --> tests/ui/default_numeric_fallback_i32.rs:121:28 | LL | GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:125:36 + --> tests/ui/default_numeric_fallback_i32.rs:124:36 | LL | let _ = GenericStruct { x: 1 }; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:143:24 + --> tests/ui/default_numeric_fallback_i32.rs:142:24 | LL | GenericEnum::X(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:163:23 + --> tests/ui/default_numeric_fallback_i32.rs:162:23 | LL | s.generic_arg(1); | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:173:25 + --> tests/ui/default_numeric_fallback_i32.rs:172:25 | LL | inline!(let x = 22;); | ^^ help: consider adding suffix: `22_i32` @@ -154,19 +154,19 @@ LL | inline!(let x = 22;); = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info) error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:215:29 + --> tests/ui/default_numeric_fallback_i32.rs:214:29 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `1_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:215:32 + --> tests/ui/default_numeric_fallback_i32.rs:214:32 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `2_i32` error: default numeric fallback might occur - --> tests/ui/default_numeric_fallback_i32.rs:215:35 + --> tests/ui/default_numeric_fallback_i32.rs:214:35 | LL | let data_i32 = vec![1, 2, 3]; | ^ help: consider adding suffix: `3_i32` diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed index eb93eb8e8ed4..e4a33193a1ab 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs index 42dc435bdd52..a418b38e3499 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr index 29cd7da6b77d..7436114fadb2 100644 --- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr +++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr @@ -1,5 +1,5 @@ error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:12:17 + --> tests/ui/derive_partial_eq_without_eq.rs:11:17 | LL | #[derive(Debug, PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` @@ -8,73 +8,73 @@ LL | #[derive(Debug, PartialEq)] = help: to override `-D warnings` add `#[allow(clippy::derive_partial_eq_without_eq)]` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:70:10 + --> tests/ui/derive_partial_eq_without_eq.rs:69:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:76:10 + --> tests/ui/derive_partial_eq_without_eq.rs:75:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:82:10 + --> tests/ui/derive_partial_eq_without_eq.rs:81:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:85:10 + --> tests/ui/derive_partial_eq_without_eq.rs:84:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:91:10 + --> tests/ui/derive_partial_eq_without_eq.rs:90:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:97:10 + --> tests/ui/derive_partial_eq_without_eq.rs:96:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:110:17 + --> tests/ui/derive_partial_eq_without_eq.rs:109:17 | LL | #[derive(Debug, PartialEq, Clone)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:113:10 + --> tests/ui/derive_partial_eq_without_eq.rs:112:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:120:14 + --> tests/ui/derive_partial_eq_without_eq.rs:119:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:123:14 + --> tests/ui/derive_partial_eq_without_eq.rs:122:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:183:14 + --> tests/ui/derive_partial_eq_without_eq.rs:182:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:191:14 + --> tests/ui/derive_partial_eq_without_eq.rs:190:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs index 72097bfabd72..2634c56794e7 100644 --- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] //! This file tests the `#[expect]` attribute implementation for tool lints. The same //! file is used to test clippy and rustdoc. Any changes to this file should be synced //! to the other test files as well. diff --git a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr index 43e0b9279e4b..f70d3408aa4d 100644 --- a/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/src/tools/clippy/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:31:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:30:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -8,31 +8,31 @@ LL | #[expect(dead_code)] = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:37:18 + --> tests/ui/expect_tool_lint_rfc_2383.rs:36:18 | LL | #[expect(invalid_nan_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:108:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:107:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:116:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:115:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:122:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:121:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> tests/ui/expect_tool_lint_rfc_2383.rs:128:14 + --> tests/ui/expect_tool_lint_rfc_2383.rs:127:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/implicit_return.fixed b/src/tools/clippy/tests/ui/implicit_return.fixed index 897f1b766163..ba73e64f1862 100644 --- a/src/tools/clippy/tests/ui/implicit_return.fixed +++ b/src/tools/clippy/tests/ui/implicit_return.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] diff --git a/src/tools/clippy/tests/ui/implicit_return.rs b/src/tools/clippy/tests/ui/implicit_return.rs index fcff67b58071..522fc6a0a447 100644 --- a/src/tools/clippy/tests/ui/implicit_return.rs +++ b/src/tools/clippy/tests/ui/implicit_return.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::implicit_return)] #![allow(clippy::needless_return, clippy::needless_bool, unused, clippy::never_loop)] diff --git a/src/tools/clippy/tests/ui/implicit_return.stderr b/src/tools/clippy/tests/ui/implicit_return.stderr index 3ffed273e0f1..b2f7bc694395 100644 --- a/src/tools/clippy/tests/ui/implicit_return.stderr +++ b/src/tools/clippy/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing `return` statement - --> tests/ui/implicit_return.rs:11:5 + --> tests/ui/implicit_return.rs:10:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -8,85 +8,85 @@ LL | true = help: to override `-D warnings` add `#[allow(clippy::implicit_return)]` error: missing `return` statement - --> tests/ui/implicit_return.rs:15:15 + --> tests/ui/implicit_return.rs:14:15 | LL | if true { true } else { false } | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:15:29 + --> tests/ui/implicit_return.rs:14:29 | LL | if true { true } else { false } | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> tests/ui/implicit_return.rs:21:17 + --> tests/ui/implicit_return.rs:20:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing `return` statement - --> tests/ui/implicit_return.rs:22:20 + --> tests/ui/implicit_return.rs:21:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:35:9 + --> tests/ui/implicit_return.rs:34:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:42:13 + --> tests/ui/implicit_return.rs:41:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:50:13 + --> tests/ui/implicit_return.rs:49:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:68:18 + --> tests/ui/implicit_return.rs:67:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:69:16 + --> tests/ui/implicit_return.rs:68:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:77:5 + --> tests/ui/implicit_return.rs:76:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` error: missing `return` statement - --> tests/ui/implicit_return.rs:86:5 + --> tests/ui/implicit_return.rs:85:5 | LL | m!(true, false) | ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)` error: missing `return` statement - --> tests/ui/implicit_return.rs:92:13 + --> tests/ui/implicit_return.rs:91:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing `return` statement - --> tests/ui/implicit_return.rs:97:17 + --> tests/ui/implicit_return.rs:96:17 | LL | break 'outer false; | ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false` error: missing `return` statement - --> tests/ui/implicit_return.rs:112:5 + --> tests/ui/implicit_return.rs:111:5 | LL | / loop { LL | | m!(true); @@ -101,7 +101,7 @@ LL + } | error: missing `return` statement - --> tests/ui/implicit_return.rs:126:5 + --> tests/ui/implicit_return.rs:125:5 | LL | true | ^^^^ help: add `return` as shown: `return true` diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed index 20940daffa7a..3456e274f6a4 100644 --- a/src/tools/clippy/tests/ui/let_unit.fixed +++ b/src/tools/clippy/tests/ui/let_unit.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::let_unit_value)] #![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)] diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs index dca66f2e3edb..e2dafbcb7714 100644 --- a/src/tools/clippy/tests/ui/let_unit.rs +++ b/src/tools/clippy/tests/ui/let_unit.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::let_unit_value)] #![allow(unused, clippy::no_effect, clippy::needless_late_init, path_statements)] diff --git a/src/tools/clippy/tests/ui/let_unit.stderr b/src/tools/clippy/tests/ui/let_unit.stderr index aafb77bcd0d6..2f62c33c8873 100644 --- a/src/tools/clippy/tests/ui/let_unit.stderr +++ b/src/tools/clippy/tests/ui/let_unit.stderr @@ -1,5 +1,5 @@ error: this let-binding has unit value - --> tests/ui/let_unit.rs:12:5 + --> tests/ui/let_unit.rs:11:5 | LL | let _x = println!("x"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `println!("x");` @@ -8,7 +8,7 @@ LL | let _x = println!("x"); = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]` error: this let-binding has unit value - --> tests/ui/let_unit.rs:60:5 + --> tests/ui/let_unit.rs:59:5 | LL | / let _ = v LL | | .into_iter() @@ -31,7 +31,7 @@ LL + .unwrap(); | error: this let-binding has unit value - --> tests/ui/let_unit.rs:109:5 + --> tests/ui/let_unit.rs:108:5 | LL | / let x = match Some(0) { LL | | None => f2(1), @@ -52,7 +52,7 @@ LL + }; | error: this let-binding has unit value - --> tests/ui/let_unit.rs:190:9 + --> tests/ui/let_unit.rs:189:9 | LL | let res = returns_unit(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed index 46c053b779e7..38ed5a957e73 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.fixed +++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed @@ -4,7 +4,6 @@ //@ignore-32bit -#![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs index 47f5c9bf8845..ae6cc16ed276 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports.rs @@ -4,7 +4,6 @@ //@ignore-32bit -#![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr index a3733b1c0c96..ea0670d36667 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports.stderr +++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr @@ -1,5 +1,5 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:19:5 + --> tests/ui/macro_use_imports.rs:18:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};` @@ -8,19 +8,19 @@ LL | #[macro_use] = help: to override `-D warnings` add `#[allow(clippy::macro_use_imports)]` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:23:5 + --> tests/ui/macro_use_imports.rs:22:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:25:5 + --> tests/ui/macro_use_imports.rs:24:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;` error: `macro_use` attributes are no longer needed in the Rust 2018 edition - --> tests/ui/macro_use_imports.rs:21:5 + --> tests/ui/macro_use_imports.rs:20:5 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;` diff --git a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs index b9677851b92d..df6d5b9fbabf 100644 --- a/src/tools/clippy/tests/ui/macro_use_imports_expect.rs +++ b/src/tools/clippy/tests/ui/macro_use_imports_expect.rs @@ -3,7 +3,6 @@ //@aux-build:proc_macro_derive.rs //@ignore-32bit -#![feature(lint_reasons)] #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] #![warn(clippy::macro_use_imports)] diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs index eb3875320311..31c3cc801372 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::manual_non_exhaustive)] #![allow(unused)] //@no-rustfix diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr index ee43b8ddc024..dc669568dd2d 100644 --- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr +++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr @@ -1,5 +1,5 @@ error: this seems like a manual implementation of the non-exhaustive pattern - --> tests/ui/manual_non_exhaustive_enum.rs:5:1 + --> tests/ui/manual_non_exhaustive_enum.rs:4:1 | LL | enum E { | ^----- @@ -15,7 +15,7 @@ LL | | } | |_^ | help: remove this variant - --> tests/ui/manual_non_exhaustive_enum.rs:10:5 + --> tests/ui/manual_non_exhaustive_enum.rs:9:5 | LL | _C, | ^^ @@ -23,7 +23,7 @@ LL | _C, = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]` error: this seems like a manual implementation of the non-exhaustive pattern - --> tests/ui/manual_non_exhaustive_enum.rs:30:1 + --> tests/ui/manual_non_exhaustive_enum.rs:29:1 | LL | enum NoUnderscore { | ^---------------- @@ -38,7 +38,7 @@ LL | | } | |_^ | help: remove this variant - --> tests/ui/manual_non_exhaustive_enum.rs:34:5 + --> tests/ui/manual_non_exhaustive_enum.rs:33:5 | LL | C, | ^ diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index 5121077b4cab..cabdc22bda84 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow( unused, non_local_definitions, diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index e3a5cb280bad..50062589645f 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow( unused, non_local_definitions, diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index 4b2b17e7e570..bf0e265c2503 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:16:15 + --> tests/ui/needless_borrow.rs:15:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -8,163 +8,163 @@ LL | let _ = x(&&a); // warn = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:20:13 + --> tests/ui/needless_borrow.rs:19:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:32:13 + --> tests/ui/needless_borrow.rs:31:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:34:15 + --> tests/ui/needless_borrow.rs:33:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:40:27 + --> tests/ui/needless_borrow.rs:39:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:47:15 + --> tests/ui/needless_borrow.rs:46:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:48:15 + --> tests/ui/needless_borrow.rs:47:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:49:15 + --> tests/ui/needless_borrow.rs:48:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:50:15 + --> tests/ui/needless_borrow.rs:49:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:53:11 + --> tests/ui/needless_borrow.rs:52:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:60:13 + --> tests/ui/needless_borrow.rs:59:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:61:13 + --> tests/ui/needless_borrow.rs:60:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:62:23 + --> tests/ui/needless_borrow.rs:61:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:63:23 + --> tests/ui/needless_borrow.rs:62:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:72:14 + --> tests/ui/needless_borrow.rs:71:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:78:14 + --> tests/ui/needless_borrow.rs:77:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:90:13 + --> tests/ui/needless_borrow.rs:89:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:92:22 + --> tests/ui/needless_borrow.rs:91:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:102:5 + --> tests/ui/needless_borrow.rs:101:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:111:5 + --> tests/ui/needless_borrow.rs:110:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:137:23 + --> tests/ui/needless_borrow.rs:136:23 | LL | let x: (&str,) = (&"",); | ^^^ help: change this to: `""` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:179:13 + --> tests/ui/needless_borrow.rs:178:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:188:13 + --> tests/ui/needless_borrow.rs:187:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:225:22 + --> tests/ui/needless_borrow.rs:224:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:232:22 + --> tests/ui/needless_borrow.rs:231:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:236:22 + --> tests/ui/needless_borrow.rs:235:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:237:22 + --> tests/ui/needless_borrow.rs:236:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:258:23 + --> tests/ui/needless_borrow.rs:257:23 | LL | option.unwrap_or((&x.0,)); | ^^^^ help: change this to: `x.0` diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs index 3f5f55f40020..eee62122fdfd 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs @@ -5,7 +5,6 @@ clippy::ptr_arg )] #![warn(clippy::needless_pass_by_ref_mut)] -#![feature(lint_reasons)] //@no-rustfix use std::ptr::NonNull; diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr index 21ca393dcb63..51e3ba37dede 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,5 +1,5 @@ error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:12:11 + --> tests/ui/needless_pass_by_ref_mut.rs:11:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` @@ -8,79 +8,79 @@ LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_ref_mut)]` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:37:12 + --> tests/ui/needless_pass_by_ref_mut.rs:36:12 | LL | fn foo6(s: &mut Vec) { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:47:12 + --> tests/ui/needless_pass_by_ref_mut.rs:46:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:50:29 + --> tests/ui/needless_pass_by_ref_mut.rs:49:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:127:16 + --> tests/ui/needless_pass_by_ref_mut.rs:126:16 | LL | async fn a1(x: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:131:16 + --> tests/ui/needless_pass_by_ref_mut.rs:130:16 | LL | async fn a2(x: &mut i32, y: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:135:16 + --> tests/ui/needless_pass_by_ref_mut.rs:134:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:139:16 + --> tests/ui/needless_pass_by_ref_mut.rs:138:16 | LL | async fn a4(x: &mut i32, y: i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:143:24 + --> tests/ui/needless_pass_by_ref_mut.rs:142:24 | LL | async fn a5(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:147:24 + --> tests/ui/needless_pass_by_ref_mut.rs:146:24 | LL | async fn a6(x: i32, y: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:151:32 + --> tests/ui/needless_pass_by_ref_mut.rs:150:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:155:24 + --> tests/ui/needless_pass_by_ref_mut.rs:154:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:155:45 + --> tests/ui/needless_pass_by_ref_mut.rs:154:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:189:16 + --> tests/ui/needless_pass_by_ref_mut.rs:188:16 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -88,7 +88,7 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:195:20 + --> tests/ui/needless_pass_by_ref_mut.rs:194:20 | LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider changing to: `&u32` @@ -96,19 +96,19 @@ LL | fn cfg_warn(s: &mut u32) {} = note: this is cfg-gated and may require further changes error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:209:39 + --> tests/ui/needless_pass_by_ref_mut.rs:208:39 | LL | async fn inner_async2(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:217:26 + --> tests/ui/needless_pass_by_ref_mut.rs:216:26 | LL | async fn inner_async3(x: &mut i32, y: &mut u32) { | ^^^^^^^^ help: consider changing to: `&i32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:236:34 + --> tests/ui/needless_pass_by_ref_mut.rs:235:34 | LL | pub async fn call_in_closure1(n: &mut str) { | ^^^^^^^^ help: consider changing to: `&str` @@ -116,7 +116,7 @@ LL | pub async fn call_in_closure1(n: &mut str) { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:255:20 + --> tests/ui/needless_pass_by_ref_mut.rs:254:20 | LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -124,7 +124,7 @@ LL | pub fn closure2(n: &mut usize) -> impl '_ + FnMut() -> usize { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:266:26 + --> tests/ui/needless_pass_by_ref_mut.rs:265:26 | LL | pub async fn closure4(n: &mut usize) { | ^^^^^^^^^^ help: consider changing to: `&usize` @@ -132,85 +132,85 @@ LL | pub async fn closure4(n: &mut usize) { = warning: changing this function will impact semver compatibility error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:315:12 + --> tests/ui/needless_pass_by_ref_mut.rs:314:12 | LL | fn bar(&mut self) {} | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:317:18 + --> tests/ui/needless_pass_by_ref_mut.rs:316:18 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^^ help: consider changing to: `&self` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:317:45 + --> tests/ui/needless_pass_by_ref_mut.rs:316:45 | LL | async fn foo(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:325:46 + --> tests/ui/needless_pass_by_ref_mut.rs:324:46 | LL | async fn foo2(&mut self, u: &mut i32, v: &mut u32) { | ^^^^^^^^ help: consider changing to: `&u32` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:341:18 + --> tests/ui/needless_pass_by_ref_mut.rs:340:18 | LL | fn _empty_tup(x: &mut (())) {} | ^^^^^^^^^ help: consider changing to: `&()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:342:19 + --> tests/ui/needless_pass_by_ref_mut.rs:341:19 | LL | fn _single_tup(x: &mut ((i32,))) {} | ^^^^^^^^^^^^^ help: consider changing to: `&(i32,)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:343:18 + --> tests/ui/needless_pass_by_ref_mut.rs:342:18 | LL | fn _multi_tup(x: &mut ((i32, u32))) {} | ^^^^^^^^^^^^^^^^^ help: consider changing to: `&(i32, u32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:344:11 + --> tests/ui/needless_pass_by_ref_mut.rs:343:11 | LL | fn _fn(x: &mut (fn())) {} | ^^^^^^^^^^^ help: consider changing to: `&fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:346:23 + --> tests/ui/needless_pass_by_ref_mut.rs:345:23 | LL | fn _extern_rust_fn(x: &mut extern "Rust" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "Rust" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:347:20 + --> tests/ui/needless_pass_by_ref_mut.rs:346:20 | LL | fn _extern_c_fn(x: &mut extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:348:18 + --> tests/ui/needless_pass_by_ref_mut.rs:347:18 | LL | fn _unsafe_fn(x: &mut unsafe fn()) {} | ^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:349:25 + --> tests/ui/needless_pass_by_ref_mut.rs:348:25 | LL | fn _unsafe_extern_fn(x: &mut unsafe extern "C" fn()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn()` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:350:20 + --> tests/ui/needless_pass_by_ref_mut.rs:349:20 | LL | fn _fn_with_arg(x: &mut unsafe extern "C" fn(i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn(i32)` error: this argument is a mutable reference, but not used mutably - --> tests/ui/needless_pass_by_ref_mut.rs:351:20 + --> tests/ui/needless_pass_by_ref_mut.rs:350:20 | LL | fn _fn_with_ret(x: &mut unsafe extern "C" fn() -> (i32)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&unsafe extern "C" fn() -> (i32)` diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index a9271cb399d8..853f685f04c7 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![feature(yeet_expr)] #![allow(unused)] #![allow( diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index dc888bf667f1..e9c1e0e8ae8e 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![feature(yeet_expr)] #![allow(unused)] #![allow( diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index b49f199ba5ab..6c891fe7ad3f 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:26:5 + --> tests/ui/needless_return.rs:25:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:30:5 + --> tests/ui/needless_return.rs:29:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:35:5 + --> tests/ui/needless_return.rs:34:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:40:5 + --> tests/ui/needless_return.rs:39:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:45:9 + --> tests/ui/needless_return.rs:44:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:47:9 + --> tests/ui/needless_return.rs:46:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:53:17 + --> tests/ui/needless_return.rs:52:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:55:13 + --> tests/ui/needless_return.rs:54:13 | LL | return true; | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:62:9 + --> tests/ui/needless_return.rs:61:9 | LL | return true; | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:64:16 + --> tests/ui/needless_return.rs:63:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:68:5 + --> tests/ui/needless_return.rs:67:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:71:21 + --> tests/ui/needless_return.rs:70:21 | LL | fn test_void_fun() { | _____________________^ @@ -146,7 +146,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:76:11 + --> tests/ui/needless_return.rs:75:11 | LL | if b { | ___________^ @@ -161,7 +161,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:78:13 + --> tests/ui/needless_return.rs:77:13 | LL | } else { | _____________^ @@ -176,7 +176,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:86:14 + --> tests/ui/needless_return.rs:85:14 | LL | _ => return, | ^^^^^^ @@ -187,7 +187,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:94:24 + --> tests/ui/needless_return.rs:93:24 | LL | let _ = 42; | ________________________^ @@ -202,7 +202,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:97:14 + --> tests/ui/needless_return.rs:96:14 | LL | _ => return, | ^^^^^^ @@ -213,7 +213,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:110:9 + --> tests/ui/needless_return.rs:109:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:112:9 + --> tests/ui/needless_return.rs:111:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:134:32 + --> tests/ui/needless_return.rs:133:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -248,7 +248,7 @@ LL | bar.unwrap_or_else(|_| {}) | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:138:21 + --> tests/ui/needless_return.rs:137:21 | LL | let _ = || { | _____________________^ @@ -263,7 +263,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:141:20 + --> tests/ui/needless_return.rs:140:20 | LL | let _ = || return; | ^^^^^^ @@ -274,7 +274,7 @@ LL | let _ = || {}; | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:147:32 + --> tests/ui/needless_return.rs:146:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -285,7 +285,7 @@ LL | res.unwrap_or_else(|_| Foo) | ~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:156:5 + --> tests/ui/needless_return.rs:155:5 | LL | return true; | ^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:160:5 + --> tests/ui/needless_return.rs:159:5 | LL | return true; | ^^^^^^^^^^^ @@ -309,7 +309,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:165:9 + --> tests/ui/needless_return.rs:164:9 | LL | return true; | ^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:167:9 + --> tests/ui/needless_return.rs:166:9 | LL | return false; | ^^^^^^^^^^^^ @@ -333,7 +333,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:173:17 + --> tests/ui/needless_return.rs:172:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:175:13 + --> tests/ui/needless_return.rs:174:13 | LL | return true; | ^^^^^^^^^^^ @@ -356,7 +356,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:182:9 + --> tests/ui/needless_return.rs:181:9 | LL | return true; | ^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:184:16 + --> tests/ui/needless_return.rs:183:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -379,7 +379,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:188:5 + --> tests/ui/needless_return.rs:187:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:191:33 + --> tests/ui/needless_return.rs:190:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -406,7 +406,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:196:11 + --> tests/ui/needless_return.rs:195:11 | LL | if b { | ___________^ @@ -421,7 +421,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:198:13 + --> tests/ui/needless_return.rs:197:13 | LL | } else { | _____________^ @@ -436,7 +436,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:206:14 + --> tests/ui/needless_return.rs:205:14 | LL | _ => return, | ^^^^^^ @@ -447,7 +447,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:219:9 + --> tests/ui/needless_return.rs:218:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:221:9 + --> tests/ui/needless_return.rs:220:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:237:5 + --> tests/ui/needless_return.rs:236:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:249:9 + --> tests/ui/needless_return.rs:248:9 | LL | return true; | ^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:251:9 + --> tests/ui/needless_return.rs:250:9 | LL | return false; | ^^^^^^^^^^^^ @@ -509,7 +509,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:258:13 + --> tests/ui/needless_return.rs:257:13 | LL | return 10; | ^^^^^^^^^ @@ -524,7 +524,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:261:13 + --> tests/ui/needless_return.rs:260:13 | LL | return 100; | ^^^^^^^^^^ @@ -537,7 +537,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:269:9 + --> tests/ui/needless_return.rs:268:9 | LL | return 0; | ^^^^^^^^ @@ -549,7 +549,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:276:13 + --> tests/ui/needless_return.rs:275:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -564,7 +564,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:278:13 + --> tests/ui/needless_return.rs:277:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -577,7 +577,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:285:20 + --> tests/ui/needless_return.rs:284:20 | LL | let _ = 42; | ____________________^ @@ -594,7 +594,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:292:20 + --> tests/ui/needless_return.rs:291:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -606,7 +606,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:304:9 + --> tests/ui/needless_return.rs:303:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -618,7 +618,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:306:9 + --> tests/ui/needless_return.rs:305:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -630,7 +630,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:312:9 + --> tests/ui/needless_return.rs:311:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -642,7 +642,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:316:9 + --> tests/ui/needless_return.rs:315:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -654,7 +654,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:337:5 + --> tests/ui/needless_return.rs:336:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index 38157116e910..d117e8bf9c7a 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -1,6 +1,4 @@ //@no-rustfix: overlapping suggestions - -#![feature(lint_reasons)] #![allow( unused, clippy::diverging_sub_expression, diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr index b6af06d845ae..eafffdaf8a63 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr +++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr @@ -1,5 +1,5 @@ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:19:13 + --> tests/ui/nonminimal_bool.rs:17:13 | LL | let _ = !true; | ^^^^^ help: try: `false` @@ -8,43 +8,43 @@ LL | let _ = !true; = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:22:13 + --> tests/ui/nonminimal_bool.rs:20:13 | LL | let _ = !false; | ^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:24:13 + --> tests/ui/nonminimal_bool.rs:22:13 | LL | let _ = !!a; | ^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:26:13 + --> tests/ui/nonminimal_bool.rs:24:13 | LL | let _ = false || a; | ^^^^^^^^^^ help: try: `a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:31:13 + --> tests/ui/nonminimal_bool.rs:29:13 | LL | let _ = !(!a && b); | ^^^^^^^^^^ help: try: `a || !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:33:13 + --> tests/ui/nonminimal_bool.rs:31:13 | LL | let _ = !(!a || b); | ^^^^^^^^^^ help: try: `a && !b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:35:13 + --> tests/ui/nonminimal_bool.rs:33:13 | LL | let _ = !a && !(b && c); | ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:44:13 + --> tests/ui/nonminimal_bool.rs:42:13 | LL | let _ = a == b && c == 5 && a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:46:13 + --> tests/ui/nonminimal_bool.rs:44:13 | LL | let _ = a == b || c == 5 || a == b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | let _ = a == b || c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:48:13 + --> tests/ui/nonminimal_bool.rs:46:13 | LL | let _ = a == b && c == 5 && b == a; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | let _ = a == b && c == 5; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:50:13 + --> tests/ui/nonminimal_bool.rs:48:13 | LL | let _ = a != b || !(a != b || c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL | let _ = a != b || c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:52:13 + --> tests/ui/nonminimal_bool.rs:50:13 | LL | let _ = a != b && !(a != b && c == d); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,43 +109,43 @@ LL | let _ = a != b && c != d; | ~~~~~~~~~~~~~~~~ error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:83:8 + --> tests/ui/nonminimal_bool.rs:81:8 | LL | if matches!(true, true) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:163:8 + --> tests/ui/nonminimal_bool.rs:161:8 | LL | if !(12 == a) {} | ^^^^^^^^^^ help: try: `12 != a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:164:8 + --> tests/ui/nonminimal_bool.rs:162:8 | LL | if !(a == 12) {} | ^^^^^^^^^^ help: try: `a != 12` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:165:8 + --> tests/ui/nonminimal_bool.rs:163:8 | LL | if !(12 != a) {} | ^^^^^^^^^^ help: try: `12 == a` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:166:8 + --> tests/ui/nonminimal_bool.rs:164:8 | LL | if !(a != 12) {} | ^^^^^^^^^^ help: try: `a == 12` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:168:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try: `b != true` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:168:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `b != true` @@ -154,61 +154,61 @@ LL | if !b == true {} = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:170:8 + --> tests/ui/nonminimal_bool.rs:168:8 | LL | if !b == true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:169:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:171:8 + --> tests/ui/nonminimal_bool.rs:169:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `true != b` error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `true != b` error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:172:8 + --> tests/ui/nonminimal_bool.rs:170:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:173:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `true == b` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:173:8 + --> tests/ui/nonminimal_bool.rs:171:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:174:8 + --> tests/ui/nonminimal_bool.rs:172:8 | LL | if !b == !c {} | ^^^^^^^^ help: try: `b == c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:175:8 + --> tests/ui/nonminimal_bool.rs:173:8 | LL | if !b != !c {} | ^^^^^^^^ help: try: `b != c` diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed b/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed index 439b1145431c..b21e91aa3ad4 100644 --- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed +++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.fixed @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::overly_complex_bool_expr)] diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs b/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs index b96fd1adf118..35ef0a1240a5 100644 --- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs +++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow(unused, clippy::diverging_sub_expression)] #![warn(clippy::overly_complex_bool_expr)] diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr b/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr index 21dd5ade5356..5a754236fe4b 100644 --- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr +++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr @@ -1,11 +1,11 @@ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:11:13 + --> tests/ui/overly_complex_bool_expr.rs:10:13 | LL | let _ = a && b || a; | ^^^^^^^^^^^ help: it would look like the following: `a` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:11:18 + --> tests/ui/overly_complex_bool_expr.rs:10:18 | LL | let _ = a && b || a; | ^ @@ -13,49 +13,49 @@ LL | let _ = a && b || a; = help: to override `-D warnings` add `#[allow(clippy::overly_complex_bool_expr)]` error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:14:13 + --> tests/ui/overly_complex_bool_expr.rs:13:13 | LL | let _ = false && a; | ^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:14:22 + --> tests/ui/overly_complex_bool_expr.rs:13:22 | LL | let _ = false && a; | ^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:25:13 + --> tests/ui/overly_complex_bool_expr.rs:24:13 | LL | let _ = a == b && a != b; | ^^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:25:13 + --> tests/ui/overly_complex_bool_expr.rs:24:13 | LL | let _ = a == b && a != b; | ^^^^^^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:27:13 + --> tests/ui/overly_complex_bool_expr.rs:26:13 | LL | let _ = a < b && a >= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:27:13 + --> tests/ui/overly_complex_bool_expr.rs:26:13 | LL | let _ = a < b && a >= b; | ^^^^^ error: this boolean expression contains a logic bug - --> tests/ui/overly_complex_bool_expr.rs:29:13 + --> tests/ui/overly_complex_bool_expr.rs:28:13 | LL | let _ = a > b && a <= b; | ^^^^^^^^^^^^^^^ help: it would look like the following: `false` | help: this expression can be optimized out by applying boolean operations to the outer expression - --> tests/ui/overly_complex_bool_expr.rs:29:13 + --> tests/ui/overly_complex_bool_expr.rs:28:13 | LL | let _ = a > b && a <= b; | ^^^^^ diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 5d6e488972cd..e6ef62681212 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![allow( unused, clippy::many_single_char_names, diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 0342130c992b..1848ef80fc49 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -1,5 +1,5 @@ error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:14:14 + --> tests/ui/ptr_arg.rs:13:14 | LL | fn do_vec(x: &Vec) { | ^^^^^^^^^ help: change this to: `&[i64]` @@ -8,49 +8,49 @@ LL | fn do_vec(x: &Vec) { = help: to override `-D warnings` add `#[allow(clippy::ptr_arg)]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:20:18 + --> tests/ui/ptr_arg.rs:19:18 | LL | fn do_vec_mut(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:25:19 + --> tests/ui/ptr_arg.rs:24:19 | LL | fn do_vec_mut2(x: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [i64]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:31:14 + --> tests/ui/ptr_arg.rs:30:14 | LL | fn do_str(x: &String) { | ^^^^^^^ help: change this to: `&str` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:36:18 + --> tests/ui/ptr_arg.rs:35:18 | LL | fn do_str_mut(x: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:41:15 + --> tests/ui/ptr_arg.rs:40:15 | LL | fn do_path(x: &PathBuf) { | ^^^^^^^^ help: change this to: `&Path` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:46:19 + --> tests/ui/ptr_arg.rs:45:19 | LL | fn do_path_mut(x: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:55:18 + --> tests/ui/ptr_arg.rs:54:18 | LL | fn do_vec(x: &Vec); | ^^^^^^^^^ help: change this to: `&[i64]` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:69:14 + --> tests/ui/ptr_arg.rs:68:14 | LL | fn cloned(x: &Vec) -> Vec { | ^^^^^^^^ @@ -68,7 +68,7 @@ LL ~ x.to_owned() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:79:18 + --> tests/ui/ptr_arg.rs:78:18 | LL | fn str_cloned(x: &String) -> String { | ^^^^^^^ @@ -85,7 +85,7 @@ LL ~ x.to_owned() | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:88:19 + --> tests/ui/ptr_arg.rs:87:19 | LL | fn path_cloned(x: &PathBuf) -> PathBuf { | ^^^^^^^^ @@ -102,7 +102,7 @@ LL ~ x.to_path_buf() | error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:97:44 + --> tests/ui/ptr_arg.rs:96:44 | LL | fn false_positive_capacity(x: &Vec, y: &String) { | ^^^^^^^ @@ -117,19 +117,19 @@ LL ~ let c = y; | error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:112:25 + --> tests/ui/ptr_arg.rs:111:25 | LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:142:66 + --> tests/ui/ptr_arg.rs:141:66 | LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec, _s: &String) {} | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:172:21 + --> tests/ui/ptr_arg.rs:171:21 | LL | fn foo_vec(vec: &Vec) { | ^^^^^^^^ @@ -143,7 +143,7 @@ LL ~ let _ = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:178:23 + --> tests/ui/ptr_arg.rs:177:23 | LL | fn foo_path(path: &PathBuf) { | ^^^^^^^^ @@ -157,7 +157,7 @@ LL ~ let _ = path.to_path_buf().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:184:21 + --> tests/ui/ptr_arg.rs:183:21 | LL | fn foo_str(str: &PathBuf) { | ^^^^^^^^ @@ -171,43 +171,43 @@ LL ~ let _ = str.to_path_buf().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:191:29 + --> tests/ui/ptr_arg.rs:190:29 | LL | fn mut_vec_slice_methods(v: &mut Vec) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:254:17 + --> tests/ui/ptr_arg.rs:253:17 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:254:35 + --> tests/ui/ptr_arg.rs:253:35 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:254:51 + --> tests/ui/ptr_arg.rs:253:51 | LL | fn dyn_trait(a: &mut Vec, b: &mut String, c: &mut PathBuf) { | ^^^^^^^^^^^^ help: change this to: `&mut Path` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:280:39 + --> tests/ui/ptr_arg.rs:279:39 | LL | fn cow_elided_lifetime<'a>(input: &'a Cow) -> &'a str { | ^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:286:36 + --> tests/ui/ptr_arg.rs:285:36 | LL | fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` error: using a reference to `Cow` is not recommended - --> tests/ui/ptr_arg.rs:290:40 + --> tests/ui/ptr_arg.rs:289:40 | LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 867f5b210171..1f79b5e53600 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -1,5 +1,4 @@ // rustfix-only-machine-applicable -#![feature(lint_reasons)] #![warn(clippy::redundant_clone)] #![allow( clippy::drop_non_drop, diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index adcbd01e819c..6909faebc993 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -1,5 +1,4 @@ // rustfix-only-machine-applicable -#![feature(lint_reasons)] #![warn(clippy::redundant_clone)] #![allow( clippy::drop_non_drop, diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index 3c37288f5507..d66972bcb5b3 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> tests/ui/redundant_clone.rs:15:42 + --> tests/ui/redundant_clone.rs:14:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:15:14 + --> tests/ui/redundant_clone.rs:14:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,169 +13,169 @@ LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/redundant_clone.rs:18:15 + --> tests/ui/redundant_clone.rs:17:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:18:14 + --> tests/ui/redundant_clone.rs:17:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:21:15 + --> tests/ui/redundant_clone.rs:20:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:21:14 + --> tests/ui/redundant_clone.rs:20:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:24:15 + --> tests/ui/redundant_clone.rs:23:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:24:14 + --> tests/ui/redundant_clone.rs:23:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:26:42 + --> tests/ui/redundant_clone.rs:25:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:26:14 + --> tests/ui/redundant_clone.rs:25:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:28:42 + --> tests/ui/redundant_clone.rs:27:42 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:28:14 + --> tests/ui/redundant_clone.rs:27:14 | LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:30:29 + --> tests/ui/redundant_clone.rs:29:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:30:14 + --> tests/ui/redundant_clone.rs:29:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:32:29 + --> tests/ui/redundant_clone.rs:31:29 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:32:14 + --> tests/ui/redundant_clone.rs:31:14 | LL | let _s = OsString::new().to_os_string(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:43:19 + --> tests/ui/redundant_clone.rs:42:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:43:14 + --> tests/ui/redundant_clone.rs:42:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:75:25 + --> tests/ui/redundant_clone.rs:74:25 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:75:24 + --> tests/ui/redundant_clone.rs:74:24 | LL | if b { (a.clone(), a.clone()) } else { (Alpha, a) } | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:132:15 + --> tests/ui/redundant_clone.rs:131:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | +note: this value is dropped without further use + --> tests/ui/redundant_clone.rs:131:14 + | +LL | let _s = s.clone(); + | ^ + +error: redundant clone + --> tests/ui/redundant_clone.rs:132:15 + | +LL | let _t = t.clone(); + | ^^^^^^^^ help: remove this + | note: this value is dropped without further use --> tests/ui/redundant_clone.rs:132:14 | -LL | let _s = s.clone(); - | ^ - -error: redundant clone - --> tests/ui/redundant_clone.rs:133:15 - | -LL | let _t = t.clone(); - | ^^^^^^^^ help: remove this - | -note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:133:14 - | LL | let _t = t.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:143:19 + --> tests/ui/redundant_clone.rs:142:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:143:18 + --> tests/ui/redundant_clone.rs:142:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> tests/ui/redundant_clone.rs:155:14 + --> tests/ui/redundant_clone.rs:154:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> tests/ui/redundant_clone.rs:155:13 + --> tests/ui/redundant_clone.rs:154:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ error: redundant clone - --> tests/ui/redundant_clone.rs:209:11 + --> tests/ui/redundant_clone.rs:208:11 | LL | foo(&x.clone(), move || { | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/redundant_clone.rs:209:10 + --> tests/ui/redundant_clone.rs:208:10 | LL | foo(&x.clone(), move || { | ^ diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs index a4444c95e33c..001ed3119490 100644 --- a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs @@ -1,6 +1,5 @@ // FIXME: run-rustfix waiting on multi-span suggestions //@no-rustfix -#![feature(lint_reasons)] #![warn(clippy::ref_binding_to_reference)] #![allow(clippy::needless_borrowed_reference, clippy::explicit_auto_deref)] diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr index 96886f80265d..25ab98223827 100644 --- a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr +++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr @@ -1,5 +1,5 @@ error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:31:14 + --> tests/ui/ref_binding_to_reference.rs:30:14 | LL | Some(ref x) => x, | ^^^^^ @@ -12,7 +12,7 @@ LL | Some(x) => &x, | ~ ~~ error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:39:14 + --> tests/ui/ref_binding_to_reference.rs:38:14 | LL | Some(ref x) => { | ^^^^^ @@ -27,7 +27,7 @@ LL ~ &x | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:50:14 + --> tests/ui/ref_binding_to_reference.rs:49:14 | LL | Some(ref x) => m2!(x), | ^^^^^ @@ -38,7 +38,7 @@ LL | Some(x) => m2!(&x), | ~ ~~ error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:56:15 + --> tests/ui/ref_binding_to_reference.rs:55:15 | LL | let _ = |&ref x: &&String| { | ^^^^^ @@ -51,7 +51,7 @@ LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:63:12 + --> tests/ui/ref_binding_to_reference.rs:62:12 | LL | fn f2<'a>(&ref x: &&'a String) -> &'a String { | ^^^^^ @@ -65,7 +65,7 @@ LL ~ x | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:71:11 + --> tests/ui/ref_binding_to_reference.rs:70:11 | LL | fn f(&ref x: &&String) { | ^^^^^ @@ -78,7 +78,7 @@ LL ~ let _: &&String = &x; | error: this pattern creates a reference to a reference - --> tests/ui/ref_binding_to_reference.rs:80:11 + --> tests/ui/ref_binding_to_reference.rs:79:11 | LL | fn f(&ref x: &&String) { | ^^^^^ diff --git a/src/tools/clippy/tests/ui/same_name_method.rs b/src/tools/clippy/tests/ui/same_name_method.rs index 26b1a299ba1c..ba876c2b5a3f 100644 --- a/src/tools/clippy/tests/ui/same_name_method.rs +++ b/src/tools/clippy/tests/ui/same_name_method.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::same_name_method)] #![allow(dead_code, non_camel_case_types)] diff --git a/src/tools/clippy/tests/ui/same_name_method.stderr b/src/tools/clippy/tests/ui/same_name_method.stderr index 6c87a64b5051..fefdb5c9c23d 100644 --- a/src/tools/clippy/tests/ui/same_name_method.stderr +++ b/src/tools/clippy/tests/ui/same_name_method.stderr @@ -1,11 +1,11 @@ error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:21:13 + --> tests/ui/same_name_method.rs:20:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> tests/ui/same_name_method.rs:26:13 + --> tests/ui/same_name_method.rs:25:13 | LL | fn foo() {} | ^^^^^^^^^^^ @@ -13,62 +13,62 @@ LL | fn foo() {} = help: to override `-D warnings` add `#[allow(clippy::same_name_method)]` error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:36:13 + --> tests/ui/same_name_method.rs:35:13 | LL | fn clone() {} | ^^^^^^^^^^^^^ | note: existing `clone` defined here - --> tests/ui/same_name_method.rs:32:18 + --> tests/ui/same_name_method.rs:31:18 | LL | #[derive(Clone)] | ^^^^^ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:47:13 + --> tests/ui/same_name_method.rs:46:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> tests/ui/same_name_method.rs:52:13 + --> tests/ui/same_name_method.rs:51:13 | LL | fn foo() {} | ^^^^^^^^^^^ error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:62:13 + --> tests/ui/same_name_method.rs:61:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> tests/ui/same_name_method.rs:66:9 + --> tests/ui/same_name_method.rs:65:9 | LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:75:13 + --> tests/ui/same_name_method.rs:74:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> tests/ui/same_name_method.rs:80:9 + --> tests/ui/same_name_method.rs:79:9 | LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ error: method's name is the same as an existing method in a trait - --> tests/ui/same_name_method.rs:75:13 + --> tests/ui/same_name_method.rs:74:13 | LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> tests/ui/same_name_method.rs:82:9 + --> tests/ui/same_name_method.rs:81:9 | LL | impl T2 for S {} | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs index 5187e0790423..14371bc203b3 100644 --- a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs +++ b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.rs @@ -1,4 +1,3 @@ -#![feature(lint_reasons)] #![warn(clippy::unsafe_derive_deserialize)] #![allow(unused, clippy::missing_safety_doc)] diff --git a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr index 06719f23d57f..f2d4429f707a 100644 --- a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr +++ b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr @@ -1,5 +1,5 @@ error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:9:10 + --> tests/ui/unsafe_derive_deserialize.rs:8:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:18:10 + --> tests/ui/unsafe_derive_deserialize.rs:17:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:25:10 + --> tests/ui/unsafe_derive_deserialize.rs:24:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:34:10 + --> tests/ui/unsafe_derive_deserialize.rs:33:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs index a8f404b1400c..84dccf28f3b2 100644 --- a/src/tools/clippy/tests/ui/used_underscore_binding.rs +++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macro_derive.rs -#![feature(rustc_private, lint_reasons)] +#![feature(rustc_private)] #![warn(clippy::used_underscore_binding)] #![allow(clippy::disallowed_names, clippy::eq_op, clippy::uninlined_format_args)] From ee0623b78dd2100f937893cbf3bbdf6746e23b6d Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 10 Feb 2024 22:33:25 +0000 Subject: [PATCH 29/53] RFC 2383: Stabilize `lint_reasons` in Miri --- src/tools/miri/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f8410db4dd0f..8da00861f905 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -10,7 +10,7 @@ #![feature(yeet_expr)] #![feature(nonzero_ops)] #![feature(let_chains)] -#![feature(lint_reasons)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![feature(trait_upcasting)] #![feature(strict_overflow_ops)] #![feature(is_none_or)] From e3a2c9887c0e08c8f0d4a1e2b040c0a00fd2d8e4 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sat, 10 Feb 2024 23:37:13 +0000 Subject: [PATCH 30/53] RFC 2383: Update documentation --- src/doc/rustc/src/lints/levels.md | 60 ++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 93892d6ade61..1558e8790934 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -1,12 +1,13 @@ # Lint Levels -In `rustc`, lints are divided into five *levels*: +In `rustc`, lints are divided into six *levels*: 1. allow -2. warn -3. force-warn -4. deny -5. forbid +2. expect +3. warn +4. force-warn +5. deny +6. forbid Each lint has a default level (explained in the lint listing later in this chapter), and the compiler has a default warning level. First, let's explain @@ -33,6 +34,40 @@ But this code violates the `missing_docs` lint. These lints exist mostly to be manually turned on via configuration, as we'll talk about later in this section. +## expect + +Sometimes, it can be helpful to suppress lints, but at the same time ensure that +the code in question still emits them. The 'expect' level does exactly this. If +the lint in question is not emitted, the `unfulfilled_lint_expectation` lint +triggers on the `expect` attribute, notifying you that the expectation is no +longer fulfilled. + +```rust +fn main() { + #[expect(unused_variables)] + let unused = "Everyone ignores me"; + + #[expect(unused_variables)] + let used = "I'm useful"; + println!("The `used` value is equal to: {:?}", used); +} +``` + +This will produce the following warning: + +```txt +warning: this lint expectation is unfulfilled + --> src/main.rs:7:14 + | +7 | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default +``` + +This level can only be defined via the `#[expect]` attribute and not via the +console. Lints with the special 'force-warn' lint will still be emitted as usual. + ## warn The 'warn' lint level will produce a warning if you violate the lint. For example, @@ -240,6 +275,21 @@ And use multiple attributes together: pub fn foo() {} ``` +All lint attributes support an additional `reason` parameter, to give context why +a certain attribute was added. This reason will be displayed as part of the lint +message, if the lint is emitted at the defined level. + +```rust +use std::path::PathBuf; +pub fn get_path() -> PathBuf { + #[allow(unused_mut, reason = "this is only modified on some platforms")] + let mut file_name = PathBuf::from("git"); + #[cfg(target_os = "windows")] + file_name.set_extension("exe"); + file_name +} +``` + ### Capping lints `rustc` supports a flag, `--cap-lints LEVEL` that sets the "lint cap level." From d9e32a69a7c12505c40349d7632eea3565609f4c Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 11 Feb 2024 11:49:17 +0100 Subject: [PATCH 31/53] RFC 2373: Update tests for rustdoc for `lint_reasons` --- tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr index 5ae3c039d275..306496b6c856 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:16:11 + --> $DIR/expect-tool-lint-rfc-2383.rs:15:11 | LL | #![expect(rustdoc::missing_crate_level_docs)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | #![expect(rustdoc::missing_crate_level_docs)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:70:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:69:14 | LL | #[expect(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:75:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:74:14 | LL | #[expect(rustdoc::invalid_html_tags)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:80:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:79:14 | LL | #[expect(rustdoc::bare_urls)] | ^^^^^^^^^^^^^^^^^^ From b124b3666e2109d01c8ec02ecae6d2e965e4bbe8 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Tue, 4 Jun 2024 11:02:03 +0200 Subject: [PATCH 32/53] `sudo CI=green` && Review changes <3 --- compiler/rustc_builtin_macros/src/lib.rs | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 2 +- src/doc/rustc/src/lints/levels.md | 8 ++++---- .../ui-toml/macro_metavars_in_unsafe/default/test.rs | 2 +- .../macro_metavars_in_unsafe/default/test.stderr | 11 +---------- tests/ui/sse2.rs | 1 - 6 files changed, 8 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index b3ec9a577b5a..f8d936661457 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,6 +5,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(bootstrap, feature(lint_reasons))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] @@ -12,7 +13,6 @@ #![feature(decl_macro)] #![feature(if_let_guard)] #![feature(let_chains)] -#![cfg_attr(bootstrap, feature(lint_reasons))] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 39066ddcf000..472e93d202d7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -608,7 +608,7 @@ declare_lint! { } declare_lint! { - /// The `unfulfilled_lint_expectations` lint warns if a lint expectation is + /// The `unfulfilled_lint_expectations` lint detects when a lint expectation is /// unfulfilled. /// /// ### Example diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 1558e8790934..18e827bd3c98 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -47,8 +47,8 @@ fn main() { #[expect(unused_variables)] let unused = "Everyone ignores me"; - #[expect(unused_variables)] - let used = "I'm useful"; + #[expect(unused_variables)] // `unused_variables` lint is not emitted + let used = "I'm useful"; // the expectation is therefore unfulfilled println!("The `used` value is equal to: {:?}", used); } ``` @@ -65,8 +65,8 @@ warning: this lint expectation is unfulfilled = note: `#[warn(unfulfilled_lint_expectations)]` on by default ``` -This level can only be defined via the `#[expect]` attribute and not via the -console. Lints with the special 'force-warn' lint will still be emitted as usual. +This level can only be defined via the `#[expect]` attribute, there is no equivalent +flag. Lints with the special 'force-warn' level will still be emitted as usual. ## warn diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs index f5e01b431ad9..a312df5a43a0 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -1,5 +1,5 @@ //! Tests macro_metavars_in_unsafe with default configuration -#![feature(decl_macro, lint_reasons)] +#![feature(decl_macro)] #![warn(clippy::macro_metavars_in_unsafe)] #![allow(clippy::no_effect)] diff --git a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr index 138eb6029494..d6b97f6fde1e 100644 --- a/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr +++ b/src/tools/clippy/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr @@ -1,12 +1,3 @@ -error: the feature `lint_reasons` has been stable since 1.81.0-dev and no longer requires an attribute to enable - --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:2:24 - | -LL | #![feature(decl_macro, lint_reasons)] - | ^^^^^^^^^^^^ - | - = note: `-D stable-features` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(stable_features)]` - error: this macro expands metavariables in an unsafe block --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9 | @@ -192,5 +183,5 @@ LL | | } = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/sse2.rs b/tests/ui/sse2.rs index 9ed6f6fefbdc..a1894cc03dbc 100644 --- a/tests/ui/sse2.rs +++ b/tests/ui/sse2.rs @@ -2,7 +2,6 @@ #![allow(stable_features)] #![feature(cfg_target_feature)] -#![feature(lint_reasons)] use std::env; From b6074fffd1d1a8d1eee4e3b9e9431761761b80c1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Jun 2024 19:03:39 +0300 Subject: [PATCH 33/53] resolve: Tweak some naming around import ambiguities --- .../src/effective_visibilities.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 74 ++++++++----------- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 14 ++-- 4 files changed, 42 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index aab4a3366daa..dabed2388386 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -99,7 +99,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // is the maximum value among visibilities of bindings corresponding to that def id. for (binding, eff_vis) in visitor.import_effective_visibilities.iter() { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; - if !binding.is_ambiguity() { + if !binding.is_ambiguity_recursive() { if let Some(node_id) = import.id() { r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx) } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 96a4647b9428..3896fe4c4fa6 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -325,8 +325,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { - // FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity. - if !binding.is_ambiguity() + // FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity. + if !binding.is_ambiguity_recursive() && let NameBindingKind::Import { import: old_import, .. } = old_binding.kind && let NameBindingKind::Import { import, .. } = binding.kind @@ -337,21 +337,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // imported from the same glob-import statement. resolution.binding = Some(binding); } else if res != old_binding.res() { - let binding = if warn_ambiguity { - this.warn_ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding) - } else { - this.ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding) - }; - resolution.binding = Some(binding); + resolution.binding = Some(this.new_ambiguity_binding( + AmbiguityKind::GlobVsGlob, + old_binding, + binding, + warn_ambiguity, + )); } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { // We are glob-importing the same item but with greater visibility. resolution.binding = Some(binding); - } else if binding.is_ambiguity() { - resolution.binding = - Some(self.arenas.alloc_name_binding(NameBindingData { - warn_ambiguity: true, - ..(*binding).clone() - })); + } else if binding.is_ambiguity_recursive() { + resolution.binding = Some(this.new_warn_ambiguity_binding(binding)); } } (old_glob @ true, false) | (old_glob @ false, true) => { @@ -361,24 +357,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && nonglob_binding.expansion != LocalExpnId::ROOT && glob_binding.res() != nonglob_binding.res() { - resolution.binding = Some(this.ambiguity( + resolution.binding = Some(this.new_ambiguity_binding( AmbiguityKind::GlobVsExpanded, nonglob_binding, glob_binding, + false, )); } else { resolution.binding = Some(nonglob_binding); } - if let Some(old_binding) = resolution.shadowed_glob { - assert!(old_binding.is_glob_import()); - if glob_binding.res() != old_binding.res() { - resolution.shadowed_glob = Some(this.ambiguity( + if let Some(old_shadowed_glob) = resolution.shadowed_glob { + assert!(old_shadowed_glob.is_glob_import()); + if glob_binding.res() != old_shadowed_glob.res() { + resolution.shadowed_glob = Some(this.new_ambiguity_binding( AmbiguityKind::GlobVsGlob, - old_binding, + old_shadowed_glob, glob_binding, + false, )); - } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { + } else if !old_shadowed_glob.vis.is_at_least(binding.vis, this.tcx) { resolution.shadowed_glob = Some(glob_binding); } } else { @@ -397,29 +395,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }) } - fn ambiguity( + fn new_ambiguity_binding( &self, - kind: AmbiguityKind, + ambiguity_kind: AmbiguityKind, primary_binding: NameBinding<'a>, secondary_binding: NameBinding<'a>, + warn_ambiguity: bool, ) -> NameBinding<'a> { - self.arenas.alloc_name_binding(NameBindingData { - ambiguity: Some((secondary_binding, kind)), - ..(*primary_binding).clone() - }) + let ambiguity = Some((secondary_binding, ambiguity_kind)); + let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding }; + self.arenas.alloc_name_binding(data) } - fn warn_ambiguity( - &self, - kind: AmbiguityKind, - primary_binding: NameBinding<'a>, - secondary_binding: NameBinding<'a>, - ) -> NameBinding<'a> { - self.arenas.alloc_name_binding(NameBindingData { - ambiguity: Some((secondary_binding, kind)), - warn_ambiguity: true, - ..(*primary_binding).clone() - }) + fn new_warn_ambiguity_binding(&self, binding: NameBinding<'a>) -> NameBinding<'a> { + assert!(binding.is_ambiguity_recursive()); + self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding }) } // Use `f` to mutate the resolution of the name in the module. @@ -1381,8 +1371,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { target_bindings[ns].get(), ) { Ok(other_binding) => { - is_redundant = - binding.res() == other_binding.res() && !other_binding.is_ambiguity(); + is_redundant = binding.res() == other_binding.res() + && !other_binding.is_ambiguity_recursive(); if is_redundant { redundant_span[ns] = Some((other_binding.span, other_binding.is_import())); @@ -1455,7 +1445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .resolution(import.parent_scope.module, key) .borrow() .binding() - .is_some_and(|binding| binding.is_warn_ambiguity()); + .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_define( import.parent_scope.module, key, @@ -1480,7 +1470,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.for_each_child(self, |this, ident, _, binding| { let res = binding.res().expect_non_local(); - let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity; + let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity; if res != def::Res::Err && !error_ambiguity { let mut reexport_chain = SmallVec::new(); let mut next_binding = binding; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5ab6ba23a7da..66a1c05289b7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3730,7 +3730,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?; let (res, binding) = match ls_binding { LexicalScopeBinding::Item(binding) - if is_syntactic_ambiguity && binding.is_ambiguity() => + if is_syntactic_ambiguity && binding.is_ambiguity_recursive() => { // For ambiguous bindings we don't know all their definitions and cannot check // whether they can be shadowed by fresh bindings or not, so force an error. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3a831a7f19e0..94cdce1025fe 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -694,10 +694,12 @@ impl<'a> fmt::Debug for Module<'a> { } /// Records a possibly-private value, type, or module definition. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] struct NameBindingData<'a> { kind: NameBindingKind<'a>, ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, + /// Produce a warning instead of an error when reporting ambiguities inside this binding. + /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required. warn_ambiguity: bool, expansion: LocalExpnId, span: Span, @@ -718,7 +720,7 @@ impl<'a> ToNameBinding<'a> for NameBinding<'a> { } } -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), @@ -830,18 +832,18 @@ impl<'a> NameBindingData<'a> { } } - fn is_ambiguity(&self) -> bool { + fn is_ambiguity_recursive(&self) -> bool { self.ambiguity.is_some() || match self.kind { - NameBindingKind::Import { binding, .. } => binding.is_ambiguity(), + NameBindingKind::Import { binding, .. } => binding.is_ambiguity_recursive(), _ => false, } } - fn is_warn_ambiguity(&self) -> bool { + fn warn_ambiguity_recursive(&self) -> bool { self.warn_ambiguity || match self.kind { - NameBindingKind::Import { binding, .. } => binding.is_warn_ambiguity(), + NameBindingKind::Import { binding, .. } => binding.warn_ambiguity_recursive(), _ => false, } } From f4059771cf25e0d53124e7c867607e4134ea87f1 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 25 Jun 2024 13:19:36 -0400 Subject: [PATCH 34/53] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index bc89bffa5987..4ed7bee47f7d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit bc89bffa5987d4af8f71011c7557119b39e44a65 +Subproject commit 4ed7bee47f7dd4416b36fada1909e9a62c546246 From 6ba0a84df9172ea01f3c3661b4d8364e5a79ba69 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 14:27:43 -0400 Subject: [PATCH 35/53] rewrite lto-empty to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-empty/Makefile | 13 ------------- tests/run-make/lto-empty/rmake.rs | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/lto-empty/Makefile create mode 100644 tests/run-make/lto-empty/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 07073ef5d40c..7c882d3ce15f 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -97,7 +97,6 @@ run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile run-make/longjmp-across-rust/Makefile run-make/lto-dylib-dep/Makefile -run-make/lto-empty/Makefile run-make/lto-linkage-used-attr/Makefile run-make/lto-no-link-whole-rlib/Makefile run-make/lto-smoke-c/Makefile diff --git a/tests/run-make/lto-empty/Makefile b/tests/run-make/lto-empty/Makefile deleted file mode 100644 index 1b795c4b7380..000000000000 --- a/tests/run-make/lto-empty/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: cdylib-fat cdylib-thin - -cdylib-fat: - $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat - $(RUSTC) lib.rs -C lto=fat -C opt-level=3 -C incremental=$(TMPDIR)/inc-fat - -cdylib-thin: - $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin - $(RUSTC) lib.rs -C lto=thin -C opt-level=3 -C incremental=$(TMPDIR)/inc-thin - diff --git a/tests/run-make/lto-empty/rmake.rs b/tests/run-make/lto-empty/rmake.rs new file mode 100644 index 000000000000..7146d6e10ef9 --- /dev/null +++ b/tests/run-make/lto-empty/rmake.rs @@ -0,0 +1,17 @@ +// Compiling Rust code twice in a row with "fat" link-time-optimizations used to cause +// an internal compiler error (ICE). This was due to how the compiler would cache some modules +// to make subsequent compilations faster, at least one of which was required for LTO to link +// into. After this was patched in #63956, this test checks that the bug does not make +// a resurgence. +// See https://github.com/rust-lang/rust/issues/63349 + +//@ ignore-cross-compile + +use run_make_support::rustc; + +fn main() { + rustc().input("lib.rs").arg("-Clto=fat").opt_level("3").incremental("inc-fat").run(); + rustc().input("lib.rs").arg("-Clto=fat").opt_level("3").incremental("inc-fat").run(); + rustc().input("lib.rs").arg("-Clto=thin").opt_level("3").incremental("inc-thin").run(); + rustc().input("lib.rs").arg("-Clto=thin").opt_level("3").incremental("inc-thin").run(); +} From fe2406bcef7d0c51a39537283c7c151c8a2da238 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 14:45:49 -0400 Subject: [PATCH 36/53] rewrite invalid-so to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/invalid-so/Makefile | 7 ------- tests/run-make/invalid-so/rmake.rs | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 8 deletions(-) delete mode 100644 tests/run-make/invalid-so/Makefile create mode 100644 tests/run-make/invalid-so/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 7c882d3ce15f..560fd5c586ee 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -55,7 +55,6 @@ run-make/incr-foreign-head-span/Makefile run-make/interdependent-c-libraries/Makefile run-make/intrinsic-unreachable/Makefile run-make/invalid-library/Makefile -run-make/invalid-so/Makefile run-make/issue-107094/Makefile run-make/issue-109934-lto-debuginfo/Makefile run-make/issue-14698/Makefile diff --git a/tests/run-make/invalid-so/Makefile b/tests/run-make/invalid-so/Makefile deleted file mode 100644 index e36c7040bc6c..000000000000 --- a/tests/run-make/invalid-so/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -) - -all: - echo >> $(TMPDIR)/$(DYLIB_NAME) - $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`' diff --git a/tests/run-make/invalid-so/rmake.rs b/tests/run-make/invalid-so/rmake.rs new file mode 100644 index 000000000000..5cfda05334eb --- /dev/null +++ b/tests/run-make/invalid-so/rmake.rs @@ -0,0 +1,17 @@ +// When a fake library was given to the compiler, it would +// result in an obscure and unhelpful error message. This test +// creates a false "foo" dylib, and checks that the standard error +// explains that the file exists, but that its metadata is incorrect. +// See https://github.com/rust-lang/rust/pull/88368 + +use run_make_support::{dynamic_lib_name, fs_wrapper, rustc}; + +fn main() { + fs_wrapper::create_file(dynamic_lib_name("foo")); + rustc() + .crate_type("lib") + .extern_("foo", dynamic_lib_name("foo")) + .input("bar.rs") + .run_fail() + .assert_stderr_contains("invalid metadata files for crate `foo`"); +} From ee529b72f911250a4c5b717f42fb955cdc08aad5 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 25 Jun 2024 15:02:19 -0400 Subject: [PATCH 37/53] rewrite and rename issue-20626 to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/issue-20626/Makefile | 9 --------- .../foo.rs | 0 .../rmake.rs | 16 ++++++++++++++++ 4 files changed, 16 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/issue-20626/Makefile rename tests/run-make/{issue-20626 => raw-fn-pointer-opt-undefined-behavior}/foo.rs (100%) create mode 100644 tests/run-make/raw-fn-pointer-opt-undefined-behavior/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 560fd5c586ee..cb68589d8a4c 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -60,7 +60,6 @@ run-make/issue-109934-lto-debuginfo/Makefile run-make/issue-14698/Makefile run-make/issue-15460/Makefile run-make/issue-18943/Makefile -run-make/issue-20626/Makefile run-make/issue-22131/Makefile run-make/issue-25581/Makefile run-make/issue-26006/Makefile diff --git a/tests/run-make/issue-20626/Makefile b/tests/run-make/issue-20626/Makefile deleted file mode 100644 index 63eee910a9c3..000000000000 --- a/tests/run-make/issue-20626/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test output to be four -# The original error only occurred when printing, not when comparing using assert! - -all: - $(RUSTC) foo.rs -O - [ `$(call RUN,foo)` = "4" ] diff --git a/tests/run-make/issue-20626/foo.rs b/tests/run-make/raw-fn-pointer-opt-undefined-behavior/foo.rs similarity index 100% rename from tests/run-make/issue-20626/foo.rs rename to tests/run-make/raw-fn-pointer-opt-undefined-behavior/foo.rs diff --git a/tests/run-make/raw-fn-pointer-opt-undefined-behavior/rmake.rs b/tests/run-make/raw-fn-pointer-opt-undefined-behavior/rmake.rs new file mode 100644 index 000000000000..61cf559a8fe7 --- /dev/null +++ b/tests/run-make/raw-fn-pointer-opt-undefined-behavior/rmake.rs @@ -0,0 +1,16 @@ +// Despite the absence of any unsafe Rust code, foo.rs in this test would, +// because of the raw function pointer, +// cause undefined behavior and fail to print the expected result, "4" - +// only when activating optimizations (opt-level 2). This test checks +// that this bug does not make a resurgence. +// Note that the bug cannot be observed in an assert_eq!, only in the stdout. +// See https://github.com/rust-lang/rust/issues/20626 + +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("foo.rs").opt().run(); + run("foo").assert_stdout_equals("4"); +} From 1d667a0937f6242366d1f47d359a2c739f3c62b1 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Tue, 25 Jun 2024 20:05:37 +0200 Subject: [PATCH 38/53] Prevent ICE from expected future breakage --- compiler/rustc_errors/src/json.rs | 7 ++- ...pect-future_breakage-crash-issue-126521.rs | 21 ++++++- ...-future_breakage-crash-issue-126521.stderr | 61 ++++++++++++++----- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index af82d8092c2f..3d2a04d58515 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -135,7 +135,12 @@ impl Emitter for JsonEmitter { let data: Vec> = diags .into_iter() .map(|mut diag| { - if diag.level == crate::Level::Allow { + // The `FutureBreakageItem` is collected and serialized. + // However, the `allow` and `expect` lint levels can't usually + // be serialized. The lint level is overwritten to allow the + // serialization again and force a lint emission. + // (This is an educated guess. I didn't originally add this) + if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { diag.level = crate::Level::Warning; } FutureBreakageItem { diff --git a/tests/ui/lint/expect-future_breakage-crash-issue-126521.rs b/tests/ui/lint/expect-future_breakage-crash-issue-126521.rs index 0e622ff3aaf7..19eb18fd17ba 100644 --- a/tests/ui/lint/expect-future_breakage-crash-issue-126521.rs +++ b/tests/ui/lint/expect-future_breakage-crash-issue-126521.rs @@ -1,3 +1,5 @@ +//@ check-pass + // This test covers similar crashes from both #126521 and #126751. macro_rules! foo { @@ -12,12 +14,25 @@ macro_rules! bar { }; } -fn main() { +fn allow() { + #[allow(semicolon_in_expressions_from_macros)] + let _ = foo!(x); + + #[allow(semicolon_in_expressions_from_macros)] + let _ = bar!(x); +} + +// The `semicolon_in_expressions_from_macros` lint seems to be emitted even if the +// lint level is `allow` as shown in the function above. The behavior of `expect` +// should mirror this behavior. However, no `unfulfilled_lint_expectation` lint +// is emitted, since the expectation is theoretically fulfilled. +fn expect() { #[expect(semicolon_in_expressions_from_macros)] - //~^ ERROR the `#[expect]` attribute is an experimental feature let _ = foo!(x); #[expect(semicolon_in_expressions_from_macros)] - //~^ ERROR the `#[expect]` attribute is an experimental feature let _ = bar!(x); } + +fn main() { +} diff --git a/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr b/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr index 994630ec23b2..72a74c1579dd 100644 --- a/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr +++ b/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr @@ -1,23 +1,52 @@ -error[E0658]: the `#[expect]` attribute is an experimental feature - --> $DIR/expect-future_breakage-crash-issue-126521.rs:16:5 +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/expect-future_breakage-crash-issue-126521.rs:7:13 | -LL | #[expect(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | true; + | ^ +... +LL | let _ = foo!(x); + | ------- in this macro invocation | - = note: see issue #54503 for more information - = help: add `#![feature(lint_reasons)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: the `#[expect]` attribute is an experimental feature - --> $DIR/expect-future_breakage-crash-issue-126521.rs:20:5 +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/expect-future_breakage-crash-issue-126521.rs:13:35 | -LL | #[expect(semicolon_in_expressions_from_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (5_i32.overflowing_sub(3)); + | ^ +... +LL | let _ = bar!(x); + | ------- in this macro invocation | - = note: see issue #54503 for more information - = help: add `#![feature(lint_reasons)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/expect-future_breakage-crash-issue-126521.rs:7:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(x); + | ------- in this macro invocation + | + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/expect-future_breakage-crash-issue-126521.rs:13:35 + | +LL | (5_i32.overflowing_sub(3)); + | ^ +... +LL | let _ = bar!(x); + | ------- in this macro invocation + | + = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -For more information about this error, try `rustc --explain E0658`. From 6402909f42566cfee84b8b66aec409adfcfc1e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 25 Jun 2024 19:55:06 +0000 Subject: [PATCH 39/53] delay bug in RPITIT refinement checking with resolution errors --- .../src/check/compare_impl_item/refine.rs | 8 +++---- .../in-trait/refine-resolution-errors.rs | 23 +++++++++++++++++++ .../in-trait/refine-resolution-errors.stderr | 16 +++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/refine-resolution-errors.rs create mode 100644 tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 6cdbd692f73b..ad3324f79e27 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -171,10 +171,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } // Resolve any lifetime variables that may have been introduced during normalization. let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else { - // This code path is not reached in any tests, but may be reachable. If - // this is triggered, it should be converted to `delayed_bug` and the - // triggering case turned into a test. - tcx.dcx().bug("encountered errors when checking RPITIT refinement (resolution)"); + // If resolution didn't fully complete, we cannot continue checking RPITIT refinement, and + // delay a bug as the original code contains load-bearing errors. + tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (resolution)"); + return; }; // For quicker lookup, use an `IndexSet` (we don't use one earlier because diff --git a/tests/ui/impl-trait/in-trait/refine-resolution-errors.rs b/tests/ui/impl-trait/in-trait/refine-resolution-errors.rs new file mode 100644 index 000000000000..a9936c7bc3fe --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-resolution-errors.rs @@ -0,0 +1,23 @@ +// This is a non-regression test for issue #126670 where RPITIT refinement checking encountered +// errors during resolution and ICEd. + +//@ edition: 2018 + +pub trait Mirror { + type Assoc; +} +impl Mirror for () { + //~^ ERROR the type parameter `T` is not constrained + type Assoc = T; +} + +pub trait First { + async fn first() -> <() as Mirror>::Assoc; + //~^ ERROR type annotations needed +} + +impl First for () { + async fn first() {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr new file mode 100644 index 000000000000..0f5573dda04c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr @@ -0,0 +1,16 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/refine-resolution-errors.rs:9:6 + | +LL | impl Mirror for () { + | ^ unconstrained type parameter + +error[E0282]: type annotations needed + --> $DIR/refine-resolution-errors.rs:15:5 + | +LL | async fn first() -> <() as Mirror>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. From 133e7b10a45bddd4ef5ba265d848ce0a1976e8ae Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 23 Jun 2024 22:16:22 +0200 Subject: [PATCH 40/53] fix Drop items getting leaked in Filter::next_chunk The optimization only makes sense for non-drop elements anyway. Use the default implementation for items that are Drop instead. It also simplifies the implementation. --- library/core/src/iter/adapters/filter.rs | 88 ++++++++++++------------ 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index ca23d1b13a88..1c99f3938e27 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -3,7 +3,7 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedF use crate::num::NonZero; use crate::ops::Try; use core::array; -use core::mem::{ManuallyDrop, MaybeUninit}; +use core::mem::MaybeUninit; use core::ops::ControlFlow; /// An iterator that filters the elements of `iter` with `predicate`. @@ -27,6 +27,41 @@ impl Filter { } } +impl Filter +where + I: Iterator, + P: FnMut(&I::Item) -> bool, +{ + #[inline] + fn next_chunk_dropless( + &mut self, + ) -> Result<[I::Item; N], array::IntoIter> { + let mut array: [MaybeUninit; N] = [const { MaybeUninit::uninit() }; N]; + let mut initialized = 0; + + let result = self.iter.try_for_each(|element| { + let idx = initialized; + initialized = idx + (self.predicate)(&element) as usize; + + // SAFETY: Loop conditions ensure the index is in bounds. + unsafe { array.get_unchecked_mut(idx) }.write(element); + + if initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } + }); + + match result { + ControlFlow::Break(()) => { + // SAFETY: The loop above is only explicitly broken when the array has been fully initialized + Ok(unsafe { MaybeUninit::array_assume_init(array) }) + } + ControlFlow::Continue(()) => { + // SAFETY: The range is in bounds since the loop breaks when reaching N elements. + Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) }) + } + } + } +} + #[stable(feature = "core_impl_debug", since = "1.9.0")] impl fmt::Debug for Filter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -64,52 +99,15 @@ where fn next_chunk( &mut self, ) -> Result<[Self::Item; N], array::IntoIter> { - let mut array: [MaybeUninit; N] = [const { MaybeUninit::uninit() }; N]; - - struct Guard<'a, T> { - array: &'a mut [MaybeUninit], - initialized: usize, - } - - impl Drop for Guard<'_, T> { - #[inline] - fn drop(&mut self) { - if const { crate::mem::needs_drop::() } { - // SAFETY: self.initialized is always <= N, which also is the length of the array. - unsafe { - core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - self.array.get_unchecked_mut(..self.initialized), - )); - } - } + let fun = const { + if crate::mem::needs_drop::() { + array::iter_next_chunk:: + } else { + Self::next_chunk_dropless:: } - } + }; - let mut guard = Guard { array: &mut array, initialized: 0 }; - - let result = self.iter.try_for_each(|element| { - let idx = guard.initialized; - guard.initialized = idx + (self.predicate)(&element) as usize; - - // SAFETY: Loop conditions ensure the index is in bounds. - unsafe { guard.array.get_unchecked_mut(idx) }.write(element); - - if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } - }); - - let guard = ManuallyDrop::new(guard); - - match result { - ControlFlow::Break(()) => { - // SAFETY: The loop above is only explicitly broken when the array has been fully initialized - Ok(unsafe { MaybeUninit::array_assume_init(array) }) - } - ControlFlow::Continue(()) => { - let initialized = guard.initialized; - // SAFETY: The range is in bounds since the loop breaks when reaching N elements. - Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) }) - } - } + fun(self) } #[inline] From 2be2d77c501730caedae8db2f0a0f02db57ae505 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Mon, 24 Jun 2024 19:56:22 +0200 Subject: [PATCH 41/53] add comments explaining optimizations for Filter::next_chunk --- library/core/src/iter/adapters/filter.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index 1c99f3938e27..ba49070329c2 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -41,8 +41,9 @@ where let result = self.iter.try_for_each(|element| { let idx = initialized; + // branchless index update combined with unconditionally copying the value even when + // it is filtered reduces branching and dependencies in the loop. initialized = idx + (self.predicate)(&element) as usize; - // SAFETY: Loop conditions ensure the index is in bounds. unsafe { array.get_unchecked_mut(idx) }.write(element); @@ -99,6 +100,7 @@ where fn next_chunk( &mut self, ) -> Result<[Self::Item; N], array::IntoIter> { + // avoid codegen for the dead branch let fun = const { if crate::mem::needs_drop::() { array::iter_next_chunk:: From 0d7aef9738b25ed4f84d11deb0add8d5345613b0 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Tue, 25 Jun 2024 23:22:27 +0200 Subject: [PATCH 42/53] regression test for leaks in the the Filter::next_chunk implementation previously next_chunk would forget items rejected by the filter --- library/core/tests/iter/adapters/filter.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/tests/iter/adapters/filter.rs b/library/core/tests/iter/adapters/filter.rs index a2050d89d856..167851e33336 100644 --- a/library/core/tests/iter/adapters/filter.rs +++ b/library/core/tests/iter/adapters/filter.rs @@ -1,4 +1,5 @@ use core::iter::*; +use std::rc::Rc; #[test] fn test_iterator_filter_count() { @@ -50,3 +51,15 @@ fn test_double_ended_filter() { assert_eq!(it.next().unwrap(), &2); assert_eq!(it.next_back(), None); } + +#[test] +fn test_next_chunk_does_not_leak() { + let drop_witness: [_; 5] = std::array::from_fn(|_| Rc::new(())); + + let v = (0..5).map(|i| drop_witness[i].clone()).collect::>(); + let _ = v.into_iter().filter(|_| false).next_chunk::<1>(); + + for ref w in drop_witness { + assert_eq!(Rc::strong_count(w), 1); + } +} From 275d922dab9c98d3a8f01f79d3f2381f26a4a99b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 21 Jun 2024 12:39:55 -0400 Subject: [PATCH 43/53] Rename tcx to cx --- .../src/solve/alias_relate.rs | 6 +- .../src/solve/assembly/mod.rs | 85 ++++---- .../src/solve/assembly/structural_traits.rs | 112 +++++----- .../src/solve/eval_ctxt/mod.rs | 22 +- .../src/solve/inspect/build.rs | 4 +- .../rustc_next_trait_solver/src/solve/mod.rs | 12 +- .../src/solve/normalizes_to/inherent.rs | 18 +- .../src/solve/normalizes_to/mod.rs | 199 +++++++++--------- .../src/solve/normalizes_to/opaque_types.rs | 6 +- .../src/solve/normalizes_to/weak_types.rs | 10 +- .../src/solve/project_goals.rs | 6 +- .../src/solve/search_graph.rs | 60 +++--- .../src/solve/trait_goals.rs | 140 ++++++------ 13 files changed, 333 insertions(+), 347 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index 5a95f4edf191..d8c1dc8b4e9f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -32,14 +32,14 @@ where &mut self, goal: Goal, ) -> QueryResult { - let tcx = self.cx(); + let cx = self.cx(); let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); // Structurally normalize the lhs. let lhs = if let Some(alias) = lhs.to_alias_term() { let term = self.next_term_infer_of_kind(lhs); - self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term })); + self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term })); term } else { lhs @@ -48,7 +48,7 @@ where // Structurally normalize the rhs. let rhs = if let Some(alias) = rhs.to_alias_term() { let term = self.next_term_infer_of_kind(rhs); - self.add_normalizes_to_goal(goal.with(tcx, ty::NormalizesTo { alias, term })); + self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term })); term } else { rhs diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index ee7279a43b2c..21439530c08f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -36,11 +36,11 @@ where { fn self_ty(self) -> I::Ty; - fn trait_ref(self, tcx: I) -> ty::TraitRef; + fn trait_ref(self, cx: I) -> ty::TraitRef; - fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self; + fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self; - fn trait_def_id(self, tcx: I) -> I::DefId; + fn trait_def_id(self, cx: I) -> I::DefId; /// Try equating an assumption predicate against a goal's predicate. If it /// holds, then execute the `then` callback, which should do any additional @@ -82,7 +82,7 @@ where assumption: I::Clause, ) -> Result, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { - let tcx = ecx.cx(); + let cx = ecx.cx(); let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; @@ -91,7 +91,7 @@ where structural_traits::predicates_for_object_candidate( ecx, goal.param_env, - goal.predicate.trait_ref(tcx), + goal.predicate.trait_ref(cx), bounds, ), ); @@ -340,15 +340,15 @@ where goal: Goal, candidates: &mut Vec>, ) { - let tcx = self.cx(); - tcx.for_each_relevant_impl( - goal.predicate.trait_def_id(tcx), + let cx = self.cx(); + cx.for_each_relevant_impl( + goal.predicate.trait_def_id(cx), goal.predicate.self_ty(), |impl_def_id| { // For every `default impl`, there's always a non-default `impl` // that will *also* apply. There's no reason to register a candidate // for this impl, since it is *not* proof that the trait goal holds. - if tcx.impl_is_default(impl_def_id) { + if cx.impl_is_default(impl_def_id) { return; } @@ -366,8 +366,8 @@ where goal: Goal, candidates: &mut Vec>, ) { - let tcx = self.cx(); - let trait_def_id = goal.predicate.trait_def_id(tcx); + let cx = self.cx(); + let trait_def_id = goal.predicate.trait_def_id(cx); // N.B. When assembling built-in candidates for lang items that are also // `auto` traits, then the auto trait candidate that is assembled in @@ -378,47 +378,47 @@ where // `solve::trait_goals` instead. let result = if let Err(guar) = goal.predicate.error_reported() { G::consider_error_guaranteed_candidate(self, guar) - } else if tcx.trait_is_auto(trait_def_id) { + } else if cx.trait_is_auto(trait_def_id) { G::consider_auto_trait_candidate(self, goal) - } else if tcx.trait_is_alias(trait_def_id) { + } else if cx.trait_is_alias(trait_def_id) { G::consider_trait_alias_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Sized) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Sized) { G::consider_builtin_sized_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Copy) - || tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Clone) + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Copy) + || cx.is_lang_item(trait_def_id, TraitSolverLangItem::Clone) { G::consider_builtin_copy_clone_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointerLike) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::PointerLike) { G::consider_builtin_pointer_like_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::FnPtrTrait) { G::consider_builtin_fn_ptr_trait_candidate(self, goal) } else if let Some(kind) = self.cx().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) } else if let Some(kind) = self.cx().async_fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_async_fn_trait_candidates(self, goal, kind) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncFnKindHelper) { G::consider_builtin_async_fn_kind_helper_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Tuple) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Tuple) { G::consider_builtin_tuple_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::PointeeTrait) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::PointeeTrait) { G::consider_builtin_pointee_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Future) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Future) { G::consider_builtin_future_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Iterator) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Iterator) { G::consider_builtin_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::FusedIterator) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::FusedIterator) { G::consider_builtin_fused_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncIterator) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncIterator) { G::consider_builtin_async_iterator_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Coroutine) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Coroutine) { G::consider_builtin_coroutine_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::DiscriminantKind) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::DiscriminantKind) { G::consider_builtin_discriminant_kind_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncDestruct) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::AsyncDestruct) { G::consider_builtin_async_destruct_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Destruct) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Destruct) { G::consider_builtin_destruct_candidate(self, goal) - } else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) { + } else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) { G::consider_builtin_transmute_candidate(self, goal) } else { Err(NoSolution) @@ -428,7 +428,7 @@ where // There may be multiple unsize candidates for a trait with several supertraits: // `trait Foo: Bar + Bar` and `dyn Foo: Unsize>` - if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) { + if cx.is_lang_item(trait_def_id, TraitSolverLangItem::Unsize) { candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal)); } } @@ -557,8 +557,8 @@ where goal: Goal, candidates: &mut Vec>, ) { - let tcx = self.cx(); - if !tcx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(tcx)) { + let cx = self.cx(); + if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) { return; } @@ -596,7 +596,7 @@ where }; // Do not consider built-in object impls for non-object-safe types. - if bounds.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) { + if bounds.principal_def_id().is_some_and(|def_id| !cx.trait_is_object_safe(def_id)) { return; } @@ -614,7 +614,7 @@ where self, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, - bound.with_self_ty(tcx, self_ty), + bound.with_self_ty(cx, self_ty), )); } } @@ -624,14 +624,13 @@ where // since we don't need to look at any supertrait or anything if we are doing // a projection goal. if let Some(principal) = bounds.principal() { - let principal_trait_ref = principal.with_self_ty(tcx, self_ty); - for (idx, assumption) in D::elaborate_supertraits(tcx, principal_trait_ref).enumerate() - { + let principal_trait_ref = principal.with_self_ty(cx, self_ty); + for (idx, assumption) in D::elaborate_supertraits(cx, principal_trait_ref).enumerate() { candidates.extend(G::probe_and_consider_object_bound_candidate( self, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)), goal, - assumption.upcast(tcx), + assumption.upcast(cx), )); } } @@ -649,11 +648,11 @@ where goal: Goal, candidates: &mut Vec>, ) { - let tcx = self.cx(); + let cx = self.cx(); candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( |ecx| { - let trait_ref = goal.predicate.trait_ref(tcx); + let trait_ref = goal.predicate.trait_ref(cx); if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { Err(NoSolution) } else { @@ -678,9 +677,9 @@ where goal: Goal, candidates: &mut Vec>, ) { - let tcx = self.cx(); + let cx = self.cx(); let trait_goal: Goal> = - goal.with(tcx, goal.predicate.trait_ref(tcx)); + goal.with(cx, goal.predicate.trait_ref(cx)); let mut trait_candidates_from_env = vec![]; self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 2df039c766cf..0cef8d9f4bc3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -23,7 +23,7 @@ where D: SolverDelegate, I: Interner, { - let tcx = ecx.cx(); + let cx = ecx.cx(); match ty.kind() { ty::Uint(_) | ty::Int(_) @@ -36,7 +36,7 @@ where | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, Ty::new_u8(tcx)))]), + ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(cx, Ty::new_u8(cx)))]), ty::Dynamic(..) | ty::Param(..) @@ -79,21 +79,21 @@ where .cx() .bound_coroutine_hidden_types(def_id) .into_iter() - .map(|bty| bty.instantiate(tcx, args)) + .map(|bty| bty.instantiate(cx, args)) .collect()), // For `PhantomData`, we pass `T`. ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), ty::Adt(def, args) => { - Ok(def.all_field_tys(tcx).iter_instantiated(tcx, args).map(ty::Binder::dummy).collect()) + Ok(def.all_field_tys(cx).iter_instantiated(cx, args).map(ty::Binder::dummy).collect()) } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))]) + Ok(vec![ty::Binder::dummy(cx.type_of(def_id).instantiate(cx, args))]) } } } @@ -247,18 +247,18 @@ where // Returns a binder of the tupled inputs types and output type from a builtin callable type. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( - tcx: I, + cx: I, self_ty: I::Ty, goal_kind: ty::ClosureKind, ) -> Result>, NoSolution> { match self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, args) => { - let sig = tcx.fn_sig(def_id); - if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) { + let sig = cx.fn_sig(def_id); + if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) { Ok(Some( - sig.instantiate(tcx, args) - .map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())), + sig.instantiate(cx, args) + .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())), )) } else { Err(NoSolution) @@ -268,7 +268,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { if sig.is_fn_trait_compatible() { Ok(Some( - sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs().as_slice()), sig.output())), + sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())), )) } else { Err(NoSolution) @@ -323,10 +323,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { // which enforces the closure is actually callable with the given trait. When we // know the kind already, we can short-circuit this check. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( - tcx: I, + cx: I, self_ty: I::Ty, goal_kind: ty::ClosureKind, env_region: I::Region, @@ -422,9 +422,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable { - let bound_sig = self_ty.fn_sig(tcx); + let bound_sig = self_ty.fn_sig(cx); let sig = bound_sig.skip_binder(); - let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future); + let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future); // `FnDef` and `FnPtr` only implement `AsyncFn*` when their // return type implements `Future`. let nested = vec![ bound_sig - .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])) - .upcast(tcx), + .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])) + .upcast(cx), ]; - let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput); - let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]); + let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput); + let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { - tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs().as_slice()), + tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()), output_coroutine_ty: sig.output(), coroutine_return_ty: future_output_ty, }), @@ -483,13 +481,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( - tcx: I, + cx: I, goal_kind: ty::ClosureKind, goal_region: I::Region, def_id: I::DefId, @@ -573,9 +571,9 @@ fn coroutine_closure_to_certain_coroutine( sig: ty::CoroutineClosureSignature, ) -> I::Ty { sig.to_coroutine_given_kind_and_upvars( - tcx, + cx, args.parent_args(), - tcx.coroutine_for_closure(def_id), + cx.coroutine_for_closure(def_id), goal_kind, goal_region, args.tupled_upvars_ty(), @@ -589,20 +587,20 @@ fn coroutine_closure_to_certain_coroutine( /// /// Note that we do not also push a `AsyncFnKindHelper` goal here. fn coroutine_closure_to_ambiguous_coroutine( - tcx: I, + cx: I, goal_kind: ty::ClosureKind, goal_region: I::Region, def_id: I::DefId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, ) -> I::Ty { - let upvars_projection_def_id = tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars); + let upvars_projection_def_id = cx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( - tcx, + cx, upvars_projection_def_id, [ I::GenericArg::from(args.kind_ty()), - Ty::from_closure_kind(tcx, goal_kind).into(), + Ty::from_closure_kind(cx, goal_kind).into(), goal_region.into(), sig.tupled_inputs_ty.into(), args.tupled_upvars_ty().into(), @@ -610,10 +608,10 @@ fn coroutine_closure_to_ambiguous_coroutine( ], ); sig.to_coroutine( - tcx, + cx, args.parent_args(), - Ty::from_closure_kind(tcx, goal_kind), - tcx.coroutine_for_closure(def_id), + Ty::from_closure_kind(cx, goal_kind), + cx.coroutine_for_closure(def_id), tupled_upvars_ty, ) } @@ -668,28 +666,28 @@ where D: SolverDelegate, I: Interner, { - let tcx = ecx.cx(); + let cx = ecx.cx(); let mut requirements = vec![]; requirements - .extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, trait_ref.args)); + .extend(cx.super_predicates_of(trait_ref.def_id).iter_instantiated(cx, trait_ref.args)); // FIXME(associated_const_equality): Also add associated consts to // the requirements here. - for associated_type_def_id in tcx.associated_type_def_ids(trait_ref.def_id) { + for associated_type_def_id in cx.associated_type_def_ids(trait_ref.def_id) { // associated types that require `Self: Sized` do not show up in the built-in // implementation of `Trait for dyn Trait`, and can be dropped here. - if tcx.generics_require_sized_self(associated_type_def_id) { + if cx.generics_require_sized_self(associated_type_def_id) { continue; } requirements - .extend(tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, trait_ref.args)); + .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args)); } let mut replace_projection_with = HashMap::default(); for bound in object_bounds.iter() { if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() { - let proj = proj.with_self_ty(tcx, trait_ref.self_ty()); + let proj = proj.with_self_ty(cx, trait_ref.self_ty()); let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj)); assert_eq!( old_ty, @@ -709,7 +707,7 @@ where folder .nested .into_iter() - .chain(folded_requirements.into_iter().map(|clause| Goal::new(tcx, param_env, clause))) + .chain(folded_requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) .collect() } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 04dce2780b07..87342eefb33e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -239,14 +239,14 @@ where /// This function takes care of setting up the inference context, setting the anchor, /// and registering opaques from the canonicalized input. fn enter_canonical( - tcx: I, + cx: I, search_graph: &'a mut search_graph::SearchGraph, canonical_input: CanonicalInput, canonical_goal_evaluation: &mut ProofTreeBuilder, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal) -> R, ) -> R { let (ref delegate, input, var_values) = - SolverDelegate::build_with_canonical(tcx, search_graph.solver_mode(), &canonical_input); + SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input); let mut ecx = EvalCtxt { delegate, @@ -292,9 +292,9 @@ where /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal] /// if you're inside of the solver or [SolverDelegateEvalExt::evaluate_root_goal] if you're /// outside of it. - #[instrument(level = "debug", skip(tcx, search_graph, goal_evaluation), ret)] + #[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)] fn evaluate_canonical_goal( - tcx: I, + cx: I, search_graph: &'a mut search_graph::SearchGraph, canonical_input: CanonicalInput, goal_evaluation: &mut ProofTreeBuilder, @@ -307,12 +307,12 @@ where // The actual solver logic happens in `ecx.compute_goal`. let result = ensure_sufficient_stack(|| { search_graph.with_new_goal( - tcx, + cx, canonical_input, &mut canonical_goal_evaluation, |search_graph, canonical_goal_evaluation| { EvalCtxt::enter_canonical( - tcx, + cx, search_graph, canonical_input, canonical_goal_evaluation, @@ -506,7 +506,7 @@ where /// /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result, NoSolution> { - let tcx = self.cx(); + let cx = self.cx(); let mut goals = core::mem::take(&mut self.nested_goals); // If this loop did not result in any progress, what's our final certainty. @@ -516,7 +516,7 @@ where // RHS does not affect projection candidate assembly. let unconstrained_rhs = self.next_term_infer_of_kind(goal.predicate.term); let unconstrained_goal = goal.with( - tcx, + cx, ty::NormalizesTo { alias: goal.predicate.alias, term: unconstrained_rhs }, ); @@ -777,7 +777,7 @@ where // NOTE: this check is purely an optimization, the structural eq would // always fail if the term is not an inference variable. if term.is_infer() { - let tcx = self.cx(); + let cx = self.cx(); // We need to relate `alias` to `term` treating only the outermost // constructor as rigid, relating any contained generic arguments as // normal. We do this by first structurally equating the `term` @@ -787,8 +787,8 @@ where // Alternatively we could modify `Equate` for this case by adding another // variant to `StructurallyRelateAliases`. let identity_args = self.fresh_args_for_item(alias.def_id); - let rigid_ctor = ty::AliasTerm::new_from_args(tcx, alias.def_id, identity_args); - let ctor_term = rigid_ctor.to_term(tcx); + let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args); + let ctor_term = rigid_ctor.to_term(cx); let obligations = self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?; debug_assert!(obligations.is_empty()); diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index 4fc58e06d67d..b50676e8d532 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -323,13 +323,13 @@ impl, I: Interner> ProofTreeBuilder { pub fn finalize_canonical_goal_evaluation( &mut self, - tcx: I, + cx: I, ) -> Option { self.as_mut().map(|this| match this { DebugSolver::CanonicalGoalEvaluation(evaluation) => { let final_revision = mem::take(&mut evaluation.final_revision).unwrap(); let final_revision = - tcx.intern_canonical_goal_evaluation_step(final_revision.finalize()); + cx.intern_canonical_goal_evaluation_step(final_revision.finalize()); let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; assert_eq!(evaluation.kind.replace(kind), None); final_revision diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index e29ae7ac0a26..24055d6cd832 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -34,7 +34,7 @@ use crate::delegate::SolverDelegate; /// How many fixpoint iterations we should attempt inside of the solver before bailing /// with overflow. /// -/// We previously used `tcx.recursion_limit().0.checked_ilog2().unwrap_or(0)` for this. +/// We previously used `cx.recursion_limit().0.checked_ilog2().unwrap_or(0)` for this. /// However, it feels unlikely that uncreasing the recursion limit by a power of two /// to get one more itereation is every useful or desirable. We now instead used a constant /// here. If there ever ends up some use-cases where a bigger number of fixpoint iterations @@ -285,7 +285,7 @@ where } fn response_no_constraints_raw( - tcx: I, + cx: I, max_universe: ty::UniverseIndex, variables: I::CanonicalVars, certainty: Certainty, @@ -294,10 +294,10 @@ fn response_no_constraints_raw( max_universe, variables, value: Response { - var_values: ty::CanonicalVarValues::make_identity(tcx, variables), - // FIXME: maybe we should store the "no response" version in tcx, like - // we do for tcx.types and stuff. - external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()), + var_values: ty::CanonicalVarValues::make_identity(cx, variables), + // FIXME: maybe we should store the "no response" version in cx, like + // we do for cx.types and stuff. + external_constraints: cx.mk_external_constraints(ExternalConstraintsData::default()), certainty, }, defining_opaque_types: Default::default(), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 004ecf2d2c4f..25e8708a3322 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -19,21 +19,21 @@ where &mut self, goal: Goal>, ) -> QueryResult { - let tcx = self.cx(); - let inherent = goal.predicate.alias.expect_ty(tcx); + let cx = self.cx(); + let inherent = goal.predicate.alias.expect_ty(cx); - let impl_def_id = tcx.parent(inherent.def_id); + let impl_def_id = cx.parent(inherent.def_id); let impl_args = self.fresh_args_for_item(impl_def_id); // Equate impl header and add impl where clauses self.eq( goal.param_env, inherent.self_ty(), - tcx.type_of(impl_def_id).instantiate(tcx, impl_args), + cx.type_of(impl_def_id).instantiate(cx, impl_args), )?; // Equate IAT with the RHS of the project goal - let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, tcx); + let inherent_args = inherent.rebase_inherent_args_onto_impl(impl_args, cx); // Check both where clauses on the impl and IAT // @@ -43,12 +43,12 @@ where // and I don't think the assoc item where-bounds are allowed to be coinductive. self.add_goals( GoalSource::Misc, - tcx.predicates_of(inherent.def_id) - .iter_instantiated(tcx, inherent_args) - .map(|pred| goal.with(tcx, pred)), + cx.predicates_of(inherent.def_id) + .iter_instantiated(cx, inherent_args) + .map(|pred| goal.with(cx, pred)), ); - let normalized = tcx.type_of(inherent.def_id).instantiate(tcx, inherent_args); + let normalized = cx.type_of(inherent.def_id).instantiate(cx, inherent_args); self.instantiate_normalizes_to_term(goal, normalized.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index bc5233c4887f..4e8cb4384f46 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -84,16 +84,16 @@ where self.self_ty() } - fn trait_ref(self, tcx: I) -> ty::TraitRef { - self.alias.trait_ref(tcx) + fn trait_ref(self, cx: I) -> ty::TraitRef { + self.alias.trait_ref(cx) } - fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self { - self.with_self_ty(tcx, self_ty) + fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + self.with_self_ty(cx, self_ty) } - fn trait_def_id(self, tcx: I) -> I::DefId { - self.trait_def_id(tcx) + fn trait_def_id(self, cx: I) -> I::DefId { + self.trait_def_id(cx) } fn probe_and_match_goal_against_assumption( @@ -105,7 +105,7 @@ where ) -> Result, NoSolution> { if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { - let tcx = ecx.cx(); + let cx = ecx.cx(); ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); @@ -120,9 +120,9 @@ where // Add GAT where clauses from the trait's definition ecx.add_goals( GoalSource::Misc, - tcx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(tcx, goal.predicate.alias.args) - .map(|pred| goal.with(tcx, pred)), + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), ); then(ecx) @@ -140,19 +140,19 @@ where goal: Goal>, impl_def_id: I::DefId, ) -> Result, NoSolution> { - let tcx = ecx.cx(); + let cx = ecx.cx(); - let goal_trait_ref = goal.predicate.alias.trait_ref(tcx); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + let goal_trait_ref = goal.predicate.alias.trait_ref(cx); + let impl_trait_ref = cx.impl_trait_ref(impl_def_id); if !ecx.cx().args_may_unify_deep( - goal.predicate.alias.trait_ref(tcx).args, + goal.predicate.alias.trait_ref(cx).args, impl_trait_ref.skip_binder().args, ) { return Err(NoSolution); } // We have to ignore negative impls when projecting. - let impl_polarity = tcx.impl_polarity(impl_def_id); + let impl_polarity = cx.impl_polarity(impl_def_id); match impl_polarity { ty::ImplPolarity::Negative => return Err(NoSolution), ty::ImplPolarity::Reservation => { @@ -163,22 +163,22 @@ where ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args); + let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args); ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; - let where_clause_bounds = tcx + let where_clause_bounds = cx .predicates_of(impl_def_id) - .iter_instantiated(tcx, impl_args) - .map(|pred| goal.with(tcx, pred)); + .iter_instantiated(cx, impl_args) + .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); // Add GAT where clauses from the trait's definition ecx.add_goals( GoalSource::Misc, - tcx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(tcx, goal.predicate.alias.args) - .map(|pred| goal.with(tcx, pred)), + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), ); // In case the associated item is hidden due to specialization, we have to @@ -195,21 +195,21 @@ where }; let error_response = |ecx: &mut EvalCtxt<'_, D>, msg: &str| { - let guar = tcx.delay_bug(msg); - let error_term = match goal.predicate.alias.kind(tcx) { - ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(), - ty::AliasTermKind::ProjectionConst => Const::new_error(tcx, guar).into(), + let guar = cx.delay_bug(msg); + let error_term = match goal.predicate.alias.kind(cx) { + ty::AliasTermKind::ProjectionTy => Ty::new_error(cx, guar).into(), + ty::AliasTermKind::ProjectionConst => Const::new_error(cx, guar).into(), kind => panic!("expected projection, found {kind:?}"), }; ecx.instantiate_normalizes_to_term(goal, error_term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; - if !tcx.has_item_definition(target_item_def_id) { + if !cx.has_item_definition(target_item_def_id) { return error_response(ecx, "missing item"); } - let target_container_def_id = tcx.parent(target_item_def_id); + let target_container_def_id = cx.parent(target_item_def_id); // Getting the right args here is complex, e.g. given: // - a goal ` as Trait>::Assoc` @@ -229,22 +229,22 @@ where target_container_def_id, )?; - if !tcx.check_args_compatible(target_item_def_id, target_args) { + if !cx.check_args_compatible(target_item_def_id, target_args) { return error_response(ecx, "associated item has mismatched arguments"); } // Finally we construct the actual value of the associated type. - let term = match goal.predicate.alias.kind(tcx) { + let term = match goal.predicate.alias.kind(cx) { ty::AliasTermKind::ProjectionTy => { - tcx.type_of(target_item_def_id).map_bound(|ty| ty.into()) + cx.type_of(target_item_def_id).map_bound(|ty| ty.into()) } ty::AliasTermKind::ProjectionConst => { - if tcx.features().associated_const_equality() { + if cx.features().associated_const_equality() { panic!("associated const projection is not supported yet") } else { ty::EarlyBinder::bind( Const::new_error_with_message( - tcx, + cx, "associated const projection is not supported yet", ) .into(), @@ -254,7 +254,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, target_args)); + ecx.instantiate_normalizes_to_term(goal, term.instantiate(cx, target_args)); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -316,10 +316,10 @@ where goal: Goal, goal_kind: ty::ClosureKind, ) -> Result, NoSolution> { - let tcx = ecx.cx(); + let cx = ecx.cx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( - tcx, + cx, goal.predicate.self_ty(), goal_kind, )? { @@ -329,19 +329,19 @@ where } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { - ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output]) + ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output]) }); let pred = tupled_inputs_and_output .map_bound(|(inputs, output)| ty::ProjectionPredicate { projection_term: ty::AliasTerm::new( - tcx, + cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs], ), term: output.into(), }) - .upcast(tcx); + .upcast(cx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -350,7 +350,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], + [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))], ) } @@ -359,27 +359,23 @@ where goal: Goal, goal_kind: ty::ClosureKind, ) -> Result, NoSolution> { - let tcx = ecx.cx(); + let cx = ecx.cx(); let env_region = match goal_kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), // Doesn't matter what this region is - ty::ClosureKind::FnOnce => Region::new_static(tcx), + ty::ClosureKind::FnOnce => Region::new_static(cx), }; let (tupled_inputs_and_output_and_coroutine, nested_preds) = structural_traits::extract_tupled_inputs_and_output_from_async_callable( - tcx, + cx, goal.predicate.self_ty(), goal_kind, env_region, )?; let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound( |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| { - ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Sized), - [output_ty], - ) + ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output_ty]) }, ); @@ -390,23 +386,23 @@ where output_coroutine_ty, coroutine_return_ty, }| { - let (projection_term, term) = if tcx + let (projection_term, term) = if cx .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallOnceFuture) { ( ty::AliasTerm::new( - tcx, + cx, goal.predicate.def_id(), [goal.predicate.self_ty(), tupled_inputs_ty], ), output_coroutine_ty.into(), ) - } else if tcx + } else if cx .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CallRefFuture) { ( ty::AliasTerm::new( - tcx, + cx, goal.predicate.def_id(), [ I::GenericArg::from(goal.predicate.self_ty()), @@ -416,13 +412,13 @@ where ), output_coroutine_ty.into(), ) - } else if tcx.is_lang_item( + } else if cx.is_lang_item( goal.predicate.def_id(), TraitSolverLangItem::AsyncFnOnceOutput, ) { ( ty::AliasTerm::new( - tcx, + cx, goal.predicate.def_id(), [ I::GenericArg::from(goal.predicate.self_ty()), @@ -440,7 +436,7 @@ where ty::ProjectionPredicate { projection_term, term } }, ) - .upcast(tcx); + .upcast(cx); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -449,9 +445,9 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)] + [goal.with(cx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred))) .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } @@ -514,8 +510,8 @@ where ecx: &mut EvalCtxt<'_, D>, goal: Goal, ) -> Result, NoSolution> { - let tcx = ecx.cx(); - let metadata_def_id = tcx.require_lang_item(TraitSolverLangItem::Metadata); + let cx = ecx.cx(); + let metadata_def_id = cx.require_lang_item(TraitSolverLangItem::Metadata); assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { @@ -537,16 +533,16 @@ where | ty::CoroutineWitness(..) | ty::Never | ty::Foreign(..) - | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(tcx), + | ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx), - ty::Error(e) => Ty::new_error(tcx, e), + ty::Error(e) => Ty::new_error(cx, e), - ty::Str | ty::Slice(_) => Ty::new_usize(tcx), + ty::Str | ty::Slice(_) => Ty::new_usize(cx), ty::Dynamic(_, _, ty::Dyn) => { - let dyn_metadata = tcx.require_lang_item(TraitSolverLangItem::DynMetadata); - tcx.type_of(dyn_metadata) - .instantiate(tcx, &[I::GenericArg::from(goal.predicate.self_ty())]) + let dyn_metadata = cx.require_lang_item(TraitSolverLangItem::DynMetadata); + cx.type_of(dyn_metadata) + .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())]) } ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { @@ -555,26 +551,26 @@ where // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't // exist. Instead, `Pointee` should be a supertrait of `Sized`. let sized_predicate = ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Sized), + cx, + cx.require_lang_item(TraitSolverLangItem::Sized), [I::GenericArg::from(goal.predicate.self_ty())], ); // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal(GoalSource::Misc, goal.with(tcx, sized_predicate)); - Ty::new_unit(tcx) + ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate)); + Ty::new_unit(cx) } - ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(tcx) { - None => Ty::new_unit(tcx), + ty::Adt(def, args) if def.is_struct() => match def.struct_tail_ty(cx) { + None => Ty::new_unit(cx), Some(tail_ty) => { - Ty::new_projection(tcx, metadata_def_id, [tail_ty.instantiate(tcx, args)]) + Ty::new_projection(cx, metadata_def_id, [tail_ty.instantiate(cx, args)]) } }, - ty::Adt(_, _) => Ty::new_unit(tcx), + ty::Adt(_, _) => Ty::new_unit(cx), ty::Tuple(elements) => match elements.last() { - None => Ty::new_unit(tcx), - Some(tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]), + None => Ty::new_unit(cx), + Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]), }, ty::Infer( @@ -601,8 +597,8 @@ where }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_async(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -616,7 +612,7 @@ where projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]), term, } - .upcast(tcx), + .upcast(cx), // Technically, we need to check that the future type is Sized, // but that's already proven by the coroutine being WF. [], @@ -633,8 +629,8 @@ where }; // Coroutines are not Iterators unless they come from `gen` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_gen(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -648,7 +644,7 @@ where projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.def_id(), [self_ty]), term, } - .upcast(tcx), + .upcast(cx), // Technically, we need to check that the iterator type is Sized, // but that's already proven by the generator being WF. [], @@ -672,8 +668,8 @@ where }; // Coroutines are not AsyncIterators unless they come from `gen` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_async_gen(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -682,12 +678,12 @@ where // Take `AsyncIterator` and turn it into the corresponding // coroutine yield ty `Poll>`. let wrapped_expected_ty = Ty::new_adt( - tcx, - tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Poll)), - tcx.mk_args(&[Ty::new_adt( - tcx, - tcx.adt_def(tcx.require_lang_item(TraitSolverLangItem::Option)), - tcx.mk_args(&[expected_ty.into()]), + cx, + cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Poll)), + cx.mk_args(&[Ty::new_adt( + cx, + cx.adt_def(cx.require_lang_item(TraitSolverLangItem::Option)), + cx.mk_args(&[expected_ty.into()]), ) .into()]), ); @@ -708,18 +704,17 @@ where }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.cx(); - if !tcx.is_general_coroutine(def_id) { + let cx = ecx.cx(); + if !cx.is_general_coroutine(def_id) { return Err(NoSolution); } let coroutine = args.as_coroutine(); - let term = if tcx - .is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn) + let term = if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineReturn) { coroutine.return_ty().into() - } else if tcx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) { + } else if cx.is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::CoroutineYield) { coroutine.yield_ty().into() } else { panic!("unexpected associated item `{:?}` for `{self_ty:?}`", goal.predicate.def_id()) @@ -737,7 +732,7 @@ where ), term, } - .upcast(tcx), + .upcast(cx), // Technically, we need to check that the coroutine type is Sized, // but that's already proven by the coroutine being WF. [], @@ -884,29 +879,29 @@ where impl_trait_ref: rustc_type_ir::TraitRef, target_container_def_id: I::DefId, ) -> Result { - let tcx = self.cx(); + let cx = self.cx(); Ok(if target_container_def_id == impl_trait_ref.def_id { // Default value from the trait definition. No need to rebase. goal.predicate.alias.args } else if target_container_def_id == impl_def_id { // Same impl, no need to fully translate, just a rebase from // the trait is sufficient. - goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, impl_args) + goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, impl_args) } else { let target_args = self.fresh_args_for_item(target_container_def_id); let target_trait_ref = - tcx.impl_trait_ref(target_container_def_id).instantiate(tcx, target_args); + cx.impl_trait_ref(target_container_def_id).instantiate(cx, target_args); // Relate source impl to target impl by equating trait refs. self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; // Also add predicates since they may be needed to constrain the // target impl's params. self.add_goals( GoalSource::Misc, - tcx.predicates_of(target_container_def_id) - .iter_instantiated(tcx, target_args) - .map(|pred| goal.with(tcx, pred)), + cx.predicates_of(target_container_def_id) + .iter_instantiated(cx, target_args) + .map(|pred| goal.with(cx, pred)), ); - goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args) + goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id, target_args) }) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index a16f9e64f2f7..120f96d24bda 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -18,7 +18,7 @@ where &mut self, goal: Goal>, ) -> QueryResult { - let tcx = self.cx(); + let cx = self.cx(); let opaque_ty = goal.predicate.alias; let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); @@ -86,7 +86,7 @@ where } (Reveal::All, _) => { // FIXME: Add an assertion that opaque type storage is empty. - let actual = tcx.type_of(opaque_ty.def_id).instantiate(tcx, opaque_ty.args); + let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -98,7 +98,7 @@ where /// /// FIXME: Interner argument is needed to constrain the `I` parameter. pub fn uses_unique_placeholders_ignoring_regions( - _interner: I, + _cx: I, args: I::GenericArgs, ) -> Result<(), NotUniqueParam> { let mut seen = GrowableBitSet::default(); diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs index ca90bc17cc7d..14e68dd52b6c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/weak_types.rs @@ -18,18 +18,18 @@ where &mut self, goal: Goal>, ) -> QueryResult { - let tcx = self.cx(); + let cx = self.cx(); let weak_ty = goal.predicate.alias; // Check where clauses self.add_goals( GoalSource::Misc, - tcx.predicates_of(weak_ty.def_id) - .iter_instantiated(tcx, weak_ty.args) - .map(|pred| goal.with(tcx, pred)), + cx.predicates_of(weak_ty.def_id) + .iter_instantiated(cx, weak_ty.args) + .map(|pred| goal.with(cx, pred)), ); - let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args); + let actual = cx.type_of(weak_ty.def_id).instantiate(cx, weak_ty.args); self.instantiate_normalizes_to_term(goal, actual.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs index a430dbb408c5..d94528800717 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs @@ -14,10 +14,10 @@ where &mut self, goal: Goal>, ) -> QueryResult { - let tcx = self.cx(); - let projection_term = goal.predicate.projection_term.to_term(tcx); + let cx = self.cx(); + let projection_term = goal.predicate.projection_term.to_term(cx); let goal = goal.with( - tcx, + cx, ty::PredicateKind::AliasRelate( projection_term, goal.predicate.term, diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index d3ad55d6491b..2cd3b10f56ad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -164,7 +164,7 @@ impl SearchGraph { /// the remaining depth of all nested goals to prevent hangs /// in case there is exponential blowup. fn allowed_depth_for_nested( - tcx: I, + cx: I, stack: &IndexVec>, ) -> Option { if let Some(last) = stack.raw.last() { @@ -178,18 +178,18 @@ impl SearchGraph { SolverLimit(last.available_depth.0 - 1) }) } else { - Some(SolverLimit(tcx.recursion_limit())) + Some(SolverLimit(cx.recursion_limit())) } } fn stack_coinductive_from( - tcx: I, + cx: I, stack: &IndexVec>, head: StackDepth, ) -> bool { stack.raw[head.index()..] .iter() - .all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx)) + .all(|entry| entry.input.value.goal.predicate.is_coinductive(cx)) } // When encountering a solver cycle, the result of the current goal @@ -247,8 +247,8 @@ impl SearchGraph { /// so we use a separate cache. Alternatively we could use /// a single cache and share it between coherence and ordinary /// trait solving. - pub(super) fn global_cache(&self, tcx: I) -> I::EvaluationCache { - tcx.evaluation_cache(self.mode) + pub(super) fn global_cache(&self, cx: I) -> I::EvaluationCache { + cx.evaluation_cache(self.mode) } /// Probably the most involved method of the whole solver. @@ -257,24 +257,24 @@ impl SearchGraph { /// handles caching, overflow, and coinductive cycles. pub(super) fn with_new_goal>( &mut self, - tcx: I, + cx: I, input: CanonicalInput, inspect: &mut ProofTreeBuilder, mut prove_goal: impl FnMut(&mut Self, &mut ProofTreeBuilder) -> QueryResult, ) -> QueryResult { self.check_invariants(); // Check for overflow. - let Some(available_depth) = Self::allowed_depth_for_nested(tcx, &self.stack) else { + let Some(available_depth) = Self::allowed_depth_for_nested(cx, &self.stack) else { if let Some(last) = self.stack.raw.last_mut() { last.encountered_overflow = true; } inspect .canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); - return Self::response_no_constraints(tcx, input, Certainty::overflow(true)); + return Self::response_no_constraints(cx, input, Certainty::overflow(true)); }; - if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) { + if let Some(result) = self.lookup_global_cache(cx, input, available_depth, inspect) { debug!("global cache hit"); return result; } @@ -287,12 +287,12 @@ impl SearchGraph { if let Some(entry) = cache_entry .with_coinductive_stack .as_ref() - .filter(|p| Self::stack_coinductive_from(tcx, &self.stack, p.head)) + .filter(|p| Self::stack_coinductive_from(cx, &self.stack, p.head)) .or_else(|| { cache_entry .with_inductive_stack .as_ref() - .filter(|p| !Self::stack_coinductive_from(tcx, &self.stack, p.head)) + .filter(|p| !Self::stack_coinductive_from(cx, &self.stack, p.head)) }) { debug!("provisional cache hit"); @@ -315,7 +315,7 @@ impl SearchGraph { inspect.canonical_goal_evaluation_kind( inspect::WipCanonicalGoalEvaluationKind::CycleInStack, ); - let is_coinductive_cycle = Self::stack_coinductive_from(tcx, &self.stack, stack_depth); + let is_coinductive_cycle = Self::stack_coinductive_from(cx, &self.stack, stack_depth); let usage_kind = if is_coinductive_cycle { HasBeenUsed::COINDUCTIVE_CYCLE } else { @@ -328,9 +328,9 @@ impl SearchGraph { return if let Some(result) = self.stack[stack_depth].provisional_result { result } else if is_coinductive_cycle { - Self::response_no_constraints(tcx, input, Certainty::Yes) + Self::response_no_constraints(cx, input, Certainty::Yes) } else { - Self::response_no_constraints(tcx, input, Certainty::overflow(false)) + Self::response_no_constraints(cx, input, Certainty::overflow(false)) }; } else { // No entry, we push this goal on the stack and try to prove it. @@ -355,9 +355,9 @@ impl SearchGraph { // not tracked by the cache key and from outside of this anon task, it // must not be added to the global cache. Notably, this is the case for // trait solver cycles participants. - let ((final_entry, result), dep_node) = tcx.with_cached_task(|| { + let ((final_entry, result), dep_node) = cx.with_cached_task(|| { for _ in 0..FIXPOINT_STEP_LIMIT { - match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) { + match self.fixpoint_step_in_task(cx, input, inspect, &mut prove_goal) { StepResult::Done(final_entry, result) => return (final_entry, result), StepResult::HasChanged => debug!("fixpoint changed provisional results"), } @@ -366,17 +366,17 @@ impl SearchGraph { debug!("canonical cycle overflow"); let current_entry = self.pop_stack(); debug_assert!(current_entry.has_been_used.is_empty()); - let result = Self::response_no_constraints(tcx, input, Certainty::overflow(false)); + let result = Self::response_no_constraints(cx, input, Certainty::overflow(false)); (current_entry, result) }); - let proof_tree = inspect.finalize_canonical_goal_evaluation(tcx); + let proof_tree = inspect.finalize_canonical_goal_evaluation(cx); // We're now done with this goal. In case this goal is involved in a larger cycle // do not remove it from the provisional cache and update its provisional result. // We only add the root of cycles to the global cache. if let Some(head) = final_entry.non_root_cycle_participant { - let coinductive_stack = Self::stack_coinductive_from(tcx, &self.stack, head); + let coinductive_stack = Self::stack_coinductive_from(cx, &self.stack, head); let entry = self.provisional_cache.get_mut(&input).unwrap(); entry.stack_depth = None; @@ -396,8 +396,8 @@ impl SearchGraph { // participant is on the stack. This is necessary to prevent unstable // results. See the comment of `StackEntry::cycle_participants` for // more details. - self.global_cache(tcx).insert( - tcx, + self.global_cache(cx).insert( + cx, input, proof_tree, reached_depth, @@ -418,15 +418,15 @@ impl SearchGraph { /// this goal. fn lookup_global_cache>( &mut self, - tcx: I, + cx: I, input: CanonicalInput, available_depth: SolverLimit, inspect: &mut ProofTreeBuilder, ) -> Option> { let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self - .global_cache(tcx) + .global_cache(cx) // FIXME: Awkward `Limit -> usize -> Limit`. - .get(tcx, input, self.stack.iter().map(|e| e.input), available_depth.0)?; + .get(cx, input, self.stack.iter().map(|e| e.input), available_depth.0)?; // If we're building a proof tree and the current cache entry does not // contain a proof tree, we do not use the entry but instead recompute @@ -467,7 +467,7 @@ impl SearchGraph { /// point we are done. fn fixpoint_step_in_task( &mut self, - tcx: I, + cx: I, input: CanonicalInput, inspect: &mut ProofTreeBuilder, prove_goal: &mut F, @@ -506,9 +506,9 @@ impl SearchGraph { let reached_fixpoint = if let Some(r) = stack_entry.provisional_result { r == result } else if stack_entry.has_been_used == HasBeenUsed::COINDUCTIVE_CYCLE { - Self::response_no_constraints(tcx, input, Certainty::Yes) == result + Self::response_no_constraints(cx, input, Certainty::Yes) == result } else if stack_entry.has_been_used == HasBeenUsed::INDUCTIVE_CYCLE { - Self::response_no_constraints(tcx, input, Certainty::overflow(false)) == result + Self::response_no_constraints(cx, input, Certainty::overflow(false)) == result } else { false }; @@ -528,11 +528,11 @@ impl SearchGraph { } fn response_no_constraints( - tcx: I, + cx: I, goal: CanonicalInput, certainty: Certainty, ) -> QueryResult { - Ok(super::response_no_constraints_raw(tcx, goal.max_universe, goal.variables, certainty)) + Ok(super::response_no_constraints_raw(cx, goal.max_universe, goal.variables, certainty)) } #[allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 9746c836aff5..2bc9d35c2b02 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -30,8 +30,8 @@ where self.trait_ref } - fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self { - self.with_self_ty(tcx, self_ty) + fn with_self_ty(self, cx: I, self_ty: I::Ty) -> Self { + self.with_self_ty(cx, self_ty) } fn trait_def_id(self, _: I) -> I::DefId { @@ -43,18 +43,17 @@ where goal: Goal>, impl_def_id: I::DefId, ) -> Result, NoSolution> { - let tcx = ecx.cx(); + let cx = ecx.cx(); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); - if !tcx - .args_may_unify_deep(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) + let impl_trait_ref = cx.impl_trait_ref(impl_def_id); + if !cx.args_may_unify_deep(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); } // An upper bound of the certainty of this goal, used to lower the certainty // of reservation impl to ambiguous during coherence. - let impl_polarity = tcx.impl_polarity(impl_def_id); + let impl_polarity = cx.impl_polarity(impl_def_id); let maximal_certainty = match (impl_polarity, goal.predicate.polarity) { // In intercrate mode, this is ambiguous. But outside of intercrate, // it's not a real impl. @@ -77,13 +76,13 @@ where ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); ecx.record_impl_args(impl_args); - let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args); + let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; - let where_clause_bounds = tcx + let where_clause_bounds = cx .predicates_of(impl_def_id) - .iter_instantiated(tcx, impl_args) - .map(|pred| goal.with(tcx, pred)); + .iter_instantiated(cx, impl_args) + .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty) @@ -181,13 +180,13 @@ where return Err(NoSolution); } - let tcx = ecx.cx(); + let cx = ecx.cx(); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - let nested_obligations = tcx + let nested_obligations = cx .predicates_of(goal.predicate.def_id()) - .iter_instantiated(tcx, goal.predicate.trait_ref.args) - .map(|p| goal.with(tcx, p)); + .iter_instantiated(cx, goal.predicate.trait_ref.args) + .map(|p| goal.with(cx, p)); // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? ecx.add_goals(GoalSource::Misc, nested_obligations); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -232,13 +231,13 @@ where return Err(NoSolution); } - let tcx = ecx.cx(); + let cx = ecx.cx(); // But if there are inference variables, we have to wait until it's resolved. if (goal.param_env, goal.predicate.self_ty()).has_non_region_infer() { return ecx.forced_ambiguity(MaybeCause::Ambiguity); } - if tcx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) { + if cx.layout_is_pointer_like(goal.param_env, goal.predicate.self_ty()) { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } else { @@ -286,10 +285,10 @@ where return Err(NoSolution); } - let tcx = ecx.cx(); + let cx = ecx.cx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( - tcx, + cx, goal.predicate.self_ty(), goal_kind, )? { @@ -299,14 +298,14 @@ where } }; let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| { - ty::TraitRef::new(tcx, tcx.require_lang_item(TraitSolverLangItem::Sized), [output]) + ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [output]) }); let pred = tupled_inputs_and_output .map_bound(|(inputs, _)| { - ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) + ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) }) - .upcast(tcx); + .upcast(cx); // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) Self::probe_and_consider_implied_clause( @@ -314,7 +313,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], + [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))], ) } @@ -327,20 +326,20 @@ where return Err(NoSolution); } - let tcx = ecx.cx(); + let cx = ecx.cx(); let (tupled_inputs_and_output_and_coroutine, nested_preds) = structural_traits::extract_tupled_inputs_and_output_from_async_callable( - tcx, + cx, goal.predicate.self_ty(), goal_kind, // This region doesn't matter because we're throwing away the coroutine type - Region::new_static(tcx), + Region::new_static(cx), )?; let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound( |AsyncCallableRelevantTypes { output_coroutine_ty, .. }| { ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Sized), + cx, + cx.require_lang_item(TraitSolverLangItem::Sized), [output_coroutine_ty], ) }, @@ -349,12 +348,12 @@ where let pred = tupled_inputs_and_output_and_coroutine .map_bound(|AsyncCallableRelevantTypes { tupled_inputs_ty, .. }| { ty::TraitRef::new( - tcx, + cx, goal.predicate.def_id(), [goal.predicate.self_ty(), tupled_inputs_ty], ) }) - .upcast(tcx); + .upcast(cx); // A built-in `AsyncFn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) Self::probe_and_consider_implied_clause( @@ -362,9 +361,9 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)] + [goal.with(cx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred))) .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } @@ -437,8 +436,8 @@ where }; // Coroutines are not futures unless they come from `async` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_async(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_async(def_id) { return Err(NoSolution); } @@ -463,8 +462,8 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_gen(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -489,8 +488,8 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_gen(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_gen(def_id) { return Err(NoSolution); } @@ -513,8 +512,8 @@ where }; // Coroutines are not iterators unless they come from `gen` desugaring - let tcx = ecx.cx(); - if !tcx.coroutine_is_async_gen(def_id) { + let cx = ecx.cx(); + if !cx.coroutine_is_async_gen(def_id) { return Err(NoSolution); } @@ -540,8 +539,8 @@ where }; // `async`-desugared coroutines do not implement the coroutine trait - let tcx = ecx.cx(); - if !tcx.is_general_coroutine(def_id) { + let cx = ecx.cx(); + if !cx.is_general_coroutine(def_id) { return Err(NoSolution); } @@ -550,8 +549,8 @@ where ecx, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()]) - .upcast(tcx), + ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()]) + .upcast(cx), // Technically, we need to check that the coroutine types are Sized, // but that's already proven by the coroutine being WF. [], @@ -727,7 +726,7 @@ where b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Vec> { - let tcx = self.cx(); + let cx = self.cx(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; let mut responses = vec![]; @@ -745,7 +744,7 @@ where )); } else if let Some(a_principal) = a_data.principal() { for new_a_principal in - D::elaborate_supertraits(self.cx(), a_principal.with_self_ty(tcx, a_ty)).skip(1) + D::elaborate_supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)).skip(1) { responses.extend(self.consider_builtin_upcast_to_principal( goal, @@ -755,7 +754,7 @@ where b_data, b_region, Some(new_a_principal.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref) })), )); } @@ -770,11 +769,11 @@ where b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result, NoSolution> { - let tcx = self.cx(); + let cx = self.cx(); let Goal { predicate: (a_ty, _), .. } = goal; // Can only unsize to an object-safe trait. - if b_data.principal_def_id().is_some_and(|def_id| !tcx.trait_is_object_safe(def_id)) { + if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_object_safe(def_id)) { return Err(NoSolution); } @@ -783,24 +782,20 @@ where // (i.e. the principal, all of the associated types match, and any auto traits) ecx.add_goals( GoalSource::ImplWhereBound, - b_data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), + b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))), ); // The type must be `Sized` to be unsized. ecx.add_goal( GoalSource::ImplWhereBound, goal.with( - tcx, - ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Sized), - [a_ty], - ), + cx, + ty::TraitRef::new(cx, cx.require_lang_item(TraitSolverLangItem::Sized), [a_ty]), ), ); // The type must outlive the lifetime of the `dyn` we're unsizing into. - ecx.add_goal(GoalSource::Misc, goal.with(tcx, ty::OutlivesPredicate(a_ty, b_region))); + ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region))); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -941,28 +936,28 @@ where a_args: I::GenericArgs, b_args: I::GenericArgs, ) -> Result, NoSolution> { - let tcx = self.cx(); + let cx = self.cx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; - let unsizing_params = tcx.unsizing_params_for_adt(def.def_id()); + let unsizing_params = cx.unsizing_params_for_adt(def.def_id()); // We must be unsizing some type parameters. This also implies // that the struct has a tail field. if unsizing_params.is_empty() { return Err(NoSolution); } - let tail_field_ty = def.struct_tail_ty(tcx).unwrap(); + let tail_field_ty = def.struct_tail_ty(cx).unwrap(); - let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); - let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); + let a_tail_ty = tail_field_ty.instantiate(cx, a_args); + let b_tail_ty = tail_field_ty.instantiate(cx, b_args); // Instantiate just the unsizing params from B into A. The type after // this instantiation must be equal to B. This is so we don't unsize // unrelated type parameters. - let new_a_args = tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| { + let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| { if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a } })); - let unsized_a_ty = Ty::new_adt(tcx, def, new_a_args); + let unsized_a_ty = Ty::new_adt(cx, def, new_a_args); // Finally, we require that `TailA: Unsize` for the tail field // types. @@ -970,10 +965,10 @@ where self.add_goal( GoalSource::ImplWhereBound, goal.with( - tcx, + cx, ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Unsize), + cx, + cx.require_lang_item(TraitSolverLangItem::Unsize), [a_tail_ty, b_tail_ty], ), ), @@ -998,25 +993,24 @@ where a_tys: I::Tys, b_tys: I::Tys, ) -> Result, NoSolution> { - let tcx = self.cx(); + let cx = self.cx(); let Goal { predicate: (_a_ty, b_ty), .. } = goal; let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); let b_last_ty = b_tys.last().unwrap(); // Instantiate just the tail field of B., and require that they're equal. - let unsized_a_ty = - Ty::new_tup_from_iter(tcx, a_rest_tys.iter().copied().chain([b_last_ty])); + let unsized_a_ty = Ty::new_tup_from_iter(cx, a_rest_tys.iter().copied().chain([b_last_ty])); self.eq(goal.param_env, unsized_a_ty, b_ty)?; // Similar to ADTs, require that we can unsize the tail. self.add_goal( GoalSource::ImplWhereBound, goal.with( - tcx, + cx, ty::TraitRef::new( - tcx, - tcx.require_lang_item(TraitSolverLangItem::Unsize), + cx, + cx.require_lang_item(TraitSolverLangItem::Unsize), [a_last_ty, b_last_ty], ), ), From efa48bfaf314529e81757ca27cff70d97be6e9d4 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 20 Jun 2024 21:35:09 +0800 Subject: [PATCH 44/53] Bump black, ruff and platformdirs Mainly because I encountered the following error, and we have no reason to prevent our upgrade. ``` ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. virtualenv 20.25.3 requires platformdirs<5,>=3.9.1, but you have platformdirs 3.6.0 which is incompatible. ``` --- src/tools/tidy/config/requirements.in | 4 +- src/tools/tidy/config/requirements.txt | 91 +++++++++++++------------- src/tools/tidy/config/ruff.toml | 23 +++---- src/tools/tidy/src/ext_tool_checks.rs | 3 +- 4 files changed, 60 insertions(+), 61 deletions(-) diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in index 047617c65598..833d62a864b1 100644 --- a/src/tools/tidy/config/requirements.in +++ b/src/tools/tidy/config/requirements.in @@ -6,5 +6,5 @@ # Note: this generation step should be run with the oldest supported python # version (currently 3.9) to ensure backward compatibility -black==23.3.0 -ruff==0.0.272 +black==24.4.2 +ruff==0.4.9 diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt index a53c98cac7a0..d5236868ad17 100644 --- a/src/tools/tidy/config/requirements.txt +++ b/src/tools/tidy/config/requirements.txt @@ -4,32 +4,29 @@ # # pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in # -black==23.3.0 \ - --hash=sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5 \ - --hash=sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915 \ - --hash=sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326 \ - --hash=sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940 \ - --hash=sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b \ - --hash=sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30 \ - --hash=sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c \ - --hash=sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c \ - --hash=sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab \ - --hash=sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27 \ - --hash=sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2 \ - --hash=sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961 \ - --hash=sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9 \ - --hash=sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb \ - --hash=sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70 \ - --hash=sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331 \ - --hash=sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2 \ - --hash=sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266 \ - --hash=sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d \ - --hash=sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6 \ - --hash=sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b \ - --hash=sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925 \ - --hash=sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8 \ - --hash=sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4 \ - --hash=sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3 +black==24.4.2 \ + --hash=sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 \ + --hash=sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1 \ + --hash=sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0 \ + --hash=sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8 \ + --hash=sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96 \ + --hash=sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 \ + --hash=sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04 \ + --hash=sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021 \ + --hash=sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94 \ + --hash=sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d \ + --hash=sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c \ + --hash=sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7 \ + --hash=sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c \ + --hash=sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc \ + --hash=sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7 \ + --hash=sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d \ + --hash=sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c \ + --hash=sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741 \ + --hash=sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce \ + --hash=sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb \ + --hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \ + --hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e # via -r src/tools/tidy/config/requirements.in click==8.1.3 \ --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ @@ -47,28 +44,28 @@ pathspec==0.11.1 \ --hash=sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687 \ --hash=sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293 # via black -platformdirs==3.6.0 \ - --hash=sha256:57e28820ca8094678b807ff529196506d7a21e17156cb1cddb3e74cebce54640 \ - --hash=sha256:ffa199e3fbab8365778c4a10e1fbf1b9cd50707de826eb304b50e57ec0cc8d38 +platformdirs==4.2.2 \ + --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ + --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 # via black -ruff==0.0.272 \ - --hash=sha256:06b8ee4eb8711ab119db51028dd9f5384b44728c23586424fd6e241a5b9c4a3b \ - --hash=sha256:1609b864a8d7ee75a8c07578bdea0a7db75a144404e75ef3162e0042bfdc100d \ - --hash=sha256:19643d448f76b1eb8a764719072e9c885968971bfba872e14e7257e08bc2f2b7 \ - --hash=sha256:273a01dc8c3c4fd4c2af7ea7a67c8d39bb09bce466e640dd170034da75d14cab \ - --hash=sha256:27b2ea68d2aa69fff1b20b67636b1e3e22a6a39e476c880da1282c3e4bf6ee5a \ - --hash=sha256:48eccf225615e106341a641f826b15224b8a4240b84269ead62f0afd6d7e2d95 \ - --hash=sha256:677284430ac539bb23421a2b431b4ebc588097ef3ef918d0e0a8d8ed31fea216 \ - --hash=sha256:691d72a00a99707a4e0b2846690961157aef7b17b6b884f6b4420a9f25cd39b5 \ - --hash=sha256:86bc788245361a8148ff98667da938a01e1606b28a45e50ac977b09d3ad2c538 \ - --hash=sha256:905ff8f3d6206ad56fcd70674453527b9011c8b0dc73ead27618426feff6908e \ - --hash=sha256:9c4bfb75456a8e1efe14c52fcefb89cfb8f2a0d31ed8d804b82c6cf2dc29c42c \ - --hash=sha256:a37ec80e238ead2969b746d7d1b6b0d31aa799498e9ba4281ab505b93e1f4b28 \ - --hash=sha256:ae9b57546e118660175d45d264b87e9b4c19405c75b587b6e4d21e6a17bf4fdf \ - --hash=sha256:bd2bbe337a3f84958f796c77820d55ac2db1e6753f39d1d1baed44e07f13f96d \ - --hash=sha256:d5a208f8ef0e51d4746930589f54f9f92f84bb69a7d15b1de34ce80a7681bc00 \ - --hash=sha256:dc406e5d756d932da95f3af082814d2467943631a587339ee65e5a4f4fbe83eb \ - --hash=sha256:ee76b4f05fcfff37bd6ac209d1370520d509ea70b5a637bdf0a04d0c99e13dff +ruff==0.4.9 \ + --hash=sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893 \ + --hash=sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff \ + --hash=sha256:2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505 \ + --hash=sha256:4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e \ + --hash=sha256:5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198 \ + --hash=sha256:673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e \ + --hash=sha256:732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db \ + --hash=sha256:784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84 \ + --hash=sha256:78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321 \ + --hash=sha256:8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521 \ + --hash=sha256:88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06 \ + --hash=sha256:8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438 \ + --hash=sha256:98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317 \ + --hash=sha256:b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991 \ + --hash=sha256:e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52 \ + --hash=sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde \ + --hash=sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3 # via -r src/tools/tidy/config/requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml index cf89ffd9ac73..c87c17f78331 100644 --- a/src/tools/tidy/config/ruff.toml +++ b/src/tools/tidy/config/ruff.toml @@ -1,17 +1,7 @@ # Configuration for ruff python linter, run as part of tidy external tools -# B (bugbear), E (pycodestyle, standard), EXE (executables) F (flakes, standard) -# ERM for error messages would be beneficial at some point -select = ["B", "E", "EXE", "F"] - -ignore = [ - "E501", # line-too-long - "F403", # undefined-local-with-import-star - "F405", # undefined-local-with-import-star-usage -] - # lowest possible for ruff -target-version = "py37" +target-version = "py39" # Ignore all submodules extend-exclude = [ @@ -41,3 +31,14 @@ extend-exclude = [ "../library/backtrace/", "../src/tools/rustc-perf/", ] + +[lint] +# B (bugbear), E (pycodestyle, standard), EXE (executables) F (flakes, standard) +# ERM for error messages would be beneficial at some point +select = ["B", "E", "EXE", "F"] + +ignore = [ + "E501", # line-too-long + "F403", # undefined-local-with-import-star + "F405", # undefined-local-with-import-star-usage +] diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 995ad58cb621..e9dd6c66f644 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -110,12 +110,13 @@ fn check_impl( } let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); + args.insert(0, "check".as_ref()); let res = py_runner(py_path.as_ref().unwrap(), "ruff", &args); if res.is_err() && show_diff { eprintln!("\npython linting failed! Printing diff suggestions:"); - args.insert(0, "--diff".as_ref()); + args.insert(1, "--diff".as_ref()); let _ = py_runner(py_path.as_ref().unwrap(), "ruff", &args); } // Rethrow error From 57c8f6f2527ad94b2ff7f16288693c2cd6d550b5 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 4 Jun 2024 22:45:01 +0800 Subject: [PATCH 45/53] Add `.clang-format` --- .clang-format | 1 + .reuse/dep5 | 1 + 2 files changed, 2 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..63027b878158 --- /dev/null +++ b/.clang-format @@ -0,0 +1 @@ +BasedOnStyle: LLVM diff --git a/.reuse/dep5 b/.reuse/dep5 index 06afec2b3fae..0e2650ff2c04 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -29,6 +29,7 @@ Files: compiler/* x x.ps1 x.py + .clang-format .editorconfig .git-blame-ignore-revs .gitattributes From 9f1f6a3387e35e8368bb546fc8ec9dd0b3b1e6a4 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 20 Jun 2024 21:25:41 +0800 Subject: [PATCH 46/53] Add clang-format to requirements.txt in tidy --- src/tools/tidy/config/requirements.in | 1 + src/tools/tidy/config/requirements.txt | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in index 833d62a864b1..8938dc032438 100644 --- a/src/tools/tidy/config/requirements.in +++ b/src/tools/tidy/config/requirements.in @@ -8,3 +8,4 @@ black==24.4.2 ruff==0.4.9 +clang-format==18.1.7 diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt index d5236868ad17..790eabf5cf8a 100644 --- a/src/tools/tidy/config/requirements.txt +++ b/src/tools/tidy/config/requirements.txt @@ -28,6 +28,23 @@ black==24.4.2 \ --hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \ --hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e # via -r src/tools/tidy/config/requirements.in +clang-format==18.1.7 \ + --hash=sha256:035204410f65d03f98cb81c9c39d6d193f9987917cc88de9d0dbd01f2aa9c302 \ + --hash=sha256:05c482a854287a5d21f7567186c0bd4b8dbd4a871751e655a45849185f30b931 \ + --hash=sha256:0b352ec51b291fe04c25a0f0ed15ba1a55b9c9c8eaa7fdf14de3d3585aef4f72 \ + --hash=sha256:217526c8189c18fd175e19bb3e4da2d1bdf14a2bf79d97108c9b6a98d9938351 \ + --hash=sha256:42d0b580ab7a45348155944adebe0bef53d1de9357b925830a59bbc351a25560 \ + --hash=sha256:57090c40a8f0a898e0db8be150a19be2551302d5f5620d2a01de07e7c9220a53 \ + --hash=sha256:607772cf474c1ebe0de44f44c1324e57a2d5b45a1d96d4aff166645532d99b43 \ + --hash=sha256:a49c44d7cc00431be8285aa120a7a21fa0475786c03c53b04a26882c4e626a43 \ + --hash=sha256:a62fca204293893badde0ab004df8b6df1d13eac4d452051554d9684d0a8254e \ + --hash=sha256:a914592a51f77c3563563c7a8970f19bc1ed59174ab992f095a78f4e142382ac \ + --hash=sha256:b3a0a09428cdd656ed87074543222a80660bc506407ed21b8e4bcb3d6d3a5a3c \ + --hash=sha256:c151d42e6ac7c3cc03d7fec61bed3211ce8f75528e1efd8fc64bdb33840987b2 \ + --hash=sha256:d6a2f051124d6ae506ba2a68accfe4ea4c8cb90d13b422c3131bb124413bac32 \ + --hash=sha256:f4f77ac0f4f9a659213fedda0f2d216886c410132e6e7dd4b13f92b34e925554 \ + --hash=sha256:f935d34152a2e11e55120eb9182862f432bc9789ab819f680c9f6db4edebf9e3 + # via -r src/tools/tidy/config/requirements.in click==8.1.3 \ --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 From cf0251d92ced77d926a2292df96cb9ad3ce14f97 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Jun 2024 18:47:09 +1000 Subject: [PATCH 47/53] Fix a span in `parse_ty_bare_fn`. It currently goes one token too far. Example: line 259 of `tests/ui/abi/compatibility.rs`: ``` test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32); ``` This commit changes the span for the second element from `fn(),` to `fn()`, i.e. removes the extraneous comma. --- compiler/rustc_ast/src/ast.rs | 3 ++- compiler/rustc_parse/src/parser/ty.rs | 2 +- tests/ui/rust-2024/safe-outside-extern.gated.stderr | 2 +- tests/ui/rust-2024/safe-outside-extern.ungated.stderr | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 30c54ef2d3c4..4a3ce0e0c306 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2126,7 +2126,8 @@ pub struct BareFnTy { pub ext: Extern, pub generic_params: ThinVec, pub decl: P, - /// Span of the `fn(...) -> ...` part. + /// Span of the `[unsafe] [extern] fn(...) -> ...` part, i.e. everything + /// after the generic params (if there are any, e.g. `for<'a>`). pub decl_span: Span, } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index fcd623b477f5..d2043c353fed 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -608,7 +608,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); } // FIXME(gen_blocks): emit a similar error for `gen fn()` - let decl_span = span_start.to(self.token.span); + let decl_span = span_start.to(self.prev_token.span); Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span }))) } diff --git a/tests/ui/rust-2024/safe-outside-extern.gated.stderr b/tests/ui/rust-2024/safe-outside-extern.gated.stderr index ea7aa1814459..18a3361f35b8 100644 --- a/tests/ui/rust-2024/safe-outside-extern.gated.stderr +++ b/tests/ui/rust-2024/safe-outside-extern.gated.stderr @@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier --> $DIR/safe-outside-extern.rs:24:14 | LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr index 908f5b504eb2..9ea6d451e8c4 100644 --- a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr +++ b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr @@ -26,7 +26,7 @@ error: function pointers cannot be declared with `safe` safety qualifier --> $DIR/safe-outside-extern.rs:24:14 | LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental --> $DIR/safe-outside-extern.rs:4:1 From 0addda65788642c9967cd151eff953be1ddee32f Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 26 Jun 2024 08:44:59 +0800 Subject: [PATCH 48/53] Fix bad replacement for unsafe extern block suggestion --- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_passes/src/errors.rs | 2 +- tests/ui/parser/fn-header-semantic-fail.stderr | 16 ++++++++++------ .../ui/parser/no-const-fn-in-extern-block.stderr | 8 +++++--- tests/ui/parser/unsafe-foreign-mod-2.stderr | 8 +++++--- ...-on-unadorned-extern-block.edition2021.stderr | 16 ++++++++++------ ...-on-unadorned-extern-block.edition2024.stderr | 16 ++++++++++------ .../unsafe-on-extern-block-issue-126756.fixed | 10 ++++++++++ .../unsafe-on-extern-block-issue-126756.rs | 10 ++++++++++ .../unsafe-on-extern-block-issue-126756.stderr | 13 +++++++++++++ 10 files changed, 75 insertions(+), 26 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 79717c969d79..6cff5392f958 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -464,7 +464,7 @@ impl<'a> AstValidator<'a> { { self.dcx().emit_err(errors::InvalidSafetyOnExtern { item_span: span, - block: self.current_extern_span(), + block: self.current_extern_span().shrink_to_lo(), }); } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 96c476b271c6..965d8fac712a 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -221,7 +221,7 @@ pub enum ExternBlockSuggestion { pub struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] pub block: Span, } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index 29404f1793ba..b519ddbe2b43 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -81,11 +81,13 @@ LL | async fn fe1(); error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:47:9 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -LL | async fn fe1(); LL | unsafe fn fe2(); | ^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:48:9 @@ -135,11 +137,13 @@ LL | const async unsafe extern "C" fn fe5(); error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/fn-header-semantic-fail.rs:50:9 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -... LL | const async unsafe extern "C" fn fe5(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:50:9 diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index f575acc839d1..8c23824a7088 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -18,11 +18,13 @@ LL | const unsafe fn bar(); error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -... LL | const unsafe fn bar(); | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index e59352395ed6..77a383d5efa2 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -13,11 +13,13 @@ LL | extern "C" unsafe { error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/unsafe-foreign-mod-2.rs:4:5 | -LL | extern "C" unsafe { - | ----------------- help: add unsafe to this `extern` block -... LL | unsafe fn foo(); | ^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" unsafe { + | ++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index 411cf48b4866..e90613357b1c 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,20 +1,24 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -LL | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -... LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index b634adc29996..1207ee158cc1 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -13,20 +13,24 @@ LL | | } error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -LL | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 | -LL | extern "C" { - | ---------- help: add unsafe to this `extern` block -... LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed new file mode 100644 index 000000000000..2ff595cc44d1 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed @@ -0,0 +1,10 @@ +//@ run-rustfix + +#![feature(unsafe_extern_blocks)] +#![allow(dead_code)] + +unsafe extern "C" { + unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs new file mode 100644 index 000000000000..6fe43f7a5b46 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs @@ -0,0 +1,10 @@ +//@ run-rustfix + +#![feature(unsafe_extern_blocks)] +#![allow(dead_code)] + +extern "C" { + unsafe fn foo(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr new file mode 100644 index 000000000000..05d23d001ada --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr @@ -0,0 +1,13 @@ +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5 + | +LL | unsafe fn foo(); + | ^^^^^^^^^^^^^^^^ + | +help: add unsafe to this `extern` block + | +LL | unsafe extern "C" { + | ++++++ + +error: aborting due to 1 previous error + From b3fb67e050e763ff80b90121f2b60f10d86204f5 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 25 Jun 2024 11:36:50 +0300 Subject: [PATCH 49/53] set `on-broken-pipe` in `prepare_cargo_tool` Currently rustdoc breaks the build cache (due to having different rustflags) when building rustdoc before building another tool (e.g., `x test miri && x test rustdoc && x test miri`). This change fixes that by moving `on-broken-pipe` into `prepare_cargo_tool` so it is set for all tools. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 850c8bfe2f8b..7411d0ba2bef 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -211,6 +211,13 @@ pub fn prepare_tool_cargo( // See https://github.com/rust-lang/rust/issues/116538 cargo.rustflag("-Zunstable-options"); + // `-Zon-broken-pipe=kill` breaks cargo tests + if !path.ends_with("cargo") { + // If the output is piped to e.g. `head -n1` we want the process to be killed, + // rather than having an error bubble up and cause a panic. + cargo.rustflag("-Zon-broken-pipe=kill"); + } + cargo } @@ -575,7 +582,8 @@ impl Step for Rustdoc { features.push("jemalloc".to_string()); } - let mut cargo = prepare_tool_cargo( + // NOTE: Never modify the rustflags here, it breaks the build cache for other tools! + let cargo = prepare_tool_cargo( builder, build_compiler, Mode::ToolRustc, @@ -586,11 +594,6 @@ impl Step for Rustdoc { features.as_slice(), ); - // If the rustdoc output is piped to e.g. `head -n1` we want the process - // to be killed, rather than having an error bubble up and cause a - // panic. - cargo.rustflag("-Zon-broken-pipe=kill"); - let _guard = builder.msg_tool( Kind::Build, Mode::ToolRustc, From de0ece2f2935d005232a5062eeb8b916b1d8a41a Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 23 Jun 2024 22:06:23 +0800 Subject: [PATCH 50/53] Add clang-format to the external tool check --- Cargo.lock | 1 + src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/ext_tool_checks.rs | 134 +++++++++++++++++++++++--- 3 files changed, 124 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 241a37588b40..6d0563839aed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5627,6 +5627,7 @@ dependencies = [ "regex", "rustc-hash", "semver", + "similar", "termcolor", "walkdir", ] diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 0b05d5add52d..1acdf9fbc7fc 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -15,6 +15,7 @@ semver = "1.0" termcolor = "1.1.3" rustc-hash = "1.1.0" fluent-syntax = "0.11.1" +similar = "2.5.0" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index e9dd6c66f644..1df4921ef864 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -73,6 +73,8 @@ fn check_impl( let python_fmt = lint_args.contains(&"py:fmt") || python_all; let shell_all = lint_args.contains(&"shell"); let shell_lint = lint_args.contains(&"shell:lint") || shell_all; + let cpp_all = lint_args.contains(&"cpp"); + let cpp_fmt = lint_args.contains(&"cpp:fmt") || cpp_all; let mut py_path = None; @@ -81,7 +83,7 @@ fn check_impl( .map(OsStr::new) .partition(|arg| arg.to_str().is_some_and(|s| s.starts_with('-'))); - if python_lint || python_fmt { + if python_lint || python_fmt || cpp_fmt { let venv_path = outdir.join("venv"); let mut reqs_path = root_path.to_owned(); reqs_path.extend(PIP_REQ_PATH); @@ -111,13 +113,13 @@ fn check_impl( let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); args.insert(0, "check".as_ref()); - let res = py_runner(py_path.as_ref().unwrap(), "ruff", &args); + let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); if res.is_err() && show_diff { eprintln!("\npython linting failed! Printing diff suggestions:"); args.insert(1, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), "ruff", &args); + let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); } // Rethrow error let _ = res?; @@ -144,13 +146,84 @@ fn check_impl( } let mut args = merge_args(&cfg_args_black, &file_args_black); - let res = py_runner(py_path.as_ref().unwrap(), "black", &args); + let res = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); if res.is_err() && show_diff { eprintln!("\npython formatting does not match! Printing diff:"); args.insert(0, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), "black", &args); + let _ = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); + } + // Rethrow error + let _ = res?; + } + + if cpp_fmt { + let mut cfg_args_clang_format = cfg_args.clone(); + let mut file_args_clang_format = file_args.clone(); + let config_path = root_path.join(".clang-format"); + let config_file_arg = format!("file:{}", config_path.display()); + cfg_args_clang_format.extend(&["--style".as_ref(), config_file_arg.as_ref()]); + if bless { + eprintln!("formatting C++ files"); + cfg_args_clang_format.push("-i".as_ref()); + } else { + eprintln!("checking C++ file formatting"); + cfg_args_clang_format.extend(&["--dry-run".as_ref(), "--Werror".as_ref()]); + } + let files; + if file_args_clang_format.is_empty() { + let llvm_wrapper = root_path.join("compiler/rustc_llvm/llvm-wrapper"); + files = find_with_extension( + root_path, + Some(llvm_wrapper.as_path()), + &[OsStr::new("h"), OsStr::new("cpp")], + )?; + file_args_clang_format.extend(files.iter().map(|p| p.as_os_str())); + } + let args = merge_args(&cfg_args_clang_format, &file_args_clang_format); + let res = py_runner(py_path.as_ref().unwrap(), false, None, "clang-format", &args); + + if res.is_err() && show_diff { + eprintln!("\nclang-format linting failed! Printing diff suggestions:"); + + let mut cfg_args_clang_format_diff = cfg_args.clone(); + cfg_args_clang_format_diff.extend(&["--style".as_ref(), config_file_arg.as_ref()]); + for file in file_args_clang_format { + let mut formatted = String::new(); + let mut diff_args = cfg_args_clang_format_diff.clone(); + diff_args.push(file); + let _ = py_runner( + py_path.as_ref().unwrap(), + false, + Some(&mut formatted), + "clang-format", + &diff_args, + ); + if formatted.is_empty() { + eprintln!( + "failed to obtain the formatted content for '{}'", + file.to_string_lossy() + ); + continue; + } + let actual = std::fs::read_to_string(file).unwrap_or_else(|e| { + panic!( + "failed to read the C++ file at '{}' due to '{e}'", + file.to_string_lossy() + ) + }); + if formatted != actual { + let diff = similar::TextDiff::from_lines(&actual, &formatted); + eprintln!( + "{}", + diff.unified_diff().context_radius(4).header( + &format!("{} (actual)", file.to_string_lossy()), + &format!("{} (formatted)", file.to_string_lossy()) + ) + ); + } + } } // Rethrow error let _ = res?; @@ -162,7 +235,7 @@ fn check_impl( let mut file_args_shc = file_args.clone(); let files; if file_args_shc.is_empty() { - files = find_with_extension(root_path, "sh")?; + files = find_with_extension(root_path, None, &[OsStr::new("sh")])?; file_args_shc.extend(files.iter().map(|p| p.as_os_str())); } @@ -181,8 +254,31 @@ fn merge_args<'a>(cfg_args: &[&'a OsStr], file_args: &[&'a OsStr]) -> Vec<&'a Os } /// Run a python command with given arguments. `py_path` should be a virtualenv. -fn py_runner(py_path: &Path, bin: &'static str, args: &[&OsStr]) -> Result<(), Error> { - let status = Command::new(py_path).arg("-m").arg(bin).args(args).status()?; +/// +/// Captures `stdout` to a string if provided, otherwise prints the output. +fn py_runner( + py_path: &Path, + as_module: bool, + stdout: Option<&mut String>, + bin: &'static str, + args: &[&OsStr], +) -> Result<(), Error> { + let mut cmd = Command::new(py_path); + if as_module { + cmd.arg("-m").arg(bin).args(args); + } else { + let bin_path = py_path.with_file_name(bin); + cmd.arg(bin_path).args(args); + } + let status = if let Some(stdout) = stdout { + let output = cmd.output()?; + if let Ok(s) = std::str::from_utf8(&output.stdout) { + stdout.push_str(s); + } + output.status + } else { + cmd.status()? + }; if status.success() { Ok(()) } else { Err(Error::FailedCheck(bin)) } } @@ -357,7 +453,11 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> { } /// Check git for tracked files matching an extension -fn find_with_extension(root_path: &Path, extension: &str) -> Result, Error> { +fn find_with_extension( + root_path: &Path, + find_dir: Option<&Path>, + extensions: &[&OsStr], +) -> Result, Error> { // Untracked files show up for short status and are indicated with a leading `?` // -C changes git to be as if run from that directory let stat_output = @@ -368,15 +468,25 @@ fn find_with_extension(root_path: &Path, extension: &str) -> Result } let mut output = Vec::new(); - let binding = Command::new("git").arg("-C").arg(root_path).args(["ls-files"]).output()?; + let binding = { + let mut command = Command::new("git"); + command.arg("-C").arg(root_path).args(["ls-files"]); + if let Some(find_dir) = find_dir { + command.arg(find_dir); + } + command.output()? + }; let tracked = String::from_utf8_lossy(&binding.stdout); for line in tracked.lines() { let line = line.trim(); let path = Path::new(line); - if path.extension() == Some(OsStr::new(extension)) { - output.push(path.to_owned()); + let Some(ref extension) = path.extension() else { + continue; + }; + if extensions.contains(extension) { + output.push(root_path.join(path)); } } From e17c16d55b20b9d2702fafa017263406d1e94042 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 4 Jun 2024 22:46:20 +0800 Subject: [PATCH 51/53] Format C++ files in `llvm-wrapper` --- .../llvm-wrapper/ArchiveWrapper.cpp | 33 +- compiler/rustc_llvm/llvm-wrapper/Linker.cpp | 18 +- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 472 ++++---- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 1005 ++++++++--------- .../llvm-wrapper/SuppressLLVMWarnings.h | 14 +- .../rustc_llvm/llvm-wrapper/SymbolWrapper.cpp | 23 +- 6 files changed, 754 insertions(+), 811 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 8871f410e366..a8c278741a77 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -13,10 +13,7 @@ struct RustArchiveMember { Archive::Child Child; RustArchiveMember() - : Filename(nullptr), Name(nullptr), - Child(nullptr, nullptr, nullptr) - { - } + : Filename(nullptr), Name(nullptr), Child(nullptr, nullptr, nullptr) {} ~RustArchiveMember() {} }; @@ -27,11 +24,8 @@ struct RustArchiveIterator { std::unique_ptr Err; RustArchiveIterator(Archive::child_iterator Cur, Archive::child_iterator End, - std::unique_ptr Err) - : First(true), - Cur(Cur), - End(End), - Err(std::move(Err)) {} + std::unique_ptr Err) + : First(true), Cur(Cur), End(End), Err(std::move(Err)) {} }; enum class LLVMRustArchiveKind { @@ -66,8 +60,8 @@ typedef Archive::Child const *LLVMRustArchiveChildConstRef; typedef RustArchiveIterator *LLVMRustArchiveIteratorRef; extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *Path) { - ErrorOr> BufOr = - MemoryBuffer::getFile(Path, /*IsText*/false, /*RequiresNullTerminator=*/false); + ErrorOr> BufOr = MemoryBuffer::getFile( + Path, /*IsText*/ false, /*RequiresNullTerminator=*/false); if (!BufOr) { LLVMRustSetLastError(BufOr.getError().message().c_str()); return nullptr; @@ -146,8 +140,8 @@ extern "C" const char * LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) { Expected NameOrErr = Child->getName(); if (!NameOrErr) { - // rustc_codegen_llvm currently doesn't use this error string, but it might be - // useful in the future, and in the meantime this tells LLVM that the + // rustc_codegen_llvm currently doesn't use this error string, but it might + // be useful in the future, and in the meantime this tells LLVM that the // error was not ignored and that it shouldn't abort the process. LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str()); return nullptr; @@ -172,10 +166,9 @@ extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) { delete Member; } -extern "C" LLVMRustResult -LLVMRustWriteArchive(char *Dst, size_t NumMembers, - const LLVMRustArchiveMemberRef *NewMembers, - bool WriteSymbtab, LLVMRustArchiveKind RustKind, bool isEC) { +extern "C" LLVMRustResult LLVMRustWriteArchive( + char *Dst, size_t NumMembers, const LLVMRustArchiveMemberRef *NewMembers, + bool WriteSymbtab, LLVMRustArchiveKind RustKind, bool isEC) { std::vector Members; auto Kind = fromRust(RustKind); @@ -206,8 +199,10 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers, #if LLVM_VERSION_LT(18, 0) auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false); #else - auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab : SymtabWritingMode::NoSymtab; - auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC); + auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab + : SymtabWritingMode::NoSymtab; + auto Result = + writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC); #endif if (!Result) return LLVMRustResult::Success; diff --git a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp index 533df0f75f8f..f43128ed5505 100644 --- a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp @@ -1,5 +1,5 @@ -#include "SuppressLLVMWarnings.h" #include "llvm/Linker/Linker.h" +#include "SuppressLLVMWarnings.h" #include "LLVMWrapper.h" @@ -9,26 +9,18 @@ struct RustLinker { Linker L; LLVMContext &Ctx; - RustLinker(Module &M) : - L(M), - Ctx(M.getContext()) - {} + RustLinker(Module &M) : L(M), Ctx(M.getContext()) {} }; -extern "C" RustLinker* -LLVMRustLinkerNew(LLVMModuleRef DstRef) { +extern "C" RustLinker *LLVMRustLinkerNew(LLVMModuleRef DstRef) { Module *Dst = unwrap(DstRef); return new RustLinker(*Dst); } -extern "C" void -LLVMRustLinkerFree(RustLinker *L) { - delete L; -} +extern "C" void LLVMRustLinkerFree(RustLinker *L) { delete L; } -extern "C" bool -LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) { +extern "C" bool LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) { std::unique_ptr Buf = MemoryBuffer::getMemBufferCopy(StringRef(BC, Len)); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index a027ddcc1508..c4cfc0b6dc6a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -2,23 +2,25 @@ #include #include -#include #include +#include #include "LLVMWrapper.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/AssemblyAnnotationWriter.h" +#include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Verifier.h" +#include "llvm/LTO/LTO.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" @@ -33,26 +35,24 @@ #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" -#include "llvm/LTO/LTO.h" -#include "llvm/Bitcode/BitcodeWriter.h" #if LLVM_VERSION_GE(18, 0) #include "llvm/TargetParser/Host.h" #endif +#include "llvm/Support/TimeProfiler.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h" -#include "llvm/Support/TimeProfiler.h" #if LLVM_VERSION_GE(19, 0) #include "llvm/Support/PGOOptions.h" #endif #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" -#include "llvm/Transforms/Instrumentation/InstrProfiling.h" -#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" -#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" +#include "llvm/Transforms/Instrumentation/InstrProfiling.h" +#include "llvm/Transforms/Instrumentation/MemorySanitizer.h" +#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" -#include "llvm/Transforms/Utils.h" using namespace llvm; @@ -74,7 +74,7 @@ extern "C" void LLVMRustTimeTraceProfilerFinishThread() { timeTraceProfilerFinishThread(); } -extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) { +extern "C" void LLVMRustTimeTraceProfilerFinish(const char *FileName) { auto FN = StringRef(FileName); std::error_code EC; auto OS = raw_fd_ostream(FN, EC, sys::fs::CD_CreateAlways); @@ -188,7 +188,7 @@ extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) { SUBTARGET_HEXAGON \ SUBTARGET_XTENSA \ SUBTARGET_RISCV \ - SUBTARGET_LOONGARCH \ + SUBTARGET_LOONGARCH #define SUBTARGET(x) \ namespace llvm { \ @@ -215,8 +215,7 @@ enum class LLVMRustCodeModel { None, }; -static std::optional -fromRust(LLVMRustCodeModel Model) { +static std::optional fromRust(LLVMRustCodeModel Model) { switch (Model) { case LLVMRustCodeModel::Tiny: return CodeModel::Tiny; @@ -243,9 +242,9 @@ enum class LLVMRustCodeGenOptLevel { }; #if LLVM_VERSION_GE(18, 0) - using CodeGenOptLevelEnum = llvm::CodeGenOptLevel; +using CodeGenOptLevelEnum = llvm::CodeGenOptLevel; #else - using CodeGenOptLevelEnum = llvm::CodeGenOpt::Level; +using CodeGenOptLevelEnum = llvm::CodeGenOpt::Level; #endif static CodeGenOptLevelEnum fromRust(LLVMRustCodeGenOptLevel Level) { @@ -319,48 +318,49 @@ static Reloc::Model fromRust(LLVMRustRelocModel RustReloc) { } /// getLongestEntryLength - Return the length of the longest entry in the table. -template -static size_t getLongestEntryLength(ArrayRef Table) { +template static size_t getLongestEntryLength(ArrayRef Table) { size_t MaxLen = 0; for (auto &I : Table) MaxLen = std::max(MaxLen, std::strlen(I.Key)); return MaxLen; } -using PrintBackendInfo = void(void*, const char* Data, size_t Len); +using PrintBackendInfo = void(void *, const char *Data, size_t Len); extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM, - const char* TargetCPU, - PrintBackendInfo Print, - void* Out) { + const char *TargetCPU, + PrintBackendInfo Print, void *Out) { const TargetMachine *Target = unwrap(TM); - const Triple::ArchType HostArch = Triple(sys::getDefaultTargetTriple()).getArch(); + const Triple::ArchType HostArch = + Triple(sys::getDefaultTargetTriple()).getArch(); const Triple::ArchType TargetArch = Target->getTargetTriple().getArch(); std::ostringstream Buf; const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const ArrayRef CPUTable = MCInfo->getAllProcessorDescriptions(); + const ArrayRef CPUTable = + MCInfo->getAllProcessorDescriptions(); unsigned MaxCPULen = getLongestEntryLength(CPUTable); Buf << "Available CPUs for this target:\n"; // Don't print the "native" entry when the user specifies --target with a // different arch since that could be wrong or misleading. if (HostArch == TargetArch) { - MaxCPULen = std::max(MaxCPULen, (unsigned) std::strlen("native")); + MaxCPULen = std::max(MaxCPULen, (unsigned)std::strlen("native")); const StringRef HostCPU = sys::getHostCPUName(); Buf << " " << std::left << std::setw(MaxCPULen) << "native" << " - Select the CPU of the current host " - "(currently " << HostCPU.str() << ").\n"; + "(currently " + << HostCPU.str() << ").\n"; } for (auto &CPU : CPUTable) { // Compare cpu against current target to label the default if (strcmp(CPU.Key, TargetCPU) == 0) { Buf << " " << std::left << std::setw(MaxCPULen) << CPU.Key << " - This is the default target CPU for the current build target " - "(currently " << Target->getTargetTriple().str() << ")."; - } - else { + "(currently " + << Target->getTargetTriple().str() << ")."; + } else { Buf << " " << CPU.Key; } Buf << "\n"; @@ -374,7 +374,8 @@ extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { #if LLVM_VERSION_GE(18, 0) const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const ArrayRef FeatTable = MCInfo->getAllProcessorFeatures(); + const ArrayRef FeatTable = + MCInfo->getAllProcessorFeatures(); return FeatTable.size(); #else return 0; @@ -382,18 +383,20 @@ extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) { } extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index, - const char** Feature, const char** Desc) { + const char **Feature, + const char **Desc) { #if LLVM_VERSION_GE(18, 0) const TargetMachine *Target = unwrap(TM); const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); - const ArrayRef FeatTable = MCInfo->getAllProcessorFeatures(); + const ArrayRef FeatTable = + MCInfo->getAllProcessorFeatures(); const SubtargetFeatureKV Feat = FeatTable[Index]; *Feature = Feat.Key; *Desc = Feat.Desc; #endif } -extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { +extern "C" const char *LLVMRustGetHostCPUName(size_t *len) { StringRef Name = sys::getHostCPUName(); *len = Name.size(); return Name.data(); @@ -403,19 +406,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( const char *TripleStr, const char *CPU, const char *Feature, const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocModel RustReloc, LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, - bool FunctionSections, - bool DataSections, - bool UniqueSectionNames, - bool TrapUnreachable, - bool Singlethread, - bool AsmComments, - bool EmitStackSizeSection, - bool RelaxELFRelocations, - bool UseInitArray, - const char *SplitDwarfFile, - const char *OutputObjFile, - const char *DebugInfoCompression, - bool UseEmulatedTls, + bool FunctionSections, bool DataSections, bool UniqueSectionNames, + bool TrapUnreachable, bool Singlethread, bool AsmComments, + bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray, + const char *SplitDwarfFile, const char *OutputObjFile, + const char *DebugInfoCompression, bool UseEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { auto OptLevel = fromRust(RustOptLevel); @@ -444,18 +439,20 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.MCOptions.PreserveAsmComments = AsmComments; Options.MCOptions.ABIName = ABIStr; if (SplitDwarfFile) { - Options.MCOptions.SplitDwarfFile = SplitDwarfFile; + Options.MCOptions.SplitDwarfFile = SplitDwarfFile; } if (OutputObjFile) { - Options.ObjectFilenameForDebug = OutputObjFile; + Options.ObjectFilenameForDebug = OutputObjFile; } - if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { + if (!strcmp("zlib", DebugInfoCompression) && + llvm::compression::zlib::isAvailable()) { #if LLVM_VERSION_GE(19, 0) Options.MCOptions.CompressDebugSections = DebugCompressionType::Zlib; #else Options.CompressDebugSections = DebugCompressionType::Zlib; #endif - } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) { + } else if (!strcmp("zstd", DebugInfoCompression) && + llvm::compression::zstd::isAvailable()) { #if LLVM_VERSION_GE(19, 0) Options.MCOptions.CompressDebugSections = DebugCompressionType::Zstd; #else @@ -499,24 +496,21 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.EmitStackSizeSection = EmitStackSizeSection; - - if (ArgsCstrBuff != nullptr) - { + if (ArgsCstrBuff != nullptr) { int buffer_offset = 0; assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0'); const size_t arg0_len = std::strlen(ArgsCstrBuff); - char* arg0 = new char[arg0_len + 1]; + char *arg0 = new char[arg0_len + 1]; memcpy(arg0, ArgsCstrBuff, arg0_len); arg0[arg0_len] = '\0'; buffer_offset += arg0_len + 1; - const int num_cmd_arg_strings = - std::count(&ArgsCstrBuff[buffer_offset], &ArgsCstrBuff[ArgsCstrBuffLen], '\0'); + const int num_cmd_arg_strings = std::count( + &ArgsCstrBuff[buffer_offset], &ArgsCstrBuff[ArgsCstrBuffLen], '\0'); - std::string* cmd_arg_strings = new std::string[num_cmd_arg_strings]; - for (int i = 0; i < num_cmd_arg_strings; ++i) - { + std::string *cmd_arg_strings = new std::string[num_cmd_arg_strings]; + for (int i = 0; i < num_cmd_arg_strings; ++i) { assert(buffer_offset < ArgsCstrBuffLen); const int len = std::strlen(ArgsCstrBuff + buffer_offset); cmd_arg_strings[i] = std::string(&ArgsCstrBuff[buffer_offset], len); @@ -527,7 +521,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.MCOptions.Argv0 = arg0; Options.MCOptions.CommandLineArgs = - llvm::ArrayRef(cmd_arg_strings, num_cmd_arg_strings); + llvm::ArrayRef(cmd_arg_strings, num_cmd_arg_strings); } TargetMachine *TM = TheTarget->createTargetMachine( @@ -537,7 +531,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { - MCTargetOptions& MCOptions = unwrap(TM)->Options.MCOptions; + MCTargetOptions &MCOptions = unwrap(TM)->Options.MCOptions; delete[] MCOptions.Argv0; delete[] MCOptions.CommandLineArgs.data(); @@ -613,7 +607,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None); EC.clear(); if (EC) - ErrorInfo = EC.message(); + ErrorInfo = EC.message(); if (ErrorInfo != "") { LLVMRustSetLastError(ErrorInfo.c_str()); return LLVMRustResult::Failure; @@ -633,10 +627,12 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Success; } -extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler - const char*, // pass name - const char*); // IR name -extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler +extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)( + void *, // LlvmSelfProfiler + const char *, // pass name + const char *); // IR name +extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)( + void *); // LlvmSelfProfiler std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { if (const auto *Cast = any_cast(&WrappedIr)) @@ -650,35 +646,35 @@ std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { return ""; } - void LLVMSelfProfileInitializeCallbacks( - PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler, + PassInstrumentationCallbacks &PIC, void *LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { - PIC.registerBeforeNonSkippedPassCallback([LlvmSelfProfiler, BeforePassCallback]( - StringRef Pass, llvm::Any Ir) { - std::string PassName = Pass.str(); - std::string IrName = LLVMRustwrappedIrGetName(Ir); - BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); - }); + PIC.registerBeforeNonSkippedPassCallback( + [LlvmSelfProfiler, BeforePassCallback](StringRef Pass, llvm::Any Ir) { + std::string PassName = Pass.str(); + std::string IrName = LLVMRustwrappedIrGetName(Ir); + BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); + }); PIC.registerAfterPassCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any IR, - const PreservedAnalyses &Preserved) { + [LlvmSelfProfiler, AfterPassCallback]( + StringRef Pass, llvm::Any IR, const PreservedAnalyses &Preserved) { AfterPassCallback(LlvmSelfProfiler); }); PIC.registerAfterPassInvalidatedCallback( - [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) { + [LlvmSelfProfiler, + AfterPassCallback](StringRef Pass, const PreservedAnalyses &Preserved) { AfterPassCallback(LlvmSelfProfiler); }); - PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback]( - StringRef Pass, llvm::Any Ir) { - std::string PassName = Pass.str(); - std::string IrName = LLVMRustwrappedIrGetName(Ir); - BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); - }); + PIC.registerBeforeAnalysisCallback( + [LlvmSelfProfiler, BeforePassCallback](StringRef Pass, llvm::Any Ir) { + std::string PassName = Pass.str(); + std::string IrName = LLVMRustwrappedIrGetName(Ir); + BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); + }); PIC.registerAfterAnalysisCallback( [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { @@ -704,7 +700,7 @@ struct LLVMRustSanitizerOptions { bool SanitizeKCFI; bool SanitizeMemory; bool SanitizeMemoryRecover; - int SanitizeMemoryTrackOrigins; + int SanitizeMemoryTrackOrigins; bool SanitizeThread; bool SanitizeHWAddress; bool SanitizeHWAddressRecover; @@ -712,31 +708,25 @@ struct LLVMRustSanitizerOptions { bool SanitizeKernelAddressRecover; }; -extern "C" LLVMRustResult -LLVMRustOptimize( - LLVMModuleRef ModuleRef, - LLVMTargetMachineRef TMRef, - LLVMRustPassBuilderOptLevel OptLevelRust, - LLVMRustOptStage OptStage, - bool IsLinkerPluginLTO, - bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers, - bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, - bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, - LLVMRustSanitizerOptions *SanitizerOptions, - const char *PGOGenPath, const char *PGOUsePath, - bool InstrumentCoverage, const char *InstrProfileOutput, - bool InstrumentGCOV, +extern "C" LLVMRustResult LLVMRustOptimize( + LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, + LLVMRustPassBuilderOptLevel OptLevelRust, LLVMRustOptStage OptStage, + bool IsLinkerPluginLTO, bool NoPrepopulatePasses, bool VerifyIR, + bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, + bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls, + bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, + const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, + const char *InstrProfileOutput, bool InstrumentGCOV, const char *PGOSampleUsePath, bool DebugInfoForProfiling, - void* LlvmSelfProfiler, + void *LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, - const char *ExtraPasses, size_t ExtraPassesLen, - const char *LLVMPlugins, size_t LLVMPluginsLen) { + const char *ExtraPasses, size_t ExtraPassesLen, const char *LLVMPlugins, + size_t LLVMPluginsLen) { Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); OptimizationLevel OptLevel = fromRust(OptLevelRust); - PipelineTuningOptions PTO; PTO.LoopUnrolling = UnrollLoops; PTO.LoopInterleaving = UnrollLoops; @@ -751,38 +741,39 @@ LLVMRustOptimize( StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); SI.registerCallbacks(PIC); - if (LlvmSelfProfiler){ - LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); + if (LlvmSelfProfiler) { + LLVMSelfProfileInitializeCallbacks(PIC, LlvmSelfProfiler, + BeforePassCallback, AfterPassCallback); } std::optional PGOOpt; auto FS = vfs::getRealFileSystem(); if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", "", FS, - PGOOptions::IRInstr, PGOOptions::NoCSAction, + PGOOpt = PGOOptions(PGOGenPath, "", "", "", FS, PGOOptions::IRInstr, + PGOOptions::NoCSAction, #if LLVM_VERSION_GE(19, 0) PGOOptions::ColdFuncOpt::Default, #endif DebugInfoForProfiling); } else if (PGOUsePath) { assert(!PGOSampleUsePath); - PGOOpt = PGOOptions(PGOUsePath, "", "", "", FS, - PGOOptions::IRUse, PGOOptions::NoCSAction, + PGOOpt = PGOOptions(PGOUsePath, "", "", "", FS, PGOOptions::IRUse, + PGOOptions::NoCSAction, #if LLVM_VERSION_GE(19, 0) PGOOptions::ColdFuncOpt::Default, #endif DebugInfoForProfiling); } else if (PGOSampleUsePath) { - PGOOpt = PGOOptions(PGOSampleUsePath, "", "", "", FS, - PGOOptions::SampleUse, PGOOptions::NoCSAction, + PGOOpt = PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse, + PGOOptions::NoCSAction, #if LLVM_VERSION_GE(19, 0) PGOOptions::ColdFuncOpt::Default, #endif DebugInfoForProfiling); } else if (DebugInfoForProfiling) { - PGOOpt = PGOOptions("", "", "", "", FS, - PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOpt = PGOOptions("", "", "", "", FS, PGOOptions::NoAction, + PGOOptions::NoCSAction, #if LLVM_VERSION_GE(19, 0) PGOOptions::ColdFuncOpt::Default, #endif @@ -799,7 +790,7 @@ LLVMRustOptimize( auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); SmallVector Plugins; PluginsStr.split(Plugins, ',', -1, false); - for (auto PluginPath: Plugins) { + for (auto PluginPath : Plugins) { auto Plugin = PassPlugin::Load(PluginPath.str()); if (!Plugin) { auto Err = Plugin.takeError(); @@ -814,7 +805,8 @@ LLVMRustOptimize( FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); }); Triple TargetTriple(TheModule->getTargetTriple()); - std::unique_ptr TLII(new TargetLibraryInfoImpl(TargetTriple)); + std::unique_ptr TLII( + new TargetLibraryInfoImpl(TargetTriple)); if (DisableSimplifyLibCalls) TLII->disableAllFunctions(); FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); }); @@ -825,58 +817,53 @@ LLVMRustOptimize( PB.registerLoopAnalyses(LAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - // We manually collect pipeline callbacks so we can apply them at O0, where the - // PassBuilder does not create a pipeline. + // We manually collect pipeline callbacks so we can apply them at O0, where + // the PassBuilder does not create a pipeline. std::vector> PipelineStartEPCallbacks; std::vector> OptimizerLastEPCallbacks; - if (!IsLinkerPluginLTO - && SanitizerOptions && SanitizerOptions->SanitizeCFI - && !NoPrepopulatePasses) { + if (!IsLinkerPluginLTO && SanitizerOptions && SanitizerOptions->SanitizeCFI && + !NoPrepopulatePasses) { PipelineStartEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr, - /*ImportSummary=*/nullptr, - /*DropTypeTests=*/false)); - } - ); + [](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr, + /*ImportSummary=*/nullptr, + /*DropTypeTests=*/false)); + }); } if (VerifyIR) { PipelineStartEPCallbacks.push_back( - [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(VerifierPass()); - } - ); + [VerifyIR](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(VerifierPass()); + }); } if (InstrumentGCOV) { PipelineStartEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault())); - } - ); + [](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(GCOVProfilerPass(GCOVOptions::getDefault())); + }); } if (InstrumentCoverage) { PipelineStartEPCallbacks.push_back( - [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) { - InstrProfOptions Options; - if (InstrProfileOutput) { - Options.InstrProfileOutput = InstrProfileOutput; - } - // cargo run tests in multhreading mode by default - // so use atomics for coverage counters - Options.Atomic = true; + [InstrProfileOutput](ModulePassManager &MPM, OptimizationLevel Level) { + InstrProfOptions Options; + if (InstrProfileOutput) { + Options.InstrProfileOutput = InstrProfileOutput; + } + // cargo run tests in multhreading mode by default + // so use atomics for coverage counters + Options.Atomic = true; #if LLVM_VERSION_GE(18, 0) - MPM.addPass(InstrProfilingLoweringPass(Options, false)); + MPM.addPass(InstrProfilingLoweringPass(Options, false)); #else - MPM.addPass(InstrProfiling(Options, false)); + MPM.addPass(InstrProfiling(Options, false)); #endif - } - ); + }); } if (SanitizerOptions) { @@ -886,10 +873,9 @@ LLVMRustOptimize( SanitizerOptions->SanitizeDataFlowABIList + SanitizerOptions->SanitizeDataFlowABIListLen); OptimizerLastEPCallbacks.push_back( - [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(DataFlowSanitizerPass(ABIListFiles)); - } - ); + [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(DataFlowSanitizerPass(ABIListFiles)); + }); } if (SanitizerOptions->SanitizeMemory) { @@ -899,54 +885,54 @@ LLVMRustOptimize( /*CompileKernel=*/false, /*EagerChecks=*/true); OptimizerLastEPCallbacks.push_back( - [Options](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(MemorySanitizerPass(Options)); - } - ); + [Options](ModulePassManager &MPM, OptimizationLevel Level) { + MPM.addPass(MemorySanitizerPass(Options)); + }); } if (SanitizerOptions->SanitizeThread) { - OptimizerLastEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(ModuleThreadSanitizerPass()); - MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); - } - ); + OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM, + OptimizationLevel Level) { + MPM.addPass(ModuleThreadSanitizerPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); + }); } - if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) { + if (SanitizerOptions->SanitizeAddress || + SanitizerOptions->SanitizeKernelAddress) { OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { - auto CompileKernel = SanitizerOptions->SanitizeKernelAddress; - AddressSanitizerOptions opts = AddressSanitizerOptions{ - CompileKernel, - SanitizerOptions->SanitizeAddressRecover - || SanitizerOptions->SanitizeKernelAddressRecover, - /*UseAfterScope=*/true, - AsanDetectStackUseAfterReturnMode::Runtime, - }; - MPM.addPass(AddressSanitizerPass(opts)); - } - ); + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { + auto CompileKernel = SanitizerOptions->SanitizeKernelAddress; + AddressSanitizerOptions opts = AddressSanitizerOptions{ + CompileKernel, + SanitizerOptions->SanitizeAddressRecover || + SanitizerOptions->SanitizeKernelAddressRecover, + /*UseAfterScope=*/true, + AsanDetectStackUseAfterReturnMode::Runtime, + }; + MPM.addPass(AddressSanitizerPass(opts)); + }); } if (SanitizerOptions->SanitizeHWAddress) { OptimizerLastEPCallbacks.push_back( - [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { - HWAddressSanitizerOptions opts( - /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover, - /*DisableOptimization=*/false); - MPM.addPass(HWAddressSanitizerPass(opts)); - } - ); + [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { + HWAddressSanitizerOptions opts( + /*CompileKernel=*/false, + SanitizerOptions->SanitizeHWAddressRecover, + /*DisableOptimization=*/false); + MPM.addPass(HWAddressSanitizerPass(opts)); + }); } } ModulePassManager MPM; bool NeedThinLTOBufferPasses = UseThinLTOBuffers; if (!NoPrepopulatePasses) { - // The pre-link pipelines don't support O0 and require using buildO0DefaultPipeline() instead. - // At the same time, the LTO pipelines do support O0 and using them is required. - bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO; + // The pre-link pipelines don't support O0 and require using + // buildO0DefaultPipeline() instead. At the same time, the LTO pipelines do + // support O0 and using them is required. + bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || + OptStage == LLVMRustOptStage::FatLTO; if (OptLevel == OptimizationLevel::O0 && !IsLTO) { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); @@ -993,7 +979,8 @@ LLVMRustOptimize( } if (ExtraPassesLen) { - if (auto Err = PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) { + if (auto Err = + PB.parsePassPipeline(MPM, StringRef(ExtraPasses, ExtraPassesLen))) { std::string ErrMsg = toString(std::move(Err)); LLVMRustSetLastError(ErrMsg.c_str()); return LLVMRustResult::Failure; @@ -1020,8 +1007,7 @@ LLVMRustOptimize( // * output buffer // * output buffer len // Returns len of demangled string, or 0 if demangle failed. -typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t); - +typedef size_t (*DemangleFn)(const char *, size_t, char *, size_t); namespace { @@ -1064,7 +1050,7 @@ public: formatted_raw_ostream &OS) override { StringRef Demangled = CallDemangle(F->getName()); if (Demangled.empty()) { - return; + return; } OS << "; " << Demangled << "\n"; @@ -1077,7 +1063,7 @@ public: if (const CallInst *CI = dyn_cast(I)) { Name = "call"; Value = CI->getCalledOperand(); - } else if (const InvokeInst* II = dyn_cast(I)) { + } else if (const InvokeInst *II = dyn_cast(I)) { Name = "invoke"; Value = II->getCalledOperand(); } else { @@ -1101,8 +1087,8 @@ public: } // namespace -extern "C" LLVMRustResult -LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) { +extern "C" LLVMRustResult LLVMRustPrintModule(LLVMModuleRef M, const char *Path, + DemangleFn Demangle) { std::string ErrorInfo; std::error_code EC; auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None); @@ -1264,11 +1250,9 @@ getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) { // The main entry point for creating the global ThinLTO analysis. The structure // here is basically the same as before threads are spawned in the `run` // function of `lib/LTO/ThinLTOCodeGenerator.cpp`. -extern "C" LLVMRustThinLTOData* -LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, - int num_modules, - const char **preserved_symbols, - int num_symbols) { +extern "C" LLVMRustThinLTOData * +LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules, + const char **preserved_symbols, int num_symbols) { auto Ret = std::make_unique(); // Load each module's summary and merge it into one combined index @@ -1290,7 +1274,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, } // Collect for each module the list of function it defines (GUID -> Summary) - Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries); + Ret->Index.collectDefinedGVSummariesPerModule( + Ret->ModuleToDefinedGVSummaries); // Convert the preserved symbols set from string to GUID, this is then needed // for internalization. @@ -1310,7 +1295,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // crate, so we need `ImportEnabled = false` to limit internalization. // Otherwise, we sometimes lose `static` values -- see #60184. computeDeadSymbolsWithConstProp(Ret->Index, Ret->GUIDPreservedSymbols, - deadIsPrevailing, /* ImportEnabled = */ false); + deadIsPrevailing, + /* ImportEnabled = */ false); // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it // impacts the caching. // @@ -1319,7 +1305,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, DenseMap PrevailingCopy; for (auto &I : Ret->Index) { if (I.second.SummaryList.size() > 1) - PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList); + PrevailingCopy[I.first] = + getFirstDefinitionForLinker(I.second.SummaryList); } auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { const auto &Prevailing = PrevailingCopy.find(GUID); @@ -1327,13 +1314,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, return true; return Prevailing->second == S; }; - ComputeCrossModuleImport( - Ret->Index, - Ret->ModuleToDefinedGVSummaries, - isPrevailing, - Ret->ImportLists, - Ret->ExportLists - ); + ComputeCrossModuleImport(Ret->Index, Ret->ModuleToDefinedGVSummaries, + isPrevailing, Ret->ImportLists, Ret->ExportLists); auto recordNewLinkage = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID, @@ -1345,8 +1327,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // formats. We probably could and should use ELF visibility scheme for many of // our targets, however. lto::Config conf; - thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, recordNewLinkage, - Ret->GUIDPreservedSymbols); + thinLTOResolvePrevailingInIndex(conf, Ret->Index, isPrevailing, + recordNewLinkage, Ret->GUIDPreservedSymbols); // Here we calculate an `ExportedGUIDs` set for use in the `isExported` // callback below. This callback below will dictate the linkage for all @@ -1355,7 +1337,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, // linkage will stay as external, and internal will stay as internal. std::set ExportedGUIDs; for (auto &List : Ret->Index) { - for (auto &GVS: List.second.SummaryList) { + for (auto &GVS : List.second.SummaryList) { if (GlobalValue::isLocalLinkage(GVS->linkage())) continue; auto GUID = GVS->getOriginalName(); @@ -1366,16 +1348,15 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, auto isExported = [&](StringRef ModuleIdentifier, ValueInfo VI) { const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier); return (ExportList != Ret->ExportLists.end() && - ExportList->second.count(VI)) || - ExportedGUIDs.count(VI.getGUID()); + ExportList->second.count(VI)) || + ExportedGUIDs.count(VI.getGUID()); }; thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported, isPrevailing); return Ret.release(); } -extern "C" void -LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { +extern "C" void LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { delete Data; } @@ -1387,20 +1368,18 @@ LLVMRustFreeThinLTOData(LLVMRustThinLTOData *Data) { // `ProcessThinLTOModule` function. Here they're split up into separate steps // so rustc can save off the intermediate bytecode between each step. -static bool -clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { +static bool clearDSOLocalOnDeclarations(Module &Mod, TargetMachine &TM) { // When linking an ELF shared object, dso_local should be dropped. We // conservatively do this for -fpic. - bool ClearDSOLocalOnDeclarations = - TM.getTargetTriple().isOSBinFormatELF() && - TM.getRelocationModel() != Reloc::Static && - Mod.getPIELevel() == PIELevel::Default; + bool ClearDSOLocalOnDeclarations = TM.getTargetTriple().isOSBinFormatELF() && + TM.getRelocationModel() != Reloc::Static && + Mod.getPIELevel() == PIELevel::Default; return ClearDSOLocalOnDeclarations; } -extern "C" bool -LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, - LLVMTargetMachineRef TM) { +extern "C" bool LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, + LLVMModuleRef M, + LLVMTargetMachineRef TM) { Module &Mod = *unwrap(M); TargetMachine &Target = *unwrap(TM); @@ -1415,24 +1394,28 @@ LLVMRustPrepareThinLTORename(const LLVMRustThinLTOData *Data, LLVMModuleRef M, } extern "C" bool -LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { +LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, + LLVMModuleRef M) { Module &Mod = *unwrap(M); - const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); + const auto &DefinedGlobals = + Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true); return true; } extern "C" bool -LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { +LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data, + LLVMModuleRef M) { Module &Mod = *unwrap(M); - const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); + const auto &DefinedGlobals = + Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); thinLTOInternalizeModule(Mod, DefinedGlobals); return true; } -extern "C" bool -LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, - LLVMTargetMachineRef TM) { +extern "C" bool LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, + LLVMModuleRef M, + LLVMTargetMachineRef TM) { Module &Mod = *unwrap(M); TargetMachine &Target = *unwrap(TM); @@ -1464,7 +1447,8 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, return Ret; } - auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections"); + auto *WasmCustomSections = + (*MOrErr)->getNamedMetadata("wasm.custom_sections"); if (WasmCustomSections) WasmCustomSections->eraseFromParent(); @@ -1498,7 +1482,7 @@ struct LLVMRustThinLTOBuffer { std::string thin_link_data; }; -extern "C" LLVMRustThinLTOBuffer* +extern "C" LLVMRustThinLTOBuffer * LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) { auto Ret = std::make_unique(); { @@ -1520,7 +1504,8 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) { // We only pass ThinLinkOS to be filled in if we want the summary, // because otherwise LLVM does extra work and may double-emit some // errors or warnings. - MPM.addPass(ThinLTOBitcodeWriterPass(OS, emit_summary ? &ThinLinkOS : nullptr)); + MPM.addPass( + ThinLTOBitcodeWriterPass(OS, emit_summary ? &ThinLinkOS : nullptr)); MPM.run(*unwrap(M), MAM); } else { WriteBitcodeToFile(*unwrap(M), OS); @@ -1530,12 +1515,11 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) { return Ret.release(); } -extern "C" void -LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) { +extern "C" void LLVMRustThinLTOBufferFree(LLVMRustThinLTOBuffer *Buffer) { delete Buffer; } -extern "C" const void* +extern "C" const void * LLVMRustThinLTOBufferPtr(const LLVMRustThinLTOBuffer *Buffer) { return Buffer->data.data(); } @@ -1545,7 +1529,7 @@ LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) { return Buffer->data.length(); } -extern "C" const void* +extern "C" const void * LLVMRustThinLTOBufferThinLinkDataPtr(const LLVMRustThinLTOBuffer *Buffer) { return Buffer->thin_link_data.data(); } @@ -1558,11 +1542,10 @@ LLVMRustThinLTOBufferThinLinkDataLen(const LLVMRustThinLTOBuffer *Buffer) { // This is what we used to parse upstream bitcode for actual ThinLTO // processing. We'll call this once per module optimized through ThinLTO, and // it'll be called concurrently on many threads. -extern "C" LLVMModuleRef -LLVMRustParseBitcodeForLTO(LLVMContextRef Context, - const char *data, - size_t len, - const char *identifier) { +extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context, + const char *data, + size_t len, + const char *identifier) { auto Data = StringRef(data, len); auto Buffer = MemoryBufferRef(Data, identifier); unwrap(Context)->enableDebugTypeODRUniquing(); @@ -1614,8 +1597,9 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, // of access globals, etc). // The precise details are determined by LLVM in `computeLTOCacheKey`, which is // used during the normal linker-plugin incremental thin-LTO process. -extern "C" void -LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThinLTOData *Data) { +extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, + const char *ModId, + LLVMRustThinLTOData *Data) { SmallString<40> Key; llvm::lto::Config conf; const auto &ImportList = Data->ImportLists.lookup(ModId); @@ -1633,9 +1617,9 @@ LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, const char *ModId, LLVMRustThin CfiFunctionDecls.insert( GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); - llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, - ImportList, ExportList, ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls - ); + llvm::computeLTOCacheKey(Key, conf, Data->Index, ModId, ImportList, + ExportList, ResolvedODR, DefinedGlobals, + CfiFunctionDefs, CfiFunctionDecls); LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size()); } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 20167a4b45ee..b6790b7df500 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1,5 +1,6 @@ #include "LLVMWrapper.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticHandler.h" #include "llvm/IR/DiagnosticInfo.h" @@ -11,17 +12,16 @@ #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Value.h" -#include "llvm/Remarks/RemarkStreamer.h" -#include "llvm/Remarks/RemarkSerializer.h" -#include "llvm/Remarks/RemarkFormat.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/ModRef.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Pass.h" -#include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Remarks/RemarkSerializer.h" +#include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Support/ModRef.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/ToolOutputFile.h" #include @@ -71,12 +71,12 @@ static LLVM_THREAD_LOCAL char *LastError; // Custom error handler for fatal LLVM errors. // // Notably it exits the process with code 101, unlike LLVM's default of 1. -static void FatalErrorHandler(void *UserData, - const char* Reason, +static void FatalErrorHandler(void *UserData, const char *Reason, bool GenCrashDiag) { // Once upon a time we emitted "LLVM ERROR:" specifically to mimic LLVM. Then, - // we developed crater and other tools which only expose logs, not error codes. - // Use a more greppable prefix that will still match the "LLVM ERROR:" prefix. + // we developed crater and other tools which only expose logs, not error + // codes. Use a more greppable prefix that will still match the "LLVM ERROR:" + // prefix. std::cerr << "rustc-LLVM ERROR: " << Reason << std::endl; // Since this error handler exits the process, we have to run any cleanup that @@ -99,8 +99,7 @@ static void FatalErrorHandler(void *UserData, // // It aborts the process without any further allocations, similar to LLVM's // default except that may be configured to `throw std::bad_alloc()` instead. -static void BadAllocErrorHandler(void *UserData, - const char* Reason, +static void BadAllocErrorHandler(void *UserData, const char *Reason, bool GenCrashDiag) { const char *OOM = "rustc-LLVM ERROR: out of memory\n"; (void)!::write(2, OOM, strlen(OOM)); @@ -190,7 +189,8 @@ static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) { } } -extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) { +extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, + LLVMRustTailCallKind TCK) { unwrap(Call)->setTailCallKind(fromRust(TCK)); } @@ -201,12 +201,13 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, return wrap(unwrap(M) ->getOrInsertFunction(StringRef(Name, NameLen), unwrap(FunctionTy)) - .getCallee() - ); + .getCallee()); } -extern "C" LLVMValueRef -LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { +extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, + const char *Name, + size_t NameLen, + LLVMTypeRef Ty) { Module *Mod = unwrap(M); auto NameRef = StringRef(Name, NameLen); @@ -221,13 +222,10 @@ LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLV return wrap(GV); } -extern "C" LLVMValueRef -LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { - return wrap(new GlobalVariable(*unwrap(M), - unwrap(Ty), - false, - GlobalValue::PrivateLinkage, - nullptr)); +extern "C" LLVMValueRef LLVMRustInsertPrivateGlobal(LLVMModuleRef M, + LLVMTypeRef Ty) { + return wrap(new GlobalVariable(*unwrap(M), unwrap(Ty), false, + GlobalValue::PrivateLinkage, nullptr)); } static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { @@ -326,8 +324,9 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { report_fatal_error("bad AttributeKind"); } -template static inline void AddAttributes(T *t, unsigned Index, - LLVMAttributeRef *Attrs, size_t AttrsLen) { +template +static inline void AddAttributes(T *t, unsigned Index, LLVMAttributeRef *Attrs, + size_t AttrsLen) { AttributeList PAL = t->getAttributes(); auto B = AttrBuilder(t->getContext()); for (LLVMAttributeRef Attr : ArrayRef(Attrs, AttrsLen)) @@ -337,19 +336,22 @@ template static inline void AddAttributes(T *t, unsigned Index, } extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index, - LLVMAttributeRef *Attrs, size_t AttrsLen) { + LLVMAttributeRef *Attrs, + size_t AttrsLen) { Function *F = unwrap(Fn); AddAttributes(F, Index, Attrs, AttrsLen); } -extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index, - LLVMAttributeRef *Attrs, size_t AttrsLen) { +extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, + unsigned Index, + LLVMAttributeRef *Attrs, + size_t AttrsLen) { CallBase *Call = unwrap(Instr); AddAttributes(Call, Index, Attrs, AttrsLen); } -extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C, - LLVMRustAttribute RustAttr) { +extern "C" LLVMAttributeRef +LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttribute RustAttr) { return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr))); } @@ -363,30 +365,36 @@ extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C, return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes)); } -extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C, - uint64_t Bytes) { +extern "C" LLVMAttributeRef +LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C, uint64_t Bytes) { return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes)); } -extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) { +extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, + LLVMTypeRef Ty) { return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty))); } -extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) { +extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, + LLVMTypeRef Ty) { return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty))); } -extern "C" LLVMAttributeRef LLVMRustCreateElementTypeAttr(LLVMContextRef C, LLVMTypeRef Ty) { +extern "C" LLVMAttributeRef LLVMRustCreateElementTypeAttr(LLVMContextRef C, + LLVMTypeRef Ty) { return wrap(Attribute::get(*unwrap(C), Attribute::ElementType, unwrap(Ty))); } -extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) { +extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, + bool Async) { return wrap(Attribute::getWithUWTableKind( *unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync)); } -extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { - return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, std::nullopt)); +extern "C" LLVMAttributeRef +LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { + return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, + std::nullopt)); } // These values **must** match ffi::AllocKindFlags. @@ -403,12 +411,15 @@ enum class LLVMRustAllocKindFlags : uint64_t { Aligned = 1 << 5, }; -static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, LLVMRustAllocKindFlags B) { +static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, + LLVMRustAllocKindFlags B) { return static_cast(static_cast(A) & - static_cast(B)); + static_cast(B)); } -static bool isSet(LLVMRustAllocKindFlags F) { return F != LLVMRustAllocKindFlags::Unknown; } +static bool isSet(LLVMRustAllocKindFlags F) { + return F != LLVMRustAllocKindFlags::Unknown; +} static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) { llvm::AllocFnKind AFK = llvm::AllocFnKind::Unknown; @@ -433,40 +444,47 @@ static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) { return AFK; } -extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64_t AllocKindArg) { - return wrap(Attribute::get(*unwrap(C), Attribute::AllocKind, - static_cast(allocKindFromRust(static_cast(AllocKindArg))))); +extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, + uint64_t AllocKindArg) { + return wrap( + Attribute::get(*unwrap(C), Attribute::AllocKind, + static_cast(allocKindFromRust( + static_cast(AllocKindArg))))); } // Simplified representation of `MemoryEffects` across the FFI boundary. // -// Each variant corresponds to one of the static factory methods on `MemoryEffects`. +// Each variant corresponds to one of the static factory methods on +// `MemoryEffects`. enum class LLVMRustMemoryEffects { None, ReadOnly, InaccessibleMemOnly, }; -extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, - LLVMRustMemoryEffects Effects) { +extern "C" LLVMAttributeRef +LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C, + LLVMRustMemoryEffects Effects) { switch (Effects) { - case LLVMRustMemoryEffects::None: - return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none())); - case LLVMRustMemoryEffects::ReadOnly: - return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly())); - case LLVMRustMemoryEffects::InaccessibleMemOnly: - return wrap(Attribute::getWithMemoryEffects(*unwrap(C), - MemoryEffects::inaccessibleMemOnly())); - default: - report_fatal_error("bad MemoryEffects."); + case LLVMRustMemoryEffects::None: + return wrap( + Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none())); + case LLVMRustMemoryEffects::ReadOnly: + return wrap( + Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly())); + case LLVMRustMemoryEffects::InaccessibleMemOnly: + return wrap(Attribute::getWithMemoryEffects( + *unwrap(C), MemoryEffects::inaccessibleMemOnly())); + default: + report_fatal_error("bad MemoryEffects."); } } -// Enable all fast-math flags, including those which will cause floating-point operations -// to return poison for some well-defined inputs. This function can only be used to build -// unsafe Rust intrinsics. That unsafety does permit additional optimizations, but at the -// time of writing, their value is not well-understood relative to those enabled by -// LLVMRustSetAlgebraicMath. +// Enable all fast-math flags, including those which will cause floating-point +// operations to return poison for some well-defined inputs. This function can +// only be used to build unsafe Rust intrinsics. That unsafety does permit +// additional optimizations, but at the time of writing, their value is not +// well-understood relative to those enabled by LLVMRustSetAlgebraicMath. // // https://llvm.org/docs/LangRef.html#fast-math-flags extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { @@ -475,14 +493,12 @@ extern "C" void LLVMRustSetFastMath(LLVMValueRef V) { } } -// Enable fast-math flags which permit algebraic transformations that are not allowed by -// IEEE floating point. For example: -// a + (b + c) = (a + b) + c -// and -// a / b = a * (1 / b) -// Note that this does NOT enable any flags which can cause a floating-point operation on -// well-defined inputs to return poison, and therefore this function can be used to build -// safe Rust intrinsics (such as fadd_algebraic). +// Enable fast-math flags which permit algebraic transformations that are not +// allowed by IEEE floating point. For example: a + (b + c) = (a + b) + c and a +// / b = a * (1 / b) Note that this does NOT enable any flags which can cause a +// floating-point operation on well-defined inputs to return poison, and +// therefore this function can be used to build safe Rust intrinsics (such as +// fadd_algebraic). // // https://llvm.org/docs/LangRef.html#fast-math-flags extern "C" void LLVMRustSetAlgebraicMath(LLVMValueRef V) { @@ -497,9 +513,9 @@ extern "C" void LLVMRustSetAlgebraicMath(LLVMValueRef V) { // Enable the reassoc fast-math flag, allowing transformations that pretend // floating-point addition and multiplication are associative. // -// Note that this does NOT enable any flags which can cause a floating-point operation on -// well-defined inputs to return poison, and therefore this function can be used to build -// safe Rust intrinsics (such as fadd_algebraic). +// Note that this does NOT enable any flags which can cause a floating-point +// operation on well-defined inputs to return poison, and therefore this +// function can be used to build safe Rust intrinsics (such as fadd_algebraic). // // https://llvm.org/docs/LangRef.html#fast-math-flags extern "C" void LLVMRustSetAllowReassoc(LLVMValueRef V) { @@ -547,11 +563,10 @@ LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, char *Constraints, size_t ConstraintsLen, LLVMBool HasSideEffects, LLVMBool IsAlignStack, LLVMRustAsmDialect Dialect, LLVMBool CanThrow) { - return wrap(InlineAsm::get(unwrap(Ty), - StringRef(AsmString, AsmStringLen), - StringRef(Constraints, ConstraintsLen), - HasSideEffects, IsAlignStack, - fromRust(Dialect), CanThrow)); + return wrap(InlineAsm::get( + unwrap(Ty), StringRef(AsmString, AsmStringLen), + StringRef(Constraints, ConstraintsLen), HasSideEffects, IsAlignStack, + fromRust(Dialect), CanThrow)); } extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, @@ -705,19 +720,22 @@ enum class LLVMRustDISPFlags : uint32_t { inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) { return static_cast(static_cast(A) & - static_cast(B)); + static_cast(B)); } inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) { return static_cast(static_cast(A) | - static_cast(B)); + static_cast(B)); } -inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) { +inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, + LLVMRustDISPFlags B) { return A = A | B; } -inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; } +inline bool isSet(LLVMRustDISPFlags F) { + return F != LLVMRustDISPFlags::SPFlagZero; +} inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) { return static_cast(static_cast(F) & 0x3); @@ -761,7 +779,8 @@ enum class LLVMRustDebugEmissionKind { DebugDirectivesOnly, }; -static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { +static DICompileUnit::DebugEmissionKind +fromRust(LLVMRustDebugEmissionKind Kind) { switch (Kind) { case LLVMRustDebugEmissionKind::NoDebug: return DICompileUnit::DebugEmissionKind::NoDebug; @@ -777,12 +796,13 @@ static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) } enum class LLVMRustDebugNameTableKind { - Default, - GNU, - None, + Default, + GNU, + None, }; -static DICompileUnit::DebugNameTableKind fromRust(LLVMRustDebugNameTableKind Kind) { +static DICompileUnit::DebugNameTableKind +fromRust(LLVMRustDebugNameTableKind Kind) { switch (Kind) { case LLVMRustDebugNameTableKind::Default: return DICompileUnit::DebugNameTableKind::Default; @@ -827,22 +847,18 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } -extern "C" void LLVMRustAddModuleFlagU32( - LLVMModuleRef M, - Module::ModFlagBehavior MergeBehavior, - const char *Name, - uint32_t Value) { +extern "C" void LLVMRustAddModuleFlagU32(LLVMModuleRef M, + Module::ModFlagBehavior MergeBehavior, + const char *Name, uint32_t Value) { unwrap(M)->addModuleFlag(MergeBehavior, Name, Value); } extern "C" void LLVMRustAddModuleFlagString( - LLVMModuleRef M, - Module::ModFlagBehavior MergeBehavior, - const char *Name, - const char *Value, - size_t ValueLen) { - unwrap(M)->addModuleFlag(MergeBehavior, Name, - MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen))); + LLVMModuleRef M, Module::ModFlagBehavior MergeBehavior, const char *Name, + const char *Value, size_t ValueLen) { + unwrap(M)->addModuleFlag( + MergeBehavior, Name, + MDString::get(unwrap(M)->getContext(), StringRef(Value, ValueLen))); } extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, @@ -850,8 +866,8 @@ extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr; } -extern "C" void LLVMRustGlobalAddMetadata( - LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) { +extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD) { unwrap(Global)->addMetadata(Kind, *unwrap(MD)); } @@ -870,33 +886,29 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) { extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, bool isOptimized, - const char *Flags, unsigned RuntimeVer, - const char *SplitName, size_t SplitNameLen, - LLVMRustDebugEmissionKind Kind, - uint64_t DWOId, bool SplitDebugInlining, - LLVMRustDebugNameTableKind TableKind) { + const char *Flags, unsigned RuntimeVer, const char *SplitName, + size_t SplitNameLen, LLVMRustDebugEmissionKind Kind, uint64_t DWOId, + bool SplitDebugInlining, LLVMRustDebugNameTableKind TableKind) { auto *File = unwrapDI(FileRef); - return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen), - isOptimized, Flags, RuntimeVer, - StringRef(SplitName, SplitNameLen), - fromRust(Kind), DWOId, SplitDebugInlining, - false, fromRust(TableKind))); + return wrap(Builder->createCompileUnit( + Lang, File, StringRef(Producer, ProducerLen), isOptimized, Flags, + RuntimeVer, StringRef(SplitName, SplitNameLen), fromRust(Kind), DWOId, + SplitDebugInlining, false, fromRust(TableKind))); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( - LLVMRustDIBuilderRef Builder, - const char *Filename, size_t FilenameLen, - const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, - const char *Checksum, size_t ChecksumLen) { +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, + size_t FilenameLen, const char *Directory, + size_t DirectoryLen, LLVMRustChecksumKind CSKind, + const char *Checksum, size_t ChecksumLen) { std::optional llvmCSKind = fromRust(CSKind); std::optional> CSInfo{}; if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), - CSInfo)); + StringRef(Directory, DirectoryLen), CSInfo)); } extern "C" LLVMMetadataRef @@ -907,63 +919,59 @@ LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder, } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *LinkageName, size_t LinkageNameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags, - LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam, - LLVMMetadataRef Decl) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, + LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) { DITemplateParameterArray TParams = DITemplateParameterArray(unwrap(TParam)); DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); DINode::DIFlags llvmFlags = fromRust(Flags); DISubprogram *Sub = Builder->createFunction( - unwrapDI(Scope), - StringRef(Name, NameLen), - StringRef(LinkageName, LinkageNameLen), - unwrapDI(File), LineNo, - unwrapDI(Ty), ScopeLine, llvmFlags, - llvmSPFlags, TParams, unwrapDIPtr(Decl)); + unwrapDI(Scope), StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, + unwrapDI(Ty), ScopeLine, llvmFlags, llvmSPFlags, + TParams, unwrapDIPtr(Decl)); if (MaybeFn) unwrap(MaybeFn)->setSubprogram(Sub); return wrap(Sub); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *LinkageName, size_t LinkageNameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, LLVMRustDIFlags Flags, - LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) { DITemplateParameterArray TParams = DITemplateParameterArray(unwrap(TParam)); DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags); DINode::DIFlags llvmFlags = fromRust(Flags); DISubprogram *Sub = Builder->createMethod( - unwrapDI(Scope), - StringRef(Name, NameLen), - StringRef(LinkageName, LinkageNameLen), - unwrapDI(File), LineNo, - unwrapDI(Ty), - 0, 0, nullptr, // VTable params aren't used + unwrapDI(Scope), StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, + unwrapDI(Ty), 0, 0, + nullptr, // VTable params aren't used llvmFlags, llvmSPFlags, TParams); return wrap(Sub); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType( - LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, - uint64_t SizeInBits, unsigned Encoding) { - return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name, + size_t NameLen, uint64_t SizeInBits, + unsigned Encoding) { + return wrap( + Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) { +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateTypedef(LLVMRustDIBuilderRef Builder, + LLVMMetadataRef Type, const char *Name, + size_t NameLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Scope) { return wrap(Builder->createTypedef( - unwrap(Type), StringRef(Name, NameLen), unwrap(File), - LineNo, unwrapDIPtr(Scope))); + unwrap(Type), StringRef(Name, NameLen), unwrap(File), + LineNo, unwrapDIPtr(Scope))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( @@ -971,118 +979,98 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, const char *Name, size_t NameLen) { return wrap(Builder->createPointerType(unwrapDI(PointeeTy), - SizeInBits, AlignInBits, - AddressSpace, + SizeInBits, AlignInBits, AddressSpace, StringRef(Name, NameLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, - LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, - unsigned RunTimeLang, LLVMMetadataRef VTableHolder, - const char *UniqueId, size_t UniqueIdLen) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang, + LLVMMetadataRef VTableHolder, const char *UniqueId, size_t UniqueIdLen) { return wrap(Builder->createStructType( unwrapDI(Scope), StringRef(Name, NameLen), - unwrapDI(File), LineNumber, - SizeInBits, AlignInBits, fromRust(Flags), unwrapDI(DerivedFrom), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, + fromRust(Flags), unwrapDI(DerivedFrom), DINodeArray(unwrapDI(Elements)), RunTimeLang, unwrapDI(VTableHolder), StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator, - LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + LLVMMetadataRef Discriminator, LLVMMetadataRef Elements, + const char *UniqueId, size_t UniqueIdLen) { return wrap(Builder->createVariantPart( unwrapDI(Scope), StringRef(Name, NameLen), - unwrapDI(File), LineNumber, - SizeInBits, AlignInBits, fromRust(Flags), unwrapDI(Discriminator), - DINodeArray(unwrapDI(Elements)), StringRef(UniqueId, UniqueIdLen))); + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, + fromRust(Flags), unwrapDI(Discriminator), + DINodeArray(unwrapDI(Elements)), + StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { - return wrap(Builder->createMemberType(unwrapDI(Scope), - StringRef(Name, NameLen), - unwrapDI(File), LineNo, - SizeInBits, AlignInBits, OffsetInBits, - fromRust(Flags), unwrapDI(Ty))); + return wrap(Builder->createMemberType( + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, + fromRust(Flags), unwrapDI(Ty))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { - llvm::ConstantInt* D = nullptr; + llvm::ConstantInt *D = nullptr; if (Discriminant) { D = unwrap(Discriminant); } - return wrap(Builder->createVariantMemberType(unwrapDI(Scope), - StringRef(Name, NameLen), - unwrapDI(File), LineNo, - SizeInBits, AlignInBits, OffsetInBits, D, - fromRust(Flags), unwrapDI(Ty))); + return wrap(Builder->createVariantMemberType( + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, D, + fromRust(Flags), unwrapDI(Ty))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType( - LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, - size_t NameLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMRustDIFlags Flags, - LLVMValueRef val, - uint32_t AlignInBits -) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMRustDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) { return wrap(Builder->createStaticMemberType( - unwrapDI(Scope), - StringRef(Name, NameLen), - unwrapDI(File), - LineNo, - unwrapDI(Ty), - fromRust(Flags), - unwrap(val), + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNo, unwrapDI(Ty), fromRust(Flags), + unwrap(val), #if LLVM_VERSION_GE(18, 0) - llvm::dwarf::DW_TAG_member, + llvm::dwarf::DW_TAG_member, #endif - AlignInBits - )); + AlignInBits)); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - LLVMMetadataRef File, unsigned Line, unsigned Col) { +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateLexicalBlock(LLVMRustDIBuilderRef Builder, + LLVMMetadataRef Scope, LLVMMetadataRef File, + unsigned Line, unsigned Col) { return wrap(Builder->createLexicalBlock(unwrapDI(Scope), unwrapDI(File), Line, Col)); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, - LLVMMetadataRef File) { +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile( + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) { return wrap(Builder->createLexicalBlockFile(unwrapDI(Scope), unwrapDI(File))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, - const char *Name, size_t NameLen, - const char *LinkageName, size_t LinkageNameLen, - LLVMMetadataRef File, unsigned LineNo, - LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V, - LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name, + size_t NameLen, const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + bool IsLocalToUnit, LLVMValueRef V, LLVMMetadataRef Decl = nullptr, + uint32_t AlignInBits = 0) { llvm::GlobalVariable *InitVal = cast(unwrap(V)); llvm::DIExpression *InitExpr = nullptr; @@ -1095,14 +1083,13 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( FPVal->getValueAPF().bitcastToAPInt().getZExtValue()); } - llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( - unwrapDI(Context), StringRef(Name, NameLen), - StringRef(LinkageName, LinkageNameLen), - unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, - /* isDefined */ true, - InitExpr, unwrapDIPtr(Decl), - /* templateParams */ nullptr, - AlignInBits); + llvm::DIGlobalVariableExpression *VarExpr = + Builder->createGlobalVariableExpression( + unwrapDI(Context), StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), unwrapDI(File), + LineNo, unwrapDI(Ty), IsLocalToUnit, + /* isDefined */ true, InitExpr, unwrapDIPtr(Decl), + /* templateParams */ nullptr, AlignInBits); InitVal->setMetadata("dbg", VarExpr); @@ -1111,20 +1098,19 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNo, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags, unsigned ArgNo, uint32_t AlignInBits) { if (Tag == 0x100) { // DW_TAG_auto_variable return wrap(Builder->createAutoVariable( unwrapDI(Scope), StringRef(Name, NameLen), - unwrapDI(File), LineNo, - unwrapDI(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits)); + unwrapDI(File), LineNo, unwrapDI(Ty), AlwaysPreserve, + fromRust(Flags), AlignInBits)); } else { return wrap(Builder->createParameterVariable( unwrapDI(Scope), StringRef(Name, NameLen), ArgNo, - unwrapDI(File), LineNo, - unwrapDI(Ty), AlwaysPreserve, fromRust(Flags))); + unwrapDI(File), LineNo, unwrapDI(Ty), AlwaysPreserve, + fromRust(Flags))); } } @@ -1157,9 +1143,9 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( LLVMBasicBlockRef InsertAtEnd) { auto Result = Builder->insertDeclare( unwrap(V), unwrap(VarInfo), - Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), - DebugLoc(cast(unwrap(DL))), - unwrap(InsertAtEnd)); + Builder->createExpression( + llvm::ArrayRef(AddrOps, AddrOpsCount)), + DebugLoc(cast(unwrap(DL))), unwrap(InsertAtEnd)); #if LLVM_VERSION_GE(19, 0) return wrap(Result.get()); #else @@ -1170,21 +1156,20 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) { - return wrap(Builder->createEnumerator(StringRef(Name, NameLen), + return wrap(Builder->createEnumerator( + StringRef(Name, NameLen), APSInt(APInt(SizeInBits, ArrayRef(Value, 2)), IsUnsigned))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMMetadataRef Elements, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef Elements, LLVMMetadataRef ClassTy, bool IsScoped) { return wrap(Builder->createEnumerationType( unwrapDI(Scope), StringRef(Name, NameLen), - unwrapDI(File), LineNumber, - SizeInBits, AlignInBits, DINodeArray(unwrapDI(Elements)), - unwrapDI(ClassTy), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, + DINodeArray(unwrapDI(Elements)), unwrapDI(ClassTy), #if LLVM_VERSION_GE(18, 0) /* RunTimeLang */ 0, #endif @@ -1192,39 +1177,38 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, - uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements, - unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, + LLVMMetadataRef Elements, unsigned RunTimeLang, const char *UniqueId, + size_t UniqueIdLen) { return wrap(Builder->createUnionType( - unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(File), - LineNumber, SizeInBits, AlignInBits, fromRust(Flags), - DINodeArray(unwrapDI(Elements)), RunTimeLang, + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, + fromRust(Flags), DINodeArray(unwrapDI(Elements)), RunTimeLang, StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, LLVMMetadataRef Ty) { + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef Ty) { bool IsDefault = false; // FIXME: should we ever set this true? return wrap(Builder->createTemplateTypeParameter( - unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(Ty), IsDefault)); + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(Ty), IsDefault)); } -extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, size_t NameLen, bool ExportSymbols) { +extern "C" LLVMMetadataRef +LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, + LLVMMetadataRef Scope, const char *Name, + size_t NameLen, bool ExportSymbols) { return wrap(Builder->createNameSpace( - unwrapDI(Scope), StringRef(Name, NameLen), ExportSymbols - )); + unwrapDI(Scope), StringRef(Name, NameLen), ExportSymbols)); } -extern "C" void -LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef CompositeTy, - LLVMMetadataRef Elements, - LLVMMetadataRef Params) { +extern "C" void LLVMRustDICompositeTypeReplaceArrays( + LLVMRustDIBuilderRef Builder, LLVMMetadataRef CompositeTy, + LLVMMetadataRef Elements, LLVMMetadataRef Params) { DICompositeType *Tmp = unwrapDI(CompositeTy); Builder->replaceArrays(Tmp, DINodeArray(unwrap(Elements)), DINodeArray(unwrap(Params))); @@ -1235,9 +1219,8 @@ LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, LLVMMetadataRef ScopeRef, LLVMMetadataRef InlinedAt) { MDNode *Scope = unwrapDIPtr(ScopeRef); - DILocation *Loc = DILocation::get( - Scope->getContext(), Line, Column, Scope, - unwrapDIPtr(InlinedAt)); + DILocation *Loc = DILocation::get(Scope->getContext(), Line, Column, Scope, + unwrapDIPtr(InlinedAt)); return wrap(Loc); } @@ -1258,8 +1241,7 @@ extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) { unwrap(Ty)->print(OS); } -extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, - RustStringRef Str) { +extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, RustStringRef Str) { auto OS = RawRustStringOstream(Str); if (!V) { OS << "(null)"; @@ -1281,7 +1263,7 @@ extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { extern "C" void LLVMRustUnpackOptimizationDiagnostic( LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut, - LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column, + LLVMValueRef *FunctionOut, unsigned *Line, unsigned *Column, RustStringRef FilenameOut, RustStringRef MessageOut) { // Undefined to call this not on an optimization diagnostic! llvm::DiagnosticInfoOptimizationBase *Opt = @@ -1304,17 +1286,15 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic( } enum class LLVMRustDiagnosticLevel { - Error, - Warning, - Note, - Remark, + Error, + Warning, + Note, + Remark, }; -extern "C" void -LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, - LLVMRustDiagnosticLevel *LevelOut, - uint64_t *CookieOut, - LLVMTwineRef *MessageOut) { +extern "C" void LLVMRustUnpackInlineAsmDiagnostic( + LLVMDiagnosticInfoRef DI, LLVMRustDiagnosticLevel *LevelOut, + uint64_t *CookieOut, LLVMTwineRef *MessageOut) { // Undefined to call this not on an inline assembly diagnostic! llvm::DiagnosticInfoInlineAsm *IA = static_cast(unwrap(DI)); @@ -1323,20 +1303,20 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, *MessageOut = wrap(&IA->getMsgStr()); switch (IA->getSeverity()) { - case DS_Error: - *LevelOut = LLVMRustDiagnosticLevel::Error; - break; - case DS_Warning: - *LevelOut = LLVMRustDiagnosticLevel::Warning; - break; - case DS_Note: - *LevelOut = LLVMRustDiagnosticLevel::Note; - break; - case DS_Remark: - *LevelOut = LLVMRustDiagnosticLevel::Remark; - break; - default: - report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); + case DS_Error: + *LevelOut = LLVMRustDiagnosticLevel::Error; + break; + case DS_Warning: + *LevelOut = LLVMRustDiagnosticLevel::Warning; + break; + case DS_Note: + *LevelOut = LLVMRustDiagnosticLevel::Note; + break; + case DS_Remark: + *LevelOut = LLVMRustDiagnosticLevel::Remark; + break; + default: + report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); } } @@ -1454,61 +1434,61 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { return LLVMBFloatTypeKind; case Type::X86_AMXTyID: return LLVMX86_AMXTypeKind; - default: - { - std::string error; - auto stream = llvm::raw_string_ostream(error); - stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID() - << " for the type: " << *unwrap(Ty); - stream.flush(); - report_fatal_error(error.c_str()); - } + default: { + std::string error; + auto stream = llvm::raw_string_ostream(error); + stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID() + << " for the type: " << *unwrap(Ty); + stream.flush(); + report_fatal_error(error.c_str()); + } } } DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) -extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic( - LLVMDiagnosticInfoRef DI, unsigned *Cookie) { - llvm::DiagnosticInfoSrcMgr *SM = static_cast(unwrap(DI)); +extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(LLVMDiagnosticInfoRef DI, + unsigned *Cookie) { + llvm::DiagnosticInfoSrcMgr *SM = + static_cast(unwrap(DI)); *Cookie = SM->getLocCookie(); return wrap(&SM->getSMDiag()); } -extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, - RustStringRef MessageOut, - RustStringRef BufferOut, - LLVMRustDiagnosticLevel* LevelOut, - unsigned* LocOut, - unsigned* RangesOut, - size_t* NumRanges) { - SMDiagnostic& D = *unwrap(DRef); +extern "C" bool +LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, + RustStringRef BufferOut, + LLVMRustDiagnosticLevel *LevelOut, unsigned *LocOut, + unsigned *RangesOut, size_t *NumRanges) { + SMDiagnostic &D = *unwrap(DRef); auto MessageOS = RawRustStringOstream(MessageOut); MessageOS << D.getMessage(); switch (D.getKind()) { - case SourceMgr::DK_Error: - *LevelOut = LLVMRustDiagnosticLevel::Error; - break; - case SourceMgr::DK_Warning: - *LevelOut = LLVMRustDiagnosticLevel::Warning; - break; - case SourceMgr::DK_Note: - *LevelOut = LLVMRustDiagnosticLevel::Note; - break; - case SourceMgr::DK_Remark: - *LevelOut = LLVMRustDiagnosticLevel::Remark; - break; - default: - report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); + case SourceMgr::DK_Error: + *LevelOut = LLVMRustDiagnosticLevel::Error; + break; + case SourceMgr::DK_Warning: + *LevelOut = LLVMRustDiagnosticLevel::Warning; + break; + case SourceMgr::DK_Note: + *LevelOut = LLVMRustDiagnosticLevel::Note; + break; + case SourceMgr::DK_Remark: + *LevelOut = LLVMRustDiagnosticLevel::Remark; + break; + default: + report_fatal_error("Invalid LLVMRustDiagnosticLevel value!"); } if (D.getLoc() == SMLoc()) return false; const SourceMgr &LSM = *D.getSourceMgr(); - const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize()); + const MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), + LBuf->getBufferSize()); *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart(); @@ -1525,7 +1505,8 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, unsigned NumInputs) { - return new OperandBundleDef(Name, ArrayRef(unwrap(Inputs), NumInputs)); + return new OperandBundleDef(Name, + ArrayRef(unwrap(Inputs), NumInputs)); } extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { @@ -1533,8 +1514,9 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) { } // OpBundlesIndirect is an array of pointers (*not* a pointer to an array). -extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, - LLVMValueRef *Args, unsigned NumArgs, +extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef Fn, LLVMValueRef *Args, + unsigned NumArgs, OperandBundleDef **OpBundlesIndirect, unsigned NumOpBundles) { Value *Callee = unwrap(Fn); @@ -1547,17 +1529,19 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVM OpBundles.push_back(*OpBundlesIndirect[i]); } - return wrap(unwrap(B)->CreateCall( - FTy, Callee, ArrayRef(unwrap(Args), NumArgs), - ArrayRef(OpBundles))); + return wrap(unwrap(B)->CreateCall(FTy, Callee, + ArrayRef(unwrap(Args), NumArgs), + ArrayRef(OpBundles))); } -extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { +extern "C" LLVMValueRef +LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_increment)); } -extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) { +extern "C" LLVMValueRef +LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) { #if LLVM_VERSION_GE(18, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); @@ -1566,7 +1550,8 @@ extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRe #endif } -extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { +extern "C" LLVMValueRef +LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { #if LLVM_VERSION_GE(18, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); @@ -1575,7 +1560,8 @@ extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModu #endif } -extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) { +extern "C" LLVMValueRef +LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) { #if LLVM_VERSION_GE(18, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update)); @@ -1584,32 +1570,31 @@ extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRe #endif } -extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Src, unsigned SrcAlign, - LLVMValueRef Size, bool IsVolatile) { - return wrap(unwrap(B)->CreateMemCpy( - unwrap(Dst), MaybeAlign(DstAlign), - unwrap(Src), MaybeAlign(SrcAlign), - unwrap(Size), IsVolatile)); +extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, + unsigned DstAlign, LLVMValueRef Src, + unsigned SrcAlign, + LLVMValueRef Size, + bool IsVolatile) { + return wrap(unwrap(B)->CreateMemCpy(unwrap(Dst), MaybeAlign(DstAlign), + unwrap(Src), MaybeAlign(SrcAlign), + unwrap(Size), IsVolatile)); } -extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Src, unsigned SrcAlign, - LLVMValueRef Size, bool IsVolatile) { - return wrap(unwrap(B)->CreateMemMove( - unwrap(Dst), MaybeAlign(DstAlign), - unwrap(Src), MaybeAlign(SrcAlign), - unwrap(Size), IsVolatile)); +extern "C" LLVMValueRef +LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, + LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, + bool IsVolatile) { + return wrap(unwrap(B)->CreateMemMove(unwrap(Dst), MaybeAlign(DstAlign), + unwrap(Src), MaybeAlign(SrcAlign), + unwrap(Size), IsVolatile)); } -extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, - LLVMValueRef Dst, unsigned DstAlign, - LLVMValueRef Val, - LLVMValueRef Size, bool IsVolatile) { - return wrap(unwrap(B)->CreateMemSet( - unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile)); +extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst, + unsigned DstAlign, LLVMValueRef Val, + LLVMValueRef Size, + bool IsVolatile) { + return wrap(unwrap(B)->CreateMemSet(unwrap(Dst), unwrap(Val), unwrap(Size), + MaybeAlign(DstAlign), IsVolatile)); } // OpBundlesIndirect is an array of pointers (*not* a pointer to an array). @@ -1630,7 +1615,7 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, } return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch), - ArrayRef(unwrap(Args), NumArgs), + ArrayRef(unwrap(Args), NumArgs), ArrayRef(OpBundles), Name)); } @@ -1647,7 +1632,7 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, FunctionType *FTy = unwrap(Ty); // FIXME: Is there a way around this? - std::vector IndirectDestsUnwrapped; + std::vector IndirectDestsUnwrapped; IndirectDestsUnwrapped.reserve(NumIndirectDests); for (unsigned i = 0; i < NumIndirectDests; ++i) { IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i])); @@ -1660,12 +1645,11 @@ LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, OpBundles.push_back(*OpBundlesIndirect[i]); } - return wrap(unwrap(B)->CreateCallBr( - FTy, Callee, unwrap(DefaultDest), - ArrayRef(IndirectDestsUnwrapped), - ArrayRef(unwrap(Args), NumArgs), - ArrayRef(OpBundles), - Name)); + return wrap( + unwrap(B)->CreateCallBr(FTy, Callee, unwrap(DefaultDest), + ArrayRef(IndirectDestsUnwrapped), + ArrayRef(unwrap(Args), NumArgs), + ArrayRef(OpBundles), Name)); } extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, @@ -1765,28 +1749,30 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, } extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) { - auto C = unwrap(CV); - if (C->getBitWidth() > 64) - return false; - *value = C->getZExtValue(); - return true; + auto C = unwrap(CV); + if (C->getBitWidth() > 64) + return false; + *value = C->getZExtValue(); + return true; } -// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of -// the common sizes (1, 8, 16, 32, 64, 128 bits) -extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low) -{ - auto C = unwrap(CV); - if (C->getBitWidth() > 128) { return false; } - APInt AP; - if (sext) { - AP = C->getValue().sext(128); - } else { - AP = C->getValue().zext(128); - } - *low = AP.getLoBits(64).getZExtValue(); - *high = AP.getHiBits(64).getZExtValue(); - return true; +// Returns true if both high and low were successfully set. Fails in case +// constant wasn’t any of the common sizes (1, 8, 16, 32, 64, 128 bits) +extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, + uint64_t *high, uint64_t *low) { + auto C = unwrap(CV); + if (C->getBitWidth() > 128) { + return false; + } + APInt AP; + if (sext) { + AP = C->getValue().sext(128); + } else { + AP = C->getValue().zext(128); + } + *low = AP.getLoBits(64).getZExtValue(); + *high = AP.getHiBits(64).getZExtValue(); + return true; } enum class LLVMRustVisibility { @@ -1836,8 +1822,7 @@ struct LLVMRustModuleBuffer { std::string data; }; -extern "C" LLVMRustModuleBuffer* -LLVMRustModuleBufferCreate(LLVMModuleRef M) { +extern "C" LLVMRustModuleBuffer *LLVMRustModuleBufferCreate(LLVMModuleRef M) { auto Ret = std::make_unique(); { auto OS = raw_string_ostream(Ret->data); @@ -1846,30 +1831,26 @@ LLVMRustModuleBufferCreate(LLVMModuleRef M) { return Ret.release(); } -extern "C" void -LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) { +extern "C" void LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) { delete Buffer; } -extern "C" const void* +extern "C" const void * LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) { return Buffer->data.data(); } -extern "C" size_t -LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) { +extern "C" size_t LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) { return Buffer->data.length(); } -extern "C" uint64_t -LLVMRustModuleCost(LLVMModuleRef M) { +extern "C" uint64_t LLVMRustModuleCost(LLVMModuleRef M) { auto f = unwrap(M)->functions(); return std::distance(std::begin(f), std::end(f)); } -extern "C" void -LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str) -{ +extern "C" void LLVMRustModuleInstructionStats(LLVMModuleRef M, + RustStringRef Str) { auto OS = RawRustStringOstream(Str); auto JOS = llvm::json::OStream(OS); auto Module = unwrap(M); @@ -1881,41 +1862,45 @@ LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str) } // Vector reductions: -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, + LLVMValueRef Acc, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc), unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, + LLVMValueRef Acc, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc), unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) { - return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, + LLVMValueRef Src) { + return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { - return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, + LLVMValueRef Src, + bool IsSigned) { + return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); } -extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { - return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); +extern "C" LLVMValueRef LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, + LLVMValueRef Src, + bool IsSigned) { + return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { @@ -1930,32 +1915,28 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { return wrap(I); } -extern "C" LLVMValueRef -LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { - return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS))); +extern "C" LLVMValueRef LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, + LLVMValueRef RHS) { + return wrap(unwrap(B)->CreateMinNum(unwrap(LHS), unwrap(RHS))); } -extern "C" LLVMValueRef -LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { - return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS))); +extern "C" LLVMValueRef LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, + LLVMValueRef RHS) { + return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS), unwrap(RHS))); } // This struct contains all necessary info about a symbol exported from a DLL. struct LLVMRustCOFFShortExport { - const char* name; + const char *name; bool ordinal_present; // The value of `ordinal` is only meaningful if `ordinal_present` is true. uint16_t ordinal; }; // Machine must be a COFF machine type, as defined in PE specs. -extern "C" LLVMRustResult LLVMRustWriteImportLibrary( - const char* ImportName, - const char* Path, - const LLVMRustCOFFShortExport* Exports, - size_t NumExports, - uint16_t Machine, - bool MinGW) -{ +extern "C" LLVMRustResult +LLVMRustWriteImportLibrary(const char *ImportName, const char *Path, + const LLVMRustCOFFShortExport *Exports, + size_t NumExports, uint16_t Machine, bool MinGW) { std::vector ConvertedExports; ConvertedExports.reserve(NumExports); @@ -1963,27 +1944,24 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( bool ordinal_present = Exports[i].ordinal_present; uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0; ConvertedExports.push_back(llvm::object::COFFShortExport{ - Exports[i].name, // Name - std::string{}, // ExtName - std::string{}, // SymbolName - std::string{}, // AliasTarget + Exports[i].name, // Name + std::string{}, // ExtName + std::string{}, // SymbolName + std::string{}, // AliasTarget #if LLVM_VERSION_GE(19, 0) - std::string{}, // ExportAs + std::string{}, // ExportAs #endif - ordinal, // Ordinal - ordinal_present, // Noname - false, // Data - false, // Private - false // Constant + ordinal, // Ordinal + ordinal_present, // Noname + false, // Data + false, // Private + false // Constant }); } auto Error = llvm::object::writeImportLibrary( - ImportName, - Path, - ConvertedExports, - static_cast(Machine), - MinGW); + ImportName, Path, ConvertedExports, + static_cast(Machine), MinGW); if (Error) { std::string errorString; auto stream = llvm::raw_string_ostream(errorString); @@ -2019,27 +1997,23 @@ using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy; // the RemarkPasses array specifies individual passes for which remarks will be // enabled. // -// If RemarkFilePath is not NULL, optimization remarks will be streamed directly into this file, -// bypassing the diagnostics handler. +// If RemarkFilePath is not NULL, optimization remarks will be streamed directly +// into this file, bypassing the diagnostics handler. extern "C" void LLVMRustContextConfigureDiagnosticHandler( LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, void *DiagnosticHandlerContext, bool RemarkAllPasses, - const char * const * RemarkPasses, size_t RemarkPassesLen, - const char * RemarkFilePath, - bool PGOAvailable -) { + const char *const *RemarkPasses, size_t RemarkPassesLen, + const char *RemarkFilePath, bool PGOAvailable) { class RustDiagnosticHandler final : public DiagnosticHandler { public: RustDiagnosticHandler( - LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, - void *DiagnosticHandlerContext, - bool RemarkAllPasses, - std::vector RemarkPasses, - std::unique_ptr RemarksFile, - std::unique_ptr RemarkStreamer, - std::unique_ptr LlvmRemarkStreamer - ) + LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, bool RemarkAllPasses, + std::vector RemarkPasses, + std::unique_ptr RemarksFile, + std::unique_ptr RemarkStreamer, + std::unique_ptr LlvmRemarkStreamer) : DiagnosticHandlerCallback(DiagnosticHandlerCallback), DiagnosticHandlerContext(DiagnosticHandlerContext), RemarkAllPasses(RemarkAllPasses), @@ -2049,11 +2023,13 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {} virtual bool handleDiagnostics(const DiagnosticInfo &DI) override { - // If this diagnostic is one of the optimization remark kinds, we can check if it's enabled - // before emitting it. This can avoid many short-lived allocations when unpacking the - // diagnostic and converting its various C++ strings into rust strings. - // FIXME: some diagnostic infos still allocate before we get here, and avoiding that would be - // good in the future. That will require changing a few call sites in LLVM. + // If this diagnostic is one of the optimization remark kinds, we can + // check if it's enabled before emitting it. This can avoid many + // short-lived allocations when unpacking the diagnostic and converting + // its various C++ strings into rust strings. + // FIXME: some diagnostic infos still allocate before we get here, and + // avoiding that would be good in the future. That will require changing a + // few call sites in LLVM. if (auto *OptDiagBase = dyn_cast(&DI)) { if (OptDiagBase->isEnabled()) { if (this->LlvmRemarkStreamer) { @@ -2109,16 +2085,15 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( bool RemarkAllPasses = false; std::vector RemarkPasses; - // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the ordering of the three - // members below is important. + // Since LlvmRemarkStreamer contains a pointer to RemarkStreamer, the + // ordering of the three members below is important. std::unique_ptr RemarksFile; std::unique_ptr RemarkStreamer; std::unique_ptr LlvmRemarkStreamer; }; std::vector Passes; - for (size_t I = 0; I != RemarkPassesLen; ++I) - { + for (size_t I = 0; I != RemarkPassesLen; ++I) { Passes.push_back(RemarkPasses[I]); } @@ -2135,13 +2110,10 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( std::error_code EC; RemarkFile = std::make_unique( - RemarkFilePath, - EC, - llvm::sys::fs::OF_TextWithCRLF - ); + RemarkFilePath, EC, llvm::sys::fs::OF_TextWithCRLF); if (EC) { std::string Error = std::string("Cannot create remark file: ") + - toString(errorCodeToError(EC)); + toString(errorCodeToError(EC)); report_fatal_error(Twine(Error)); } @@ -2149,28 +2121,22 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( RemarkFile->keep(); auto RemarkSerializer = remarks::createRemarkSerializer( - llvm::remarks::Format::YAML, - remarks::SerializerMode::Separate, - RemarkFile->os() - ); - if (Error E = RemarkSerializer.takeError()) - { - std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E)); + llvm::remarks::Format::YAML, remarks::SerializerMode::Separate, + RemarkFile->os()); + if (Error E = RemarkSerializer.takeError()) { + std::string Error = std::string("Cannot create remark serializer: ") + + toString(std::move(E)); report_fatal_error(Twine(Error)); } - RemarkStreamer = std::make_unique(std::move(*RemarkSerializer)); + RemarkStreamer = std::make_unique( + std::move(*RemarkSerializer)); LlvmRemarkStreamer = std::make_unique(*RemarkStreamer); } unwrap(C)->setDiagnosticHandler(std::make_unique( - DiagnosticHandlerCallback, - DiagnosticHandlerContext, - RemarkAllPasses, - Passes, - std::move(RemarkFile), - std::move(RemarkStreamer), - std::move(LlvmRemarkStreamer) - )); + DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, + Passes, std::move(RemarkFile), std::move(RemarkStreamer), + std::move(LlvmRemarkStreamer))); } extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { @@ -2180,14 +2146,14 @@ extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { } extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) { - auto *CB = unwrap(CallSite); - switch (CB->getIntrinsicID()) { - case Intrinsic::arm_ldrex: - return 0; - case Intrinsic::arm_strex: - return 1; - } - return -1; + auto *CB = unwrap(CallSite); + switch (CB->getIntrinsicID()) { + case Intrinsic::arm_ldrex: + return 0; + case Intrinsic::arm_strex: + return 1; + } + return -1; } extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) { @@ -2214,10 +2180,10 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { } // Operations on composite constants. -// These are clones of LLVM api functions that will become available in future releases. -// They can be removed once Rust's minimum supported LLVM version supports them. -// See https://github.com/rust-lang/rust/issues/121868 -// See https://llvm.org/doxygen/group__LLVMCCoreValueConstantComposite.html +// These are clones of LLVM api functions that will become available in future +// releases. They can be removed once Rust's minimum supported LLVM version +// supports them. See https://github.com/rust-lang/rust/issues/121868 See +// https://llvm.org/doxygen/group__LLVMCCoreValueConstantComposite.html // FIXME: Remove when Rust's minimum supported LLVM version reaches 19. // https://github.com/llvm/llvm-project/commit/e1405e4f71c899420ebf8262d5e9745598419df8 @@ -2226,6 +2192,7 @@ extern "C" LLVMValueRef LLVMConstStringInContext2(LLVMContextRef C, const char *Str, size_t Length, bool DontNullTerminate) { - return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), !DontNullTerminate)); + return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), + !DontNullTerminate)); } #endif diff --git a/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h b/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h index 56964e4eaa70..09ecfd54cd8e 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h +++ b/compiler/rustc_llvm/llvm-wrapper/SuppressLLVMWarnings.h @@ -1,13 +1,17 @@ #ifndef _rustc_llvm_SuppressLLVMWarnings_h #define _rustc_llvm_SuppressLLVMWarnings_h -// LLVM currently generates many warnings when compiled using MSVC. These warnings make it difficult -// to diagnose real problems when working on C++ code, so we suppress them. +// LLVM currently generates many warnings when compiled using MSVC. These +// warnings make it difficult to diagnose real problems when working on C++ +// code, so we suppress them. #ifdef _MSC_VER -#pragma warning(disable:4530) // C++ exception handler used, but unwind semantics are not enabled. -#pragma warning(disable:4624) // 'xxx': destructor was implicitly defined as deleted -#pragma warning(disable:4244) // conversion from 'xxx' to 'yyy', possible loss of data +#pragma warning(disable : 4530) // C++ exception handler used, but unwind + // semantics are not enabled. +#pragma warning( \ + disable : 4624) // 'xxx': destructor was implicitly defined as deleted +#pragma warning( \ + disable : 4244) // conversion from 'xxx' to 'yyy', possible loss of data #endif #endif // _rustc_llvm_SuppressLLVMWarnings_h diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index ee8239ef8e79..a9d1362a338d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -34,14 +34,15 @@ static bool isArchiveSymbol(const object::BasicSymbolRef &S) { typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *); typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *); -// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't -// implement getSymbolName, only printSymbolName, which is inaccessible from the C api. -extern "C" void *LLVMRustGetSymbols( - char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback, - LLVMRustGetSymbolsErrorCallback ErrorCallback) { - std::unique_ptr Buf = - MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), - false); +// Note: This is implemented in C++ instead of using the C api from Rust as +// IRObjectFile doesn't implement getSymbolName, only printSymbolName, which is +// inaccessible from the C api. +extern "C" void * +LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, + LLVMRustGetSymbolsCallback Callback, + LLVMRustGetSymbolsErrorCallback ErrorCallback) { + std::unique_ptr Buf = MemoryBuffer::getMemBuffer( + StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); SmallString<0> SymNameBuf; auto SymName = raw_svector_ostream(SymNameBuf); @@ -57,7 +58,7 @@ extern "C" void *LLVMRustGetSymbols( if (Type == file_magic::bitcode) { auto ObjOrErr = object::SymbolicFile::createSymbolicFile( - Buf->getMemBufferRef(), file_magic::bitcode, &Context); + Buf->getMemBufferRef(), file_magic::bitcode, &Context); if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; @@ -67,7 +68,8 @@ extern "C" void *LLVMRustGetSymbols( } Obj = std::move(*ObjOrErr); } else { - auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); + auto ObjOrErr = + object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); if (!ObjOrErr) { Error E = ObjOrErr.takeError(); SmallString<0> ErrorBuf; @@ -78,7 +80,6 @@ extern "C" void *LLVMRustGetSymbols( Obj = std::move(*ObjOrErr); } - for (const object::BasicSymbolRef &S : Obj->symbols()) { if (!isArchiveSymbol(S)) continue; From c163d5c99d381efb74c02182996b69b32ecfcff1 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 25 Jun 2024 18:37:15 +0800 Subject: [PATCH 52/53] Add `cpp:fmt` to mingw-check-tidy --- src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index 0a49eab4d502..cb17592b201c 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -35,4 +35,4 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ # NOTE: intentionally uses python2 for x.py so we can test it still works. # validate-toolstate only runs in our CI, so it's ok for it to only support python3. ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \ - --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint + --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint,cpp:fmt From 7666534381042f5febdc995e024af051ceecc2f5 Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Wed, 26 Jun 2024 17:00:46 +0200 Subject: [PATCH 53/53] Clarify comment on changing to warn future breakage items https://github.com/rust-lang/rust/pull/120924/files#r1653512240 --- compiler/rustc_errors/src/json.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 3d2a04d58515..764134d5335f 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -135,11 +135,11 @@ impl Emitter for JsonEmitter { let data: Vec> = diags .into_iter() .map(|mut diag| { - // The `FutureBreakageItem` is collected and serialized. - // However, the `allow` and `expect` lint levels can't usually - // be serialized. The lint level is overwritten to allow the - // serialization again and force a lint emission. - // (This is an educated guess. I didn't originally add this) + // Allowed or expected lints don't normally (by definition) emit a lint + // but future incompat lints are special and are emitted anyway. + // + // So to avoid ICEs and confused users we "upgrade" the lint level for + // those `FutureBreakageItem` to warn. if matches!(diag.level, crate::Level::Allow | crate::Level::Expect(..)) { diag.level = crate::Level::Warning; }