From 99006922342ee6923277052240704255b455dd51 Mon Sep 17 00:00:00 2001 From: PedroTurik Date: Thu, 29 Aug 2024 00:08:10 -0300 Subject: [PATCH 01/22] adds new trait-method-added lint (#891) * adds new trait-method-added lint * corrects lint to account for traits that have also become sealed, and adds tests for it --- src/lints/trait_method_added.ron | 60 +++ src/query.rs | 1 + test_crates/trait_method_added/new/Cargo.toml | 7 + test_crates/trait_method_added/new/src/lib.rs | 49 +++ test_crates/trait_method_added/old/Cargo.toml | 7 + test_crates/trait_method_added/old/src/lib.rs | 31 ++ test_outputs/trait_method_added.output.ron | 360 ++++++++++++++++++ test_outputs/trait_newly_sealed.output.ron | 12 + 8 files changed, 527 insertions(+) create mode 100644 src/lints/trait_method_added.ron create mode 100644 test_crates/trait_method_added/new/Cargo.toml create mode 100644 test_crates/trait_method_added/new/src/lib.rs create mode 100644 test_crates/trait_method_added/old/Cargo.toml create mode 100644 test_crates/trait_method_added/old/src/lib.rs create mode 100644 test_outputs/trait_method_added.output.ron diff --git a/src/lints/trait_method_added.ron b/src/lints/trait_method_added.ron new file mode 100644 index 00000000..c5ebd43b --- /dev/null +++ b/src/lints/trait_method_added.ron @@ -0,0 +1,60 @@ +SemverQuery( + id: "trait_method_added", + human_readable_name: "pub trait method added", + description: "A non-sealed public trait added a new method without a default implementation", + required_update: Major, + lint_level: Deny, + reference_link: Some("https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-item-no-default"), + query: r#" + { + CrateDiff { + current { + item { + ... on Trait { + visibility_limit @filter(op: "=", value: ["$public"]) @output + name @output + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + + method { + method_name: name @output @tag + has_body @filter(op: "!=", value: ["$true"]) + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + baseline { + item { + ... on Trait { + visibility_limit @filter(op: "=", value: ["$public"]) + sealed @filter(op: "!=", value: ["$true"]) + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "=", value: ["$true"]) + } + + method @fold @transform(op: "count") @filter(op: "=", value: ["$zero"]) { + name @filter(op: "=", value: ["%method_name"]) + } + } + } + } + } + }"#, + arguments: { + "true": true, + "public": "public", + "zero": 0, + }, + error_message: "A non-sealed public trait added a new method without a default implementation, which breaks downstream implementations of the trait", + per_result_error_template: Some("trait method {{join \"::\" path}}::{{method_name}} in file {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index 79a1f1cd..a0125dfc 100644 --- a/src/query.rs +++ b/src/query.rs @@ -840,6 +840,7 @@ add_lints!( trait_associated_type_default_removed, trait_associated_type_now_doc_hidden, trait_default_impl_removed, + trait_method_added, trait_method_missing, trait_method_now_doc_hidden, trait_method_unsafe_added, diff --git a/test_crates/trait_method_added/new/Cargo.toml b/test_crates/trait_method_added/new/Cargo.toml new file mode 100644 index 00000000..878fba75 --- /dev/null +++ b/test_crates/trait_method_added/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "trait_method_added" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/trait_method_added/new/src/lib.rs b/test_crates/trait_method_added/new/src/lib.rs new file mode 100644 index 00000000..564a786a --- /dev/null +++ b/test_crates/trait_method_added/new/src/lib.rs @@ -0,0 +1,49 @@ +mod sealed { + pub(crate) trait Sealed {} +} + +// ---- Should be reported ---- +pub trait WillGainMethodWithoutDefault { + fn one_method(self); +} + +pub trait WillGainAnotherMethodWithoutDefault { + fn one_method(self); + fn two_method(self); +} + +pub trait WillGainMultipleMethodsWithoutDefault { + fn one_method(self); + fn two_method(self); +} + +pub trait WillGainMethodWithoutDefaultAndSeal: sealed::Sealed { + fn one_method(self); +} + +pub trait WIllGainDocHiddenMethodWithoutDefault { + #[doc(hidden)] + fn one_method(self); +} + +// ---- Should not be reported ---- +pub trait WillGainMethodWithDefault { + fn one_method(self) {} +} + +pub trait WillGainAnotherMethodWithDefault { + fn one_method(self); + fn two_method(self) {} +} + +pub trait WillGainMethodWithoutDefaultSealed: sealed::Sealed { + fn one_method(self); +} + +pub trait WillGainMethodWithoutDefaultAndLoseSeal { + fn one_method(self); +} + +pub trait WillKeepAMethodWithoutDefault { + fn one_method(self); +} diff --git a/test_crates/trait_method_added/old/Cargo.toml b/test_crates/trait_method_added/old/Cargo.toml new file mode 100644 index 00000000..878fba75 --- /dev/null +++ b/test_crates/trait_method_added/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "trait_method_added" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/trait_method_added/old/src/lib.rs b/test_crates/trait_method_added/old/src/lib.rs new file mode 100644 index 00000000..004952ea --- /dev/null +++ b/test_crates/trait_method_added/old/src/lib.rs @@ -0,0 +1,31 @@ +mod sealed { + pub(crate) trait Sealed {} +} + +// ---- Should be reported ---- +pub trait WillGainMethodWithoutDefault {} + +pub trait WillGainAnotherMethodWithoutDefault { + fn one_method(self); +} + +pub trait WillGainMultipleMethodsWithoutDefault {} + +pub trait WillGainMethodWithoutDefaultAndSeal {} + +pub trait WIllGainDocHiddenMethodWithoutDefault {} + +// ---- Should not be reported ---- +pub trait WillGainMethodWithDefault {} + +pub trait WillGainAnotherMethodWithDefault { + fn one_method(self); +} + +pub trait WillGainMethodWithoutDefaultSealed: sealed::Sealed {} + +pub trait WillGainMethodWithoutDefaultAndLoseSeal: sealed::Sealed {} + +pub trait WillKeepAMethodWithoutDefault { + fn one_method(self); +} diff --git a/test_outputs/trait_method_added.output.ron b/test_outputs/trait_method_added.output.ron new file mode 100644 index 00000000..c1589c82 --- /dev/null +++ b/test_outputs/trait_method_added.output.ron @@ -0,0 +1,360 @@ +{ + "./test_crates/method_moved_to_trait_must_use_added/": [ + { + "method_name": String("MethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(49), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(52), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(54), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(57), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(59), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(62), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(65), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedImplDeclaredMustUseMethod"), + "name": String("TraitWithMovedImplMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("enum_method_moved_to_trait_must_use_added"), + String("TraitWithMovedImplMustUseMethods"), + ]), + "span_begin_line": Uint64(135), + "span_filename": String("src/enum_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(45), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(48), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(50), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(53), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(55), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(58), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(61), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedImplDeclaredMustUseMethod"), + "name": String("TraitWithMovedImplMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("struct_method_moved_to_trait_must_use_added"), + String("TraitWithMovedImplMustUseMethods"), + ]), + "span_begin_line": Uint64(127), + "span_filename": String("src/struct_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(49), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(52), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(54), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(57), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(59), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(62), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MustUseMessageMethodToMovedDeclaredMustUseMessageMethod"), + "name": String("TraitWithMovedDeclaredMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedDeclaredMustUseMethods"), + ]), + "span_begin_line": Uint64(65), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("MethodToMovedImplDeclaredMustUseMethod"), + "name": String("TraitWithMovedImplMustUseMethods"), + "path": List([ + String("method_moved_to_trait_must_use_added"), + String("union_method_moved_to_trait_must_use_added"), + String("TraitWithMovedImplMustUseMethods"), + ]), + "span_begin_line": Uint64(135), + "span_filename": String("src/union_method_moved_to_trait_must_use_added.rs"), + "visibility_limit": String("public"), + }, + ], + "./test_crates/trait_method_added/": [ + { + "method_name": String("one_method"), + "name": String("WillGainMethodWithoutDefault"), + "path": List([ + String("trait_method_added"), + String("WillGainMethodWithoutDefault"), + ]), + "span_begin_line": Uint64(7), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("two_method"), + "name": String("WillGainAnotherMethodWithoutDefault"), + "path": List([ + String("trait_method_added"), + String("WillGainAnotherMethodWithoutDefault"), + ]), + "span_begin_line": Uint64(12), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("one_method"), + "name": String("WillGainMultipleMethodsWithoutDefault"), + "path": List([ + String("trait_method_added"), + String("WillGainMultipleMethodsWithoutDefault"), + ]), + "span_begin_line": Uint64(16), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("two_method"), + "name": String("WillGainMultipleMethodsWithoutDefault"), + "path": List([ + String("trait_method_added"), + String("WillGainMultipleMethodsWithoutDefault"), + ]), + "span_begin_line": Uint64(17), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("one_method"), + "name": String("WillGainMethodWithoutDefaultAndSeal"), + "path": List([ + String("trait_method_added"), + String("WillGainMethodWithoutDefaultAndSeal"), + ]), + "span_begin_line": Uint64(21), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "method_name": String("one_method"), + "name": String("WIllGainDocHiddenMethodWithoutDefault"), + "path": List([ + String("trait_method_added"), + String("WIllGainDocHiddenMethodWithoutDefault"), + ]), + "span_begin_line": Uint64(26), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], +} diff --git a/test_outputs/trait_newly_sealed.output.ron b/test_outputs/trait_newly_sealed.output.ron index 1363a9d1..14aee41b 100644 --- a/test_outputs/trait_newly_sealed.output.ron +++ b/test_outputs/trait_newly_sealed.output.ron @@ -11,6 +11,18 @@ "visibility_limit": String("public"), }, ], + "./test_crates/trait_method_added/": [ + { + "name": String("WillGainMethodWithoutDefaultAndSeal"), + "path": List([ + String("trait_method_added"), + String("WillGainMethodWithoutDefaultAndSeal"), + ]), + "span_begin_line": Uint64(20), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], "./test_crates/trait_newly_sealed/": [ { "name": String("TraitBecomesSealed"), From a39dc2b46bb52aadfb02d067ea3904719ec89fe8 Mon Sep 17 00:00:00 2001 From: Max Carr Date: Sun, 1 Sep 2024 13:19:32 -0700 Subject: [PATCH 02/22] enable `implicit some` feature on query rons. (#897) --- src/query.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/query.rs b/src/query.rs index a0125dfc..9eebd1a9 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1,5 +1,6 @@ use std::{collections::BTreeMap, sync::Arc}; +use ron::extensions::Extensions; use serde::{Deserialize, Serialize}; use trustfall::TransparentValue; @@ -128,7 +129,13 @@ impl SemverQuery { pub fn all_queries() -> BTreeMap { let mut queries = BTreeMap::default(); for (id, query_text) in get_queries() { - let query: SemverQuery = ron::from_str(query_text).unwrap_or_else(|e| { + let mut deserializer = ron::Deserializer::from_str_with_options( + query_text, + ron::Options::default().with_default_extension(Extensions::IMPLICIT_SOME), + ) + .expect("Failed to construct deserializer."); + + let query = Self::deserialize(&mut deserializer).unwrap_or_else(|e| { panic!( "\ Failed to parse a query: {e} From cf060a624fbac0ffc6332319d9b7c560330a8e83 Mon Sep 17 00:00:00 2001 From: Max Carr Date: Sun, 1 Sep 2024 15:01:51 -0700 Subject: [PATCH 03/22] Make verbosity a global option (#899) make verbosity a global option --- src/main.rs | 14 +++++--------- src/snapshot_tests.rs | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index d9e0ea7f..1c5cb749 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,15 +20,13 @@ fn main() { configure_color(args.color_choice); let mut config = GlobalConfig::new(); + config.set_log_level(args.verbosity.log_level()); if args.bugreport { print_issue_url(&mut config); std::process::exit(0); } else if args.list { exit_on_error(true, || { - let mut config = GlobalConfig::new(); - config.set_log_level(args.check_release.verbosity.log_level()); - let queries = SemverQuery::all_queries(); let mut rows = vec![["id", "type", "description"], ["==", "====", "==========="]]; for query in queries.values() { @@ -90,8 +88,6 @@ fn main() { None => args.check_release, }; - config.set_log_level(check_release.verbosity.log_level()); - let check: cargo_semver_checks::Check = check_release.into(); let report = exit_on_error(config.is_error(), || check.check_release(&mut config)); @@ -241,6 +237,10 @@ struct SemverChecks { /// Choose whether to output colors #[arg(long = "color", global = true, value_name = "WHEN", value_enum)] color_choice: Option, + + // docstring for help is on the `clap_verbosity_flag::Verbosity` struct itself + #[command(flatten)] + verbosity: clap_verbosity_flag::Verbosity, } /// Check your crate for semver violations. @@ -390,10 +390,6 @@ struct CheckRelease { /// `x86_64-unknown-linux-gnu`. #[arg(long = "target")] build_target: Option, - - // docstring for help is on the `clap_verbosity_flag::Verbosity` struct itself - #[command(flatten)] - verbosity: clap_verbosity_flag::Verbosity, } impl From for cargo_semver_checks::Check { diff --git a/src/snapshot_tests.rs b/src/snapshot_tests.rs index deb6e550..bba4e50a 100644 --- a/src/snapshot_tests.rs +++ b/src/snapshot_tests.rs @@ -153,7 +153,7 @@ fn assert_integration_test(test_name: &str, invocation: &[&str]) { config.set_stdout(Box::new(stdout.clone())); config.set_stderr(Box::new(stderr.clone())); config.set_color_choice(false); - config.set_log_level(arguments.check_release.verbosity.log_level()); + config.set_log_level(arguments.verbosity.log_level()); let check = Check::from(arguments.check_release); From 8c4c51c0bf43e30d2befefbf4f8e84e2193d58fc Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:51:02 -0400 Subject: [PATCH 04/22] Explicitly `cargo update` in path dependency workspaces. (#901) Resolves a variant of #167 described here: https://github.com/obi1kenobi/cargo-semver-checks/issues/167#issuecomment-2324959305 This issue was observed during a CI run of #900, where an older tokio-stream version was using a brand-new tokio with stronger guarantees: several types had newly become `UnwindSafe`. Since the baseline tokio-stream was a registry version, it was using a fresh lockfile with the latest dependencies. The current arm, meanwhile, was a path dependency fixed to a specific commit, where cargo had decided to reuse an older version of tokio without the `UnwindSafe` trait on those types. This presented as a (phantom) breaking change: the older tokio-stream's types were `UnwindSafe` due to auto-trait propagation from a newer tokio while the newer tokio-stream with an older tokio did not have that trait. The solution is to explicitly run `cargo update` inside path dependency workspaces we create. This way, both path dependency and index-based rustdoc JSON generation happens with the latest versions of the target library's own dependencies. --- src/rustdoc_cmd.rs | 164 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 133 insertions(+), 31 deletions(-) diff --git a/src/rustdoc_cmd.rs b/src/rustdoc_cmd.rs index 39047ea9..1883dd86 100644 --- a/src/rustdoc_cmd.rs +++ b/src/rustdoc_cmd.rs @@ -53,6 +53,10 @@ impl RustdocCommand { crate_source: &CrateSource, crate_data: &CrateDataForRustdoc, ) -> anyhow::Result { + let crate_name = crate_source.name()?; + let version = crate_source.version()?; + let pkg_spec = format!("{crate_name}@{version}"); + // Generate an empty placeholder project with a dependency on the crate // whose rustdoc we need. We take this indirect generation path to avoid issues like: // https://github.com/obi1kenobi/cargo-semver-checks/issues/167#issuecomment-1382367128 @@ -62,6 +66,100 @@ impl RustdocCommand { let placeholder_manifest_path = save_placeholder_rustdoc_manifest(build_dir.as_path(), placeholder_manifest) .context("failed to save placeholder rustdoc manifest")?; + if matches!(crate_source, CrateSource::Registry { .. }) { + // We have to run `cargo update` inside the newly-generated project, to ensure + // all dependencies of the library we're scanning are up-to-date. + // + // Otherwise, we risk having a newer version of a dependency in the baseline arm, + // and an older version of the same dependency in the current arm. If that dependency + // started providing stronger guarantees in the newer version, such as newly starting + // to implementing an auto-trait on an existing type, the baseline could contain + // types that inherit that stronger guarantee whereas the current would not. + // That would be reported as a breaking change -- incorrectly so. + // + // cargo does not guarantee it'll update dependencies to a newer lockfile + // if using a path dependency. This bit us in this case: + // https://github.com/obi1kenobi/cargo-semver-checks/issues/167#issuecomment-2324959305 + let stderr = if self.silence { + std::process::Stdio::piped() + } else { + // Print cargo update progress + std::process::Stdio::inherit() + }; + + let mut cmd = std::process::Command::new("cargo"); + cmd.stdout(std::process::Stdio::null()) // Don't pollute output + .stderr(stderr) + .current_dir(build_dir.as_path()) + .arg("update") + .arg("--manifest-path") + .arg(&placeholder_manifest_path); + + // Respect our configured color choice. + cmd.arg(if config.err_color_choice() { + "--color=always" + } else { + "--color=never" + }); + + let output = cmd.output()?; + if !output.status.success() { + if self.silence { + config.log_error(|config| { + let mut stderr = config.stderr(); + let delimiter = "-----"; + writeln!( + stderr, + "error: running 'cargo update' on crate {crate_name} failed with output:" + )?; + writeln!( + stderr, + "{delimiter}\n{}\n{delimiter}\n", + String::from_utf8_lossy(&output.stderr) + )?; + writeln!( + stderr, + "error: failed to update dependencies for crate {crate_name} v{version}" + )?; + Ok(()) + })?; + } else { + config.log_error(|config| { + writeln!( + config.stderr(), + "error: running 'cargo update' on crate {crate_name} v{version} failed, see stderr output above" + )?; + Ok(()) + })?; + } + config.log_error(|config| { + let features = + crate_source.feature_list_from_config(config, crate_data.feature_config); + let mut stderr = config.stderr(); + writeln!( + stderr, + "note: this is unlikely to be a bug in cargo-semver-checks," + )?; + writeln!( + stderr, + " and is probably an issue with the crate's Cargo.toml" + )?; + writeln!( + stderr, + "note: the following command can be used to reproduce the compilation error:" + )?; + let repro_base = produce_repro_workspace(crate_name, crate_source, &features); + writeln!( + stderr, + "{repro_base}cargo update\n" + )?; + Ok(()) + })?; + anyhow::bail!( + "aborting due to failure to run 'cargo update' for crate {crate_name} v{version}" + ); + } + } let metadata = cargo_metadata::MetadataCommand::new() .manifest_path(&placeholder_manifest_path) @@ -82,10 +180,6 @@ impl RustdocCommand { std::process::Stdio::inherit() }; - let crate_name = crate_source.name()?; - let version = crate_source.version()?; - let pkg_spec = format!("{crate_name}@{version}"); - // Generating rustdoc JSON for a crate also involves checking that crate's dependencies. // The check is done by rustc, not rustdoc, so it's subject to RUSTFLAGS not RUSTDOCFLAGS. // We don't want rustc to fail that check if the user has set RUSTFLAGS="-Dwarnings" here. @@ -130,7 +224,7 @@ impl RustdocCommand { cmd.arg("--no-deps"); } - // respect our configured color choice + // Respect our configured color choice cmd.arg(if config.err_color_choice() { "--color=always" } else { @@ -183,32 +277,8 @@ impl RustdocCommand { stderr, "note: the following command can be used to reproduce the compilation error:" )?; - let selector = match crate_source { - CrateSource::Registry { version, .. } => format!("{crate_name}@={version}"), - CrateSource::ManifestPath { manifest } => format!( - "--path {}", - manifest - .path - .parent() - .expect("source Cargo.toml had no parent path") - .to_str() - .expect("failed to create path string") - ), - }; - let feature_list = if features.is_empty() { - "".to_string() - } else { - format!("--features {} ", features.into_iter().join(",")) - }; - writeln!( - stderr, - " \ -cargo new --lib example && - cd example && - echo '[workspace]' >> Cargo.toml && - cargo add {selector} --no-default-features {feature_list}&& - cargo check\n" - )?; + let repro_base = produce_repro_workspace(crate_name, crate_source, &features); + writeln!(stderr, "{repro_base}cargo check\n")?; Ok(()) })?; anyhow::bail!( @@ -345,6 +415,38 @@ in the metadata and stderr didn't mention it was lacking a lib target. This is p } } +fn produce_repro_workspace( + crate_name: &str, + crate_source: &CrateSource, + features: &[String], +) -> String { + let selector = match crate_source { + CrateSource::Registry { version, .. } => format!("{crate_name}@={version}"), + CrateSource::ManifestPath { manifest } => format!( + "--path {}", + manifest + .path + .parent() + .expect("source Cargo.toml had no parent path") + .to_str() + .expect("failed to create path string") + ), + }; + let feature_list = if features.is_empty() { + "".to_string() + } else { + format!("--features {} ", features.iter().join(",")) + }; + format!( + " \ + cargo new --lib example && + cd example && + echo '[workspace]' >> Cargo.toml && + cargo add {selector} --no-default-features {feature_list}&& + " + ) +} + impl Default for RustdocCommand { fn default() -> Self { Self::new() From 9ba903c837e9bc98983b61020cc931b627a47eea Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:57:44 -0400 Subject: [PATCH 05/22] Invoke `cargo update` on path dependencies, not registry ones. (#904) was crates.io. The intended behavior is to run it on path sources. --- src/rustdoc_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc_cmd.rs b/src/rustdoc_cmd.rs index 1883dd86..507448f4 100644 --- a/src/rustdoc_cmd.rs +++ b/src/rustdoc_cmd.rs @@ -66,7 +66,7 @@ impl RustdocCommand { let placeholder_manifest_path = save_placeholder_rustdoc_manifest(build_dir.as_path(), placeholder_manifest) .context("failed to save placeholder rustdoc manifest")?; - if matches!(crate_source, CrateSource::Registry { .. }) { + if matches!(crate_source, CrateSource::ManifestPath { .. }) { // We have to run `cargo update` inside the newly-generated project, to ensure // all dependencies of the library we're scanning are up-to-date. // From 9b31c7ef10bbbab83b7fee2f779704b553cbc710 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:59:45 -0400 Subject: [PATCH 06/22] Properly silence cargo output unless `--verbose`. (#903) Before this, output was always silenced since the check was inverted. It would only be unsilenced if the log level was less verbose than INFO, which is the opposite of what we want. --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cfe5aadd..9a95702f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -378,7 +378,9 @@ impl Check { } pub fn check_release(&self, config: &mut GlobalConfig) -> anyhow::Result { - let rustdoc_cmd = RustdocCommand::new().deps(false).silence(config.is_info()); + let rustdoc_cmd = RustdocCommand::new() + .deps(false) + .silence(!config.is_verbose()); // If both the current and baseline rustdoc are given explicitly as a file path, // we don't need to use the installed rustc, and this check can be skipped. From 924003e1cf9cc2b0097289433476083e1596db5e Mon Sep 17 00:00:00 2001 From: PedroTurik Date: Mon, 2 Sep 2024 15:34:06 -0300 Subject: [PATCH 07/22] Enum unit variant changed kind (#894) * adds enum_unit_variant_changed_kind lint * fix reference link * added more useful info to output * better reference link, lint more cases, better comments and messages, and adjust tests * Update src/lints/enum_unit_variant_changed_kind.ron --------- Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --- src/lints/enum_unit_variant_changed_kind.ron | 71 +++++++++++++++ src/query.rs | 1 + .../new/Cargo.toml | 7 ++ .../new/src/lib.rs | 63 +++++++++++++ .../old/Cargo.toml | 7 ++ .../old/src/lib.rs | 61 +++++++++++++ .../enum_unit_variant_changed_kind.output.ron | 90 +++++++++++++++++++ .../variant_marked_non_exhaustive.output.ron | 13 +++ 8 files changed, 313 insertions(+) create mode 100644 src/lints/enum_unit_variant_changed_kind.ron create mode 100644 test_crates/enum_unit_variant_changed_kind/new/Cargo.toml create mode 100644 test_crates/enum_unit_variant_changed_kind/new/src/lib.rs create mode 100644 test_crates/enum_unit_variant_changed_kind/old/Cargo.toml create mode 100644 test_crates/enum_unit_variant_changed_kind/old/src/lib.rs create mode 100644 test_outputs/enum_unit_variant_changed_kind.output.ron diff --git a/src/lints/enum_unit_variant_changed_kind.ron b/src/lints/enum_unit_variant_changed_kind.ron new file mode 100644 index 00000000..7f213b54 --- /dev/null +++ b/src/lints/enum_unit_variant_changed_kind.ron @@ -0,0 +1,71 @@ +SemverQuery( + id: "enum_unit_variant_changed_kind", + human_readable_name: "An enum unit variant changed kind", + description: "A public enum unit variant that isn't #[non_exhaustive] changed kind", + required_update: Major, + lint_level: Deny, + // TODO: If the Rust reference gains a more detailed explanation of enum *variants*, + // switch the explanation to point there instead. The current link isn't great. + reference_link: Some("https://doc.rust-lang.org/reference/items/enumerations.html"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + enum_name: name @output @tag + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + + variant { + ... on PlainVariant { + kind: __typename @output @tag + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + public_api_eligible @filter(op: "=", value: ["$true"]) + variant_name: name @output @tag + } + } + } + } + } + current { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + name @filter(op: "=", value: ["%enum_name"]) + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "=", value: ["$true"]) + } + + # Don't check for exhaustiveness and public API eligibility here. + # Variants that changed kind and gained `#[doc(hidden)]` should + # report for both lints, since there is no implied continuity + # between the old variant and the new one with the same name. + variant { + name @filter(op: "=", value: ["%variant_name"]) + new_kind: __typename @filter(op: "!=", value: ["%kind"]) @output + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "true": true, + "non_exhaustive": "#[non_exhaustive]", + }, + error_message: "A public enum's exhaustive unit variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.", + per_result_error_template: Some("variant {{enum_name}}::{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index 9eebd1a9..b20e5782 100644 --- a/src/query.rs +++ b/src/query.rs @@ -802,6 +802,7 @@ add_lints!( enum_tuple_variant_field_added, enum_tuple_variant_field_missing, enum_tuple_variant_field_now_doc_hidden, + enum_unit_variant_changed_kind, enum_variant_added, enum_variant_missing, exported_function_changed_abi, diff --git a/test_crates/enum_unit_variant_changed_kind/new/Cargo.toml b/test_crates/enum_unit_variant_changed_kind/new/Cargo.toml new file mode 100644 index 00000000..990b12be --- /dev/null +++ b/test_crates/enum_unit_variant_changed_kind/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_unit_variant_changed_kind" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_unit_variant_changed_kind/new/src/lib.rs b/test_crates/enum_unit_variant_changed_kind/new/src/lib.rs new file mode 100644 index 00000000..79501a97 --- /dev/null +++ b/test_crates/enum_unit_variant_changed_kind/new/src/lib.rs @@ -0,0 +1,63 @@ +// ---- Should be reported ---- +pub enum TestStruct { + WillBecomeStructLike{} +} + +pub enum TestTuple { + WillBecomeTupleLike(()) +} + +pub enum MultipleTest { + WillBecomeStructLike{}, + WillBecomeTupleLike(()), + WillStayUnitLike +} + +pub enum TestBecomeDocHidden { + #[doc(hidden)] + WillBecomeStructLike{} +} + +pub enum TestBecomeNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{} +} + +// ---- Should not be reported ---- +pub enum TestUnit { + WillStayUnitLike +} + +pub enum TestStructNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{} +} + +pub enum TestTupleNonExhaustive { + #[non_exhaustive] + WillBecomeTupleLike(()) +} + +pub enum MultipleTestNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{}, + #[non_exhaustive] + WillBecomeTupleLike(()), + #[non_exhaustive] + WillStayUnitLike +} + +pub enum TestDocHidden { + #[doc(hidden)] + WillBecomeStructLike{}, + #[doc(hidden)] + WillBecomeTupleLike(()), + #[doc(hidden)] + WillStayUnitLike +} + +pub enum MultipleStayTheSame { + StructLike{}, + TupleLike(()), + UnitLike +} diff --git a/test_crates/enum_unit_variant_changed_kind/old/Cargo.toml b/test_crates/enum_unit_variant_changed_kind/old/Cargo.toml new file mode 100644 index 00000000..990b12be --- /dev/null +++ b/test_crates/enum_unit_variant_changed_kind/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_unit_variant_changed_kind" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_unit_variant_changed_kind/old/src/lib.rs b/test_crates/enum_unit_variant_changed_kind/old/src/lib.rs new file mode 100644 index 00000000..68af78a8 --- /dev/null +++ b/test_crates/enum_unit_variant_changed_kind/old/src/lib.rs @@ -0,0 +1,61 @@ +// ---- Should be reported ---- +pub enum TestStruct { + WillBecomeStructLike +} + +pub enum TestTuple { + WillBecomeTupleLike +} + +pub enum MultipleTest { + WillBecomeStructLike, + WillBecomeTupleLike, + WillStayUnitLike +} + +pub enum TestBecomeDocHidden { + WillBecomeStructLike +} + +pub enum TestBecomeNonExhaustive { + WillBecomeStructLike +} + +// ---- Should not be reported ---- +pub enum TestUnit { + WillStayUnitLike +} + +pub enum TestStructNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike +} + +pub enum TestTupleNonExhaustive { + #[non_exhaustive] + WillBecomeTupleLike +} + +pub enum MultipleTestNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike, + #[non_exhaustive] + WillBecomeTupleLike, + #[non_exhaustive] + WillStayUnitLike +} + +pub enum TestDocHidden { + #[doc(hidden)] + WillBecomeStructLike, + #[doc(hidden)] + WillBecomeTupleLike, + #[doc(hidden)] + WillStayUnitLike +} + +pub enum MultipleStayTheSame { + StructLike{}, + TupleLike(()), + UnitLike +} diff --git a/test_outputs/enum_unit_variant_changed_kind.output.ron b/test_outputs/enum_unit_variant_changed_kind.output.ron new file mode 100644 index 00000000..479522cb --- /dev/null +++ b/test_outputs/enum_unit_variant_changed_kind.output.ron @@ -0,0 +1,90 @@ +{ + "./test_crates/enum_tuple_variant_field_added/": [ + { + "enum_name": String("PublicEnum"), + "kind": String("PlainVariant"), + "new_kind": String("TupleVariant"), + "path": List([ + String("enum_tuple_variant_field_added"), + String("PublicEnum"), + ]), + "span_begin_line": Uint64(13), + "span_filename": String("src/lib.rs"), + "variant_name": String("PlainVariantBecomesTuple"), + }, + ], + "./test_crates/enum_unit_variant_changed_kind/": [ + { + "enum_name": String("TestStruct"), + "kind": String("PlainVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("TestStruct"), + ]), + "span_begin_line": Uint64(3), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("TestTuple"), + "kind": String("PlainVariant"), + "new_kind": String("TupleVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("TestTuple"), + ]), + "span_begin_line": Uint64(7), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeTupleLike"), + }, + { + "enum_name": String("MultipleTest"), + "kind": String("PlainVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("MultipleTest"), + ]), + "span_begin_line": Uint64(11), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("MultipleTest"), + "kind": String("PlainVariant"), + "new_kind": String("TupleVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("MultipleTest"), + ]), + "span_begin_line": Uint64(12), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeTupleLike"), + }, + { + "enum_name": String("TestBecomeDocHidden"), + "kind": String("PlainVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("TestBecomeDocHidden"), + ]), + "span_begin_line": Uint64(18), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("TestBecomeNonExhaustive"), + "kind": String("PlainVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("TestBecomeNonExhaustive"), + ]), + "span_begin_line": Uint64(23), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + ], +} diff --git a/test_outputs/variant_marked_non_exhaustive.output.ron b/test_outputs/variant_marked_non_exhaustive.output.ron index 302a31dc..31c0bee0 100644 --- a/test_outputs/variant_marked_non_exhaustive.output.ron +++ b/test_outputs/variant_marked_non_exhaustive.output.ron @@ -25,6 +25,19 @@ "visibility_limit": String("public"), }, ], + "./test_crates/enum_unit_variant_changed_kind/": [ + { + "name": String("TestBecomeNonExhaustive"), + "path": List([ + String("enum_unit_variant_changed_kind"), + String("TestBecomeNonExhaustive"), + ]), + "span_begin_line": Uint64(23), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + "visibility_limit": String("public"), + }, + ], "./test_crates/non_exhaustive/": [ { "name": String("MyEnum"), From 61c5b1fc9bfb8f8a61ce433e56291e89817c2a78 Mon Sep 17 00:00:00 2001 From: PedroTurik Date: Mon, 2 Sep 2024 17:04:01 -0300 Subject: [PATCH 08/22] Enum tuple variant changed kind (#906) * add enum_tuple_viariant_changed_kind lint * fixes trailling newline --- src/lints/enum_tuple_variant_changed_kind.ron | 71 ++++++++++++ src/query.rs | 1 + .../new/Cargo.toml | 7 ++ .../new/src/lib.rs | 63 +++++++++++ .../old/Cargo.toml | 7 ++ .../old/src/lib.rs | 61 +++++++++++ ...enum_tuple_variant_changed_kind.output.ron | 102 ++++++++++++++++++ .../variant_marked_non_exhaustive.output.ron | 13 +++ 8 files changed, 325 insertions(+) create mode 100644 src/lints/enum_tuple_variant_changed_kind.ron create mode 100644 test_crates/enum_tuple_variant_changed_kind/new/Cargo.toml create mode 100644 test_crates/enum_tuple_variant_changed_kind/new/src/lib.rs create mode 100644 test_crates/enum_tuple_variant_changed_kind/old/Cargo.toml create mode 100644 test_crates/enum_tuple_variant_changed_kind/old/src/lib.rs create mode 100644 test_outputs/enum_tuple_variant_changed_kind.output.ron diff --git a/src/lints/enum_tuple_variant_changed_kind.ron b/src/lints/enum_tuple_variant_changed_kind.ron new file mode 100644 index 00000000..bbc12877 --- /dev/null +++ b/src/lints/enum_tuple_variant_changed_kind.ron @@ -0,0 +1,71 @@ +SemverQuery( + id: "enum_tuple_variant_changed_kind", + human_readable_name: "An enum tuple variant changed kind", + description: "A public enum tuple variant that isn't #[non_exhaustive] changed kind", + required_update: Major, + lint_level: Deny, + // TODO: If the Rust reference gains a more detailed explanation of enum *variants*, + // switch the explanation to point there instead. The current link isn't great. + reference_link: Some("https://doc.rust-lang.org/reference/items/enumerations.html"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + enum_name: name @output @tag + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + + variant { + ... on TupleVariant { + kind: __typename @output @tag + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + public_api_eligible @filter(op: "=", value: ["$true"]) + variant_name: name @output @tag + } + } + } + } + } + current { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + name @filter(op: "=", value: ["%enum_name"]) + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "=", value: ["$true"]) + } + + # Don't check for exhaustiveness and public API eligibility here. + # Variants that changed kind and gained `#[doc(hidden)]` should + # report for both lints, since there is no implied continuity + # between the old variant and the new one with the same name. + variant { + name @filter(op: "=", value: ["%variant_name"]) + new_kind: __typename @filter(op: "!=", value: ["%kind"]) @output + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "true": true, + "non_exhaustive": "#[non_exhaustive]", + }, + error_message: "A public enum's exhaustive tuple variant has changed to a different kind of enum variant, breaking possible instantiations and patterns.", + per_result_error_template: Some("variant {{enum_name}}::{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index b20e5782..049d581d 100644 --- a/src/query.rs +++ b/src/query.rs @@ -799,6 +799,7 @@ add_lints!( enum_struct_variant_field_added, enum_struct_variant_field_missing, enum_struct_variant_field_now_doc_hidden, + enum_tuple_variant_changed_kind, enum_tuple_variant_field_added, enum_tuple_variant_field_missing, enum_tuple_variant_field_now_doc_hidden, diff --git a/test_crates/enum_tuple_variant_changed_kind/new/Cargo.toml b/test_crates/enum_tuple_variant_changed_kind/new/Cargo.toml new file mode 100644 index 00000000..194c053e --- /dev/null +++ b/test_crates/enum_tuple_variant_changed_kind/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_tuple_variant_changed_kind" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_tuple_variant_changed_kind/new/src/lib.rs b/test_crates/enum_tuple_variant_changed_kind/new/src/lib.rs new file mode 100644 index 00000000..db1e42d8 --- /dev/null +++ b/test_crates/enum_tuple_variant_changed_kind/new/src/lib.rs @@ -0,0 +1,63 @@ +// ---- Should be reported ---- +pub enum TestStruct { + WillBecomeStructLike{} +} + +pub enum TestUnit { + WillBecomeUnitLike +} + +pub enum MultipleTest { + WillBecomeStructLike{}, + WillBecomeUnitLike, + WillStayTupleLike(()), +} + +pub enum TestBecomeDocHidden { + #[doc(hidden)] + WillBecomeStructLike{} +} + +pub enum TestBecomeNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{} +} + +// ---- Should not be reported ---- +pub enum TestTuple { + WillStayTupleLike(()) +} + +pub enum TestStructNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{} +} + +pub enum TestUnitNonExhaustive { + #[non_exhaustive] + WillBecomeUnitLike +} + +pub enum MultipleTestNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike{}, + #[non_exhaustive] + WillBecomeUnitLike, + #[non_exhaustive] + WillStayTupleLike(()), +} + +pub enum TestDocHidden { + #[doc(hidden)] + WillBecomeStructLike{}, + #[doc(hidden)] + WillBecomeUnitLike, + #[doc(hidden)] + WillStayTupleLike(()), +} + +pub enum MultipleStayTheSame { + StructLike{}, + TupleLike(()), + UnitLike +} diff --git a/test_crates/enum_tuple_variant_changed_kind/old/Cargo.toml b/test_crates/enum_tuple_variant_changed_kind/old/Cargo.toml new file mode 100644 index 00000000..194c053e --- /dev/null +++ b/test_crates/enum_tuple_variant_changed_kind/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_tuple_variant_changed_kind" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_tuple_variant_changed_kind/old/src/lib.rs b/test_crates/enum_tuple_variant_changed_kind/old/src/lib.rs new file mode 100644 index 00000000..4142cfe0 --- /dev/null +++ b/test_crates/enum_tuple_variant_changed_kind/old/src/lib.rs @@ -0,0 +1,61 @@ +// ---- Should be reported ---- +pub enum TestStruct { + WillBecomeStructLike(()) +} + +pub enum TestUnit { + WillBecomeUnitLike(()) +} + +pub enum MultipleTest { + WillBecomeStructLike(()), + WillBecomeUnitLike(()), + WillStayTupleLike(()), +} + +pub enum TestBecomeDocHidden { + WillBecomeStructLike(()) +} + +pub enum TestBecomeNonExhaustive { + WillBecomeStructLike(()) +} + +// ---- Should not be reported ---- +pub enum TestTuple { + WillStayTupleLike(()) +} + +pub enum TestStructNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike(()) +} + +pub enum TestUnitNonExhaustive { + #[non_exhaustive] + WillBecomeUnitLike +} + +pub enum MultipleTestNonExhaustive { + #[non_exhaustive] + WillBecomeStructLike(()), + #[non_exhaustive] + WillBecomeUnitLike(()), + #[non_exhaustive] + WillStayTupleLike(()), +} + +pub enum TestDocHidden { + #[doc(hidden)] + WillBecomeStructLike(()), + #[doc(hidden)] + WillBecomeUnitLike(()), + #[doc(hidden)] + WillStayTupleLike(()), +} + +pub enum MultipleStayTheSame { + StructLike{}, + TupleLike(()), + UnitLike +} diff --git a/test_outputs/enum_tuple_variant_changed_kind.output.ron b/test_outputs/enum_tuple_variant_changed_kind.output.ron new file mode 100644 index 00000000..d42df580 --- /dev/null +++ b/test_outputs/enum_tuple_variant_changed_kind.output.ron @@ -0,0 +1,102 @@ +{ + "./test_crates/enum_tuple_variant_changed_kind/": [ + { + "enum_name": String("TestStruct"), + "kind": String("TupleVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("TestStruct"), + ]), + "span_begin_line": Uint64(3), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("TestUnit"), + "kind": String("TupleVariant"), + "new_kind": String("PlainVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("TestUnit"), + ]), + "span_begin_line": Uint64(7), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeUnitLike"), + }, + { + "enum_name": String("MultipleTest"), + "kind": String("TupleVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("MultipleTest"), + ]), + "span_begin_line": Uint64(11), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("MultipleTest"), + "kind": String("TupleVariant"), + "new_kind": String("PlainVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("MultipleTest"), + ]), + "span_begin_line": Uint64(12), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeUnitLike"), + }, + { + "enum_name": String("TestBecomeDocHidden"), + "kind": String("TupleVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("TestBecomeDocHidden"), + ]), + "span_begin_line": Uint64(18), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + { + "enum_name": String("TestBecomeNonExhaustive"), + "kind": String("TupleVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("TestBecomeNonExhaustive"), + ]), + "span_begin_line": Uint64(23), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + }, + ], + "./test_crates/enum_tuple_variant_field_missing/": [ + { + "enum_name": String("PublicEnum"), + "kind": String("TupleVariant"), + "new_kind": String("PlainVariant"), + "path": List([ + String("enum_tuple_variant_field_missing"), + String("PublicEnum"), + ]), + "span_begin_line": Uint64(5), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariantBecomesPlain"), + }, + { + "enum_name": String("PublicEnum"), + "kind": String("TupleVariant"), + "new_kind": String("StructVariant"), + "path": List([ + String("enum_tuple_variant_field_missing"), + String("PublicEnum"), + ]), + "span_begin_line": Uint64(7), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariantBecomesStruct"), + }, + ] +} diff --git a/test_outputs/variant_marked_non_exhaustive.output.ron b/test_outputs/variant_marked_non_exhaustive.output.ron index 31c0bee0..fbd58f68 100644 --- a/test_outputs/variant_marked_non_exhaustive.output.ron +++ b/test_outputs/variant_marked_non_exhaustive.output.ron @@ -12,6 +12,19 @@ "visibility_limit": String("public"), }, ], + "./test_crates/enum_tuple_variant_changed_kind/": [ + { + "name": String("TestBecomeNonExhaustive"), + "path": List([ + String("enum_tuple_variant_changed_kind"), + String("TestBecomeNonExhaustive"), + ]), + "span_begin_line": Uint64(23), + "span_filename": String("src/lib.rs"), + "variant_name": String("WillBecomeStructLike"), + "visibility_limit": String("public"), + }, + ], "./test_crates/enum_tuple_variant_field_added/": [ { "name": String("PublicEnum"), From a2b1913990f5b57d411a56e739ee6151b46c52b0 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:47:18 -0400 Subject: [PATCH 09/22] Disable tests currently broken by #902. (#907) --- .github/workflows/ci.yml | 256 ++++++++++++++++++++++----------------- 1 file changed, 146 insertions(+), 110 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0e0baa9..1712f821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1084,69 +1084,87 @@ jobs: persist-credentials: false path: 'semver' - - name: Checkout tokio - uses: actions/checkout@v4 - with: - persist-credentials: false - repository: 'tokio-rs/tokio' - ref: 'd7b7c6131774ab631be6529fef3680abfeeb4781' - path: 'subject' - - - name: Install rust - id: toolchain - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - cache: false - rustflags: "" - - - name: Restore cargo index and rustdoc target dir - uses: Swatinem/rust-cache@v2 - with: - workspaces: | - subject/target/semver-checks/local-tokio-1_25_0 - subject/target/semver-checks/local-tokio_macros-1_8_2 - subject/target/semver-checks/local-tokio_stream-0_1_12 - subject/target/semver-checks/local-tokio_test-0_4_2 - subject/target/semver-checks/local-tokio_util-0_7_7 - - - name: Restore binary - id: cache-binary - uses: actions/cache/restore@v4 - with: - path: bins/ - key: bins-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }} - fail-on-cache-miss: true - - - name: Restore rustdoc - id: cache - uses: actions/cache/restore@v4 - with: - key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc - path: subject/target/semver-checks/cache - - # This test caught two bugs: - # - The default baseline was set to the current path instead of the default registry version. - # - Specifying `--exclude` together with a crate manifest that is within a workspace - # (but doesn't *itself* define the workspace) would cause the entire workspace to - # get tested, even though only a single crate's manifest was specified. - - name: Run semver-checks on tokio-stream crate manifest only + - name: Disabled due to \#902 + env: + GH_TOKEN: ${{ github.token }} run: | cd semver - ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/tokio-stream/Cargo.toml" --release-type minor --exclude benches --exclude examples --exclude stress-test --exclude tests-build --exclude tests-integration --verbose + STATE="$(gh issue view 902 --json state --jq .state)" - # This test caught a bug where `--exclude` was silently ignored - # if `--workspace` wasn't set at the same time. - - name: Run semver-checks on workspace manifest with explicit exclusions - run: | - cd semver - ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/Cargo.toml" --release-type minor --exclude examples --exclude stress-test --exclude tests-build --exclude tests-integration --verbose + if [[ "$STATE" == 'OPEN' ]]; then + echo 'Test disabled due to https://github.com/obi1kenobi/cargo-semver-checks/issues/902' + elif [[ "$STATE" == 'CLOSED' ]]; then + echo 'Please re-enable this test since the underlying issue has been closed' + exit 1 + else + echo 'Unknown state for issue #902:' + echo "$STATE" + exit 1 + fi - - name: Save rustdoc - uses: actions/cache/save@v4 - if: steps.cache.outputs.cache-hit != 'true' - with: - key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc - path: subject/target/semver-checks/cache + # - name: Checkout tokio + # uses: actions/checkout@v4 + # with: + # persist-credentials: false + # repository: 'tokio-rs/tokio' + # ref: 'd7b7c6131774ab631be6529fef3680abfeeb4781' + # path: 'subject' + + # - name: Install rust + # id: toolchain + # uses: actions-rust-lang/setup-rust-toolchain@v1 + # with: + # cache: false + # rustflags: "" + + # - name: Restore cargo index and rustdoc target dir + # uses: Swatinem/rust-cache@v2 + # with: + # workspaces: | + # subject/target/semver-checks/local-tokio-1_25_0 + # subject/target/semver-checks/local-tokio_macros-1_8_2 + # subject/target/semver-checks/local-tokio_stream-0_1_12 + # subject/target/semver-checks/local-tokio_test-0_4_2 + # subject/target/semver-checks/local-tokio_util-0_7_7 + + # - name: Restore binary + # id: cache-binary + # uses: actions/cache/restore@v4 + # with: + # path: bins/ + # key: bins-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }} + # fail-on-cache-miss: true + + # - name: Restore rustdoc + # id: cache + # uses: actions/cache/restore@v4 + # with: + # key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc + # path: subject/target/semver-checks/cache + + # # This test caught two bugs: + # # - The default baseline was set to the current path instead of the default registry version. + # # - Specifying `--exclude` together with a crate manifest that is within a workspace + # # (but doesn't *itself* define the workspace) would cause the entire workspace to + # # get tested, even though only a single crate's manifest was specified. + # - name: Run semver-checks on tokio-stream crate manifest only + # run: | + # cd semver + # ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/tokio-stream/Cargo.toml" --release-type minor --exclude benches --exclude examples --exclude stress-test --exclude tests-build --exclude tests-integration --verbose + + # # This test caught a bug where `--exclude` was silently ignored + # # if `--workspace` wasn't set at the same time. + # - name: Run semver-checks on workspace manifest with explicit exclusions + # run: | + # cd semver + # ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/Cargo.toml" --release-type minor --exclude examples --exclude stress-test --exclude tests-build --exclude tests-integration --verbose + + # - name: Save rustdoc + # uses: actions/cache/save@v4 + # if: steps.cache.outputs.cache-hit != 'true' + # with: + # key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc + # path: subject/target/semver-checks/cache run-on-tokio-implicit: # cargo-semver-checks crashed here due to improper CLI argument handling: @@ -1161,60 +1179,78 @@ jobs: with: persist-credentials: false path: 'semver' - - - name: Checkout tokio - uses: actions/checkout@v4 - with: - persist-credentials: false - repository: 'tokio-rs/tokio' - ref: 'd7b7c6131774ab631be6529fef3680abfeeb4781' - path: 'subject' - - - name: Install rust - id: toolchain - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - cache: false - rustflags: "" - - - name: Restore cargo index and rustdoc target dir - uses: Swatinem/rust-cache@v2 - with: - workspaces: | - subject/target/semver-checks/local-tokio-1_25_0 - subject/target/semver-checks/local-tokio_macros-1_8_2 - subject/target/semver-checks/local-tokio_stream-0_1_12 - subject/target/semver-checks/local-tokio_test-0_4_2 - subject/target/semver-checks/local-tokio_util-0_7_7 - - - name: Restore binary - id: cache-binary - uses: actions/cache/restore@v4 - with: - path: bins/ - key: bins-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }} - fail-on-cache-miss: true - - - name: Restore rustdoc - id: cache - uses: actions/cache/restore@v4 - with: - key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc - path: subject/target/semver-checks/cache - - # This test caught a bug where `publish = false` items in a workspace were semver-checked - # unless either explicit `--workspace` was present or was implied e.g. via `--exclude`. - - name: Run semver-checks on workspace manifest with implicit exclusions + - name: Disabled due to \#902 + env: + GH_TOKEN: ${{ github.token }} run: | cd semver - ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/Cargo.toml" --release-type minor --verbose + STATE="$(gh issue view 902 --json state --jq .state)" - - name: Save rustdoc - uses: actions/cache/save@v4 - if: steps.cache.outputs.cache-hit != 'true' - with: - key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc - path: subject/target/semver-checks/cache + if [[ "$STATE" == 'OPEN' ]]; then + echo 'Test disabled due to https://github.com/obi1kenobi/cargo-semver-checks/issues/902' + elif [[ "$STATE" == 'CLOSED' ]]; then + echo 'Please re-enable this test since the underlying issue has been closed' + exit 1 + else + echo 'Unknown state for issue #902:' + echo "$STATE" + exit 1 + fi + + + # - name: Checkout tokio + # uses: actions/checkout@v4 + # with: + # persist-credentials: false + # repository: 'tokio-rs/tokio' + # ref: 'd7b7c6131774ab631be6529fef3680abfeeb4781' + # path: 'subject' + + # - name: Install rust + # id: toolchain + # uses: actions-rust-lang/setup-rust-toolchain@v1 + # with: + # cache: false + # rustflags: "" + + # - name: Restore cargo index and rustdoc target dir + # uses: Swatinem/rust-cache@v2 + # with: + # workspaces: | + # subject/target/semver-checks/local-tokio-1_25_0 + # subject/target/semver-checks/local-tokio_macros-1_8_2 + # subject/target/semver-checks/local-tokio_stream-0_1_12 + # subject/target/semver-checks/local-tokio_test-0_4_2 + # subject/target/semver-checks/local-tokio_util-0_7_7 + + # - name: Restore binary + # id: cache-binary + # uses: actions/cache/restore@v4 + # with: + # path: bins/ + # key: bins-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }} + # fail-on-cache-miss: true + + # - name: Restore rustdoc + # id: cache + # uses: actions/cache/restore@v4 + # with: + # key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc + # path: subject/target/semver-checks/cache + + # # This test caught a bug where `publish = false` items in a workspace were semver-checked + # # unless either explicit `--workspace` was present or was implied e.g. via `--exclude`. + # - name: Run semver-checks on workspace manifest with implicit exclusions + # run: | + # cd semver + # ../bins/cargo-semver-checks semver-checks check-release --manifest-path="../subject/Cargo.toml" --release-type minor --verbose + + # - name: Save rustdoc + # uses: actions/cache/save@v4 + # if: steps.cache.outputs.cache-hit != 'true' + # with: + # key: ${{ runner.os }}-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('semver/**/Cargo.lock') }}-${{ github.job }}-rustdoc + # path: subject/target/semver-checks/cache run-on-clap: # clap v3.2.0 added a semver violation From c07cd2770bc26a29ff3f6c40392253e05ec3b5a4 Mon Sep 17 00:00:00 2001 From: Max Carr Date: Mon, 2 Sep 2024 13:52:54 -0700 Subject: [PATCH 10/22] Add integration test snapshots (#905) * add test and output * add insta-cmd * ci hacking * i think it was my fault * fix color and fix toml filter * fix version regex --- Cargo.lock | 12 ++ Cargo.toml | 1 + .../integration_snapshots__bugreport.snap | 58 ++++++++++ tests/integration_snapshots.rs | 106 ++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 test_outputs/integration_snapshots__bugreport.snap create mode 100644 tests/integration_snapshots.rs diff --git a/Cargo.lock b/Cargo.lock index 875b2cab..b17600d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,6 +346,7 @@ dependencies = [ "human-panic", "ignore", "insta", + "insta-cmd", "itertools 0.13.0", "log", "predicates", @@ -1894,6 +1895,17 @@ dependencies = [ "similar", ] +[[package]] +name = "insta-cmd" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffeeefa927925cced49ccb01bf3e57c9d4cd132df21e576eb9415baeab2d3de6" +dependencies = [ + "insta", + "serde", + "serde_json", +] + [[package]] name = "ipnet" version = "2.9.0" diff --git a/Cargo.toml b/Cargo.toml index 370d191b..ad496650 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ predicates = "3.1.0" insta = { version = "1.39.0", features = ["ron", "filters"] } fs-err = "2.11.0" regex = "1.10.6" +insta-cmd = "0.6.0" # In dev and test profiles, compile all dependencies with optimizations enabled, # but still checking debug assertions and overflows. diff --git a/test_outputs/integration_snapshots__bugreport.snap b/test_outputs/integration_snapshots__bugreport.snap new file mode 100644 index 00000000..fcc76018 --- /dev/null +++ b/test_outputs/integration_snapshots__bugreport.snap @@ -0,0 +1,58 @@ +--- +source: tests/integration_snapshots.rs +info: + program: cargo-semver-checks + args: + - semver-checks + - "--bugreport" + env: + CARGO_TERM_COLOR: never +--- +success: true +exit_code: 0 +----- stdout ----- +System information: +------------------- +#### Software version + +cargo-semver-checks [VERSION] ([HASH]) + +#### Operating system + +[OS] + +#### Command-line + +```bash +[EXECUTABLE_PATH] semver-checks --bugreport +``` + +#### cargo version + +``` +> cargo -V +cargo [CARGO_VERSION] ([CARGO_VERSION_DETAILS]) +``` + +#### Compile time information + +- Profile: [PROFILE] +- Target triple: [TARGET_TRIPLE] +- Family: [FAMILY] +- OS: [OS] +- Architecture: [ARCH] +- Pointer width: [WIDTH] +- Endian: [ENDIAN] +- CPU features: [FEATURES] +- Host: [HOST_TRIPLE] + + +Cargo build configuration: +-------------------------- +[CARGO_BUILD_TOML] +Please file an issue on GitHub reporting your bug. +Consider adding the diagnostic information above, either manually or automatically through the link below: + +https://github.com/obi1kenobi/cargo-semver-checks/issues/new?[INFO_URLENCODED] + +----- stderr ----- diff --git a/tests/integration_snapshots.rs b/tests/integration_snapshots.rs new file mode 100644 index 00000000..25f30f67 --- /dev/null +++ b/tests/integration_snapshots.rs @@ -0,0 +1,106 @@ +//! Integration snapshot tests for testing `cargo-semver-checks` binary behavior. +//! +//! These tests have greater compile time penalties than `src/snapshot_tests.rs`. +//! Prefer those unless your test needs to access behavior in the `main` function of +//! `cargo-semver-checks`. +//! +//! See the module-level doc comment on `src/snapshot_tests.rs` for information on how +//! to create and update snapshot tests. +//! +//! To write an integration test, make a `#[test]` function and call [`assert_integration_test`] +//! to configure and run an integration test on the `cargo-semver-checks` binary. + +use std::path::{Path, PathBuf}; + +use assert_cmd::cargo::CommandCargoExt; +use insta_cmd::Command; + +/// Create a snapshot of the output of a `cargo semver-checks` invocation, using [`insta_cmd`]. +/// Add arguments and mutate the command using the passed closure (you do not need to include the +/// `semver-checks` subcommand`. This also lets you modify the [`insta::Settings`], e.g., to add +/// filters. +/// +/// The snapshot will be the `test_crates/snapshot_tests/integration_snapshots__{test_name}.snap` +/// file, so make sure to check this file into version control when adding/updating a test. +/// `test_name` will often be the name of the `#[test]` function that calls this function. +fn assert_integration_test( + test_name: &str, + modify: impl FnOnce(&mut Command, &mut insta::Settings), +) { + let mut settings = insta::Settings::clone_current(); + let mut cmd = + Command::cargo_bin("cargo-semver-checks").expect("failed to get cargo-semver-checks"); + cmd.env("CARGO_TERM_COLOR", "never"); + + cmd.arg("semver-checks"); + settings.set_snapshot_path("../test_outputs/"); + + modify(&mut cmd, &mut settings); + + settings.bind(|| insta_cmd::assert_cmd_snapshot!(test_name, cmd)); +} + +/// Snapshots the behavior of the `--bugreport` argument. +#[test] +fn bugreport() { + assert_integration_test("bugreport", |cmd, settings| { + cmd.arg("--bugreport"); + // much of this is not reproducible on different machines, so we have + // to heavily filter it. + settings.add_filter( + r"cargo-semver-checks \d+\.\d+\.\d+(-[\w\.-]+)? \(\w+(-modified)?\)", + "cargo-semver-checks [VERSION] ([HASH])", + ); + settings.add_filter( + r"#### Operating system\n\n[^\n]+", + "#### Operating system\n\n[OS]", + ); + settings.add_filter( + ®ex::escape(executable_path().to_str().expect("non-UTF-8 path")), + "[EXECUTABLE_PATH]", + ); + + settings.add_filter( + r"cargo \d+\.\d+\.\d+(-[\w\.-]+)? \(.+\)", + "cargo [CARGO_VERSION] ([CARGO_VERSION_DETAILS])", + ); + + settings.add_filter(r"Profile: \w+", "Profile: [PROFILE]"); + settings.add_filter(r"Target triple: [\w-]+", "Target triple: [TARGET_TRIPLE]"); + settings.add_filter(r"Family: \w+", "Family: [FAMILY]"); + settings.add_filter(r"OS: \w+", "OS: [OS]"); + settings.add_filter(r"Architecture: \w+", "Architecture: [ARCH]"); + settings.add_filter(r"Pointer width: \d+", "Pointer width: [WIDTH]"); + settings.add_filter(r"Endian: \w+", "Endian: [ENDIAN]"); + settings.add_filter(r"CPU features: [\w,-]+", "CPU features: [FEATURES]"); + settings.add_filter(r"Host: [\w-]+", "Host: [HOST_TRIPLE]"); + + // this should be serialized TOML + settings.add_filter( + "Cargo build configuration:\\n\ + --------------------------\\n\ + [\\s\\S]*\\n\ + Please file an issue", + "Cargo build configuration:\n\ + --------------------------\n\ + [CARGO_BUILD_TOML]\n\ + Please file an issue", + ); + + settings.add_filter( + r"https://github\.com/obi1kenobi/cargo-semver-checks/issues/new\?\S+", + "https://github.com/obi1kenobi/cargo-semver-checks/issues/new?[INFO_URLENCODED]", + ); + }); +} + +/// Helper function to get a canonicalized version of the cargo executable bin. +fn executable_path() -> PathBuf { + Path::new( + Command::cargo_bin("cargo-semver-checks") + .expect("expected cargo-semver-checks") + .get_program(), + ) + .canonicalize() + .expect("error canonicalizing") +} From f289eebab207a311bb3dc4270cf27c61edff2d6c Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:53:47 -0400 Subject: [PATCH 11/22] Rename `variant_marked_non_exhaustive` to `enum_variant_marked_non_exhaustive`. (#908) This improves our lint naming consistency, since other enum variant lints have `enum_variant_` prefixes. --- ...on_exhaustive.ron => enum_variant_marked_non_exhaustive.ron} | 2 +- src/query.rs | 2 +- ...output.ron => enum_variant_marked_non_exhaustive.output.ron} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/lints/{variant_marked_non_exhaustive.ron => enum_variant_marked_non_exhaustive.ron} (98%) rename test_outputs/{variant_marked_non_exhaustive.output.ron => enum_variant_marked_non_exhaustive.output.ron} (100%) diff --git a/src/lints/variant_marked_non_exhaustive.ron b/src/lints/enum_variant_marked_non_exhaustive.ron similarity index 98% rename from src/lints/variant_marked_non_exhaustive.ron rename to src/lints/enum_variant_marked_non_exhaustive.ron index fb354dcd..ca806b36 100644 --- a/src/lints/variant_marked_non_exhaustive.ron +++ b/src/lints/enum_variant_marked_non_exhaustive.ron @@ -1,5 +1,5 @@ SemverQuery( - id: "variant_marked_non_exhaustive", + id: "enum_variant_marked_non_exhaustive", human_readable_name: "enum variant marked #[non_exhaustive]", description: "An exhaustive enum variant has been marked #[non_exhaustive].", reference: Some("An exhaustive enum variant has been marked #[non_exhaustive], preventing it from being constructed using a literal from outside its own crate."), diff --git a/src/query.rs b/src/query.rs index 049d581d..d81db08a 100644 --- a/src/query.rs +++ b/src/query.rs @@ -805,6 +805,7 @@ add_lints!( enum_tuple_variant_field_now_doc_hidden, enum_unit_variant_changed_kind, enum_variant_added, + enum_variant_marked_non_exhaustive, enum_variant_missing, exported_function_changed_abi, function_abi_no_longer_unwind, @@ -872,5 +873,4 @@ add_lints!( union_now_doc_hidden, union_pub_field_now_doc_hidden, unit_struct_changed_kind, - variant_marked_non_exhaustive, ); diff --git a/test_outputs/variant_marked_non_exhaustive.output.ron b/test_outputs/enum_variant_marked_non_exhaustive.output.ron similarity index 100% rename from test_outputs/variant_marked_non_exhaustive.output.ron rename to test_outputs/enum_variant_marked_non_exhaustive.output.ron From 75acf487ea0353d53982c1e110125d738e10425f Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:05:19 -0400 Subject: [PATCH 12/22] Weekly `cargo update` of dependencies (#900) cargo update Locking 14 packages to latest compatible versions Updating cargo-config2 v0.1.27 -> v0.1.29 Updating cc v1.1.14 -> v1.1.15 Updating filetime v0.2.24 -> v0.2.25 Updating indexmap v2.4.0 -> v2.5.0 Updating jiff v0.1.10 -> v0.1.12 Updating object v0.36.3 -> v0.36.4 Updating quinn v0.11.3 -> v0.11.4 Updating quinn-proto v0.11.6 -> v0.11.7 Updating rustc_version v0.4.0 -> v0.4.1 Updating rustix v0.38.34 -> v0.38.35 Updating rustls-webpki v0.102.6 -> v0.102.7 Updating syn v2.0.76 -> v2.0.77 Updating tokio v1.39.3 -> v1.40.0 Updating webpki-roots v0.26.3 -> v0.26.5 note: pass `--verbose` to see 60 unchanged dependencies behind latest Co-authored-by: github-actions --- Cargo.lock | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b17600d5..d1121ffb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "cargo-config2" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd6dbf7694882745446c74e2dfc4f63b2139c6d2d5692fe33c0999709c40b9e" +checksum = "1124054becb9262cc15c5e96e82f0d782f2aed3a3034d1f71a6385a6fa9e9595" dependencies = [ "home", "serde", @@ -392,9 +392,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.14" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -738,9 +738,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -1871,9 +1871,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1944,9 +1944,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ef8bc400f8312944a9f879db116fed372c4f0859af672eba2a80f79c767dd19" +checksum = "437651126da47900d4d70255ab15f5c69510ca4e0d88c9f01b5b8d41a45c3a9b" dependencies = [ "jiff-tzdb-platform", "windows-sys 0.59.0", @@ -2168,9 +2168,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -2390,9 +2390,9 @@ checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" [[package]] name = "quinn" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +checksum = "a2d2fb862b7ba45e615c1429def928f2e15f815bdf933b27a2d3824e224c1f46" dependencies = [ "bytes", "pin-project-lite", @@ -2408,9 +2408,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" +checksum = "ea0a9b3a42929fad8a7c3de7f86ce0814cfa893328157672680e9fb1145549c5" dependencies = [ "bytes", "rand", @@ -2644,9 +2644,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -2698,9 +2698,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags 2.6.0", "errno", @@ -2741,9 +2741,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" dependencies = [ "ring", "rustls-pki-types", @@ -2982,9 +2982,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.76" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3145,9 +3145,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -3610,9 +3610,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] From 028e52d8aa72eb49e504c65cf67e38081ca3b41d Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:40:52 -0400 Subject: [PATCH 13/22] Rename `trait_default_impl_removed` to `trait_method_default_impl_removed` (#909) --- ...moved.ron => trait_method_default_impl_removed.ron} | 2 +- src/query.rs | 2 +- .../new/Cargo.toml | 2 +- .../new/src/lib.rs | 0 .../old/Cargo.toml | 2 +- .../old/src/lib.rs | 0 ...on => trait_method_default_impl_removed.output.ron} | 10 +++++----- test_outputs/trait_method_missing.output.ron | 4 ++-- test_outputs/trait_newly_sealed.output.ron | 7 +++---- test_outputs/trait_no_longer_object_safe.output.ron | 4 ++-- 10 files changed, 16 insertions(+), 17 deletions(-) rename src/lints/{trait_default_impl_removed.ron => trait_method_default_impl_removed.ron} (98%) rename test_crates/{trait_default_impl_removed => trait_method_default_impl_removed}/new/Cargo.toml (64%) rename test_crates/{trait_default_impl_removed => trait_method_default_impl_removed}/new/src/lib.rs (100%) rename test_crates/{trait_default_impl_removed => trait_method_default_impl_removed}/old/Cargo.toml (64%) rename test_crates/{trait_default_impl_removed => trait_method_default_impl_removed}/old/src/lib.rs (100%) rename test_outputs/{trait_default_impl_removed.output.ron => trait_method_default_impl_removed.output.ron} (86%) diff --git a/src/lints/trait_default_impl_removed.ron b/src/lints/trait_method_default_impl_removed.ron similarity index 98% rename from src/lints/trait_default_impl_removed.ron rename to src/lints/trait_method_default_impl_removed.ron index 4af6a117..cbde9607 100644 --- a/src/lints/trait_default_impl_removed.ron +++ b/src/lints/trait_method_default_impl_removed.ron @@ -1,5 +1,5 @@ SemverQuery( - id: "trait_default_impl_removed", + id: "trait_method_default_impl_removed", human_readable_name: "pub trait default method impl removed", description: "A non-sealed public trait default method impl was removed", required_update: Major, diff --git a/src/query.rs b/src/query.rs index d81db08a..be1696e1 100644 --- a/src/query.rs +++ b/src/query.rs @@ -849,7 +849,7 @@ add_lints!( trait_associated_type_added, trait_associated_type_default_removed, trait_associated_type_now_doc_hidden, - trait_default_impl_removed, + trait_method_default_impl_removed, trait_method_added, trait_method_missing, trait_method_now_doc_hidden, diff --git a/test_crates/trait_default_impl_removed/new/Cargo.toml b/test_crates/trait_method_default_impl_removed/new/Cargo.toml similarity index 64% rename from test_crates/trait_default_impl_removed/new/Cargo.toml rename to test_crates/trait_method_default_impl_removed/new/Cargo.toml index f3a5cc86..ea95420e 100644 --- a/test_crates/trait_default_impl_removed/new/Cargo.toml +++ b/test_crates/trait_method_default_impl_removed/new/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "trait_default_impl_removed" +name = "trait_method_default_impl_removed" version = "0.1.0" edition = "2021" diff --git a/test_crates/trait_default_impl_removed/new/src/lib.rs b/test_crates/trait_method_default_impl_removed/new/src/lib.rs similarity index 100% rename from test_crates/trait_default_impl_removed/new/src/lib.rs rename to test_crates/trait_method_default_impl_removed/new/src/lib.rs diff --git a/test_crates/trait_default_impl_removed/old/Cargo.toml b/test_crates/trait_method_default_impl_removed/old/Cargo.toml similarity index 64% rename from test_crates/trait_default_impl_removed/old/Cargo.toml rename to test_crates/trait_method_default_impl_removed/old/Cargo.toml index f3a5cc86..ea95420e 100644 --- a/test_crates/trait_default_impl_removed/old/Cargo.toml +++ b/test_crates/trait_method_default_impl_removed/old/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "trait_default_impl_removed" +name = "trait_method_default_impl_removed" version = "0.1.0" edition = "2021" diff --git a/test_crates/trait_default_impl_removed/old/src/lib.rs b/test_crates/trait_method_default_impl_removed/old/src/lib.rs similarity index 100% rename from test_crates/trait_default_impl_removed/old/src/lib.rs rename to test_crates/trait_method_default_impl_removed/old/src/lib.rs diff --git a/test_outputs/trait_default_impl_removed.output.ron b/test_outputs/trait_method_default_impl_removed.output.ron similarity index 86% rename from test_outputs/trait_default_impl_removed.output.ron rename to test_outputs/trait_method_default_impl_removed.output.ron index d2b3f484..888cf96f 100644 --- a/test_outputs/trait_default_impl_removed.output.ron +++ b/test_outputs/trait_method_default_impl_removed.output.ron @@ -1,10 +1,10 @@ { - "./test_crates/trait_default_impl_removed/": [ + "./test_crates/trait_method_default_impl_removed/": [ { "method_name": String("method_default_impl_removed"), "name": String("TraitA"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitA"), ]), "span_begin_line": Uint64(8), @@ -15,7 +15,7 @@ "method_name": String("method_default_impl_removed_and_becomes_non_obj_safe"), "name": String("TraitD"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitD"), ]), "span_begin_line": Uint64(22), @@ -26,7 +26,7 @@ "method_name": String("method_default_impl_removed_and_becomes_sealed"), "name": String("TraitE"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitE"), ]), "span_begin_line": Uint64(27), @@ -37,7 +37,7 @@ "method_name": String("method_partially_sealed_has_default_impl_removed"), "name": String("TraitF"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitF"), ]), "span_begin_line": Uint64(32), diff --git a/test_outputs/trait_method_missing.output.ron b/test_outputs/trait_method_missing.output.ron index b084be8a..84a4be7f 100644 --- a/test_outputs/trait_method_missing.output.ron +++ b/test_outputs/trait_method_missing.output.ron @@ -1,10 +1,10 @@ { - "./test_crates/trait_default_impl_removed/": [ + "./test_crates/trait_method_default_impl_removed/": [ { "method_name": String("method_becomes_removed"), "name": String("TraitB"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitB"), ]), "span_begin_line": Uint64(14), diff --git a/test_outputs/trait_newly_sealed.output.ron b/test_outputs/trait_newly_sealed.output.ron index 14aee41b..42cd1032 100644 --- a/test_outputs/trait_newly_sealed.output.ron +++ b/test_outputs/trait_newly_sealed.output.ron @@ -57,11 +57,11 @@ "visibility_limit": String("public"), }, ], - "./test_crates/trait_default_impl_removed/": [ + "./test_crates/trait_method_default_impl_removed/": [ { "name": String("TraitE"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitE"), ]), "span_begin_line": Uint64(26), @@ -71,7 +71,7 @@ { "name": String("TraitF"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitF"), ]), "span_begin_line": Uint64(31), @@ -80,4 +80,3 @@ }, ], } - diff --git a/test_outputs/trait_no_longer_object_safe.output.ron b/test_outputs/trait_no_longer_object_safe.output.ron index f69d496f..b78ecb79 100644 --- a/test_outputs/trait_no_longer_object_safe.output.ron +++ b/test_outputs/trait_no_longer_object_safe.output.ron @@ -21,11 +21,11 @@ "visibility_limit": String("public"), }, ], - "./test_crates/trait_default_impl_removed/": [ + "./test_crates/trait_method_default_impl_removed/": [ { "name": String("TraitD"), "path": List([ - String("trait_default_impl_removed"), + String("trait_method_default_impl_removed"), String("TraitD"), ]), "span_begin_line": Uint64(21), From d8232456a8a739652e83bd8ec1727b29ba88bb0a Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:06:14 -0400 Subject: [PATCH 14/22] Weekly `cargo update` of dependencies (#910) cargo update Locking 9 packages to latest compatible versions Updating quinn v0.11.4 -> v0.11.5 Updating quinn-proto v0.11.7 -> v0.11.8 Updating quinn-udp v0.5.4 -> v0.5.5 Removing trustfall-rustdoc-adapter v28.1.3 Removing trustfall-rustdoc-adapter v29.1.3 Removing trustfall-rustdoc-adapter v30.1.3 Removing trustfall-rustdoc-adapter v32.1.3 Removing trustfall-rustdoc-adapter v33.1.3 Adding trustfall-rustdoc-adapter v28.1.4 (latest: v33.1.4) Adding trustfall-rustdoc-adapter v29.1.4 (latest: v33.1.4) Adding trustfall-rustdoc-adapter v30.1.4 (latest: v33.1.4) Adding trustfall-rustdoc-adapter v32.1.4 (latest: v33.1.4) Adding trustfall-rustdoc-adapter v33.1.4 Updating trustfall_rustdoc v0.16.0 -> v0.16.1 note: pass `--verbose` to see 57 unchanged dependencies behind latest Co-authored-by: github-actions --- Cargo.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1121ffb..212c7899 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2390,9 +2390,9 @@ checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" [[package]] name = "quinn" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d2fb862b7ba45e615c1429def928f2e15f815bdf933b27a2d3824e224c1f46" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ "bytes", "pin-project-lite", @@ -2408,9 +2408,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0a9b3a42929fad8a7c3de7f86ce0814cfa893328157672680e9fb1145549c5" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand", @@ -2425,15 +2425,15 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ "libc", "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3284,9 +3284,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "28.1.3" +version = "28.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f215d49f2108689a3cf1c4ba4e48a47d40301567a1df3106836f882bd433a682" +checksum = "0247b21c545fc4aed1c877450e9750743937d5eaddc6e1f085f72c8713ab3043" dependencies = [ "rustdoc-types 0.24.0", "trustfall", @@ -3294,9 +3294,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "29.1.3" +version = "29.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c78be19778059e175300fe71f3869d3aa4991c72af09c65b232d1870904b287b" +checksum = "962069854192b26d8073c052e26806afd74faed02131df5e344a8ea6ca30e2a4" dependencies = [ "rustdoc-types 0.25.0", "trustfall", @@ -3304,9 +3304,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "30.1.3" +version = "30.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f89d7ebd7029268433ac0e647a45f1f6a829102441c95d4908dcea8803356e" +checksum = "33c944186765c3c36585ff52d0d67fc02e5bc79a0ec52b96fe26d4ffe4de7dc7" dependencies = [ "rustdoc-types 0.26.0", "trustfall", @@ -3314,9 +3314,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "32.1.3" +version = "32.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b381607f0009a87215190cc3ed5469eabfb4c057fc40117364de794fda09f86" +checksum = "a0ed00d3646c9e22ebdf4565e21919a7b39b410839ef9e4026ac5524b60480a3" dependencies = [ "rustdoc-types 0.28.1", "trustfall", @@ -3324,9 +3324,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "33.1.3" +version = "33.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11e9b5aeb138eb9c4eb323fbcb1118816cebce7735ecb4916164c86b109c00f3" +checksum = "830bc6cee8376524a6ef429ed4bf5ba1b7b4b58bfc6270e1339401c46a828135" dependencies = [ "rustdoc-types 0.29.1", "trustfall", @@ -3362,19 +3362,19 @@ dependencies = [ [[package]] name = "trustfall_rustdoc" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285db3f0985971888b37632f9b28529ee069c9c941489c7049bf0f456e842c68" +checksum = "838964586da4bf4aa7831f864411fddf7712140ff897f6d9279563081102aa5f" dependencies = [ "anyhow", "serde", "serde_json", "trustfall", - "trustfall-rustdoc-adapter 28.1.3", - "trustfall-rustdoc-adapter 29.1.3", - "trustfall-rustdoc-adapter 30.1.3", - "trustfall-rustdoc-adapter 32.1.3", - "trustfall-rustdoc-adapter 33.1.3", + "trustfall-rustdoc-adapter 28.1.4", + "trustfall-rustdoc-adapter 29.1.4", + "trustfall-rustdoc-adapter 30.1.4", + "trustfall-rustdoc-adapter 32.1.4", + "trustfall-rustdoc-adapter 33.1.4", ] [[package]] From 609289294764ce73b0231584e710f9a8695a3506 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:06:52 -0400 Subject: [PATCH 15/22] Release v0.35.0. (#911) --- Cargo.lock | 2 +- Cargo.toml | 2 +- ...snapshot_tests__workspace_baseline_compile_error-output.snap | 2 +- ...snapshot_tests__workspace_publish_false_explicit-output.snap | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 212c7899..b6115367 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,7 +325,7 @@ dependencies = [ [[package]] name = "cargo-semver-checks" -version = "0.34.0" +version = "0.35.0" dependencies = [ "anstream", "anstyle", diff --git a/Cargo.toml b/Cargo.toml index ad496650..4841450b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-semver-checks" -version = "0.34.0" +version = "0.35.0" edition = "2021" authors = ["Predrag Gruevski "] license = "Apache-2.0 OR MIT" diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap index f832410e..1c86560d 100644 --- a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap @@ -11,7 +11,7 @@ aborting due to failure to build rustdoc for crate error v0.1.0 Description: A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely. ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove - impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.34.0/src/lints/function_missing.ron + impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.35.0/src/lints/function_missing.ron Failed in: function no_error::my_fn, previously in file [ROOT]/test_crates/manifest_tests/workspace_baseline_compile_error/old/no-error/src/lib.rs:3 diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap index e28cdd34..b361e487 100644 --- a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap @@ -10,7 +10,7 @@ success: false Description: A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely. ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove - impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.34.0/src/lints/function_missing.ron + impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.35.0/src/lints/function_missing.ron Failed in: function a::should_not_run, previously in file [ROOT]/test_crates/manifest_tests/workspace_all_publish_false/old/a/src/lib.rs:4 From 7b7a518150b7ff2701c40a61829896a2cd05898b Mon Sep 17 00:00:00 2001 From: Max Carr Date: Tue, 3 Sep 2024 11:03:23 -0700 Subject: [PATCH 16/22] Filter versions in lint reference links in snapshots (#913) filter versions in lint references --- src/snapshot_tests.rs | 6 ++++++ ...shot_tests__workspace_baseline_compile_error-output.snap | 2 +- ...shot_tests__workspace_publish_false_explicit-output.snap | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/snapshot_tests.rs b/src/snapshot_tests.rs index bba4e50a..471d6e4c 100644 --- a/src/snapshot_tests.rs +++ b/src/snapshot_tests.rs @@ -172,6 +172,12 @@ fn assert_integration_test(test_name: &str, invocation: &[&str]) { // Remove cargo blocking lines (e.g. from `cargo doc` output) as the amount of blocks // is not reproducible. settings.add_filter(" Blocking waiting for file lock on package cache\n", ""); + // Filter out the current `cargo-semver-checks` version in links to lint references, + // as this will break across version changes. + settings.add_filter( + r"v\d+\.\d+\.\d+(-[\w\.-]+)?/src/lints", + "[VERSION]/src/lints", + ); // The `settings` are applied to the current thread as long as the returned // drop guard `_grd` is alive, so we use a `let` binding to keep it alive diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap index 1c86560d..aed6ff30 100644 --- a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_baseline_compile_error-output.snap @@ -11,7 +11,7 @@ aborting due to failure to build rustdoc for crate error v0.1.0 Description: A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely. ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove - impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.35.0/src/lints/function_missing.ron + impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/[VERSION]/src/lints/function_missing.ron Failed in: function no_error::my_fn, previously in file [ROOT]/test_crates/manifest_tests/workspace_baseline_compile_error/old/no-error/src/lib.rs:3 diff --git a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap index b361e487..018804e2 100644 --- a/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap +++ b/test_outputs/snapshot_tests/cargo_semver_checks__snapshot_tests__workspace_publish_false_explicit-output.snap @@ -10,7 +10,7 @@ success: false Description: A publicly-visible function cannot be imported by its prior path. A `pub use` may have been removed, or the function itself may have been renamed or removed entirely. ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove - impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.35.0/src/lints/function_missing.ron + impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/[VERSION]/src/lints/function_missing.ron Failed in: function a::should_not_run, previously in file [ROOT]/test_crates/manifest_tests/workspace_all_publish_false/old/a/src/lib.rs:4 From eb0c7713c61a3bc9de5a872e3327eaa2e59c462e Mon Sep 17 00:00:00 2001 From: Max Carr Date: Wed, 4 Sep 2024 19:04:15 -0700 Subject: [PATCH 17/22] Functionality for unstable feature flags and options (#896) * add test and output * unstable feature flags and options * clippy :( * update featureflags, add docs, and... - update behavior for stable flags and test - move bugreport action to the top - add test that all unstable features are hidden * fmt docstring * better validation for unstable options * annotate code paths and consolidate helps * use stdout * error consistency Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> * add two integration tests. * delete snap.new * remove backtrace variable * move unstable options to checkrelease * error check for string write Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --------- Co-authored-by: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> --- src/config.rs | 134 ++++++++++- src/lib.rs | 2 +- src/main.rs | 219 +++++++++++++++++- ...pshots__unstable_options_without_flag.snap | 15 ++ .../integration_snapshots__z_help.snap | 22 ++ tests/integration_snapshots.rs | 25 ++ 6 files changed, 410 insertions(+), 7 deletions(-) create mode 100644 test_outputs/integration_snapshots__unstable_options_without_flag.snap create mode 100644 test_outputs/integration_snapshots__z_help.snap diff --git a/src/config.rs b/src/config.rs index 06701a6e..0de4a174 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,7 @@ use anstream::{AutoStream, ColorChoice}; use anstyle::{AnsiColor, Color, Reset, Style}; -use std::io::Write; +use clap::ValueEnum; +use std::{collections::HashSet, io::Write}; use crate::templating::make_handlebars_registry; @@ -14,6 +15,7 @@ pub struct GlobalConfig { minimum_rustc_version: semver::Version, stdout: AutoStream>, stderr: AutoStream>, + feature_flags: HashSet, } impl Default for GlobalConfig { @@ -38,6 +40,7 @@ impl GlobalConfig { minimum_rustc_version: semver::Version::new(1, 77, 0), stdout: AutoStream::new(Box::new(std::io::stdout()), stdout_choice), stderr: AutoStream::new(Box::new(std::io::stderr()), stderr_choice), + feature_flags: HashSet::new(), } } @@ -284,6 +287,120 @@ impl GlobalConfig { ColorChoice::Never | ColorChoice::Auto => false, } } + + /// Set (overwrite) the [`FeatureFlag`] set. + #[inline] + pub fn set_feature_flags(&mut self, flags: HashSet) -> &mut Self { + self.feature_flags = flags; + self + } + + /// Enable a single [feature flag](FeatureFlag). + #[inline] + pub fn enable_feature_flag(&mut self, flag: FeatureFlag) -> &mut Self { + self.feature_flags.insert(flag); + self + } + + /// Test for whether a specific feature flag is enabled. If the flag has been + /// stabilized, this will always return true. + #[must_use] + #[inline] + pub fn feature_flag_enabled(&self, flag: FeatureFlag) -> bool { + flag.stable || self.feature_flags.contains(&flag) + } + + /// Returns a set of all enabled feature flags. + #[must_use] + #[inline] + pub fn feature_flags(&self) -> &HashSet { + &self.feature_flags + } +} + +/// A feature flag for gating unstable `cargo-semver-checks` features. +/// +/// ## Feature-gating code +/// +/// To only execute a block of code when a given feature flag `flag` has been enabled, +/// wrap the block in `if config.feature_flag_enabled(flag)`, where `config` is the +/// program's [`GlobalConfig`]. +/// +/// ## Adding a new unstable feature flag +/// +/// Create a new associated constant in the `impl FeatureFlag` block with an identifier, +/// help message, and `stable: false`, and **add this constant** to the +/// [`ALL_FLAGS`](Self::ALL_FLAGS) slice. +/// +/// ## Stabilizing a feature flag +/// +/// Set `stable: true` on the associated constant for that flag. To keep the transition +/// from unstable flag to stable feature, mark the associated constant `#[deprecated]`, but +/// don't remove it. This will warn downstream code and `cargo-semver-checks` binary users +/// that the flag has been stabilized and may be removed in a future release, and hide it +/// from `-Z help`, without breaking downstream code and binary users right when it is stabilized. +/// +/// When you stabilize a flag and mark it as `#[deprecated]`, remove any `if` blocks +/// that feature-gate code. Testing if a flag is enabled with [`GlobalConfig::feature_flag_enabled`] +/// will always return `true` when a flag has been stabilized. +/// +/// ## See also +/// +/// - [`GlobalConfig::feature_flag_enabled] +/// - [`GlobalConfig::feature_flags] +/// - [`GlobalConfig::set_feature_flags] +/// - [`GlobalConfig::enable_feature_flag] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct FeatureFlag { + /// `kebab-case` identifier for this feature flag. + pub id: &'static str, + /// Optional help message for this flag. + /// + /// If this contains multiple lines. the first should be able to serve as + /// a one-line 'short help' when needed, and the full help string will be + /// used as a `long help`. + pub help: Option<&'static str>, + /// Whether this flag is stable and enabled by default. Stable flags may + /// be removed in future releases of `cargo-semver-checks` as the feature + /// is stabilized and feature-gated code is unconditionally executed. + pub stable: bool, +} + +impl FeatureFlag { + /// Print a list of the current unstable feature flags. + pub const HELP: Self = Self { + id: "help", + help: Some("Print a list of the current unstable feature flags"), + stable: false, + }; + + /// Enables the use of unstable CLI flags. + pub const UNSTABLE_OPTIONS: Self = Self { + id: "unstable-options", + help: Some( + "Enables the use of unstable CLI flags.\n\ + Run `cargo semver-checks -Z help` to list them", + ), + stable: false, + }; + + /// All feature flags that currently exist in `cargo-semver-checks`. + pub const ALL_FLAGS: &'static [Self] = &[Self::HELP, Self::UNSTABLE_OPTIONS]; +} + +impl ValueEnum for FeatureFlag { + #[inline] + fn value_variants<'a>() -> &'a [Self] { + Self::ALL_FLAGS + } + + fn to_possible_value(&self) -> Option { + Some( + clap::builder::PossibleValue::new(self.id) + .hide(self.stable) + .help(self.help), + ) + } } #[cfg(test)] @@ -495,4 +612,19 @@ mod tests { assert!(config.err_color_choice()); assert!(config.out_color_choice()); } + + #[test] + fn stable_flags_always_enabled() { + let config = GlobalConfig::new(); + assert!(config.feature_flag_enabled(FeatureFlag { + id: "ad-hoc", + help: None, + stable: true + })); + assert!(!config.feature_flag_enabled(FeatureFlag { + id: "ad-hoc", + help: None, + stable: false, + })); + } } diff --git a/src/lib.rs b/src/lib.rs index 9a95702f..89f6c0c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Instant; -pub use config::GlobalConfig; +pub use config::{FeatureFlag, GlobalConfig}; pub use query::{ ActualSemverUpdate, LintLevel, OverrideMap, OverrideStack, QueryOverride, RequiredSemverUpdate, SemverQuery, diff --git a/src/main.rs b/src/main.rs index 1c5cb749..e5690b06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,13 @@ #![forbid(unsafe_code)] -use std::{env, path::PathBuf}; +use std::{collections::HashSet, env, path::PathBuf}; use anstyle::{AnsiColor, Color, Reset, Style}; use cargo_config2::Config; use cargo_semver_checks::{ - GlobalConfig, PackageSelection, ReleaseType, Rustdoc, ScopeSelection, SemverQuery, + FeatureFlag, GlobalConfig, PackageSelection, ReleaseType, Rustdoc, ScopeSelection, SemverQuery, }; -use clap::{Args, Parser, Subcommand}; +use clap::{Args, CommandFactory, Parser, Subcommand}; use std::io::Write; #[cfg(test)] @@ -18,14 +18,22 @@ fn main() { let Cargo::SemverChecks(args) = Cargo::parse(); + let feature_flags = HashSet::from_iter(args.unstable_features.clone()); + configure_color(args.color_choice); let mut config = GlobalConfig::new(); config.set_log_level(args.verbosity.log_level()); + config.set_feature_flags(feature_flags); + + exit_on_error(true, || validate_feature_flags(&mut config, &args)); + // --bugreport: generate a bug report URL if args.bugreport { print_issue_url(&mut config); std::process::exit(0); - } else if args.list { + } + // --list: print a list of all lints + else if args.list { exit_on_error(true, || { let queries = SemverQuery::all_queries(); let mut rows = vec![["id", "type", "description"], ["==", "====", "==========="]]; @@ -56,7 +64,9 @@ fn main() { config.shell_note("Use `--explain ` to see more details") }); std::process::exit(0); - } else if let Some(id) = args.explain.as_deref() { + } + // --explain ID: print detailed information about a lint + else if let Some(id) = args.explain.as_deref() { exit_on_error(true, || { let queries = SemverQuery::all_queries(); let query = queries.get(id).ok_or_else(|| { @@ -82,6 +92,64 @@ fn main() { }); std::process::exit(0); } + // -Z help: print information on all unstable FeatureFlags (-Z flag) + else if config.feature_flag_enabled(FeatureFlag::HELP) { + config + .log_info(|config| { + let header = Style::new() + .bold() + .fg_color(Some(Color::Ansi(AnsiColor::Cyan))); + let option = Style::new().bold(); + + let mut stdout = config.stdout(); + + writeln!(stdout, "{header}Unstable feature flags:{header:#}")?; + writeln!(stdout, "{header}{:<20}{header:#}Description", "-Z name",)?; + + for flag in FeatureFlag::ALL_FLAGS.iter().filter(|x| !x.stable) { + write!(stdout, "{option}{:<20}{option:#}", flag.id)?; + + if let Some(help) = flag.help { + let mut lines = help.lines(); + + if let Some(first) = lines.next() { + writeln!(stdout, "{first}")?; + + for line in lines { + writeln!(stdout, "{:<20}{line}", "")?; + } + } + } else { + writeln!(stdout)?; + } + } + + // helper struct for rendering help for just the unstable options. + #[derive(Parser)] + #[clap( + disable_help_flag = true, + help_template = "{options}", + mut_args = |arg| arg.hide(false), + )] + struct HelpPrinter { + #[command(flatten)] + args: UnstableOptions, + } + + write!( + stdout, + "{header}Unstable options:{header:#}\n\ + {}", + HelpPrinter::command().render_long_help() + ) + .expect("print failed"); + + Ok(()) + }) + .expect("write failed"); + + std::process::exit(0); + } let check_release = match args.command { Some(SemverChecksCommands::CheckRelease(c)) => c, @@ -241,6 +309,65 @@ struct SemverChecks { // docstring for help is on the `clap_verbosity_flag::Verbosity` struct itself #[command(flatten)] verbosity: clap_verbosity_flag::Verbosity, + + /// Enable unstable feature flags, run `cargo semver-checks -Z help` for more help. + #[arg( + short = 'Z', + value_name = "FLAG", + global = true, + hide_possible_values = true // show explictly with -Z help + )] + unstable_features: Vec, +} + +/// Encapsulated unstable CLI flags. These will only be used if +/// `-Z unstable-options` is passed to `cargo-semver-checks`. +/// +/// Note for adding arguments: make sure your added argument has a default value to detect +/// when arguments are passed without `-Z unstable-options`, so make sure the behavior +/// when the arg is its default value is the same as the behavior on stable +/// `cargo-semver-checks` when this flag is not passed. +/// +/// Also make sure to add `#[arg(hide = true)]` to your argument so it doesn't show +/// up in stable help when it is not valid. Users can run +/// `cargo semver-checks -Z help` to show help messages +/// instead, so a docstring help message will be shown then. +#[derive(Debug, Clone, Args, Default, PartialEq, Eq)] +#[clap(hide = true)] +#[non_exhaustive] +struct UnstableOptions { + /// Enable printing witness hints, examples of potentially-broken downstream code. + #[arg(long, hide = true)] + witness_hints: bool, +} + +impl UnstableOptions { + /// Returns a list of command line flags set when fields in this struct are + /// not their default values, used for detecting and printing when unstable options + /// are set without `-Z unstable-options`. + /// + /// When you add a new unstable option, the exhaustive let pattern below will not compile. + /// Fix this by adding the new field to the let pattern, then adding a similar if statement + /// to the ones below to detect when the field is not its default value, and insert the + /// command line flag that caused this into the list. See the implementation + /// for examples. + /// + /// When you remove an unstable option (e.g., to stabilize it), remove the field from + /// the match pattern, and remove the if block corresponding to that struct field. + #[must_use] + fn non_default(&self) -> Vec { + let mut list = Vec::new(); + + // If this has a compilation error from adding or removing fields, see this function's + // docstring for how to fix this function's implementation. + let Self { witness_hints } = self; + + if *witness_hints { + list.push("--witness-hints".into()); + } + + list + } } /// Check your crate for semver violations. @@ -390,6 +517,9 @@ struct CheckRelease { /// `x86_64-unknown-linux-gnu`. #[arg(long = "target")] build_target: Option, + + #[clap(flatten)] + unstable_options: UnstableOptions, } impl From for cargo_semver_checks::Check { @@ -487,6 +617,54 @@ impl From for cargo_semver_checks::Check { } } +/// Helper function to encapsulate the logic of validating that unstable options +/// were not used without `-Z unstable-options` and issuing deprecation warnings +/// for any stable feature flags that were explicitly specified. +fn validate_feature_flags(config: &mut GlobalConfig, args: &SemverChecks) -> anyhow::Result<()> { + // needed to avoid borrow checker errors when printing with config. + let stable_flags: Vec<_> = config + .feature_flags() + .iter() + .filter(|x| x.stable) + .copied() + .collect(); + + for stable_flag in stable_flags { + config + .shell_warn(format_args!( + "the feature flag {} has been stabilized and may be removed + from the list of feature flags in a future release.", + stable_flag.id + )) + .expect("printing failed"); + } + + if !config.feature_flag_enabled(FeatureFlag::UNSTABLE_OPTIONS) { + let unstable_options = match &args.command { + Some(SemverChecksCommands::CheckRelease(cr)) => &cr.unstable_options, + None => &args.check_release.unstable_options, + }; + + let non_default_options = unstable_options.non_default(); + + if !non_default_options.is_empty() { + let mut message = String::from( + "the following options are not supported without `-Z unstable-options`:\n", + ); + + for option in non_default_options { + use std::fmt::Write as _; + + writeln!(&mut message, " - `{option}`").expect("writes to strings are infallible"); + } + + anyhow::bail!(message); + } + } + + Ok(()) +} + #[test] fn verify_cli() { use clap::CommandFactory; @@ -511,3 +689,34 @@ fn features_empty_string_is_no_op() { assert_eq!(Check::from(no_features), Check::from(empty_features)); } + +/// Test to assert that all flags added to the [`UnstableOptions`] are +/// hidden and won't show up in stable `--help`. +#[test] +fn all_unstable_features_are_hidden() { + // Helper struct to get a `Command` to use reflection on the unstable options. + #[derive(Debug, Parser)] + struct Wrapper { + #[clap(flatten)] + inner: UnstableOptions, + } + + let unstable_options = Wrapper::command(); + let cargo_command = Cargo::command(); + let semver_checks = cargo_command + .find_subcommand("semver-checks") + .expect("expected semver-checks command"); + + for option in unstable_options.get_arguments() { + let argument = semver_checks + .get_arguments() + .find(|x| x.get_id() == option.get_id()) + .expect("expected unstable argument"); + + assert!( + argument.is_hide_set(), + "unstable argument {} should be hidden by default", + argument.get_id() + ); + } +} diff --git a/test_outputs/integration_snapshots__unstable_options_without_flag.snap b/test_outputs/integration_snapshots__unstable_options_without_flag.snap new file mode 100644 index 00000000..e32e4894 --- /dev/null +++ b/test_outputs/integration_snapshots__unstable_options_without_flag.snap @@ -0,0 +1,15 @@ +--- +source: tests/integration_snapshots.rs +info: + program: cargo-semver-checks + args: + - semver-checks + - "--witness-hints" +--- +success: false +exit_code: 1 +----- stdout ----- + +----- stderr ----- +error: the following options are not supported without `-Z unstable-options`: + - `--witness-hints` diff --git a/test_outputs/integration_snapshots__z_help.snap b/test_outputs/integration_snapshots__z_help.snap new file mode 100644 index 00000000..6b934a0f --- /dev/null +++ b/test_outputs/integration_snapshots__z_help.snap @@ -0,0 +1,22 @@ +--- +source: tests/integration_snapshots.rs +info: + program: cargo-semver-checks + args: + - semver-checks + - "-Z" + - help +--- +success: true +exit_code: 0 +----- stdout ----- +Unstable feature flags: +-Z name Description +help Print a list of the current unstable feature flags +unstable-options Enables the use of unstable CLI flags. + Run `cargo semver-checks -Z help` to list them +Unstable options: + --witness-hints + Enable printing witness hints, examples of potentially-broken downstream code + +----- stderr ----- diff --git a/tests/integration_snapshots.rs b/tests/integration_snapshots.rs index 25f30f67..f6584f19 100644 --- a/tests/integration_snapshots.rs +++ b/tests/integration_snapshots.rs @@ -30,7 +30,11 @@ fn assert_integration_test( let mut settings = insta::Settings::clone_current(); let mut cmd = Command::cargo_bin("cargo-semver-checks").expect("failed to get cargo-semver-checks"); + + // never use color for more readable snapshots cmd.env("CARGO_TERM_COLOR", "never"); + // disable backtrace printing for reproducibility + cmd.env("RUST_BACKTRACE", "0"); cmd.arg("semver-checks"); settings.set_snapshot_path("../test_outputs/"); @@ -94,6 +98,27 @@ fn bugreport() { }); } +// TODO: this test will break when the `--witness-hints` is stabilized. It will need to +// be replaced with a different unstable option. See the module-level doc comment for +// how to update this test. +/// Tests the behavior of unstable options being passed without `-Z unstable-options`. +#[test] +fn unstable_options_without_flag() { + assert_integration_test("unstable_options_without_flag", |cmd, _| { + cmd.arg("--witness-hints"); + }); +} + +/// Snapshots the behavior of `-Z help`. This snapshot will need to be updated when any +/// unstable options or feature flags are added, removed, or stabilized. See the module-level +/// doc comment for how to update this test. +#[test] +fn z_help() { + assert_integration_test("z_help", |cmd, _| { + cmd.args(["-Z", "help"]); + }) +} + /// Helper function to get a canonicalized version of the cargo executable bin. fn executable_path() -> PathBuf { Path::new( From 8b2a51b6500ec918f4608ec8cb19335e1a89e4a7 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:55:24 -0400 Subject: [PATCH 18/22] Add next Rust minor to test matrix (#917) Automation to ensure we test on all supported Rust versions as new stable Rust versions are released. The following is the output from `git diff`: ```diff diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1712f82..ca7d480 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,7 +169,7 @@ jobs: # # Also make sure to update the MSRV in the cargo-semver-checks-action CI: # https://github.com/obi1kenobi/cargo-semver-checks-action/blob/main/.github/workflows/test-action.yml#L18 - toolchain: ["1.77", "1.78", "1.79", "stable", "beta"] + toolchain: ["1.77", "1.78", "1.79", "1.80", "stable", "beta"] experimental: [false] include: - toolchain: "nightly" ``` Co-authored-by: github-actions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1712f821..ca7d480c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,7 +169,7 @@ jobs: # # Also make sure to update the MSRV in the cargo-semver-checks-action CI: # https://github.com/obi1kenobi/cargo-semver-checks-action/blob/main/.github/workflows/test-action.yml#L18 - toolchain: ["1.77", "1.78", "1.79", "stable", "beta"] + toolchain: ["1.77", "1.78", "1.79", "1.80", "stable", "beta"] experimental: [false] include: - toolchain: "nightly" From 269f88bec51e546c9ead5f8687a0adc63f98fe2f Mon Sep 17 00:00:00 2001 From: David Matos Date: Fri, 6 Sep 2024 01:47:17 +0200 Subject: [PATCH 19/22] Add support for specifying features with commas `feat1,feat2` (#918) --- src/main.rs | 22 +++++++-- .../feature_flags_validation/new/Cargo.toml | 19 ++++++++ .../feature_flags_validation/new/src/lib.rs | 8 ++++ .../feature_flags_validation/old/Cargo.toml | 20 ++++++++ .../feature_flags_validation/old/src/lib.rs | 17 +++++++ test_outputs/function_missing.output.ron | 22 +++++++++ tests/feature_config.rs | 46 +++++++++++++++++++ 7 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 test_crates/feature_flags_validation/new/Cargo.toml create mode 100644 test_crates/feature_flags_validation/new/src/lib.rs create mode 100644 test_crates/feature_flags_validation/old/Cargo.toml create mode 100644 test_crates/feature_flags_validation/old/src/lib.rs diff --git a/src/main.rs b/src/main.rs index e5690b06..6ed9d5ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -484,17 +484,31 @@ struct CheckRelease { /// Add a feature to the set of features being checked. /// The feature will be used in both the baseline and the current version /// of the crate. - #[arg(long, value_name = "NAME", help_heading = "Features")] + #[arg( + long, + value_delimiter = ',', + value_name = "NAME", + help_heading = "Features" + )] features: Vec, /// Add a feature to the set of features being checked. /// The feature will be used in the baseline version of the crate only. - #[arg(long, value_name = "NAME", help_heading = "Features")] + #[arg( + long, + value_delimiter = ',', + value_name = "NAME", + help_heading = "Features" + )] baseline_features: Vec, - /// Add a feature to the set of features being checked. /// The feature will be used in the current version of the crate only. - #[arg(long, value_name = "NAME", help_heading = "Features")] + #[arg( + long, + value_delimiter = ',', + value_name = "NAME", + help_heading = "Features" + )] current_features: Vec, /// Use all the features, including features named diff --git a/test_crates/feature_flags_validation/new/Cargo.toml b/test_crates/feature_flags_validation/new/Cargo.toml new file mode 100644 index 00000000..80e0302e --- /dev/null +++ b/test_crates/feature_flags_validation/new/Cargo.toml @@ -0,0 +1,19 @@ +[package] +publish = false +name = "feature_flags_validation" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[features] +default = ["std", "alloc"] +foo = [] +std = [] +bar = [] +alloc = [] +unstable = [] +nightly = [] +bench = [] +no_std = [] +__foo = [] diff --git a/test_crates/feature_flags_validation/new/src/lib.rs b/test_crates/feature_flags_validation/new/src/lib.rs new file mode 100644 index 00000000..5ce39bbc --- /dev/null +++ b/test_crates/feature_flags_validation/new/src/lib.rs @@ -0,0 +1,8 @@ +#[cfg(feature = "foo")] +pub fn foo_becomes_gated() {} + +#[cfg(feature = "bar")] +pub fn bar_becomes_gated() {} + +#[cfg(any(feature = "unstable", feature = "nightly",))] +pub fn unstable_function() {} diff --git a/test_crates/feature_flags_validation/old/Cargo.toml b/test_crates/feature_flags_validation/old/Cargo.toml new file mode 100644 index 00000000..3e4bffa3 --- /dev/null +++ b/test_crates/feature_flags_validation/old/Cargo.toml @@ -0,0 +1,20 @@ +[package] +publish = false +name = "feature_flags_validation" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[features] +default = ["std", "alloc"] +std = [] +alloc = [] +unstable = [] +nightly = [] +bench = [] +no_std = [] +__foo = [] +unstable-foo=[] +unstable_foo=[] +_bar=[] diff --git a/test_crates/feature_flags_validation/old/src/lib.rs b/test_crates/feature_flags_validation/old/src/lib.rs new file mode 100644 index 00000000..cdcf404c --- /dev/null +++ b/test_crates/feature_flags_validation/old/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(not(all(feature = "std", feature = "alloc")))] +compile_error!("`std` and `alloc` features are currently required to build this awesome crate"); + +pub fn foo_becomes_gated() {} +pub fn bar_becomes_gated() {} + +#[cfg(any( + feature = "unstable", + feature = "nightly", + feature = "bench", + feature = "no_std", + feature = "__foo", + feature = "unstable-foo", + feature = "unstable_foo", + feature = "_bar" +))] +pub fn unstable_function() {} diff --git a/test_outputs/function_missing.output.ron b/test_outputs/function_missing.output.ron index b2f81ed2..dd4ceff3 100644 --- a/test_outputs/function_missing.output.ron +++ b/test_outputs/function_missing.output.ron @@ -1,4 +1,26 @@ { + "./test_crates/feature_flags_validation/": [ + { + "name": String("foo_becomes_gated"), + "path": List([ + String("feature_flags_validation"), + String("foo_becomes_gated"), + ]), + "span_begin_line": Uint64(4), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + { + "name": String("bar_becomes_gated"), + "path": List([ + String("feature_flags_validation"), + String("bar_becomes_gated"), + ]), + "span_begin_line": Uint64(5), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], "./test_crates/features_simple/": [ { "name": String("feature_dependent_function"), diff --git a/tests/feature_config.rs b/tests/feature_config.rs index 32c0d0e4..1c32651a 100644 --- a/tests/feature_config.rs +++ b/tests/feature_config.rs @@ -70,6 +70,52 @@ fn simple_default_features() { }); } +#[test] +fn simple_validation_feature_flags() { + CargoSemverChecks::new( + "test_crates/feature_flags_validation/new/", + "test_crates/feature_flags_validation/old/Cargo.toml", + ) + .add_arg("--only-explicit-features") + .add_arg("--baseline-features") + .add_arg("std,alloc") + .add_arg("--current-features") + .add_arg("foo,bar") + // without --features flag still works, but this is about flag validation + .add_arg("--features") + .add_arg("unstable,nightly") + .run_all() + .into_iter() + .for_each(|a| { + a.success(); + }); + // We repeat the same test, but specify each flag separately, + // to ensure that both ways can be parsed + CargoSemverChecks::new( + "test_crates/feature_flags_validation/new/", + "test_crates/feature_flags_validation/old/Cargo.toml", + ) + .add_arg("--only-explicit-features") + .add_arg("--baseline-features") + .add_arg("std") + .add_arg("--baseline-features") + .add_arg("alloc") + .add_arg("--current-features") + .add_arg("foo") + .add_arg("--current-features") + .add_arg("bar") + // without --features flag still works, but this is about flag validation + .add_arg("--features") + .add_arg("unstable") + .add_arg("--features") + .add_arg("nightly") + .run_all() + .into_iter() + .for_each(|a| { + a.success(); + }); +} + #[test] fn simple_heuristic_features() { CargoSemverChecks::new( From 3352f525554a825745465ba02f41af2200c37a73 Mon Sep 17 00:00:00 2001 From: Max Carr Date: Fri, 6 Sep 2024 14:35:08 -0700 Subject: [PATCH 20/22] Encapsulate query deserializing logic (#919) encapsulate query deserializing logic --- src/query.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/query.rs b/src/query.rs index be1696e1..b1bbf284 100644 --- a/src/query.rs +++ b/src/query.rs @@ -126,22 +126,28 @@ pub struct SemverQuery { } impl SemverQuery { + /// Deserializes a [`SemverQuery`] from a [`ron`]-encoded string slice. + /// + /// Returns an `Err` if the deserialization fails. + pub fn from_ron_str(query_text: &str) -> ron::Result { + let mut deserializer = ron::Deserializer::from_str_with_options( + query_text, + ron::Options::default().with_default_extension(Extensions::IMPLICIT_SOME), + )?; + + Self::deserialize(&mut deserializer) + } + pub fn all_queries() -> BTreeMap { let mut queries = BTreeMap::default(); for (id, query_text) in get_queries() { - let mut deserializer = ron::Deserializer::from_str_with_options( - query_text, - ron::Options::default().with_default_extension(Extensions::IMPLICIT_SOME), - ) - .expect("Failed to construct deserializer."); - - let query = Self::deserialize(&mut deserializer).unwrap_or_else(|e| { + let query = Self::from_ron_str(query_text).unwrap_or_else(|e| { panic!( "\ -Failed to parse a query: {e} -```ron -{query_text} -```" + Failed to parse a query: {e} + ```ron + {query_text} + ```" ); }); assert_eq!(id, query.id, "Query id must match file name"); @@ -469,7 +475,7 @@ mod tests { pub(in crate::query) fn check_query_execution(query_name: &str) { let query_text = std::fs::read_to_string(format!("./src/lints/{query_name}.ron")).unwrap(); - let semver_query: SemverQuery = ron::from_str(&query_text).unwrap(); + let semver_query = SemverQuery::from_ron_str(&query_text).unwrap(); let expected_result_text = std::fs::read_to_string(format!("./test_outputs/{query_name}.output.ron")) From 5f2c18e2daeeee896fd321ed4660827c1c8e664c Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Sat, 7 Sep 2024 01:07:17 -0400 Subject: [PATCH 21/22] Weekly `cargo update` of dependencies (#920) cargo update Locking 25 packages to latest compatible versions Updating anyhow v1.0.86 -> v1.0.87 Updating cc v1.1.15 -> v1.1.17 Updating clap v4.5.16 -> v4.5.17 Updating clap_builder v4.5.15 -> v4.5.17 Updating cpufeatures v0.2.13 -> v0.2.14 Updating gix-path v0.10.10 -> v0.10.11 Updating gix-trace v0.1.9 -> v0.1.10 Updating handlebars v6.0.0 -> v6.1.0 Updating hyper-rustls v0.27.2 -> v0.27.3 Updating insta v1.39.0 -> v1.40.0 Updating pest v2.7.11 -> v2.7.12 Updating pest_derive v2.7.11 -> v2.7.12 Updating pest_generator v2.7.11 -> v2.7.12 Updating pest_meta v2.7.11 -> v2.7.12 Updating rustix v0.38.35 -> v0.38.36 Updating serde v1.0.209 -> v1.0.210 Updating serde_derive v1.0.209 -> v1.0.210 Updating serde_json v1.0.127 -> v1.0.128 Updating similar-asserts v1.5.0 -> v1.6.0 Updating tokio-util v0.7.11 -> v0.7.12 Removing trustfall-rustdoc-adapter v28.1.4 Removing trustfall-rustdoc-adapter v29.1.4 Removing trustfall-rustdoc-adapter v30.1.4 Removing trustfall-rustdoc-adapter v32.1.4 Removing trustfall-rustdoc-adapter v33.1.4 Adding trustfall-rustdoc-adapter v28.1.5 (latest: v33.1.5) Adding trustfall-rustdoc-adapter v29.1.5 (latest: v33.1.5) Adding trustfall-rustdoc-adapter v30.1.5 (latest: v33.1.5) Adding trustfall-rustdoc-adapter v32.1.5 (latest: v33.1.5) Adding trustfall-rustdoc-adapter v33.1.5 note: pass `--verbose` to see 57 unchanged dependencies behind latest Co-authored-by: github-actions --- Cargo.lock | 110 ++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6115367..ac283e7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "arc-swap" @@ -392,9 +392,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "a93fe60e2fc87b6ba2c117f67ae14f66e3fc7d6a1e612a25adb238cc980eadb3" dependencies = [ "shlex", ] @@ -407,9 +407,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -438,9 +438,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -517,9 +517,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1373,9 +1373,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.10" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d5b8722112fa2fa87135298780bc833b0e9f6c56cc82795d209804b3a03484" +checksum = "ebfc4febd088abdcbc9f1246896e57e37b7a34f6909840045a1767c6dafac7af" dependencies = [ "bstr", "gix-trace", @@ -1549,9 +1549,9 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" +checksum = "6cae0e8661c3ff92688ce1c8b8058b3efb312aba9492bbe93661a21705ab431b" [[package]] name = "gix-transport" @@ -1677,9 +1677,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5226a0e122dc74917f3a701484482bed3ee86d016c7356836abbaa033133a157" +checksum = "ce25b617d1375ef96eeb920ae717e3da34a02fc979fe632c75128350f9e1f74a" dependencies = [ "log", "pest", @@ -1807,9 +1807,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", @@ -1882,9 +1882,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.39.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" +checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" dependencies = [ "console", "lazy_static", @@ -2247,9 +2247,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" dependencies = [ "memchr", "thiserror", @@ -2258,9 +2258,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" dependencies = [ "pest", "pest_generator", @@ -2268,9 +2268,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" dependencies = [ "pest", "pest_meta", @@ -2281,9 +2281,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" dependencies = [ "once_cell", "pest", @@ -2698,9 +2698,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" dependencies = [ "bitflags 2.6.0", "errno", @@ -2791,18 +2791,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -2811,9 +2811,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -2910,9 +2910,9 @@ dependencies = [ [[package]] name = "similar-asserts" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" +checksum = "cfe85670573cd6f0fa97940f26e7e6601213c3b0555246c24234131f88c5709e" dependencies = [ "console", "serde", @@ -3171,9 +3171,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3284,9 +3284,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "28.1.4" +version = "28.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0247b21c545fc4aed1c877450e9750743937d5eaddc6e1f085f72c8713ab3043" +checksum = "7feb94b180de42d6fa25df8f12a71476c021c1a4114430391609471ba591d5f8" dependencies = [ "rustdoc-types 0.24.0", "trustfall", @@ -3294,9 +3294,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "29.1.4" +version = "29.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962069854192b26d8073c052e26806afd74faed02131df5e344a8ea6ca30e2a4" +checksum = "4bf958a2f4f3c8ed5f7193a2e2cf6c99eff175a3373080f622d34b78b970f891" dependencies = [ "rustdoc-types 0.25.0", "trustfall", @@ -3304,9 +3304,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "30.1.4" +version = "30.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c944186765c3c36585ff52d0d67fc02e5bc79a0ec52b96fe26d4ffe4de7dc7" +checksum = "c30e68db34f9cb6584cca09ca6de5a7163c60d85f778ceeddbe16119f0d1932a" dependencies = [ "rustdoc-types 0.26.0", "trustfall", @@ -3314,9 +3314,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "32.1.4" +version = "32.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0ed00d3646c9e22ebdf4565e21919a7b39b410839ef9e4026ac5524b60480a3" +checksum = "cc6ca1ffeb855fa81d420c15467eccc55467d3cd496e62d255611e2bc6b54500" dependencies = [ "rustdoc-types 0.28.1", "trustfall", @@ -3324,9 +3324,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "33.1.4" +version = "33.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830bc6cee8376524a6ef429ed4bf5ba1b7b4b58bfc6270e1339401c46a828135" +checksum = "6b1a982df472bd29ec24918884b0a0d50f54e7a4ed8868cfa4852c102f052883" dependencies = [ "rustdoc-types 0.29.1", "trustfall", @@ -3370,11 +3370,11 @@ dependencies = [ "serde", "serde_json", "trustfall", - "trustfall-rustdoc-adapter 28.1.4", - "trustfall-rustdoc-adapter 29.1.4", - "trustfall-rustdoc-adapter 30.1.4", - "trustfall-rustdoc-adapter 32.1.4", - "trustfall-rustdoc-adapter 33.1.4", + "trustfall-rustdoc-adapter 28.1.5", + "trustfall-rustdoc-adapter 29.1.5", + "trustfall-rustdoc-adapter 30.1.5", + "trustfall-rustdoc-adapter 32.1.5", + "trustfall-rustdoc-adapter 33.1.5", ] [[package]] From d663b44f59586f9c98a30a1b67be41c32ff39120 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Sun, 8 Sep 2024 12:19:07 -0400 Subject: [PATCH 22/22] Weekly `cargo update` of dependencies (#921) cargo update Locking 11 packages to latest compatible versions Updating cc v1.1.17 -> v1.1.18 Updating ipnet v2.9.0 -> v2.10.0 Updating jiff v0.1.12 -> v0.1.13 Updating jiff-tzdb v0.1.0 -> v0.1.1 Updating jiff-tzdb-platform v0.1.0 -> v0.1.1 Updating schannel v0.1.23 -> v0.1.24 Removing trustfall-rustdoc-adapter v28.1.5 Removing trustfall-rustdoc-adapter v29.1.5 Removing trustfall-rustdoc-adapter v30.1.5 Removing trustfall-rustdoc-adapter v32.1.5 Removing trustfall-rustdoc-adapter v33.1.5 Adding trustfall-rustdoc-adapter v28.1.6 (latest: v33.1.6) Adding trustfall-rustdoc-adapter v29.1.6 (latest: v33.1.6) Adding trustfall-rustdoc-adapter v30.1.6 (latest: v33.1.6) Adding trustfall-rustdoc-adapter v32.1.6 (latest: v33.1.6) Adding trustfall-rustdoc-adapter v33.1.6 note: pass `--verbose` to see 57 unchanged dependencies behind latest Co-authored-by: github-actions --- Cargo.lock | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac283e7e..aa543f08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -392,9 +392,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.17" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93fe60e2fc87b6ba2c117f67ae14f66e3fc7d6a1e612a25adb238cc980eadb3" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ "shlex", ] @@ -1908,9 +1908,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is_terminal_polyfill" @@ -1944,9 +1944,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiff" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437651126da47900d4d70255ab15f5c69510ca4e0d88c9f01b5b8d41a45c3a9b" +checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" dependencies = [ "jiff-tzdb-platform", "windows-sys 0.59.0", @@ -1954,15 +1954,15 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05fac328b3df1c0f18a3c2ab6cb7e06e4e549f366017d796e3e66b6d6889abe6" +checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" [[package]] name = "jiff-tzdb-platform" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8da387d5feaf355954c2c122c194d6df9c57d865125a67984bb453db5336940" +checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" dependencies = [ "jiff-tzdb", ] @@ -2767,11 +2767,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3284,9 +3284,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "28.1.5" +version = "28.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7feb94b180de42d6fa25df8f12a71476c021c1a4114430391609471ba591d5f8" +checksum = "3c75c87b6555d5d888e2d7047d820cd4586302e42e9dd881ee28800f225b82a7" dependencies = [ "rustdoc-types 0.24.0", "trustfall", @@ -3294,9 +3294,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "29.1.5" +version = "29.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf958a2f4f3c8ed5f7193a2e2cf6c99eff175a3373080f622d34b78b970f891" +checksum = "0f2c2b64014ee66c61be248d12ee8db2d6973db90b6f68046e89f13588ca3475" dependencies = [ "rustdoc-types 0.25.0", "trustfall", @@ -3304,9 +3304,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "30.1.5" +version = "30.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c30e68db34f9cb6584cca09ca6de5a7163c60d85f778ceeddbe16119f0d1932a" +checksum = "0b6a00f2f51bc5f88028ad5ef064e40a9e8af5b313d7e37834c315b681cae2f4" dependencies = [ "rustdoc-types 0.26.0", "trustfall", @@ -3314,9 +3314,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "32.1.5" +version = "32.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6ca1ffeb855fa81d420c15467eccc55467d3cd496e62d255611e2bc6b54500" +checksum = "f826c74e11761b4ef919396c16b3472ed767c81ce40ea6f234d9ba2ac79b65bd" dependencies = [ "rustdoc-types 0.28.1", "trustfall", @@ -3324,9 +3324,9 @@ dependencies = [ [[package]] name = "trustfall-rustdoc-adapter" -version = "33.1.5" +version = "33.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1a982df472bd29ec24918884b0a0d50f54e7a4ed8868cfa4852c102f052883" +checksum = "970e7763e31dffc6ee25699cde56c11a45e33c505ab4b08da5e1f4c0861e44f4" dependencies = [ "rustdoc-types 0.29.1", "trustfall", @@ -3370,11 +3370,11 @@ dependencies = [ "serde", "serde_json", "trustfall", - "trustfall-rustdoc-adapter 28.1.5", - "trustfall-rustdoc-adapter 29.1.5", - "trustfall-rustdoc-adapter 30.1.5", - "trustfall-rustdoc-adapter 32.1.5", - "trustfall-rustdoc-adapter 33.1.5", + "trustfall-rustdoc-adapter 28.1.6", + "trustfall-rustdoc-adapter 29.1.6", + "trustfall-rustdoc-adapter 30.1.6", + "trustfall-rustdoc-adapter 32.1.6", + "trustfall-rustdoc-adapter 33.1.6", ] [[package]]