From daa1e8d169711b6e2d4c42d2f867db4e5939536f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 13 Sep 2025 13:13:20 +0200 Subject: [PATCH 01/59] Add Nix flake This is required for building `openssl-sys` on NixOS --- .envrc | 1 + flake.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 26 +++++++++++++++++++++ triagebot.toml | 3 +++ 4 files changed, 91 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..7a1bac90 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1757686808, + "narHash": "sha256-PL+Z3OrNpFNHddbsBaxeojYkWObYc2NlyhTmsmpt+hc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "098982b6eca9b809cc2f583e733338f5a36b3ad8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..496ed780 --- /dev/null +++ b/flake.nix @@ -0,0 +1,26 @@ +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = + { nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + gcc + cargo + + # for openssl-sys + openssl + pkg-config + ]; + PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig"; # workaround for openssl-sys, see https://github.com/sfackler/rust-openssl/issues/1663 + }; + } + ); +} diff --git a/triagebot.toml b/triagebot.toml index f0ad6964..63b34256 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -27,3 +27,6 @@ This is just testing some functionality, please ignore this ping. label = "help wanted" [review-changes-since] + +[assign.owners] +"/flake.*" = ["@ada4a"] From f82b3c2e550cbaac39b9f817047777118f164ea9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 13 Sep 2025 13:26:35 +0200 Subject: [PATCH 02/59] parser: bump edition to 2024 Required for all the let-chains --- parser/Cargo.toml | 2 +- parser/src/token.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 307504f1..1809f1aa 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -2,7 +2,7 @@ name = "parser" version = "0.1.0" authors = ["Mark Rousskov "] -edition = "2021" +edition = "2024" [dependencies] pulldown-cmark = "0.12.0" diff --git a/parser/src/token.rs b/parser/src/token.rs index d1323eaf..ff164f0e 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -232,8 +232,8 @@ impl<'a> Tokenizer<'a> { #[cfg(test)] fn tokenize<'a>(input: &'a str) -> Result>, Error<'a>> { let mut tokens = Vec::new(); - let mut gen = Tokenizer::new(input); - while let Some(tok) = gen.next_token()? { + let mut input = Tokenizer::new(input); + while let Some(tok) = input.next_token()? { tokens.push(tok); } Ok(tokens) From deb543979aa7da1c61e64549a3a189997db47890 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:22:58 +0200 Subject: [PATCH 03/59] unused/elidable lifetimes clippy::{unused_lifetimes,elidable_lifetime_names} --- parser/src/command.rs | 2 +- parser/src/error.rs | 8 ++++---- src/actions.rs | 2 +- src/agenda.rs | 10 +++++----- src/config.rs | 2 +- src/github.rs | 2 +- src/handlers/notify_zulip.rs | 2 +- src/handlers/pr_tracking.rs | 2 +- src/zulip.rs | 10 +++++----- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/parser/src/command.rs b/parser/src/command.rs index 27b8c0fa..f81d2a39 100644 --- a/parser/src/command.rs +++ b/parser/src/command.rs @@ -201,7 +201,7 @@ impl<'a> Iterator for Input<'a> { } } -impl<'a> Command<'a> { +impl Command<'_> { pub fn is_ok(&self) -> bool { match self { Command::Relabel(r) => r.is_ok(), diff --git a/parser/src/error.rs b/parser/src/error.rs index 90d8fef0..cf94ba96 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -8,25 +8,25 @@ pub struct Error<'a> { pub source: Box, } -impl<'a> PartialEq for Error<'a> { +impl PartialEq for Error<'_> { fn eq(&self, other: &Self) -> bool { self.input == other.input && self.position == other.position } } -impl<'a> error::Error for Error<'a> { +impl error::Error for Error<'_> { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&*self.source) } } -impl<'a> Error<'a> { +impl Error<'_> { pub fn position(&self) -> usize { self.position } } -impl<'a> fmt::Display for Error<'a> { +impl fmt::Display for Error<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let space = 10; let end = std::cmp::min(self.input.len(), self.position + space); diff --git a/src/actions.rs b/src/actions.rs index 41e49ddb..31fb4843 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -103,7 +103,7 @@ pub fn to_human(d: DateTime) -> String { } #[async_trait] -impl<'a> Action for Step<'a> { +impl Action for Step<'_> { async fn call(&self) -> anyhow::Result { let mut gh = GithubClient::new_from_env(); gh.set_retry_rate_limit(true); diff --git a/src/agenda.rs b/src/agenda.rs index ac67904a..37152754 100644 --- a/src/agenda.rs +++ b/src/agenda.rs @@ -17,7 +17,7 @@ pub async fn types_planning_http() -> axum::response::Result { Ok(types_planning().call().await?) } -pub fn prioritization<'a>() -> Box { +pub fn prioritization() -> Box { Box::new(Step { name: "prioritization_agenda", actions: vec![ @@ -476,7 +476,7 @@ pub fn prioritization<'a>() -> Box { }) } -pub fn lang<'a>() -> Box { +pub fn lang() -> Box { Box::new(Step { name: "lang_agenda", actions: vec![ @@ -595,7 +595,7 @@ pub fn lang<'a>() -> Box { }) } -pub fn lang_planning<'a>() -> Box { +pub fn lang_planning() -> Box { Box::new(Step { name: "lang_planning_agenda", actions: vec![ @@ -645,7 +645,7 @@ pub fn lang_planning<'a>() -> Box { }) } -pub fn types_planning<'a>() -> Box { +pub fn types_planning() -> Box { Box::new(Step { name: "types_planning_agenda", actions: vec![ @@ -711,7 +711,7 @@ pub fn types_planning<'a>() -> Box { // Things to add (maybe): // - Compiler RFCs // - P-high issues -pub fn compiler_backlog_bonanza<'a>() -> Box { +pub fn compiler_backlog_bonanza() -> Box { Box::new(Step { name: "compiler_backlog_bonanza", actions: vec![Query { diff --git a/src/config.rs b/src/config.rs index 09d58cec..6d47bb76 100644 --- a/src/config.rs +++ b/src/config.rs @@ -548,7 +548,7 @@ impl<'de> serde::Deserialize<'de> for IssueLinksCheckCommitsConfig { { struct CheckCommitsVisitor; - impl<'de> serde::de::Visitor<'de> for CheckCommitsVisitor { + impl serde::de::Visitor<'_> for CheckCommitsVisitor { type Value = IssueLinksCheckCommitsConfig; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/github.rs b/src/github.rs index 5756de65..7e7e7d33 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2142,7 +2142,7 @@ fn quote_reply(markdown: &str) -> String { } #[async_trait] -impl<'q> IssuesQuery for Query<'q> { +impl IssuesQuery for Query<'_> { async fn query<'a>( &'a self, repo: &'a Repository, diff --git a/src/handlers/notify_zulip.rs b/src/handlers/notify_zulip.rs index d6e7b954..d021f638 100644 --- a/src/handlers/notify_zulip.rs +++ b/src/handlers/notify_zulip.rs @@ -174,7 +174,7 @@ fn has_all_required_labels(issue: &Issue, config: &NotifyZulipLabelConfig) -> bo true } -pub(super) async fn handle_input<'a>( +pub(super) async fn handle_input( ctx: &Context, config: &NotifyZulipConfig, event: &IssuesEvent, diff --git a/src/handlers/pr_tracking.rs b/src/handlers/pr_tracking.rs index 9e43cc1b..ad276fae 100644 --- a/src/handlers/pr_tracking.rs +++ b/src/handlers/pr_tracking.rs @@ -95,7 +95,7 @@ pub(super) async fn parse_input( } } -pub(super) async fn handle_input<'a>( +pub(super) async fn handle_input( ctx: &Context, _config: &ReviewPrefsConfig, event: &IssuesEvent, diff --git a/src/zulip.rs b/src/zulip.rs index 23a47721..836ff7c1 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -781,7 +781,7 @@ pub(crate) struct MessageApiRequest<'a> { pub(crate) content: &'a str, } -impl<'a> MessageApiRequest<'a> { +impl MessageApiRequest<'_> { pub fn url(&self, zulip: &ZulipClient) -> String { self.recipient.url(zulip) } @@ -799,7 +799,7 @@ pub struct UpdateMessageApiRequest<'a> { pub content: Option<&'a str>, } -impl<'a> UpdateMessageApiRequest<'a> { +impl UpdateMessageApiRequest<'_> { pub async fn send(&self, client: &ZulipClient) -> anyhow::Result<()> { client .update_message( @@ -812,10 +812,10 @@ impl<'a> UpdateMessageApiRequest<'a> { } } -async fn acknowledge<'a>( +async fn acknowledge( ctx: &Context, gh_id: u64, - ident: Identifier<'a>, + ident: Identifier<'_>, ) -> anyhow::Result> { let mut db = ctx.db.get().await; let deleted = delete_ping(&mut *db, gh_id, ident) @@ -928,7 +928,7 @@ struct AddReaction<'a> { emoji_name: &'a str, } -impl<'a> AddReaction<'a> { +impl AddReaction<'_> { pub async fn send(self, client: &ZulipClient) -> anyhow::Result<()> { client.add_reaction(self.message_id, self.emoji_name).await } From 5b2c130f69f1fb573776d6f2804e36f6f2244106 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:37:22 +0200 Subject: [PATCH 04/59] redundant refs/derefs --- parser/src/token.rs | 2 +- src/changelogs/rustc.rs | 2 +- src/config.rs | 2 +- src/db.rs | 20 ++++++++-------- src/gh_range_diff.rs | 8 +++---- src/gha_logs.rs | 3 +-- src/github.rs | 24 +++++++++---------- src/github/webhook.rs | 20 ++++++++-------- src/handlers.rs | 2 +- src/handlers/assign.rs | 22 ++++++++--------- src/handlers/check_commits.rs | 7 +++--- .../check_commits/force_push_range_diff.rs | 2 +- src/handlers/check_commits/validate_config.rs | 2 +- src/handlers/close.rs | 2 +- src/handlers/concern.rs | 14 +++++------ src/handlers/major_change.rs | 10 ++++---- src/handlers/mentions.rs | 4 ++-- src/handlers/merge_conflicts.rs | 2 +- src/handlers/milestone_prs.rs | 2 +- src/handlers/nominate.rs | 6 ++--- src/handlers/note.rs | 2 +- src/handlers/notify_zulip.rs | 4 ++-- src/handlers/ping.rs | 4 ++-- src/handlers/pr_tracking.rs | 2 +- src/handlers/project_goals.rs | 4 ++-- src/handlers/relabel.rs | 6 ++--- src/handlers/relnotes.rs | 4 ++-- src/handlers/rendered_link.rs | 2 +- src/handlers/review_submitted.rs | 2 +- src/handlers/shortcut.rs | 4 ++-- src/handlers/transfer.rs | 2 +- src/handlers/types_planning_updates.rs | 2 +- src/interactions.rs | 8 +++---- src/rfcbot.rs | 2 +- src/zulip.rs | 10 ++++---- src/zulip/client.rs | 2 +- src/zulip/commands.rs | 2 +- 37 files changed, 108 insertions(+), 110 deletions(-) diff --git a/parser/src/token.rs b/parser/src/token.rs index ff164f0e..aeeccb08 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -215,7 +215,7 @@ impl<'a> Tokenizer<'a> { } self.advance(); } - Ok(Some(Token::Word(&self.str_from(start)))) + Ok(Some(Token::Word(self.str_from(start)))) } pub fn eat_token(&mut self, token: Token<'a>) -> Result> { diff --git a/src/changelogs/rustc.rs b/src/changelogs/rustc.rs index f53dc9af..1fc21a22 100644 --- a/src/changelogs/rustc.rs +++ b/src/changelogs/rustc.rs @@ -24,7 +24,7 @@ impl<'a> RustcFormat<'a> { } pub(super) fn parse(mut self, content: &str) -> anyhow::Result { - let ast = comrak::parse_document(&self.arena, &content, &ComrakOptions::default()); + let ast = comrak::parse_document(self.arena, content, &ComrakOptions::default()); let mut section_ast = Vec::new(); for child in ast.children() { diff --git a/src/config.rs b/src/config.rs index 6d47bb76..abfdccf6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -650,7 +650,7 @@ async fn get_fresh_config( .await .map_err(|e| ConfigurationError::Http(Arc::new(e)))? .ok_or(ConfigurationError::Missing)?; - let contents = String::from_utf8_lossy(&*contents); + let contents = String::from_utf8_lossy(&contents); let config = Arc::new(toml::from_str::(&contents).map_err(ConfigurationError::Toml)?); log::debug!("fresh configuration for {}: {:?}", repo.full_name, config); Ok(config) diff --git a/src/db.rs b/src/db.rs index 9a33aac8..e50a806d 100644 --- a/src/db.rs +++ b/src/db.rs @@ -99,7 +99,7 @@ pub async fn make_client(db_url: &str) -> anyhow::Result let connector = builder.build().context("built TlsConnector")?; let connector = MakeTlsConnector::new(connector); - let (db_client, connection) = match tokio_postgres::connect(&db_url, connector).await { + let (db_client, connection) = match tokio_postgres::connect(db_url, connector).await { Ok(v) => v, Err(e) => { anyhow::bail!("failed to connect to DB: {}", e); @@ -115,7 +115,7 @@ pub async fn make_client(db_url: &str) -> anyhow::Result } else { eprintln!("Warning: Non-TLS connection to non-RDS DB"); let (db_client, connection) = - match tokio_postgres::connect(&db_url, tokio_postgres::NoTls).await { + match tokio_postgres::connect(db_url, tokio_postgres::NoTls).await { Ok(v) => v, Err(e) => { anyhow::bail!("failed to connect to DB: {}", e); @@ -225,9 +225,9 @@ pub async fn schedule_job( anyhow::bail!("Job {} does not exist in the current job list.", job_name); } - if let Err(_) = get_job_by_name_and_scheduled_at(&db, job_name, &when).await { + if let Err(_) = get_job_by_name_and_scheduled_at(db, job_name, &when).await { // mean there's no job already in the db with that name and scheduled_at - insert_job(&db, job_name, &when, &job_metadata).await?; + insert_job(db, job_name, &when, &job_metadata).await?; } Ok(()) @@ -235,20 +235,20 @@ pub async fn schedule_job( pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { let db = &ctx.db.get().await; - let jobs = get_jobs_to_execute(&db).await?; + let jobs = get_jobs_to_execute(db).await?; tracing::trace!("jobs to execute: {:#?}", jobs); for job in jobs.iter() { - update_job_executed_at(&db, &job.id).await?; + update_job_executed_at(db, &job.id).await?; - match handle_job(&ctx, &job.name, &job.metadata).await { + match handle_job(ctx, &job.name, &job.metadata).await { Ok(_) => { tracing::trace!("job successfully executed (id={})", job.id); - delete_job(&db, &job.id).await?; + delete_job(db, &job.id).await?; } Err(e) => { tracing::error!("job failed on execution (id={:?}, error={:?})", job.id, e); - update_job_error_message(&db, &job.id, &e.to_string()).await?; + update_job_error_message(db, &job.id, &e.to_string()).await?; } } } @@ -263,7 +263,7 @@ async fn handle_job( metadata: &serde_json::Value, ) -> anyhow::Result<()> { for job in jobs() { - if &job.name() == &name { + if job.name() == name { return job.run(ctx, metadata).await; } } diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 77a6ade9..38fc4101 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -170,7 +170,7 @@ pub async fn gh_ranges_diff( // Get the comparison between the oldbase..oldhead let old = async { ctx.github - .compare(&issue_repo, &oldbase, oldhead) + .compare(&issue_repo, oldbase, oldhead) .await .with_context(|| { format!("failed to retrive the comparison between {oldbase} and {oldhead}") @@ -180,7 +180,7 @@ pub async fn gh_ranges_diff( // Get the comparison between the newbase..newhead let new = async { ctx.github - .compare(&issue_repo, &newbase, newhead) + .compare(&issue_repo, newbase, newhead) .await .with_context(|| { format!("failed to retrive the comparison between {newbase} and {newhead}") @@ -193,8 +193,8 @@ pub async fn gh_ranges_diff( process_old_new( host, (&owner, &repo), - (&oldbase, oldhead, old), - (&newbase, newhead, new), + (oldbase, oldhead, old), + (newbase, newhead, new), ) } diff --git a/src/gha_logs.rs b/src/gha_logs.rs index 23061f98..570b5ee9 100644 --- a/src/gha_logs.rs +++ b/src/gha_logs.rs @@ -358,8 +358,7 @@ body {{ ); headers.insert( CONTENT_SECURITY_POLICY, - HeaderValue::from_str(&* - format!( + HeaderValue::from_str(&format!( "default-src 'none'; script-src 'nonce-{nonce}' 'self'; style-src 'unsafe-inline'; img-src 'self' www.rust-lang.org" )).unwrap(), ); diff --git a/src/github.rs b/src/github.rs index 7e7e7d33..a26cda5d 100644 --- a/src/github.rs +++ b/src/github.rs @@ -134,7 +134,7 @@ impl GithubClient { .client .execute( self.client - .get(&format!("{}/rate_limit", self.api_url)) + .get(format!("{}/rate_limit", self.api_url)) .configure(self) .build() .unwrap(), @@ -197,7 +197,7 @@ impl GithubClient { body: &'a str, labels: Vec, } - let url = format!("{}/issues", repo.url(&self)); + let url = format!("{}/issues", repo.url(self)); self.json(self.post(&url).json(&NewIssue { title, body, @@ -217,7 +217,7 @@ impl GithubClient { struct Update { state: PrState, } - let url = format!("{}/pulls/{number}", repo.url(&self)); + let url = format!("{}/pulls/{number}", repo.url(self)); self.send_req(self.patch(&url).json(&Update { state })) .await .context("failed to update pr state")?; @@ -229,7 +229,7 @@ impl GithubClient { repo: &IssueRepository, job_id: u128, ) -> anyhow::Result { - let url = format!("{}/actions/jobs/{job_id}/logs", repo.url(&self)); + let url = format!("{}/actions/jobs/{job_id}/logs", repo.url(self)); let (body, _req_dbg) = self .send_req(self.get(&url)) .await @@ -242,7 +242,7 @@ impl GithubClient { repo: &IssueRepository, job_id: u128, ) -> anyhow::Result { - let url = format!("{}/actions/jobs/{job_id}", repo.url(&self)); + let url = format!("{}/actions/jobs/{job_id}", repo.url(self)); self.json(self.get(&url)) .await .context("failed to retrive workflow job run details") @@ -253,7 +253,7 @@ impl GithubClient { repo: &IssueRepository, sha: &str, ) -> anyhow::Result { - let url = format!("{}/git/trees/{sha}", repo.url(&self)); + let url = format!("{}/git/trees/{sha}", repo.url(self)); self.json(self.get(&url)) .await .context("failed to retrive git trees") @@ -265,14 +265,14 @@ impl GithubClient { before: &str, after: &str, ) -> anyhow::Result { - let url = format!("{}/compare/{before}...{after}", repo.url(&self)); + let url = format!("{}/compare/{before}...{after}", repo.url(self)); self.json(self.get(&url)) .await .context("failed to retrive the compare") } pub async fn pull_request(&self, repo: &IssueRepository, pr_num: u64) -> anyhow::Result { - let url = format!("{}/pulls/{pr_num}", repo.url(&self)); + let url = format!("{}/pulls/{pr_num}", repo.url(self)); let mut pr: Issue = self .json(self.get(&url)) .await @@ -833,7 +833,7 @@ impl Issue { // Don't try to add labels already present on this issue. let labels = labels .into_iter() - .filter(|l| !self.labels().contains(&l)) + .filter(|l| !self.labels().contains(l)) .map(|l| l.name) .collect::>(); @@ -2152,7 +2152,7 @@ impl IssuesQuery for Query<'_> { team_client: &'a TeamClient, ) -> anyhow::Result> { let issues = repo - .get_issues(&gh_client, self) + .get_issues(gh_client, self) .await .with_context(|| "Unable to get issues.")?; @@ -2260,7 +2260,7 @@ impl IssuesQuery for Query<'_> { }; let mcp_details = if include_mcp_details { - let first100_comments = issue.get_first100_comments(&gh_client).await?; + let first100_comments = issue.get_first100_comments(gh_client).await?; let (zulip_link, concerns) = if !first100_comments.is_empty() { let split = re_zulip_link .split(&first100_comments[0].body) @@ -2346,7 +2346,7 @@ fn find_open_concerns(comments: Vec) -> Option> { // remove solved concerns and return the rest let unresolved_concerns = raised .iter() - .filter_map(|(&ref title, &ref comment_url)| { + .filter_map(|(title, comment_url)| { if !solved.contains_key(title) { Some((title.to_string(), comment_url.to_string())) } else { diff --git a/src/github/webhook.rs b/src/github/webhook.rs index 22914012..e19f5140 100644 --- a/src/github/webhook.rs +++ b/src/github/webhook.rs @@ -96,7 +96,7 @@ impl fmt::Display for EventName { } pub fn deserialize_payload(v: &str) -> anyhow::Result { - let mut deserializer = serde_json::Deserializer::from_str(&v); + let mut deserializer = serde_json::Deserializer::from_str(v); let res: Result = serde_path_to_error::deserialize(&mut deserializer); match res { Ok(r) => Ok(r), @@ -148,7 +148,7 @@ pub async fn webhook( debug!("signature={signature}"); // Check signature on body - if let Err(err) = check_payload_signed(&signature, &body) { + if let Err(err) = check_payload_signed(signature, &body) { tracing::error!("check_payload_signed: {}", err); return (StatusCode::FORBIDDEN, "Wrong signature").into_response(); } @@ -198,7 +198,7 @@ async fn process_payload( }) } EventName::PullRequestReviewComment => { - let mut payload = deserialize_payload::(&payload) + let mut payload = deserialize_payload::(payload) .context("failed to deserialize to PullRequestReviewComment")?; payload.issue.pull_request = Some(PullRequestDetails::new()); @@ -216,7 +216,7 @@ async fn process_payload( }) } EventName::IssueComment => { - let payload = deserialize_payload::(&payload) + let payload = deserialize_payload::(payload) .context("failed to deserialize IssueCommentEvent")?; log::info!("handling issue comment {:?}", payload); @@ -224,7 +224,7 @@ async fn process_payload( Event::IssueComment(payload) } EventName::Issue | EventName::PullRequest => { - let mut payload = deserialize_payload::(&payload) + let mut payload = deserialize_payload::(payload) .context("failed to deserialize IssuesEvent")?; if matches!(event, EventName::PullRequest) { @@ -236,7 +236,7 @@ async fn process_payload( Event::Issue(payload) } EventName::Push => { - let payload = deserialize_payload::(&payload) + let payload = deserialize_payload::(payload) .context("failed to deserialize to PushEvent")?; log::info!("handling push event {:?}", payload); @@ -244,7 +244,7 @@ async fn process_payload( Event::Push(payload) } EventName::Create => { - let payload = deserialize_payload::(&payload) + let payload = deserialize_payload::(payload) .context("failed to deserialize to CreateEvent")?; log::info!("handling create event {:?}", payload); @@ -256,7 +256,7 @@ async fn process_payload( return Ok(false); } }; - let errors = crate::handlers::handle(&ctx, &host, &event).await; + let errors = crate::handlers::handle(ctx, host, &event).await; let mut other_error = false; let mut message = String::new(); for err in errors { @@ -303,7 +303,7 @@ pub fn check_payload_signed(signature: &str, payload: &[u8]) -> Result<(), Signe let signature = signature .strip_prefix("sha256=") .ok_or(SignedPayloadError)?; - let signature = match hex::decode(&signature) { + let signature = match hex::decode(signature) { Ok(e) => e, Err(e) => { tracing::trace!("hex decode failed for {:?}: {:?}", signature, e); @@ -317,6 +317,6 @@ pub fn check_payload_signed(signature: &str, payload: &[u8]) -> Result<(), Signe .as_bytes(), ) .unwrap(); - mac.update(&payload); + mac.update(payload); mac.verify_slice(&signature).map_err(|_| SignedPayloadError) } diff --git a/src/handlers.rs b/src/handlers.rs index 35383ce3..0da37427 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -77,7 +77,7 @@ pub async fn handle(ctx: &Context, host: &str, event: &Event) -> Vec anyhow::Result<()> { let mut db = ctx.db.get().await; let mut state: IssueData<'_, Reviewers> = - IssueData::load(&mut db, &issue, PREVIOUS_REVIEWERS_KEY).await?; + IssueData::load(&mut db, issue, PREVIOUS_REVIEWERS_KEY).await?; // Don't re-assign if already assigned, e.g. on comment edit if issue.contain_assignee(&reviewer.name) { @@ -336,7 +336,7 @@ async fn determine_assignee( match find_reviewer_from_names( &mut db_client, ctx.workqueue.clone(), - &teams, + teams, config, &event.issue, &event.issue.user.login, @@ -360,7 +360,7 @@ async fn determine_assignee( match find_reviewer_from_names( &mut db_client, ctx.workqueue.clone(), - &teams, + teams, config, &event.issue, &event.issue.user.login, @@ -402,7 +402,7 @@ async fn determine_assignee( match find_reviewer_from_names( &mut db_client, ctx.workqueue.clone(), - &teams, + teams, config, &event.issue, &event.issue.user.login, @@ -557,7 +557,7 @@ pub(super) async fn handle_command( } AssignCommand::RequestReview { name } => { // Determine if assignee is a team. If yes, add the corresponding GH label. - if let Some(team_name) = get_team_name(&teams, &issue, &name) { + if let Some(team_name) = get_team_name(&teams, issue, &name) { let t_label = format!("T-{team_name}"); if let Err(err) = issue .add_labels(&ctx.github, vec![github::Label { name: t_label }]) @@ -605,7 +605,7 @@ pub(super) async fn handle_command( } else { let mut client = ctx.db.get().await; let mut e: EditIssueBody<'_, AssignData> = - EditIssueBody::load(&mut client, &issue, "ASSIGN").await?; + EditIssueBody::load(&mut client, issue, "ASSIGN").await?; let d = e.data_mut(); let to_assign = match cmd { @@ -633,7 +633,7 @@ pub(super) async fn handle_command( let current = &event.user().login; if issue.contain_assignee(current) { issue - .remove_assignees(&ctx.github, Selection::One(¤t)) + .remove_assignees(&ctx.github, Selection::One(current)) .await?; *d = AssignData { user: None }; e.apply(&ctx.github, String::new()).await?; @@ -995,7 +995,7 @@ async fn candidate_reviewers_from_names<'a>( let candidate = &reviewer_candidate.name; let name_lower = candidate.to_lowercase(); let is_pr_author = name_lower == issue.user.login.to_lowercase(); - let is_on_vacation = config.is_on_vacation(&candidate); + let is_on_vacation = config.is_on_vacation(candidate); let is_already_assigned = issue .assignees .iter() @@ -1139,7 +1139,7 @@ async fn candidate_reviewers_from_names<'a>( async fn get_previous_reviewer_names(db: &mut DbClient, issue: &Issue) -> HashSet { let state: IssueData<'_, Reviewers> = - match IssueData::load(db, &issue, PREVIOUS_REVIEWERS_KEY).await { + match IssueData::load(db, issue, PREVIOUS_REVIEWERS_KEY).await { Ok(state) => state, Err(_) => return HashSet::new(), }; diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index 5b69ccf3..d9e0b71d 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -138,8 +138,7 @@ pub(super) async fn handle( .days_threshold .unwrap_or(behind_upstream::DEFAULT_DAYS_THRESHOLD); - if let Some(warning) = - behind_upstream::behind_upstream(age_threshold, event, &compare).await + if let Some(warning) = behind_upstream::behind_upstream(age_threshold, event, compare).await { warnings.push(warning); } @@ -148,12 +147,12 @@ pub(super) async fn handle( // Check if this is a force-push with rebase and if it is emit comment // with link to our range-diff viewer. if let Some(range_diff) = &config.range_diff { - force_push_range_diff::handle_event(ctx, host, range_diff, &event, &compare).await?; + force_push_range_diff::handle_event(ctx, host, range_diff, event, compare).await?; } // Check if the `triagebot.toml` config is valid errors.extend( - validate_config::validate_config(ctx, &event, diff) + validate_config::validate_config(ctx, event, diff) .await .context("validating the the triagebot config")?, ); diff --git a/src/handlers/check_commits/force_push_range_diff.rs b/src/handlers/check_commits/force_push_range_diff.rs index 57c734da..67d2bd4d 100644 --- a/src/handlers/check_commits/force_push_range_diff.rs +++ b/src/handlers/check_commits/force_push_range_diff.rs @@ -43,7 +43,7 @@ pub(super) async fn handle_event( let compare_before = ctx .github - .compare(&issue_repo, &base.sha, &before) + .compare(&issue_repo, &base.sha, before) .await .context("failed to get the before compare")?; diff --git a/src/handlers/check_commits/validate_config.rs b/src/handlers/check_commits/validate_config.rs index 561297a4..50890af6 100644 --- a/src/handlers/check_commits/validate_config.rs +++ b/src/handlers/check_commits/validate_config.rs @@ -31,7 +31,7 @@ pub(super) async fn validate_config( .context("{CONFIG_FILE_NAME} modified, but failed to get content")?; let triagebot_content = triagebot_content.unwrap_or_default(); - let triagebot_content = String::from_utf8_lossy(&*triagebot_content); + let triagebot_content = String::from_utf8_lossy(&triagebot_content); match toml::from_str::(&triagebot_content) { Err(e) => { diff --git a/src/handlers/close.rs b/src/handlers/close.rs index fdb77986..084e13a6 100644 --- a/src/handlers/close.rs +++ b/src/handlers/close.rs @@ -16,7 +16,7 @@ pub(super) async fn handle_command( .await .unwrap_or(false); if !is_team_member { - let cmnt = ErrorComment::new(&issue, "Only team members can close issues."); + let cmnt = ErrorComment::new(issue, "Only team members can close issues."); cmnt.post(&ctx.github).await?; return Ok(()); } diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index ca79d54e..c124e154 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -81,7 +81,7 @@ pub(super) async fn handle_command( issue.number, issue_comment.comment.user, ); - ErrorComment::new(&issue, "Only team members in the [team repo](https://github.com/rust-lang/team) can add or resolve concerns.") + ErrorComment::new(issue, "Only team members in the [team repo](https://github.com/rust-lang/team) can add or resolve concerns.") .post(&ctx.github) .await?; return Ok(()); @@ -89,7 +89,7 @@ pub(super) async fn handle_command( let mut client = ctx.db.get().await; let mut edit: EditIssueBody<'_, ConcernData> = - EditIssueBody::load(&mut client, &issue, CONCERN_ISSUE_KEY) + EditIssueBody::load(&mut client, issue, CONCERN_ISSUE_KEY) .await .context("unable to fetch the concerns data")?; let concern_data = edit.data_mut(); @@ -154,7 +154,7 @@ pub(super) async fn handle_command( } else { for l in &config.labels { issue - .remove_label(&ctx.github, &l) + .remove_label(&ctx.github, l) .await .context("unable to remove the concern labels")?; } @@ -191,10 +191,10 @@ fn markdown_content(concerns: &[Concern], bot: &str) -> String { let _ = writeln!(md, "> # Concerns ({active_concerns} active)"); let _ = writeln!(md, ">"); - for &Concern { - ref title, - ref status, - ref comment_url, + for Concern { + title, + status, + comment_url, } in concerns { let _ = match status { diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index c3de8ac0..919f1f14 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -254,8 +254,8 @@ pub(super) async fn handle_command( .any(|l| l.name == config.enabling_label) { let cmnt = ErrorComment::new( - &issue, - &format!( + issue, + format!( "This issue cannot be seconded; it lacks the `{}` label.", config.enabling_label ), @@ -272,7 +272,7 @@ pub(super) async fn handle_command( .unwrap_or(false); if !is_team_member { - let cmnt = ErrorComment::new(&issue, "Only team members can second issues."); + let cmnt = ErrorComment::new(issue, "Only team members can second issues."); cmnt.post(&ctx.github).await?; return Ok(()); } @@ -536,7 +536,7 @@ impl Job for MajorChangeAcceptenceJob { let now = Utc::now(); - match process_seconded(&ctx, &major_change, now).await { + match process_seconded(ctx, &major_change, now).await { Ok(()) => { tracing::info!( "{}: major change ({:?}) as been accepted", @@ -686,7 +686,7 @@ async fn process_seconded( issue .post_comment( &ctx.github, - &*format!( + &format!( r#"The final comment period is now complete, this major change is now **accepted**. As the automated representative, I would like to thank the author for their work and everyone else who contributed to this major change proposal. diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 99a57bc6..b20abdf4 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -80,14 +80,14 @@ pub(super) async fn parse_input( // Only mentions byte-for-byte matching content inside the patch. files .iter() - .filter(|f| patch_adds(&f.patch, &**entry)) + .filter(|f| patch_adds(&f.patch, entry)) .map(|f| PathBuf::from(&f.filename)) .collect() } }; // Don't mention if only the author is in the list. let pings_non_author = match &cc[..] { - [only_cc] => only_cc.trim_start_matches('@') != &event.issue.user.login, + [only_cc] => only_cc.trim_start_matches('@') != event.issue.user.login, _ => true, }; if !relevant_file_paths.is_empty() && pings_non_author { diff --git a/src/handlers/merge_conflicts.rs b/src/handlers/merge_conflicts.rs index 44a8d3e5..24457b9e 100644 --- a/src/handlers/merge_conflicts.rs +++ b/src/handlers/merge_conflicts.rs @@ -243,7 +243,7 @@ async fn scan_unknowns( repo.full_name ); for unknown in unknowns { - let pr = repo.get_pr(&gh, unknown.number).await?; + let pr = repo.get_pr(gh, unknown.number).await?; // Ignore None, we don't want to repeatedly hammer GitHub asking for the answer. if pr.mergeable == Some(false) { maybe_add_comment(gh, &mut db, config, &pr, possibly.as_deref()).await?; diff --git a/src/handlers/milestone_prs.rs b/src/handlers/milestone_prs.rs index eb61b995..72adcb3d 100644 --- a/src/handlers/milestone_prs.rs +++ b/src/handlers/milestone_prs.rs @@ -87,7 +87,7 @@ async fn get_version_standalone( ) -> anyhow::Result> { let resp = gh .raw() - .get(&format!( + .get(format!( "https://raw.githubusercontent.com/rust-lang/rust/{}/src/version", merge_sha )) diff --git a/src/handlers/nominate.rs b/src/handlers/nominate.rs index 49c110a8..5ee7f193 100644 --- a/src/handlers/nominate.rs +++ b/src/handlers/nominate.rs @@ -22,7 +22,7 @@ pub(super) async fn handle_command( if !is_team_member { let cmnt = ErrorComment::new( - &event.issue().unwrap(), + event.issue().unwrap(), format!( "Nominating and approving issues and pull requests is restricted to members of\ the Rust teams." @@ -37,7 +37,7 @@ pub(super) async fn handle_command( if cmd.style == Style::BetaApprove { if !issue_labels.iter().any(|l| l.name == "beta-nominated") { let cmnt = ErrorComment::new( - &event.issue().unwrap(), + event.issue().unwrap(), format!( "This pull request is not beta-nominated, so it cannot be approved yet.\ Perhaps try to beta-nominate it by using `@{} beta-nominate `?", @@ -56,7 +56,7 @@ pub(super) async fn handle_command( } else { if !config.teams.contains_key(&cmd.team) { let cmnt = ErrorComment::new( - &event.issue().unwrap(), + event.issue().unwrap(), format!( "This team (`{}`) cannot be nominated for via this command;\ it may need to be added to `triagebot.toml` on the default branch.", diff --git a/src/handlers/note.rs b/src/handlers/note.rs index 5311f7c3..c4d387b2 100644 --- a/src/handlers/note.rs +++ b/src/handlers/note.rs @@ -128,7 +128,7 @@ pub(super) async fn handle_command( let mut client = ctx.db.get().await; let mut e: EditIssueBody<'_, NoteData> = - EditIssueBody::load(&mut client, &issue, "SUMMARY").await?; + EditIssueBody::load(&mut client, issue, "SUMMARY").await?; let current = e.data_mut(); let comment_url = String::from(event.html_url().unwrap()); diff --git a/src/handlers/notify_zulip.rs b/src/handlers/notify_zulip.rs index d021f638..0c392c14 100644 --- a/src/handlers/notify_zulip.rs +++ b/src/handlers/notify_zulip.rs @@ -62,7 +62,7 @@ fn parse_label_change_input( let mut include_config_names: Vec = vec![]; for (name, label_config) in &config.subtables { - if has_all_required_labels(&event.issue, &label_config) { + if has_all_required_labels(&event.issue, label_config) { match event.action { IssuesAction::Labeled { .. } if !label_config.messages_on_add.is_empty() => { include_config_names.push(name.to_string()); @@ -114,7 +114,7 @@ fn parse_open_close_reopen_input( let mut include_config_names: Vec = vec![]; for (name, label_config) in &config.subtables { - if has_all_required_labels(&event.issue, &label_config) { + if has_all_required_labels(&event.issue, label_config) { match event.action { IssuesAction::Opened if !label_config.messages_on_add.is_empty() => { include_config_names.push(name.to_string()); diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 86c361e6..0ee5f260 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -26,7 +26,7 @@ pub(super) async fn handle_command( if !is_team_member { let cmnt = ErrorComment::new( - &event.issue().unwrap(), + event.issue().unwrap(), format!("Only Rust team members can ping teams."), ); cmnt.post(&ctx.github).await?; @@ -77,7 +77,7 @@ pub(super) async fn handle_command( .await { let cmnt = ErrorComment::new( - &event.issue().unwrap(), + event.issue().unwrap(), format!("Error adding team label (`{}`): {:?}.", label, err), ); cmnt.post(&ctx.github).await?; diff --git a/src/handlers/pr_tracking.rs b/src/handlers/pr_tracking.rs index ad276fae..53ccb3a3 100644 --- a/src/handlers/pr_tracking.rs +++ b/src/handlers/pr_tracking.rs @@ -168,7 +168,7 @@ pub(super) async fn handle_input( /// Loads the workqueue (mapping of open PRs assigned to users) from GitHub pub async fn load_workqueue(client: &Octocrab) -> anyhow::Result { tracing::debug!("Loading workqueue for rust-lang/rust"); - let prs = retrieve_pull_request_assignments("rust-lang", "rust", &client).await?; + let prs = retrieve_pull_request_assignments("rust-lang", "rust", client).await?; // Aggregate PRs by user let aggregated: HashMap> = prs diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index ccdcde0a..44735f7c 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -130,7 +130,7 @@ pub async fn ping_project_goals_owners( days_threshold: i64, next_update: &str, ) -> anyhow::Result<()> { - let goals_repo = gh.repository(&RUST_PROJECT_GOALS_REPO).await?; + let goals_repo = gh.repository(RUST_PROJECT_GOALS_REPO).await?; let tracking_issues_query = github::Query { filters: vec![("state", "open"), ("is", "issue")], @@ -138,7 +138,7 @@ pub async fn ping_project_goals_owners( exclude_labels: vec![], }; let issues = goals_repo - .get_issues(&gh, &tracking_issues_query) + .get_issues(gh, &tracking_issues_query) .await .with_context(|| "Unable to get issues.")?; diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index 31c5908e..1a7d223e 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -28,7 +28,7 @@ pub(super) async fn handle_command( let mut to_add = vec![]; for delta in &input.0 { let name = delta.label().as_str(); - let err = match check_filter(name, config, is_member(&event.user(), &ctx.team).await) { + let err = match check_filter(name, config, is_member(event.user(), &ctx.team).await) { Ok(CheckFilterResult::Allow) => None, Ok(CheckFilterResult::Deny) => Some(format!( "Label {} can only be set by Rust team members", @@ -42,7 +42,7 @@ pub(super) async fn handle_command( Err(err) => Some(err), }; if let Some(msg) = err { - let cmnt = ErrorComment::new(&event.issue().unwrap(), msg); + let cmnt = ErrorComment::new(event.issue().unwrap(), msg); cmnt.post(&ctx.github).await?; return Ok(()); } @@ -55,7 +55,7 @@ pub(super) async fn handle_command( LabelDelta::Remove(label) => { results.push(( label, - event.issue().unwrap().remove_label(&ctx.github, &label), + event.issue().unwrap().remove_label(&ctx.github, label), )); } } diff --git a/src/handlers/relnotes.rs b/src/handlers/relnotes.rs index 154e9983..42938d07 100644 --- a/src/handlers/relnotes.rs +++ b/src/handlers/relnotes.rs @@ -115,7 +115,7 @@ If this change is notable enough for inclusion in the blog post then this sectio let resp = ctx .github .new_issue( - &e.issue.repository(), + e.issue.repository(), &title, &body, ["relnotes", "relnotes-tracking-issue"] @@ -134,7 +134,7 @@ If this change is notable enough for inclusion in the blog post then this sectio .await?; if let Some(milestone) = &e.issue.milestone { ctx.github - .set_milestone(&e.issue.repository().to_string(), &milestone, resp.number) + .set_milestone(&e.issue.repository().to_string(), milestone, resp.number) .await?; } state.data.relnotes_issue = Some(resp.number); diff --git a/src/handlers/rendered_link.rs b/src/handlers/rendered_link.rs index 646c9bde..883060e2 100644 --- a/src/handlers/rendered_link.rs +++ b/src/handlers/rendered_link.rs @@ -21,7 +21,7 @@ pub(super) async fn handle( return Ok(()); } - if let Err(e) = add_rendered_link(&ctx, &e, config).await { + if let Err(e) = add_rendered_link(ctx, e, config).await { tracing::error!("Error adding rendered link: {:?}", e); } diff --git a/src/handlers/review_submitted.rs b/src/handlers/review_submitted.rs index 92716aee..2ef84c52 100644 --- a/src/handlers/review_submitted.rs +++ b/src/handlers/review_submitted.rs @@ -24,7 +24,7 @@ pub(crate) async fn handle( if event.issue.assignees.contains(&event.comment.user) { // Remove review labels for label in &config.review_labels { - event.issue.remove_label(&ctx.github, &label).await?; + event.issue.remove_label(&ctx.github, label).await?; } // Add waiting on author event diff --git a/src/handlers/shortcut.rs b/src/handlers/shortcut.rs index 061d1697..b05babe5 100644 --- a/src/handlers/shortcut.rs +++ b/src/handlers/shortcut.rs @@ -32,7 +32,7 @@ pub(super) async fn handle_command( // NOTE: if shortcuts available to issues are created, they need to be allowed here if !issue.is_pr() { let msg = format!("The \"{:?}\" shortcut only works on pull requests.", input); - let cmnt = ErrorComment::new(&issue, msg); + let cmnt = ErrorComment::new(issue, msg); cmnt.post(&ctx.github).await?; return Ok(()); } @@ -79,7 +79,7 @@ pub(super) async fn handle_command( // Get the state of the author reminder for this PR let mut db = ctx.db.get().await; let mut state: IssueData<'_, AuthorReminderState> = - IssueData::load(&mut db, &issue, AUTHOR_REMINDER_KEY).await?; + IssueData::load(&mut db, issue, AUTHOR_REMINDER_KEY).await?; if state.data.reminder_comment.is_none() { let comment_body = format!( diff --git a/src/handlers/transfer.rs b/src/handlers/transfer.rs index 5b8593ee..5eebba27 100644 --- a/src/handlers/transfer.rs +++ b/src/handlers/transfer.rs @@ -42,7 +42,7 @@ pub(super) async fn handle_command( return Ok(()); } - if let Err(e) = issue.transfer(&ctx.github, "rust-lang", &repo).await { + if let Err(e) = issue.transfer(&ctx.github, "rust-lang", repo).await { issue .post_comment(&ctx.github, &format!("Failed to transfer issue:\n{e:?}")) .await?; diff --git a/src/handlers/types_planning_updates.rs b/src/handlers/types_planning_updates.rs index 8ede7522..69711278 100644 --- a/src/handlers/types_planning_updates.rs +++ b/src/handlers/types_planning_updates.rs @@ -100,7 +100,7 @@ pub async fn request_updates( exclude_labels: vec![], }; let issues = types_repo - .get_issues(&gh, &tracking_issues_query) + .get_issues(gh, &tracking_issues_query) .await .with_context(|| "Unable to get issues.")?; diff --git a/src/interactions.rs b/src/interactions.rs index 387263a0..1bcfe213 100644 --- a/src/interactions.rs +++ b/src/interactions.rs @@ -108,16 +108,16 @@ where let end_idx = start_idx + all_new.len(); current_body.replace_range(start_idx..end_idx, ""); } - self.issue.edit_body(&client, ¤t_body).await?; + self.issue.edit_body(client, ¤t_body).await?; } else { - let end_idx = current_body.find(&END_BOT).unwrap(); + let end_idx = current_body.find(END_BOT).unwrap(); current_body.insert_str(end_idx, &bot_section); - self.issue.edit_body(&client, ¤t_body).await?; + self.issue.edit_body(client, ¤t_body).await?; } } else { let new_body = format!("{}{}", current_body, all_new); - self.issue.edit_body(&client, &new_body).await?; + self.issue.edit_body(client, &new_body).await?; } // Save the state in the database diff --git a/src/rfcbot.rs b/src/rfcbot.rs index 9d1bb1c1..60de6e7b 100644 --- a/src/rfcbot.rs +++ b/src/rfcbot.rs @@ -69,7 +69,7 @@ pub struct FullFCP { } pub async fn get_all_fcps() -> anyhow::Result> { - let url = Url::parse(&"https://rfcbot.rs/api/all")?; + let url = Url::parse("https://rfcbot.rs/api/all")?; let res = reqwest::get(url).await?.json::>().await?; let mut map: HashMap = HashMap::new(); for full_fcp in res.into_iter() { diff --git a/src/zulip.rs b/src/zulip.rs index 836ff7c1..be48f411 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -226,7 +226,7 @@ async fn handle_command<'a>( acknowledge(&ctx, gh_id, identifier.into()).await } ChatCommand::Add { url, description } => { - add_notification(&ctx, gh_id, &url, &description.join(" ")).await + add_notification(&ctx, gh_id, url, &description.join(" ")).await } ChatCommand::Move { from, to } => move_notification(&ctx, gh_id, *from, *to).await, ChatCommand::Meta { index, description } => { @@ -236,10 +236,10 @@ async fn handle_command<'a>( ChatCommand::Lookup(cmd) => lookup_cmd(&ctx, cmd).await, ChatCommand::Work(cmd) => workqueue_commands(&ctx, gh_id, cmd).await, ChatCommand::PingGoals(args) => { - ping_goals_cmd(ctx.clone(), gh_id, message_data, &args).await + ping_goals_cmd(ctx.clone(), gh_id, message_data, args).await } ChatCommand::DocsUpdate => trigger_docs_update(message_data, &ctx.zulip), - ChatCommand::TeamStats { name } => team_status_cmd(&ctx, &name).await, + ChatCommand::TeamStats { name } => team_status_cmd(&ctx, name).await, }; let output = output?; @@ -656,7 +656,7 @@ async fn lookup_cmd(ctx: &Context, cmd: &LookupCmd) -> anyhow::Result**`, so strip the // extra sigils. - let username = username.trim_matches(&['@', '*']); + let username = username.trim_matches(['@', '*']); match cmd { LookupCmd::GitHub { .. } => Ok(Some(lookup_github_username(ctx, username).await?)), @@ -818,7 +818,7 @@ async fn acknowledge( ident: Identifier<'_>, ) -> anyhow::Result> { let mut db = ctx.db.get().await; - let deleted = delete_ping(&mut *db, gh_id, ident) + let deleted = delete_ping(&mut db, gh_id, ident) .await .map_err(|e| format_err!("Failed to acknowledge {ident:?}: {e:?}."))?; diff --git a/src/zulip/client.rs b/src/zulip/client.rs index 40d16dc1..b09e6a41 100644 --- a/src/zulip/client.rs +++ b/src/zulip/client.rs @@ -169,7 +169,7 @@ impl ZulipClient { fn make_request(&self, method: Method, url: &str) -> RequestBuilder { let api_token = self.get_api_token(); self.client - .request(method, &format!("{}/api/v1/{url}", self.instance_url)) + .request(method, format!("{}/api/v1/{url}", self.instance_url)) .basic_auth(&self.bot_email, Some(api_token)) } diff --git a/src/zulip/commands.rs b/src/zulip/commands.rs index 46e54306..ddd23a68 100644 --- a/src/zulip/commands.rs +++ b/src/zulip/commands.rs @@ -125,7 +125,7 @@ pub enum IdentifierCli { impl<'a> From<&'a IdentifierCli> for Identifier<'a> { fn from(value: &'a IdentifierCli) -> Self { match value { - IdentifierCli::Url(url) => Self::Url(&url), + IdentifierCli::Url(url) => Self::Url(url), IdentifierCli::Index(index) => Self::Index(*index), IdentifierCli::All => Self::All, } From 8a7c9f78895b7d22209eae1074d679b4ca981016 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:34:29 +0200 Subject: [PATCH 05/59] clippy::uninlined_format_args --- parser/src/token.rs | 4 +- src/actions.rs | 4 +- src/changelogs/rustc.rs | 2 +- src/db.rs | 18 +++----- src/db/jobs.rs | 12 ++---- src/db/notifications.rs | 3 +- src/github.rs | 40 +++++++---------- src/github/webhook.rs | 22 +++++----- src/handlers.rs | 76 +++++++-------------------------- src/handlers/assign.rs | 13 +++--- src/handlers/autolabel.rs | 8 ++-- src/handlers/backport.rs | 2 +- src/handlers/concern.rs | 7 +-- src/handlers/github_releases.rs | 5 +-- src/handlers/major_change.rs | 6 +-- src/handlers/mentions.rs | 4 +- src/handlers/milestone_prs.rs | 15 +++---- src/handlers/notification.rs | 22 ++++------ src/handlers/notify_zulip.rs | 12 +++--- src/handlers/ping.rs | 2 +- src/handlers/project_goals.rs | 8 +--- src/handlers/relabel.rs | 30 ++++++------- src/handlers/rendered_link.rs | 2 +- src/handlers/rustc_commits.rs | 17 ++++---- src/handlers/shortcut.rs | 2 +- src/interactions.rs | 10 ++--- src/main.rs | 2 +- src/utils.rs | 2 +- src/zulip.rs | 2 +- src/zulip/api.rs | 6 +-- 30 files changed, 131 insertions(+), 227 deletions(-) diff --git a/parser/src/token.rs b/parser/src/token.rs index aeeccb08..85c49012 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -30,8 +30,8 @@ impl fmt::Display for Token<'_> { Token::ParenRight => write!(f, ")"), Token::ParenLeft => write!(f, "("), Token::EndOfLine => Ok(()), - Token::Quote(body) => write!(f, r#""{}""#, body), - Token::Word(word) => write!(f, "{}", word), + Token::Quote(body) => write!(f, r#""{body}""#), + Token::Word(word) => write!(f, "{word}"), } } } diff --git a/src/actions.rs b/src/actions.rs index 31fb4843..a52bc905 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -87,7 +87,7 @@ pub struct MCPDetails { pub static TEMPLATES: LazyLock = LazyLock::new(|| match Tera::new("templates/*") { Ok(t) => t, Err(e) => { - println!("Parsing error(s): {}", e); + println!("Parsing error(s): {e}"); ::std::process::exit(1); } }); @@ -98,7 +98,7 @@ pub fn to_human(d: DateTime) -> String { if days > 60 { format!("{} months ago", days / 30) } else { - format!("about {} days ago", days) + format!("about {days} days ago") } } diff --git a/src/changelogs/rustc.rs b/src/changelogs/rustc.rs index 1fc21a22..bf3a7026 100644 --- a/src/changelogs/rustc.rs +++ b/src/changelogs/rustc.rs @@ -69,7 +69,7 @@ impl<'a> RustcFormat<'a> { if let Some(version) = h1.split(' ').nth(1) { self.result.versions.insert(version.to_string(), content); } else { - println!("skipped version, invalid header: {}", h1); + println!("skipped version, invalid header: {h1}"); } Ok(()) diff --git a/src/db.rs b/src/db.rs index e50a806d..7ab1e7fc 100644 --- a/src/db.rs +++ b/src/db.rs @@ -107,7 +107,7 @@ pub async fn make_client(db_url: &str) -> anyhow::Result }; tokio::task::spawn(async move { if let Err(e) = connection.await { - eprintln!("database connection error: {}", e); + eprintln!("database connection error: {e}"); } }); @@ -123,7 +123,7 @@ pub async fn make_client(db_url: &str) -> anyhow::Result }; tokio::spawn(async move { if let Err(e) = connection.await { - eprintln!("database connection error: {}", e); + eprintln!("database connection error: {e}"); } }); @@ -186,13 +186,13 @@ pub async fn run_migrations(client: &mut DbClient) -> anyhow::Result<()> { .context("Cannot create migration transactin")?; tx.execute(*migration, &[]) .await - .with_context(|| format!("executing {}th migration", idx))?; + .with_context(|| format!("executing {idx}th migration"))?; tx.execute( "UPDATE database_versions SET migration_counter = $1", &[&(idx as i32 + 1)], ) .await - .with_context(|| format!("updating migration counter to {}", idx))?; + .with_context(|| format!("updating migration counter to {idx}"))?; tx.commit() .await .context("Cannot commit migration transaction")?; @@ -236,7 +236,7 @@ pub async fn schedule_job( pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { let db = &ctx.db.get().await; let jobs = get_jobs_to_execute(db).await?; - tracing::trace!("jobs to execute: {:#?}", jobs); + tracing::trace!("jobs to execute: {jobs:#?}"); for job in jobs.iter() { update_job_executed_at(db, &job.id).await?; @@ -247,7 +247,7 @@ pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { delete_job(db, &job.id).await?; } Err(e) => { - tracing::error!("job failed on execution (id={:?}, error={:?})", job.id, e); + tracing::error!("job failed on execution (id={:?}, error={e:?})", job.id); update_job_error_message(db, &job.id, &e.to_string()).await?; } } @@ -267,11 +267,7 @@ async fn handle_job( return job.run(ctx, metadata).await; } } - tracing::trace!( - "handle_job fell into default case: (name={:?}, metadata={:?})", - name, - metadata - ); + tracing::trace!("handle_job fell into default case: (name={name:?}, metadata={metadata:?})"); Ok(()) } diff --git a/src/db/jobs.rs b/src/db/jobs.rs index cc0f3e65..74f50a5a 100644 --- a/src/db/jobs.rs +++ b/src/db/jobs.rs @@ -28,7 +28,7 @@ pub async fn insert_job( scheduled_at: &DateTime, metadata: &serde_json::Value, ) -> Result<()> { - tracing::trace!("insert_job(name={})", name); + tracing::trace!("insert_job(name={name})"); db.execute( "INSERT INTO jobs (name, scheduled_at, metadata) VALUES ($1, $2, $3) @@ -52,7 +52,7 @@ pub async fn delete_job(db: &DbClient, id: &Uuid) -> Result<()> { } pub async fn update_job_error_message(db: &DbClient, id: &Uuid, message: &String) -> Result<()> { - tracing::trace!("update_job_error_message(id={})", id); + tracing::trace!("update_job_error_message(id={id})"); db.execute( "UPDATE jobs SET error_message = $2 WHERE id = $1", @@ -65,7 +65,7 @@ pub async fn update_job_error_message(db: &DbClient, id: &Uuid, message: &String } pub async fn update_job_executed_at(db: &DbClient, id: &Uuid) -> Result<()> { - tracing::trace!("update_job_executed_at(id={})", id); + tracing::trace!("update_job_executed_at(id={id})"); db.execute("UPDATE jobs SET executed_at = now() WHERE id = $1", &[&id]) .await @@ -79,11 +79,7 @@ pub async fn get_job_by_name_and_scheduled_at( name: &str, scheduled_at: &DateTime, ) -> Result { - tracing::trace!( - "get_job_by_name_and_scheduled_at(name={}, scheduled_at={})", - name, - scheduled_at - ); + tracing::trace!("get_job_by_name_and_scheduled_at(name={name}, scheduled_at={scheduled_at})"); let job = db .query_one( diff --git a/src/db/notifications.rs b/src/db/notifications.rs index 985e97ea..f66535d4 100644 --- a/src/db/notifications.rs +++ b/src/db/notifications.rs @@ -99,8 +99,7 @@ pub async fn delete_ping( ) .await .context(format!( - "Failed to delete notification with id {}", - notification_id + "Failed to delete notification with id {notification_id}" ))?; let origin_url: String = row.get(0); diff --git a/src/github.rs b/src/github.rs index a26cda5d..8281f07b 100644 --- a/src/github.rs +++ b/src/github.rs @@ -42,10 +42,10 @@ impl GithubClient { async fn send_req(&self, req: RequestBuilder) -> anyhow::Result<(Bytes, String)> { const MAX_ATTEMPTS: u32 = 2; log::debug!("send_req with {:?}", req); - let req_dbg = format!("{:?}", req); + let req_dbg = format!("{req:?}"); let req = req .build() - .with_context(|| format!("building reqwest {}", req_dbg))?; + .with_context(|| format!("building reqwest {req_dbg}"))?; let mut resp = self.client.execute(req.try_clone().unwrap()).await?; if self.retry_rate_limit { @@ -562,7 +562,7 @@ impl fmt::Display for AssignmentError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { AssignmentError::InvalidAssignee => write!(f, "invalid assignee"), - AssignmentError::Http(e) => write!(f, "cannot assign: {}", e), + AssignmentError::Http(e) => write!(f, "cannot assign: {e}"), } } } @@ -1454,7 +1454,7 @@ impl Repository { let result = client .json::(result) .await - .with_context(|| format!("failed to list issues from {}", url))?; + .with_context(|| format!("failed to list issues from {url}"))?; issues.extend(result.items); if (issues.len() as u64) < result.total_count { ordering.page += 1; @@ -1465,7 +1465,7 @@ impl Repository { issues = client .json(result) .await - .with_context(|| format!("failed to list issues from {}", url))? + .with_context(|| format!("failed to list issues from {url}"))?; } break; @@ -1503,7 +1503,7 @@ impl Repository { ) -> String { let filters = filters .iter() - .map(|(key, val)| format!("{}={}", key, val)) + .map(|(key, val)| format!("{key}={val}")) .chain(std::iter::once(format!( "labels={}", include_labels.join(",") @@ -1533,17 +1533,9 @@ impl Repository { let filters = filters .iter() .filter(|&&(key, val)| !(key == "state" && val == "all")) - .map(|(key, val)| format!("{}:{}", key, val)) - .chain( - include_labels - .iter() - .map(|label| format!("label:{}", label)), - ) - .chain( - exclude_labels - .iter() - .map(|label| format!("-label:{}", label)), - ) + .map(|(key, val)| format!("{key}:{val}")) + .chain(include_labels.iter().map(|label| format!("label:{label}"))) + .chain(exclude_labels.iter().map(|label| format!("-label:{label}"))) .chain(std::iter::once(format!("repo:{}", self.full_name))) .collect::>() .join("+"); @@ -1661,7 +1653,7 @@ impl Repository { refname: &str, sha: &str, ) -> anyhow::Result { - let url = format!("{}/git/refs/{}", self.url(client), refname); + let url = format!("{}/git/refs/{refname}", self.url(client)); client .json(client.patch(&url).json(&serde_json::json!({ "sha": sha, @@ -1723,7 +1715,7 @@ impl Repository { })?; if let Some(errors) = data.errors { - anyhow::bail!("There were graphql errors. {:?}", errors); + anyhow::bail!("There were graphql errors. {errors:?}"); } let target = data .data @@ -2581,10 +2573,10 @@ impl GithubClient { ) -> anyhow::Result> { let url = format!("{}/{repo}/{branch}/{path}", self.raw_url); let req = self.get(&url); - let req_dbg = format!("{:?}", req); + let req_dbg = format!("{req:?}"); let req = req .build() - .with_context(|| format!("failed to build request {:?}", req_dbg))?; + .with_context(|| format!("failed to build request {req_dbg:?}"))?; let resp = self.client.execute(req).await.context(req_dbg.clone())?; let status = resp.status(); let body = resp @@ -2817,7 +2809,7 @@ impl GithubClient { let req = self.get(&format!("{}/repos/{full_name}", self.api_url)); self.json(req) .await - .with_context(|| format!("{} failed to get repo", full_name)) + .with_context(|| format!("{full_name} failed to get repo")) } /// Get or create a [`Milestone`]. @@ -3022,7 +3014,7 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests { let data: cynic::GraphQlResponse = client.json(req).await?; if let Some(errors) = data.errors { - anyhow::bail!("There were graphql errors. {:?}", errors); + anyhow::bail!("There were graphql errors. {errors:?}"); } let repository = data .data @@ -3159,7 +3151,7 @@ async fn project_items_by_status( let data: cynic::GraphQlResponse = client.json(req).await?; if let Some(errors) = data.errors { - anyhow::bail!("There were graphql errors. {:?}", errors); + anyhow::bail!("There were graphql errors. {errors:?}"); } let items = data .data diff --git a/src/github/webhook.rs b/src/github/webhook.rs index e19f5140..37ffd866 100644 --- a/src/github/webhook.rs +++ b/src/github/webhook.rs @@ -149,7 +149,7 @@ pub async fn webhook( // Check signature on body if let Err(err) = check_payload_signed(signature, &body) { - tracing::error!("check_payload_signed: {}", err); + tracing::error!("check_payload_signed: {err}"); return (StatusCode::FORBIDDEN, "Wrong signature").into_response(); } @@ -163,7 +163,7 @@ pub async fn webhook( Ok(false) => ("ignored request",).into_response(), Err(err) => { tracing::error!("{err:?}"); - let body = format!("request failed: {:?}", err); + let body = format!("request failed: {err:?}"); (StatusCode::INTERNAL_SERVER_ERROR, body).into_response() } } @@ -180,7 +180,7 @@ async fn process_payload( let mut payload = deserialize_payload::(payload) .context("failed to deserialize to PullRequestReviewEvent")?; - log::info!("handling pull request review comment {:?}", payload); + log::info!("handling pull request review comment {payload:?}"); payload.pull_request.pull_request = Some(PullRequestDetails::new()); // Treat pull request review comments exactly like pull request @@ -203,7 +203,7 @@ async fn process_payload( payload.issue.pull_request = Some(PullRequestDetails::new()); - log::info!("handling pull request review comment {:?}", payload); + log::info!("handling pull request review comment {payload:?}"); // Treat pull request review comments exactly like pull request // review comments. @@ -219,7 +219,7 @@ async fn process_payload( let payload = deserialize_payload::(payload) .context("failed to deserialize IssueCommentEvent")?; - log::info!("handling issue comment {:?}", payload); + log::info!("handling issue comment {payload:?}"); Event::IssueComment(payload) } @@ -231,7 +231,7 @@ async fn process_payload( payload.issue.pull_request = Some(PullRequestDetails::new()); } - log::info!("handling issue event {:?}", payload); + log::info!("handling issue event {payload:?}"); Event::Issue(payload) } @@ -239,7 +239,7 @@ async fn process_payload( let payload = deserialize_payload::(payload) .context("failed to deserialize to PushEvent")?; - log::info!("handling push event {:?}", payload); + log::info!("handling push event {payload:?}"); Event::Push(payload) } @@ -247,7 +247,7 @@ async fn process_payload( let payload = deserialize_payload::(payload) .context("failed to deserialize to CreateEvent")?; - log::info!("handling create event {:?}", payload); + log::info!("handling create event {payload:?}"); Event::Create(payload) } @@ -268,7 +268,7 @@ async fn process_payload( message.push_str(&msg); } HandlerError::Other(err) => { - log::error!("handling event failed: {:?}", err); + log::error!("handling event failed: {err:?}"); other_error = true; } } @@ -278,7 +278,7 @@ async fn process_payload( let cmnt = ErrorComment::new(issue, message); cmnt.post(&ctx.github).await?; } else { - log::error!("handling event failed: {:?}", message); + log::error!("handling event failed: {message:?}"); } } if other_error { @@ -306,7 +306,7 @@ pub fn check_payload_signed(signature: &str, payload: &[u8]) -> Result<(), Signe let signature = match hex::decode(signature) { Ok(e) => e, Err(e) => { - tracing::trace!("hex decode failed for {:?}: {:?}", signature, e); + tracing::trace!("hex decode failed for {signature:?}: {e:?}"); return Err(SignedPayloadError); } }; diff --git a/src/handlers.rs b/src/handlers.rs index 0da37427..20edf2c6 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -21,7 +21,7 @@ impl std::error::Error for HandlerError {} impl fmt::Display for HandlerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - HandlerError::Message(msg) => write!(f, "{}", msg), + HandlerError::Message(msg) => write!(f, "{msg}"), HandlerError::Other(_) => write!(f, "An internal error occurred."), } } @@ -78,72 +78,40 @@ pub async fn handle(ctx: &Context, host: &str, event: &Event) -> Vec Vec Vec Vec Vec Some(exclude_glob), Err(error) => { - log::error!("Invalid glob pattern: {}", error); + log::error!("Invalid glob pattern: {error}"); None } }) @@ -170,7 +168,7 @@ pub(super) async fn parse_input( .filter_map(|label| match glob::Pattern::new(label) { Ok(exclude_glob) => Some(exclude_glob), Err(error) => { - log::error!("Invalid glob pattern: {}", error); + log::error!("Invalid glob pattern: {error}"); None } }) diff --git a/src/handlers/backport.rs b/src/handlers/backport.rs index 51a2bd4d..edfff342 100644 --- a/src/handlers/backport.rs +++ b/src/handlers/backport.rs @@ -156,7 +156,7 @@ pub(super) async fn handle_input( // Add backport nomination label to the pull request for issue in issues { if let Err(ref err) = issue { - log::warn!("Failed to get issue: {:?}", err); + log::warn!("Failed to get issue: {err:?}"); continue; } let issue = issue.context("failed to get issue")?; diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index c124e154..f8f966e7 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -60,10 +60,7 @@ pub(super) async fn handle_command( } } Err(err) => { - tracing::warn!( - "unable to fetch rfcbot active FCPs: {:?}, skipping check", - err - ); + tracing::warn!("unable to fetch rfcbot active FCPs: {err:?}, skipping check"); } } @@ -144,7 +141,7 @@ pub(super) async fn handle_command( ) .await { - tracing::error!("unable to add concern labels: {:?}", err); + tracing::error!("unable to add concern labels: {err:?}"); let labels = config.labels.join(", "); issue.post_comment( &ctx.github, diff --git a/src/handlers/github_releases.rs b/src/handlers/github_releases.rs index d9ecbffa..eec00d24 100644 --- a/src/handlers/github_releases.rs +++ b/src/handlers/github_releases.rs @@ -107,10 +107,7 @@ pub(super) async fn handle( log::debug!("sleeping for one second to avoid hitting any rate limit"); tokio::time::sleep(Duration::from_secs(1)).await; } else { - log::trace!( - "skipping tag {} since it doesn't have a changelog entry", - tag - ); + log::trace!("skipping tag {tag} since it doesn't have a changelog entry"); } } diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index 919f1f14..d274ed2c 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -180,8 +180,7 @@ pub(super) async fn handle_input( } .url(&ctx.zulip); let breadcrumb_comment = format!( - "The associated GitHub issue has been renamed. Please see the [renamed Zulip topic]({}).", - new_topic_url + "The associated GitHub issue has been renamed. Please see the [renamed Zulip topic]({new_topic_url})." ); let zulip_send_breadcrumb_req = crate::zulip::MessageApiRequest { recipient: Recipient::Stream { @@ -407,9 +406,8 @@ See documentation at [https://forge.rust-lang.org](https://forge.rust-lang.org/c {} -[stream]: {}"#, +[stream]: {topic_url}"#, config.open_extra_text.as_deref().unwrap_or_default(), - topic_url ); issue .post_comment(&ctx.github, &comment) diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index b20abdf4..762dffcf 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -56,9 +56,7 @@ pub(super) async fn parse_input( .issue .diff(&ctx.github) .await - .map_err(|e| { - log::error!("failed to fetch diff: {:?}", e); - }) + .map_err(|e| log::error!("failed to fetch diff: {e:?}")) .unwrap_or_default() { let file_paths: Vec<_> = files.iter().map(|fd| Path::new(&fd.filename)).collect(); diff --git a/src/handlers/milestone_prs.rs b/src/handlers/milestone_prs.rs index 72adcb3d..cfba4bc4 100644 --- a/src/handlers/milestone_prs.rs +++ b/src/handlers/milestone_prs.rs @@ -46,12 +46,12 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let version = if let Some(version) = get_version_standalone(&ctx.github, merge_sha).await? { version } else { - log::error!("could not find the version of {:?}", merge_sha); + log::error!("could not find the version of {merge_sha:?}"); return Ok(()); }; if !version.starts_with("1.") && version.len() < 8 { - log::error!("Weird version {:?} for {:?}", version, merge_sha); + log::error!("Weird version {version:?} for {merge_sha:?}"); return Ok(()); } @@ -88,28 +88,25 @@ async fn get_version_standalone( let resp = gh .raw() .get(format!( - "https://raw.githubusercontent.com/rust-lang/rust/{}/src/version", - merge_sha + "https://raw.githubusercontent.com/rust-lang/rust/{merge_sha}/src/version" )) .send() .await - .with_context(|| format!("retrieving src/version for {}", merge_sha))?; + .with_context(|| format!("retrieving src/version for {merge_sha}"))?; match resp.status() { StatusCode::OK => {} // Don't treat a 404 as a failure, we'll try another way to retrieve the version. StatusCode::NOT_FOUND => return Ok(None), status => anyhow::bail!( - "unexpected status code {} while retrieving src/version for {}", - status, - merge_sha + "unexpected status code {status} while retrieving src/version for {merge_sha}" ), } Ok(Some( resp.text() .await - .with_context(|| format!("deserializing src/version for {}", merge_sha))? + .with_context(|| format!("deserializing src/version for {merge_sha}"))? .trim() .to_string(), )) diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index d3cbc1fd..a913edf2 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -74,10 +74,10 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { } Ok(None) => {} Err(err) => { - log::error!("Failed to query ID for {:?}: {:?}", event.user(), err); + log::error!("Failed to query ID for {:?}: {err:?}", event.user()); } } - log::trace!("Captured usernames in comment: {:?}", caps); + log::trace!("Captured usernames in comment: {caps:?}"); for login in caps { let (users, team_name) = match id_from_user(ctx, login).await? { Some((users, team_name)) => (users, team_name), @@ -95,7 +95,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { .await .context("failed to record username") { - log::error!("record username: {:?}", err); + log::error!("record username: {err:?}"); } if let Err(err) = notifications::record_ping( @@ -112,7 +112,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { .await .context("failed to record ping") { - log::error!("record ping: {:?}", err); + log::error!("record ping: {err:?}"); } } } @@ -142,18 +142,14 @@ async fn id_from_user( // error, but should be investigated). Otherwise it's probably not going to be in // the team repository so isn't actually an error. if login.starts_with("rust") { - log::error!("team ping ({}) failed to resolve to a known team", login); + log::error!("team ping ({login}) failed to resolve to a known team"); } else { - log::info!("team ping ({}) failed to resolve to a known team", login); + log::info!("team ping ({login}) failed to resolve to a known team"); } return Ok(None); } Err(err) => { - log::error!( - "team ping ({}) failed to resolve to a known team: {:?}", - login, - err - ); + log::error!("team ping ({login}) failed to resolve to a known team: {err:?}",); return Ok(None); } }; @@ -173,10 +169,10 @@ async fn id_from_user( .team .get_gh_id_from_username(login) .await - .with_context(|| format!("failed to get user {} ID", login))?; + .with_context(|| format!("failed to get user {login} ID"))?; let Some(id) = id else { // If the user was not in the team(s) then just don't record it. - log::trace!("Skipping {} because no id found", login); + log::trace!("Skipping {login} because no id found"); return Ok(None); }; Ok(Some(( diff --git a/src/handlers/notify_zulip.rs b/src/handlers/notify_zulip.rs index 0c392c14..fc53b9d0 100644 --- a/src/handlers/notify_zulip.rs +++ b/src/handlers/notify_zulip.rs @@ -162,7 +162,7 @@ fn has_all_required_labels(issue: &Issue, config: &NotifyZulipLabelConfig) -> bo let pattern = match glob::Pattern::new(req_label) { Ok(pattern) => pattern, Err(err) => { - log::error!("Invalid glob pattern: {}", err); + log::error!("Invalid glob pattern: {err}"); continue; } }; @@ -227,7 +227,7 @@ pub(super) async fn handle_input( .await; if let Err(err) = req { - log::error!("Failed to send notification to Zulip {}", err); + log::error!("Failed to send notification to Zulip {err}"); } } } @@ -259,7 +259,7 @@ fn replace_team_to_be_nominated(labels: &[Label], msg: String) -> String { #[test] fn test_notification() { let mut msg = replace_team_to_be_nominated(&[], "Needs `I-{team}-nominated`?".to_string()); - assert!(msg.contains("Needs `I-{team}-nominated`?"), "{}", msg); + assert!(msg.contains("Needs `I-{team}-nominated`?"), "{msg}"); msg = replace_team_to_be_nominated( &[Label { @@ -267,7 +267,7 @@ fn test_notification() { }], "Needs `I-{team}-nominated`?".to_string(), ); - assert!(msg.contains("I-cooks-nominated"), "{}", msg); + assert!(msg.contains("I-cooks-nominated"), "{msg}"); msg = replace_team_to_be_nominated( &[ @@ -283,7 +283,7 @@ fn test_notification() { ], "Needs `I-{team}-nominated`?".to_string(), ); - assert!(msg.contains("I-compiler-nominated"), "{}", msg); + assert!(msg.contains("I-compiler-nominated"), "{msg}"); msg = replace_team_to_be_nominated( &[ @@ -296,5 +296,5 @@ fn test_notification() { ], "Needs `I-{team}-nominated`?".to_string(), ); - assert!(msg.contains("Needs `I-{team}-nominated`?"), "{}", msg); + assert!(msg.contains("Needs `I-{team}-nominated`?"), "{msg}"); } diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 0ee5f260..f76fd510 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -78,7 +78,7 @@ pub(super) async fn handle_command( { let cmnt = ErrorComment::new( event.issue().unwrap(), - format!("Error adding team label (`{}`): {:?}.", label, err), + format!("Error adding team label (`{label}`): {err:?}."), ); cmnt.post(&ctx.github).await?; } diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index 44735f7c..bee33e6d 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -62,15 +62,11 @@ pub async fn check_project_goal_acl(team_client: &TeamClient, gh_id: u64) -> any let team = match team_client.get_team(GOALS_TEAM).await { Ok(Some(team)) => team, Ok(None) => { - log::info!("team ({}) failed to resolve to a known team", GOALS_TEAM); + log::info!("team ({GOALS_TEAM}) failed to resolve to a known team"); return Ok(false); } Err(err) => { - log::error!( - "team ({}) failed to resolve to a known team: {:?}", - GOALS_TEAM, - err - ); + log::error!("team ({GOALS_TEAM}) failed to resolve to a known team: {err:?}"); return Ok(false); } }; diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index 1a7d223e..a496dc7e 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -30,14 +30,12 @@ pub(super) async fn handle_command( let name = delta.label().as_str(); let err = match check_filter(name, config, is_member(event.user(), &ctx.team).await) { Ok(CheckFilterResult::Allow) => None, - Ok(CheckFilterResult::Deny) => Some(format!( - "Label {} can only be set by Rust team members", - name - )), + Ok(CheckFilterResult::Deny) => { + Some(format!("Label {name} can only be set by Rust team members")) + } Ok(CheckFilterResult::DenyUnknown) => Some(format!( - "Label {} can only be set by Rust team members;\ - we were unable to check if you are a team member.", - name + "Label {name} can only be set by Rust team members;\ + we were unable to check if you are a team member." )), Err(err) => Some(err), }; @@ -68,10 +66,8 @@ pub(super) async fn handle_command( .await { tracing::error!( - "failed to add {:?} from issue {}: {:?}", - to_add, - event.issue().unwrap().global_id(), - e + "failed to add {to_add:?} from issue {issue}: {e:?}", + issue = event.issue().unwrap().global_id(), ); if let Some(err @ UnknownLabels { .. }) = e.downcast_ref() { event @@ -87,10 +83,8 @@ pub(super) async fn handle_command( for (label, res) in results { if let Err(e) = res.await { tracing::error!( - "failed to remove {:?} from issue {}: {:?}", - label, - event.issue().unwrap().global_id(), - e + "failed to remove {label:?} from issue {issue}: {e:?}", + issue = event.issue().unwrap().global_id(), ); return Err(e); } @@ -111,7 +105,7 @@ async fn is_member(user: &github::User, client: &TeamClient) -> TeamMembership { Ok(true) => TeamMembership::Member, Ok(false) => TeamMembership::Outsider, Err(err) => { - eprintln!("failed to check team membership: {:?}", err); + eprintln!("failed to check team membership: {err:?}"); TeamMembership::Unknown } } @@ -143,8 +137,8 @@ fn check_filter( } Ok(MatchPatternResult::NoMatch) => {} Err(err) => { - eprintln!("failed to match pattern {}: {}", pattern, err); - return Err(format!("failed to match pattern {}", pattern)); + eprintln!("failed to match pattern {pattern}: {err}"); + return Err(format!("failed to match pattern {pattern}")); } } } diff --git a/src/handlers/rendered_link.rs b/src/handlers/rendered_link.rs index 883060e2..b0c3a428 100644 --- a/src/handlers/rendered_link.rs +++ b/src/handlers/rendered_link.rs @@ -22,7 +22,7 @@ pub(super) async fn handle( } if let Err(e) = add_rendered_link(ctx, e, config).await { - tracing::error!("Error adding rendered link: {:?}", e); + tracing::error!("Error adding rendered link: {e:?}"); } Ok(()) diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index cbc0c0b2..89e72f2e 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -48,7 +48,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let (start, end) = if let (Some(start), Some(end)) = (start, end) { (start, end) } else { - log::warn!("Unable to extract build completion from comment {:?}", body); + log::warn!("Unable to extract build completion from comment {body:?}"); return Ok(()); }; @@ -56,16 +56,15 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { Ok(bors) => bors, Err(e) => { log::error!( - "failed to parse build completion from {:?}: {:?}", - &body[start..end], - e + "failed to parse build completion from {:?}: {e:?}", + &body[start..end] ); return Ok(()); } }; if bors.type_ != "BuildCompleted" { - log::trace!("Not build completion? {:?}", bors); + log::trace!("Not build completion? {bors:?}"); } if bors.base_ref != event.repository.default_branch { @@ -80,7 +79,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { /// Fetch commits that are not present in the database. async fn synchronize_commits(ctx: &Context, sha: &str, pr: u32) { - log::trace!("synchronize_commits for sha={:?}, pr={}", sha, pr); + log::trace!("synchronize_commits for sha={sha:?}, pr={pr}"); synchronize_commits_inner(ctx, Some((sha.to_owned(), pr))).await; } @@ -99,7 +98,7 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u .into_iter() .map(|c| (c, None::)), ); - log::info!("synchronize_commits for {:?}", to_be_resolved); + log::info!("synchronize_commits for {to_be_resolved:?}"); let db = ctx.db.get().await; while let Some((sha, mut pr)) = to_be_resolved.pop_front() { @@ -125,7 +124,7 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u let pr = match pr.take() { Some(number) => number, None => { - log::warn!("Failed to find PR number for commit {}", sha); + log::warn!("Failed to find PR number for commit {sha}"); continue; } }; @@ -146,7 +145,7 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u to_be_resolved.push_back((parent_sha, None)) } } - Err(e) => log::error!("Failed to record commit {:?}", e), + Err(e) => log::error!("Failed to record commit {e:?}"), } } } diff --git a/src/handlers/shortcut.rs b/src/handlers/shortcut.rs index b05babe5..36e75cc7 100644 --- a/src/handlers/shortcut.rs +++ b/src/handlers/shortcut.rs @@ -31,7 +31,7 @@ pub(super) async fn handle_command( let issue = event.issue().unwrap(); // NOTE: if shortcuts available to issues are created, they need to be allowed here if !issue.is_pr() { - let msg = format!("The \"{:?}\" shortcut only works on pull requests.", input); + let msg = format!("The \"{input:?}\" shortcut only works on pull requests."); let cmnt = ErrorComment::new(issue, msg); cmnt.post(&ctx.github).await?; return Ok(()); diff --git a/src/interactions.rs b/src/interactions.rs index 1bcfe213..f8abc3cb 100644 --- a/src/interactions.rs +++ b/src/interactions.rs @@ -93,9 +93,9 @@ where let start_section = self.start_section(); let end_section = self.end_section(); - let bot_section = format!("{}{}{}", start_section, text, end_section); - let empty_bot_section = format!("{}{}", start_section, end_section); - let all_new = format!("\n\n{}{}{}", START_BOT, bot_section, END_BOT); + let bot_section = format!("{start_section}{text}{end_section}"); + let empty_bot_section = format!("{start_section}{end_section}"); + let all_new = format!("\n\n{START_BOT}{bot_section}{END_BOT}"); // Edit or add the new text the current triagebot section if current_body.contains(START_BOT) { @@ -115,7 +115,7 @@ where self.issue.edit_body(client, ¤t_body).await?; } } else { - let new_body = format!("{}{}", current_body, all_new); + let new_body = format!("{current_body}{all_new}"); self.issue.edit_body(client, &new_body).await?; } @@ -144,7 +144,7 @@ where let end_idx = all.find(&end)?; let text = &all[(start_idx + start.len())..end_idx]; Some(serde_json::from_str(text).unwrap_or_else(|e| { - panic!("deserializing data {:?} failed: {:?}", text, e); + panic!("deserializing data {text:?} failed: {e:?}"); })) } diff --git a/src/main.rs b/src/main.rs index 0a64ee53..d5272a65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -154,7 +154,7 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> { .layer(HandleErrorLayer::new(|err: BoxError| async move { ( StatusCode::INTERNAL_SERVER_ERROR, - format!("Unhandled error: {}", err), + format!("Unhandled error: {err}"), ) })) .layer(BufferLayer::new(5)) diff --git a/src/utils.rs b/src/utils.rs index d737605f..9effca4c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,7 +12,7 @@ pub fn pluralize(text: &str, count: usize) -> Cow<'_, str> { if count == 1 { text.into() } else { - format!("{}s", text).into() + format!("{text}s").into() } } diff --git a/src/zulip.rs b/src/zulip.rs index be48f411..9f70ebb3 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -836,7 +836,7 @@ async fn acknowledge( deleted.origin_url, deleted .metadata - .map_or(String::new(), |m| format!(" ({})", m)), + .map_or(String::new(), |m| format!(" ({m})")), )); } resp diff --git a/src/zulip/api.rs b/src/zulip/api.rs index ca7d5a3b..e624f6ef 100644 --- a/src/zulip/api.rs +++ b/src/zulip/api.rs @@ -74,14 +74,14 @@ impl Recipient<'_> { let mut encoded_topic = String::new(); for ch in topic.bytes() { if !(ALWAYS_SAFE.contains(ch as char)) { - write!(encoded_topic, ".{:02X}", ch).unwrap(); + write!(encoded_topic, ".{ch:02X}").unwrap(); } else { encoded_topic.push(ch as char); } } - format!("stream/{}-xxx/topic/{}", id, encoded_topic) + format!("stream/{id}-xxx/topic/{encoded_topic}") } - Recipient::Private { id, .. } => format!("pm-with/{}-xxx", id), + Recipient::Private { id, .. } => format!("pm-with/{id}-xxx"), } } From b0947571f6203b07807287751c601da7bcd41cf2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:49:22 +0200 Subject: [PATCH 06/59] clippy::if_not_else --- parser/src/command/nominate.rs | 12 +++++------- src/github.rs | 18 +++++++++--------- src/handlers/assign.rs | 8 ++++---- src/handlers/concern.rs | 12 ++++++------ src/handlers/major_change.rs | 10 +++++----- src/handlers/project_goals.rs | 6 +++--- src/zulip/api.rs | 6 +++--- src/zulip/client.rs | 8 ++++---- 8 files changed, 39 insertions(+), 41 deletions(-) diff --git a/parser/src/command/nominate.rs b/parser/src/command/nominate.rs index e8bea584..3a26f05d 100644 --- a/parser/src/command/nominate.rs +++ b/parser/src/command/nominate.rs @@ -60,14 +60,12 @@ impl NominateCommand { None | Some(_) => return Ok(None), }; toks.next_token()?; - let team = if style != Style::BetaApprove { - if let Some(Token::Word(team)) = toks.next_token()? { - team.to_owned() - } else { - return Err(toks.error(ParseError::NoTeam)); - } - } else { + let team = if style == Style::BetaApprove { String::new() + } else if let Some(Token::Word(team)) = toks.next_token()? { + team.to_owned() + } else { + return Err(toks.error(ParseError::NoTeam)); }; if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; diff --git a/src/github.rs b/src/github.rs index 8281f07b..090f41db 100644 --- a/src/github.rs +++ b/src/github.rs @@ -846,10 +846,10 @@ impl Issue { let mut unknown_labels = vec![]; let mut known_labels = vec![]; for label in labels { - if !self.repository().has_label(client, &label).await? { - unknown_labels.push(label); - } else { + if self.repository().has_label(client, &label).await? { known_labels.push(label); + } else { + unknown_labels.push(label); } } @@ -2253,15 +2253,15 @@ impl IssuesQuery for Query<'_> { let mcp_details = if include_mcp_details { let first100_comments = issue.get_first100_comments(gh_client).await?; - let (zulip_link, concerns) = if !first100_comments.is_empty() { + let (zulip_link, concerns) = if first100_comments.is_empty() { + ("".to_string(), None) + } else { let split = re_zulip_link .split(&first100_comments[0].body) .collect::>(); let zulip_link = split.last().unwrap_or(&"#").to_string(); let concerns = find_open_concerns(first100_comments); (zulip_link, concerns) - } else { - ("".to_string(), None) }; Some(crate::actions::MCPDetails { @@ -2339,10 +2339,10 @@ fn find_open_concerns(comments: Vec) -> Option> { let unresolved_concerns = raised .iter() .filter_map(|(title, comment_url)| { - if !solved.contains_key(title) { - Some((title.to_string(), comment_url.to_string())) - } else { + if solved.contains_key(title) { None + } else { + Some((title.to_string(), comment_url.to_string())) } }) .collect(); diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index beef84fe..ae894942 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -146,7 +146,10 @@ pub(super) async fn handle_input( return Ok(()); } let welcome = if let Some(custom_messages) = &config.custom_messages { - if !from_comment { + if from_comment { + // No welcome is posted if they used `r?` in the opening body. + None + } else { let mut welcome = match &assignee { Some(assignee) => custom_messages .auto_assign_someone @@ -167,9 +170,6 @@ pub(super) async fn handle_input( } } welcome - } else { - // No welcome is posted if they used `r?` in the opening body. - None } } else if matches!( event.issue.author_association, diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index f8f966e7..2be3942f 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -95,17 +95,17 @@ pub(super) async fn handle_command( match cmd { ConcernCommand::Concern { title } => { // Only add a concern if it wasn't already added, we could be in an edit - if !concern_data.concerns.iter().any(|c| c.title == title) { + if concern_data.concerns.iter().any(|c| c.title == title) { + tracing::info!( + "concern with the same name ({title}) already exists ({:?})", + &concern_data.concerns + ); + } else { concern_data.concerns.push(Concern { title, status: ConcernStatus::Active, comment_url: comment_url.to_string(), }); - } else { - tracing::info!( - "concern with the same name ({title}) already exists ({:?})", - &concern_data.concerns - ); } } ConcernCommand::Resolve { title } => concern_data diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index d274ed2c..24ac16d3 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -282,21 +282,21 @@ pub(super) async fn handle_command( false }; - let zulip_msg = if !has_concerns { + let zulip_msg = if has_concerns { format!( - "@*{}*: Proposal [#{}]({}) has been seconded, and will be approved in {} days if no objections are raised.", + "@*{}*: Proposal [#{}]({}) has been seconded, but there are unresolved concerns preventing approval, use `@{} resolve concern-name` in the GitHub thread to resolve them.", config.zulip_ping, issue.number, event.html_url().unwrap(), - config.waiting_period, + &ctx.username, ) } else { format!( - "@*{}*: Proposal [#{}]({}) has been seconded, but there are unresolved concerns preventing approval, use `@{} resolve concern-name` in the GitHub thread to resolve them.", + "@*{}*: Proposal [#{}]({}) has been seconded, and will be approved in {} days if no objections are raised.", config.zulip_ping, issue.number, event.html_url().unwrap(), - &ctx.username, + config.waiting_period, ) }; diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index bee33e6d..5fa516d1 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -185,12 +185,12 @@ pub async fn ping_project_goals_owners( log::debug!("zulip_topic_name = {zulip_topic_name:#?}"); log::debug!("message = {message:#?}"); - if !dry_run { - zulip_req.send(&zulip).await?; - } else { + if dry_run { eprintln!(); eprintln!("-- Dry Run ------------------------------------"); eprintln!("Would send to {zulip_topic_name}: {}", zulip_req.content); + } else { + zulip_req.send(zulip).await?; } } diff --git a/src/zulip/api.rs b/src/zulip/api.rs index e624f6ef..44a41319 100644 --- a/src/zulip/api.rs +++ b/src/zulip/api.rs @@ -73,10 +73,10 @@ impl Recipient<'_> { let mut encoded_topic = String::new(); for ch in topic.bytes() { - if !(ALWAYS_SAFE.contains(ch as char)) { - write!(encoded_topic, ".{ch:02X}").unwrap(); - } else { + if ALWAYS_SAFE.contains(ch as char) { encoded_topic.push(ch as char); + } else { + write!(encoded_topic, ".{ch:02X}").unwrap(); } } format!("stream/{id}-xxx/topic/{encoded_topic}") diff --git a/src/zulip/client.rs b/src/zulip/client.rs index b09e6a41..3da79e00 100644 --- a/src/zulip/client.rs +++ b/src/zulip/client.rs @@ -186,15 +186,15 @@ where { let status = response.status(); - if !status.is_success() { - let body = response.text().await.context("Zulip API request failed")?; - Err(anyhow::anyhow!(body)) - } else { + if status.is_success() { Ok(response.json::().await.with_context(|| { anyhow::anyhow!( "Failed to deserialize value of type {}", std::any::type_name::() ) })?) + } else { + let body = response.text().await.context("Zulip API request failed")?; + Err(anyhow::anyhow!(body)) } } From 659d85e2dc7d3ed21390347bd6cfcaf0a97339ec Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:27:42 +0200 Subject: [PATCH 07/59] clippy::needless_return --- parser/src/command/assign.rs | 14 +++++++------- parser/src/command/nominate.rs | 4 ++-- parser/src/command/ping.rs | 6 +++--- src/handlers/assign.rs | 2 +- src/handlers/major_change.rs | 2 +- src/handlers/relabel.rs | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/parser/src/command/assign.rs b/parser/src/command/assign.rs index 2f5941cb..ca846b6d 100644 --- a/parser/src/command/assign.rs +++ b/parser/src/command/assign.rs @@ -51,9 +51,9 @@ impl AssignCommand { if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; - return Ok(Some(AssignCommand::Claim)); + Ok(Some(AssignCommand::Claim)) } else { - return Err(toks.error(ParseError::ExpectedEnd)); + Err(toks.error(ParseError::ExpectedEnd)) } } else if let Some(Token::Word("assign")) = toks.peek_token()? { toks.next_token()?; @@ -63,22 +63,22 @@ impl AssignCommand { username: user[1..].to_owned(), })) } else { - return Err(toks.error(ParseError::MentionUser)); + Err(toks.error(ParseError::MentionUser)) } } else { - return Err(toks.error(ParseError::NoUser)); + Err(toks.error(ParseError::NoUser)) } } else if let Some(Token::Word("release-assignment" | "unclaim")) = toks.peek_token()? { toks.next_token()?; if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; - return Ok(Some(AssignCommand::ReleaseAssignment)); + Ok(Some(AssignCommand::ReleaseAssignment)) } else { - return Err(toks.error(ParseError::ExpectedEnd)); + Err(toks.error(ParseError::ExpectedEnd)) } } else { - return Ok(None); + Ok(None) } } diff --git a/parser/src/command/nominate.rs b/parser/src/command/nominate.rs index 3a26f05d..e551a66a 100644 --- a/parser/src/command/nominate.rs +++ b/parser/src/command/nominate.rs @@ -70,9 +70,9 @@ impl NominateCommand { if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; - return Ok(Some(NominateCommand { team, style })); + Ok(Some(NominateCommand { team, style })) } else { - return Err(toks.error(ParseError::ExpectedEnd)); + Err(toks.error(ParseError::ExpectedEnd)) } } } diff --git a/parser/src/command/ping.rs b/parser/src/command/ping.rs index 16089549..825d1218 100644 --- a/parser/src/command/ping.rs +++ b/parser/src/command/ping.rs @@ -47,12 +47,12 @@ impl PingCommand { if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; - return Ok(Some(PingCommand { team })); + Ok(Some(PingCommand { team })) } else { - return Err(toks.error(ParseError::ExpectedEnd)); + Err(toks.error(ParseError::ExpectedEnd)) } } else { - return Ok(None); + Ok(None) } } } diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index ae894942..3bea4288 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -1077,7 +1077,7 @@ async fn candidate_reviewers_from_names<'a>( }); } - return Ok(candidate); + Ok(candidate) }) .collect(); } diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index 24ac16d3..6e5283d9 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -98,7 +98,7 @@ pub(super) async fn parse_input( } // All other issue events are ignored - return Ok(None); + Ok(None) } pub(super) async fn handle_input( diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index a496dc7e..2cc45fe6 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -143,11 +143,11 @@ fn check_filter( } } if matched { - return Ok(CheckFilterResult::Allow); + Ok(CheckFilterResult::Allow) } else if is_member == TeamMembership::Outsider { - return Ok(CheckFilterResult::Deny); + Ok(CheckFilterResult::Deny) } else { - return Ok(CheckFilterResult::DenyUnknown); + Ok(CheckFilterResult::DenyUnknown) } } From 8df056ee79b705a68cbf524a7ad8df38279e706f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:54:20 +0200 Subject: [PATCH 08/59] explicit iterator loops --- parser/src/ignore_block.rs | 4 ++-- src/config.rs | 4 ++-- src/db.rs | 2 +- src/gh_range_diff.rs | 4 ++-- src/handlers/autolabel.rs | 2 +- src/handlers/notification.rs | 2 +- src/rfcbot.rs | 2 +- src/triage.rs | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/parser/src/ignore_block.rs b/parser/src/ignore_block.rs index f093a126..7f10106f 100644 --- a/parser/src/ignore_block.rs +++ b/parser/src/ignore_block.rs @@ -15,7 +15,7 @@ impl IgnoreBlocks { macro_rules! ignore_till_end { ($p:pat) => { let start = range.start; - while let Some((event, range)) = parser.next() { + for (event, range) in parser.by_ref() { if let Event::End($p) = event { ignore.push(start..range.end); break; @@ -36,7 +36,7 @@ impl IgnoreBlocks { Event::Start(Tag::BlockQuote(_)) => { let start = range.start; let mut count = 1; - while let Some((event, range)) = parser.next() { + for (event, range) in parser.by_ref() { if let Event::Start(Tag::BlockQuote(_)) = event { count += 1; } else if let Event::End(TagEnd::BlockQuote(_)) = event { diff --git a/src/config.rs b/src/config.rs index abfdccf6..6c121fe7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,7 +73,7 @@ impl PingConfig { return Some((team, cfg)); } - for (name, cfg) in self.teams.iter() { + for (name, cfg) in &self.teams { if cfg.alias.contains(team) { return Some((name, cfg)); } @@ -277,7 +277,7 @@ pub(crate) struct AutolabelConfig { impl AutolabelConfig { pub(crate) fn get_by_trigger(&self, trigger: &str) -> Vec<(&str, &AutolabelLabelConfig)> { let mut results = Vec::new(); - for (label, cfg) in self.labels.iter() { + for (label, cfg) in &self.labels { if cfg.trigger_labels.iter().any(|l| l == trigger) { results.push((label.as_str(), cfg)); } diff --git a/src/db.rs b/src/db.rs index 7ab1e7fc..fef1b195 100644 --- a/src/db.rs +++ b/src/db.rs @@ -238,7 +238,7 @@ pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { let jobs = get_jobs_to_execute(db).await?; tracing::trace!("jobs to execute: {jobs:#?}"); - for job in jobs.iter() { + for job in &jobs { update_job_executed_at(db, &job.id).await?; match handle_job(ctx, &job.name, &job.metadata).await { diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 38fc4101..73e19e73 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -554,7 +554,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { .collect(); // Process all before lines first - for (diff, input) in diffs_and_inputs.iter() { + for (diff, input) in &diffs_and_inputs { self.handle_hunk_line( &mut f, HunkTokenStatus::Removed, @@ -565,7 +565,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { } // Then process all after lines - for (diff, input) in diffs_and_inputs.iter() { + for (diff, input) in &diffs_and_inputs { self.handle_hunk_line( &mut f, HunkTokenStatus::Added, diff --git a/src/handlers/autolabel.rs b/src/handlers/autolabel.rs index 420f62fa..17ceca17 100644 --- a/src/handlers/autolabel.rs +++ b/src/handlers/autolabel.rs @@ -56,7 +56,7 @@ pub(super) async fn parse_input( let mut autolabels = Vec::new(); let mut to_remove = Vec::new(); - 'outer: for (label, cfg) in config.labels.iter() { + 'outer: for (label, cfg) in &config.labels { let exclude_patterns: Vec = cfg .exclude_labels .iter() diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index a913edf2..dc88de39 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -56,7 +56,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { // comment, so they don't get notified again let mut users_notified = HashSet::new(); if let Some(from) = event.comment_from() { - for login in parser::get_mentions(from).into_iter() { + for login in parser::get_mentions(from) { if let Some((users, _)) = id_from_user(ctx, login).await? { users_notified.extend(users.into_iter().map(|user| user.id)); } diff --git a/src/rfcbot.rs b/src/rfcbot.rs index 60de6e7b..e8f7b9f3 100644 --- a/src/rfcbot.rs +++ b/src/rfcbot.rs @@ -72,7 +72,7 @@ pub async fn get_all_fcps() -> anyhow::Result> { let url = Url::parse("https://rfcbot.rs/api/all")?; let res = reqwest::get(url).await?.json::>().await?; let mut map: HashMap = HashMap::new(); - for full_fcp in res.into_iter() { + for full_fcp in res { map.insert( format!( "{}:{}:{}", diff --git a/src/triage.rs b/src/triage.rs index 20335be9..b1d3fed8 100644 --- a/src/triage.rs +++ b/src/triage.rs @@ -51,7 +51,7 @@ pub async fn pulls( } let mut pulls: Vec = Vec::new(); - for base_pull in base_pulls.into_iter() { + for base_pull in base_pulls { let assignee = base_pull.assignee.map_or("".to_string(), |v| v.login); let updated_at = base_pull .updated_at From 52d527040b668c8efd72ce0ab1b8192f3f951bfb Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 20:46:52 +0200 Subject: [PATCH 09/59] clippy::useless_conversion --- src/handlers/notification.rs | 2 +- src/handlers/pr_tracking.rs | 2 +- src/zulip.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index dc88de39..aa4684aa 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -70,7 +70,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { // via the Zulip interface. match ctx.team.get_gh_id_from_username(&event.user().login).await { Ok(Some(id)) => { - users_notified.insert(id.try_into().unwrap()); + users_notified.insert(id); } Ok(None) => {} Err(err) => { diff --git a/src/handlers/pr_tracking.rs b/src/handlers/pr_tracking.rs index 53ccb3a3..e139b89e 100644 --- a/src/handlers/pr_tracking.rs +++ b/src/handlers/pr_tracking.rs @@ -238,7 +238,7 @@ pub async fn retrieve_pull_request_assignments( assignments.push(( User { login: user.login, - id: (*user.id).into(), + id: *user.id, }, pr.number, AssignedPullRequest { diff --git a/src/zulip.rs b/src/zulip.rs index 9f70ebb3..2866683b 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -199,7 +199,7 @@ async fn handle_command<'a>( .await .context("getting ID of github user")? { - Some(id) => id.try_into()?, + Some(id) => id, None => anyhow::bail!("Can only authorize for other GitHub users."), }; From 258e3b7d41b74cfe66137709ad47be433e96e712 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 20:49:56 +0200 Subject: [PATCH 10/59] simplify thanks to the previous commit --- src/zulip.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/zulip.rs b/src/zulip.rs index 2866683b..cc938c41 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -193,15 +193,12 @@ async fn handle_command<'a>( let mut impersonated = false; if let Some(&"as") = words.get(0) { if let Some(username) = words.get(1) { - let impersonated_gh_id = match ctx + let impersonated_gh_id = ctx .team .get_gh_id_from_username(username) .await .context("getting ID of github user")? - { - Some(id) => id, - None => anyhow::bail!("Can only authorize for other GitHub users."), - }; + .context("Can only authorize for other GitHub users.")?; // Impersonate => change actual gh_id if impersonated_gh_id != gh_id { From 60602d02d8adc025049836584daa6fb007b8f17d Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 13 Sep 2025 13:30:35 +0200 Subject: [PATCH 11/59] simplify `match`es clippy::{collapsible_match,unnested_or_patterns,match_same_arms} --- parser/src/command/assign.rs | 4 ++-- parser/src/command/nominate.rs | 5 ++--- parser/src/command/ping.rs | 2 +- parser/src/command/relabel.rs | 7 ++----- parser/src/mentions.rs | 16 +++++++--------- src/github.rs | 27 ++++++++++++--------------- src/handlers/assign.rs | 23 +++++++++-------------- src/handlers/nominate.rs | 6 +----- src/handlers/ping.rs | 6 +----- src/main.rs | 13 ++++++------- src/team_data.rs | 13 +++---------- src/zulip.rs | 31 +++++++++++++++---------------- 12 files changed, 61 insertions(+), 92 deletions(-) diff --git a/parser/src/command/assign.rs b/parser/src/command/assign.rs index ca846b6d..a681c5f6 100644 --- a/parser/src/command/assign.rs +++ b/parser/src/command/assign.rs @@ -48,7 +48,7 @@ impl AssignCommand { let mut toks = input.clone(); if let Some(Token::Word("claim")) = toks.peek_token()? { toks.next_token()?; - if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { + if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; Ok(Some(AssignCommand::Claim)) @@ -70,7 +70,7 @@ impl AssignCommand { } } else if let Some(Token::Word("release-assignment" | "unclaim")) = toks.peek_token()? { toks.next_token()?; - if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { + if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; Ok(Some(AssignCommand::ReleaseAssignment)) diff --git a/parser/src/command/nominate.rs b/parser/src/command/nominate.rs index e551a66a..e4346833 100644 --- a/parser/src/command/nominate.rs +++ b/parser/src/command/nominate.rs @@ -55,8 +55,7 @@ impl NominateCommand { let style = match toks.peek_token()? { Some(Token::Word("beta-nominate")) => Style::Beta, Some(Token::Word("nominate")) => Style::Decision, - Some(Token::Word("beta-accept")) => Style::BetaApprove, - Some(Token::Word("beta-approve")) => Style::BetaApprove, + Some(Token::Word("beta-accept" | "beta-approve")) => Style::BetaApprove, None | Some(_) => return Ok(None), }; toks.next_token()?; @@ -67,7 +66,7 @@ impl NominateCommand { } else { return Err(toks.error(ParseError::NoTeam)); }; - if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { + if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; Ok(Some(NominateCommand { team, style })) diff --git a/parser/src/command/ping.rs b/parser/src/command/ping.rs index 825d1218..e5423f8d 100644 --- a/parser/src/command/ping.rs +++ b/parser/src/command/ping.rs @@ -44,7 +44,7 @@ impl PingCommand { } else { return Err(toks.error(ParseError::NoTeam)); }; - if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? { + if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; Ok(Some(PingCommand { team })) diff --git a/parser/src/command/relabel.rs b/parser/src/command/relabel.rs index ef5a305c..98c55e77 100644 --- a/parser/src/command/relabel.rs +++ b/parser/src/command/relabel.rs @@ -85,8 +85,7 @@ impl LabelDelta { pub fn label(&self) -> &Label { match self { - LabelDelta::Add(l) => l, - LabelDelta::Remove(l) => l, + LabelDelta::Add(l) | LabelDelta::Remove(l) => l, } } } @@ -129,9 +128,7 @@ impl RelabelCommand { toks.eat_token(Token::Comma)?; toks.eat_token(Token::Word("and"))?; - if let Some(Token::Semi) | Some(Token::Dot) | Some(Token::EndOfLine) = - toks.peek_token()? - { + if let Some(Token::Semi | Token::Dot | Token::EndOfLine) = toks.peek_token()? { toks.next_token()?; *input = toks; return Ok(Some(RelabelCommand(deltas))); diff --git a/parser/src/mentions.rs b/parser/src/mentions.rs index 7734318b..0edeea38 100644 --- a/parser/src/mentions.rs +++ b/parser/src/mentions.rs @@ -10,15 +10,13 @@ pub fn get_mentions(input: &str) -> Vec<&str> { let mut mentions = Vec::new(); for (idx, _) in input.match_indices('@') { - if let Some(previous) = input[..idx].chars().next_back() { - // A github username must stand apart from other text. - // - // Oddly enough, english letters do not work, but letters outside - // ASCII do work as separators; for now just go with this limited - // list. - if let 'a'..='z' | 'A'..='Z' | '0'..='9' = previous { - continue; - } + // A github username must stand apart from other text. + // + // Oddly enough, english letters do not work, but letters outside + // ASCII do work as separators; for now just go with this limited + // list. + if let Some('a'..='z' | 'A'..='Z' | '0'..='9') = input[..idx].chars().next_back() { + continue; } let mut saw_slash = false; let username_end = input diff --git a/src/github.rs b/src/github.rs index 090f41db..5343c54d 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1758,24 +1758,21 @@ impl Repository { .first() .map(|parent| parent.oid.0.clone()); - match &next_first_parent { - Some(first_parent) => { - if first_parent == &node.oid.0 { - // Found the next first parent, include it and - // set next_first_parent to look for this - // commit's first parent. - next_first_parent = this_first_parent; - true - } else { - // Still looking for the next first parent. - false - } - } - None => { - // First commit. + if let Some(first_parent) = &next_first_parent { + if first_parent == &node.oid.0 { + // Found the next first parent, include it and + // set next_first_parent to look for this + // commit's first parent. next_first_parent = this_first_parent; true + } else { + // Still looking for the next first parent. + false } + } else { + // First commit. + next_first_parent = this_first_parent; + true } }) // Stop once reached the `oldest` commit diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index 3bea4288..35dc9a0d 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -374,13 +374,13 @@ async fn determine_assignee( event.issue.global_id() ), Err( - e @ FindReviewerError::NoReviewer { .. } - | e @ FindReviewerError::ReviewerIsPrAuthor { .. } - | e @ FindReviewerError::ReviewerAlreadyAssigned { .. } - | e @ FindReviewerError::ReviewerPreviouslyAssigned { .. } - | e @ FindReviewerError::ReviewerOffRotation { .. } - | e @ FindReviewerError::DatabaseError(_) - | e @ FindReviewerError::ReviewerAtMaxCapacity { .. }, + e @ (FindReviewerError::NoReviewer { .. } + | FindReviewerError::ReviewerIsPrAuthor { .. } + | FindReviewerError::ReviewerAlreadyAssigned { .. } + | FindReviewerError::ReviewerPreviouslyAssigned { .. } + | FindReviewerError::ReviewerOffRotation { .. } + | FindReviewerError::DatabaseError(_) + | FindReviewerError::ReviewerAtMaxCapacity { .. }), ) => log::trace!( "no reviewer could be determined for PR {}: {e}", event.issue.global_id() @@ -508,11 +508,7 @@ pub(super) async fn handle_command( event: &Event, cmd: AssignCommand, ) -> anyhow::Result<()> { - let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team).await { - false - } else { - true - }; + let is_team_member = matches!(event.user().is_team_member(&ctx.team).await, Ok(true)); // Don't handle commands in comments from the bot. Some of the comments it // posts contain commands to instruct the user, not things that the bot @@ -898,8 +894,7 @@ fn expand_teams_and_groups( // Loop over names to recursively expand them. while let Some(candidate) = to_be_expanded.pop() { let name_to_expand = match &candidate { - Candidate::Direct(name) => name, - Candidate::Expanded(name) => name, + Candidate::Direct(name) | Candidate::Expanded(name) => name, }; // `name_to_expand` could be a team name, an adhoc group name or a username. diff --git a/src/handlers/nominate.rs b/src/handlers/nominate.rs index 5ee7f193..66b4c0ca 100644 --- a/src/handlers/nominate.rs +++ b/src/handlers/nominate.rs @@ -14,11 +14,7 @@ pub(super) async fn handle_command( event: &Event, cmd: NominateCommand, ) -> anyhow::Result<()> { - let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team).await { - false - } else { - true - }; + let is_team_member = matches!(event.user().is_team_member(&ctx.team).await, Ok(true)); if !is_team_member { let cmnt = ErrorComment::new( diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index f76fd510..665ba100 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -18,11 +18,7 @@ pub(super) async fn handle_command( event: &Event, team_name: PingCommand, ) -> anyhow::Result<()> { - let is_team_member = if let Err(_) | Ok(false) = event.user().is_team_member(&ctx.team).await { - false - } else { - true - }; + let is_team_member = matches!(event.user().is_team_member(&ctx.team).await, Ok(true)); if !is_team_member { let cmnt = ErrorComment::new( diff --git a/src/main.rs b/src/main.rs index d5272a65..b864bad0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,15 +119,14 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> { // Log the request id as generated. let request_id = request.headers().get(REQUEST_ID_HEADER); - match request_id { - Some(request_id) => info_span!( + if let Some(request_id) = request_id { + info_span!( "request", request_id = ?request_id, - ), - None => { - tracing::error!("could not extract request_id"); - info_span!("request") - } + ) + } else { + tracing::error!("could not extract request_id"); + info_span!("request") } }) .on_request(|request: &Request, _span: &tracing::Span| { diff --git a/src/team_data.rs b/src/team_data.rs index a9ea2945..6c078c59 100644 --- a/src/team_data.rs +++ b/src/team_data.rs @@ -169,16 +169,9 @@ async fn download( for _ in 0i32..3 { let response = client.get(&url).send().await; match response { - Ok(v) => { - return Ok(v.json().await?); - } - Err(e) => { - if e.is_timeout() { - continue; - } else { - return Err(e.into()); - } - } + Ok(v) => return Ok(v.json().await?), + Err(e) if e.is_timeout() => continue, + Err(e) => return Err(e.into()), } } diff --git a/src/zulip.rs b/src/zulip.rs index cc938c41..f4399e9b 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -681,22 +681,21 @@ async fn lookup_github_username(ctx: &Context, zulip_username: &str) -> anyhow:: // Prefer what is configured on Zulip. If there is nothing, try to lookup the GitHub username // from the team database. - let github_username = match zulip_user.get_github_username() { - Some(name) => name.to_string(), - None => { - let zulip_id = zulip_user.user_id; - let Some(gh_id) = ctx.team.zulip_to_github_id(zulip_id).await? else { - return Ok(format!( - "Zulip user {zulip_username} was not found in team Zulip mapping. Maybe they do not have zulip-id configured in team." - )); - }; - let Some(username) = ctx.team.username_from_gh_id(gh_id).await? else { - return Ok(format!( - "Zulip user {zulip_username} was not found in the team database." - )); - }; - username - } + let github_username = if let Some(name) = zulip_user.get_github_username() { + name.to_string() + } else { + let zulip_id = zulip_user.user_id; + let Some(gh_id) = ctx.team.zulip_to_github_id(zulip_id).await? else { + return Ok(format!( + "Zulip user {zulip_username} was not found in team Zulip mapping. Maybe they do not have zulip-id configured in team." + )); + }; + let Some(username) = ctx.team.username_from_gh_id(gh_id).await? else { + return Ok(format!( + "Zulip user {zulip_username} was not found in the team database." + )); + }; + username }; Ok(format!( From 88731edc1661922096973b43d17cb05be383a794 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:49:34 +0200 Subject: [PATCH 12/59] use `std::iter::zip` takes up fewer lines --- src/gh_range_diff.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 73e19e73..7eac69f3 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; use std::fmt::{self, Write}; +use std::iter; use std::sync::{Arc, LazyLock}; use anyhow::Context as _; @@ -536,9 +537,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { // Same number of lines before and after, can do word-hightling. // Diff the individual lines together. - let diffs_and_inputs: Vec<_> = before - .into_iter() - .zip(after.into_iter()) + let diffs_and_inputs: Vec<_> = iter::zip(before, after) .map(|(b_token, a_token)| { // Split both lines by words and intern them. let input: InternedInput<&str> = InternedInput::new( From 82259d8ef7bcd7f8fc86dc4763ad0442654ab902 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 01:13:21 +0200 Subject: [PATCH 13/59] clippy::inefficient_to_string --- src/github.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github.rs b/src/github.rs index 5343c54d..b7c7f168 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2256,7 +2256,7 @@ impl IssuesQuery for Query<'_> { let split = re_zulip_link .split(&first100_comments[0].body) .collect::>(); - let zulip_link = split.last().unwrap_or(&"#").to_string(); + let zulip_link = (*split.last().unwrap_or(&"#")).to_string(); let concerns = find_open_concerns(first100_comments); (zulip_link, concerns) }; From ef55ea7138dde682996106340433b97d7550c4fe Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 22:20:46 +0200 Subject: [PATCH 14/59] clippy::ignored_unit_patterns --- src/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db.rs b/src/db.rs index fef1b195..251f66cb 100644 --- a/src/db.rs +++ b/src/db.rs @@ -242,7 +242,7 @@ pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { update_job_executed_at(db, &job.id).await?; match handle_job(ctx, &job.name, &job.metadata).await { - Ok(_) => { + Ok(()) => { tracing::trace!("job successfully executed (id={})", job.id); delete_job(db, &job.id).await?; } From 69cb11438de9eb5245c63006800148f7072f3ff3 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 21:59:04 +0200 Subject: [PATCH 15/59] derive `Default` for `IssueLinksCheckCommitsConfig` clippy::derivable_impls --- src/config.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/config.rs b/src/config.rs index 6c121fe7..0e12c2cd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -525,22 +525,17 @@ pub(crate) struct IssueLinksConfig { pub(crate) check_commits: IssueLinksCheckCommitsConfig, } -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug, Default)] pub(crate) enum IssueLinksCheckCommitsConfig { /// No checking of commits Off, /// Only check for uncanonicalized issue links in commits Uncanonicalized, /// Check for all issue links in commits + #[default] All, } -impl Default for IssueLinksCheckCommitsConfig { - fn default() -> Self { - IssueLinksCheckCommitsConfig::All - } -} - impl<'de> serde::Deserialize<'de> for IssueLinksCheckCommitsConfig { fn deserialize(deserializer: D) -> Result where From 8760f3677e962bf1a148c7ef2c6b8351bf4acdd4 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:45:42 +0200 Subject: [PATCH 16/59] use more idiomatic iterator/`Option` adaptors --- parser/src/token.rs | 2 +- src/gha_logs.rs | 3 +-- src/github.rs | 24 ++++++++++------------- src/handlers/assign.rs | 2 +- src/handlers/check_commits.rs | 8 ++++---- src/handlers/check_commits/issue_links.rs | 2 +- src/handlers/check_commits/no_mentions.rs | 2 +- src/handlers/notify_zulip.rs | 2 +- src/handlers/project_goals.rs | 3 +-- src/handlers/rendered_link.rs | 5 ++--- src/zulip.rs | 4 ++-- 11 files changed, 25 insertions(+), 32 deletions(-) diff --git a/parser/src/token.rs b/parser/src/token.rs index 85c49012..64f5e80a 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -125,7 +125,7 @@ impl<'a> Tokenizer<'a> { } fn cur(&mut self) -> Option<(usize, char)> { - self.chars.peek().cloned() + self.chars.peek().copied() } fn at_end(&mut self) -> bool { diff --git a/src/gha_logs.rs b/src/gha_logs.rs index 570b5ee9..cf8cb52e 100644 --- a/src/gha_logs.rs +++ b/src/gha_logs.rs @@ -138,14 +138,13 @@ pub async fn gha_logs( .tree .iter() .zip(&roots_trees) - .map(|(root, childs)| { + .flat_map(|(root, childs)| { childs .tree .iter() .filter(|t| t.object_type == "tree" || t.object_type == "blob") .map(|t| format!("{}/{}", root.path, t.path)) }) - .flatten() .collect(); // We need to sort the tree roots by descending order, otherwise `library/std` will diff --git a/src/github.rs b/src/github.rs index b7c7f168..3b4ceeef 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2213,19 +2213,15 @@ impl IssuesQuery for Query<'_> { pending_reviewers: fcp .reviews .iter() - .filter_map(|r| { - (!r.approved).then(|| crate::actions::FCPReviewerDetails { - github_login: r.reviewer.login.clone(), - zulip_id: zulip_map - .as_ref() - .map(|map| { - map.users - .iter() - .find(|&(_, &github)| github == r.reviewer.id) - .map(|v| *v.0) - }) - .flatten(), - }) + .filter(|r| !r.approved) + .map(|r| crate::actions::FCPReviewerDetails { + github_login: r.reviewer.login.clone(), + zulip_id: zulip_map.as_ref().and_then(|map| { + map.users + .iter() + .find(|&(_, &github)| github == r.reviewer.id) + .map(|(&zulip, _)| zulip) + }), }) .collect(), concerns: fcp @@ -3216,7 +3212,7 @@ impl IssuesQuery for DesignMeetings { .await?; Ok(items .into_iter() - .flat_map(|item| match item.content { + .filter_map(|item| match item.content { Some(ProjectV2ItemContent::Issue(issue)) => Some(crate::actions::IssueDecorator { assignees: String::new(), author: String::new(), diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index 35dc9a0d..eae40e5d 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -492,7 +492,7 @@ fn find_reviewers_from_diff( .map(|(path, _)| path); let mut potential: Vec<_> = max_paths .flat_map(|owner_path| &config.owners[*owner_path]) - .map(|owner| owner.to_string()) + .cloned() .collect(); // Dedupe. This isn't strictly necessary, as `find_reviewer_from_names` will deduplicate. // However, this helps with testing. diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index d9e0b71d..60fd0e2b 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -290,8 +290,8 @@ fn calculate_label_changes( previous: &Vec, current: &Vec, ) -> (Vec, Vec) { - let previous_set: HashSet = previous.into_iter().cloned().collect(); - let current_set: HashSet = current.into_iter().cloned().collect(); + let previous_set: HashSet = previous.iter().cloned().collect(); + let current_set: HashSet = current.iter().cloned().collect(); let removals = previous_set.difference(¤t_set).cloned().collect(); let additions = current_set.difference(&previous_set).cloned().collect(); @@ -304,8 +304,8 @@ fn calculate_error_changes( previous: &Vec<(String, String)>, current: &Vec, ) -> (Vec<(String, String)>, Vec) { - let previous_set: HashSet<(String, String)> = previous.into_iter().cloned().collect(); - let current_set: HashSet = current.into_iter().cloned().collect(); + let previous_set: HashSet<(String, String)> = previous.iter().cloned().collect(); + let current_set: HashSet = current.iter().cloned().collect(); let removals = previous_set .iter() diff --git a/src/handlers/check_commits/issue_links.rs b/src/handlers/check_commits/issue_links.rs index 72a08bd2..e0c9e85a 100644 --- a/src/handlers/check_commits/issue_links.rs +++ b/src/handlers/check_commits/issue_links.rs @@ -23,7 +23,7 @@ pub(super) fn issue_links_in_commits( }; let issue_links_commits = commits - .into_iter() + .iter() .filter(|c| { !MERGE_IGNORE_LIST .iter() diff --git a/src/handlers/check_commits/no_mentions.rs b/src/handlers/check_commits/no_mentions.rs index 4b4cd399..d06691d2 100644 --- a/src/handlers/check_commits/no_mentions.rs +++ b/src/handlers/check_commits/no_mentions.rs @@ -17,7 +17,7 @@ pub(super) fn mentions_in_commits( } let mentions_commits = commits - .into_iter() + .iter() .filter(|c| { let mentions = parser::get_mentions(&c.commit.message); !mentions.is_empty() && mentions.iter().any(|m| *m != "rustbot") diff --git a/src/handlers/notify_zulip.rs b/src/handlers/notify_zulip.rs index fc53b9d0..bab32bee 100644 --- a/src/handlers/notify_zulip.rs +++ b/src/handlers/notify_zulip.rs @@ -110,7 +110,7 @@ fn parse_open_close_reopen_input( .get(&label.name) .map(|config| (label, config)) }) - .flat_map(|(label, config)| { + .filter_map(|(label, config)| { let mut include_config_names: Vec = vec![]; for (name, label_config) in &config.subtables { diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index 5fa516d1..23b49962 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -74,8 +74,7 @@ pub async fn check_project_goal_acl(team_client: &TeamClient, gh_id: u64) -> any Ok(team .members .into_iter() - .find(|member| member.github_id == gh_id) - .is_some()) + .any(|member| member.github_id == gh_id)) } async fn ping_project_goals_owners_automatically( diff --git a/src/handlers/rendered_link.rs b/src/handlers/rendered_link.rs index b0c3a428..f9096775 100644 --- a/src/handlers/rendered_link.rs +++ b/src/handlers/rendered_link.rs @@ -55,7 +55,7 @@ async fn add_rendered_link( // Sort the relavant files by the total number of lines changed, as to // improve our guess for the relevant file to show the link to. .max_by_key(|f| f.additions + f.deletions + f.changes) - .map(|file| { + .and_then(|file| { let head = e.issue.head.as_ref()?; let base = e.issue.base.as_ref()?; @@ -91,8 +91,7 @@ async fn add_rendered_link( }, file.filename )) - }) - .flatten(); + }); let new_body: Cow<'_, str> = if !e.issue.body.contains("[Rendered]") { if let Some(rendered_link) = rendered_link { diff --git a/src/zulip.rs b/src/zulip.rs index f4399e9b..ece5efa3 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -207,7 +207,7 @@ async fn handle_command<'a>( } // Skip the first two arguments for the rest of CLI parsing - words = words[2..].iter().copied().collect(); + words = words[2..].to_vec(); } else { return Err(anyhow::anyhow!( "Failed to parse command; expected `as `." @@ -282,7 +282,7 @@ async fn handle_command<'a>( return Ok(Some("Unknown command".to_string())); } - let cmd = parse_cli::(words[cmd_index..].into_iter().copied())?; + let cmd = parse_cli::(words[cmd_index..].iter().copied())?; tracing::info!("command parsed to {cmd:?}"); match cmd { From 32ea01774fd837123d863fec5b7f5b8884aa53ba Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:43:50 +0200 Subject: [PATCH 17/59] clean-up consts --- src/handlers/project_goals.rs | 4 ++-- src/handlers/rustc_commits.rs | 2 +- src/handlers/types_planning_updates.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index 23b49962..f56be192 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -13,8 +13,8 @@ use chrono::{Datelike, NaiveDate, Utc}; use tracing::{self as log}; const MAX_ZULIP_TOPIC: usize = 60; -const RUST_PROJECT_GOALS_REPO: &'static str = "rust-lang/rust-project-goals"; -const GOALS_STREAM: u64 = 435869; // #project-goals +const RUST_PROJECT_GOALS_REPO: &str = "rust-lang/rust-project-goals"; +const GOALS_STREAM: u64 = 435_869; // #project-goals const C_TRACKING_ISSUE: &str = "C-tracking-issue"; fn message( diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index 89e72f2e..f60ffdf8 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use std::collections::VecDeque; use tracing as log; -const BORS_GH_ID: u64 = 3372342; +const BORS_GH_ID: u64 = 3_372_342; pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let body = match event.comment_body() { diff --git a/src/handlers/types_planning_updates.rs b/src/handlers/types_planning_updates.rs index 69711278..83f6c5a9 100644 --- a/src/handlers/types_planning_updates.rs +++ b/src/handlers/types_planning_updates.rs @@ -7,9 +7,9 @@ use async_trait::async_trait; use chrono::{Datelike, Duration, NaiveTime, TimeZone, Utc}; use serde::{Deserialize, Serialize}; -const TYPES_REPO: &'static str = "rust-lang/types-team"; +const TYPES_REPO: &str = "rust-lang/types-team"; // T-types/meetings -const TYPES_MEETINGS_STREAM: u64 = 326132; +const TYPES_MEETINGS_STREAM: u64 = 326_132; pub struct TypesPlanningMeetingThreadOpenJob; From 778ba028ff979fca6729353cef8472313a8691e6 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:35:36 +0200 Subject: [PATCH 18/59] use `let-else` --- src/github.rs | 5 ++- src/handlers/autolabel.rs | 5 ++- src/handlers/backport.rs | 5 ++- src/handlers/major_change.rs | 4 +-- src/handlers/mentions.rs | 5 ++- src/handlers/milestone_prs.rs | 12 ++----- src/handlers/notification.rs | 10 +++--- src/handlers/notify_zulip.rs | 5 ++- src/handlers/ping.rs | 49 +++++++++++--------------- src/handlers/rustc_commits.rs | 39 ++++++++------------ src/handlers/types_planning_updates.rs | 7 ++-- src/triage.rs | 13 +++---- 12 files changed, 61 insertions(+), 98 deletions(-) diff --git a/src/github.rs b/src/github.rs index 3b4ceeef..467a9223 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1726,9 +1726,8 @@ impl Repository { .ok_or_else(|| anyhow::anyhow!("No ref."))? .target .ok_or_else(|| anyhow::anyhow!("No target."))?; - let commit = match target { - GitObject::Commit(commit) => commit, - _ => anyhow::bail!("unexpected target type {target:?}"), + let GitObject::Commit(commit) = target else { + anyhow::bail!("unexpected target type {target:?}") }; let commits = commit .history diff --git a/src/handlers/autolabel.rs b/src/handlers/autolabel.rs index 17ceca17..7261675b 100644 --- a/src/handlers/autolabel.rs +++ b/src/handlers/autolabel.rs @@ -16,9 +16,8 @@ pub(super) async fn parse_input( event: &IssuesEvent, config: Option<&AutolabelConfig>, ) -> Result, String> { - let config = match config { - Some(config) => config, - None => return Ok(None), + let Some(config) = config else { + return Ok(None); }; // On opening a new PR or sync'ing the branch, look at the diff and try to diff --git a/src/handlers/backport.rs b/src/handlers/backport.rs index edfff342..5a340fe0 100644 --- a/src/handlers/backport.rs +++ b/src/handlers/backport.rs @@ -45,9 +45,8 @@ pub(super) async fn parse_input( event: &IssuesEvent, config: Option<&BackportConfig>, ) -> Result, String> { - let config = match config { - Some(config) => config, - None => return Ok(None), + let Some(config) = config else { + return Ok(None); }; // Only handle events when the PR is opened or the first comment is edited diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index 6e5283d9..87a77877 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -30,9 +30,7 @@ pub(super) async fn parse_input( event: &IssuesEvent, config: Option<&MajorChangeConfig>, ) -> Result, String> { - let config = if let Some(config) = config { - config - } else { + let Some(config) = config else { return Ok(None); }; let enabling_label = config.enabling_label.as_str(); diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 762dffcf..49d858c1 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -32,9 +32,8 @@ pub(super) async fn parse_input( event: &IssuesEvent, config: Option<&MentionsConfig>, ) -> Result, String> { - let config = match config { - Some(config) => config, - None => return Ok(None), + let Some(config) = config else { + return Ok(None); }; if !matches!( diff --git a/src/handlers/milestone_prs.rs b/src/handlers/milestone_prs.rs index cfba4bc4..cf65c337 100644 --- a/src/handlers/milestone_prs.rs +++ b/src/handlers/milestone_prs.rs @@ -8,9 +8,7 @@ use reqwest::StatusCode; use tracing as log; pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { - let e = if let Event::Issue(e) = event { - e - } else { + let Event::Issue(e) = event else { return Ok(()); }; @@ -32,9 +30,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { return Ok(()); } - let merge_sha = if let Some(s) = &e.issue.merge_commit_sha { - s - } else { + let Some(merge_sha) = &e.issue.merge_commit_sha else { log::error!( "rust-lang/rust#{}: no merge_commit_sha in event", e.issue.number @@ -43,9 +39,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { }; // Fetch the version from the upstream repository. - let version = if let Some(version) = get_version_standalone(&ctx.github, merge_sha).await? { - version - } else { + let Some(version) = get_version_standalone(&ctx.github, merge_sha).await? else { log::error!("could not find the version of {merge_sha:?}"); return Ok(()); }; diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index aa4684aa..920487ef 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -14,10 +14,9 @@ use std::collections::HashSet; use tracing as log; pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { - let body = match event.comment_body() { - Some(v) => v, + let Some(body) = event.comment_body() else { // Skip events that don't have comment bodies associated - None => return Ok(()), + return Ok(()); }; if let Event::Issue(e) = event { @@ -79,9 +78,8 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { } log::trace!("Captured usernames in comment: {caps:?}"); for login in caps { - let (users, team_name) = match id_from_user(ctx, login).await? { - Some((users, team_name)) => (users, team_name), - None => continue, + let Some((users, team_name)) = id_from_user(ctx, login).await? else { + continue; }; let client = ctx.db.get().await; diff --git a/src/handlers/notify_zulip.rs b/src/handlers/notify_zulip.rs index bab32bee..9c1b8f83 100644 --- a/src/handlers/notify_zulip.rs +++ b/src/handlers/notify_zulip.rs @@ -31,9 +31,8 @@ pub(super) async fn parse_input( event: &IssuesEvent, config: Option<&NotifyZulipConfig>, ) -> Result>, String> { - let config = match config { - Some(config) => config, - None => return Ok(None), + let Some(config) = config else { + return Ok(None); }; match &event.action { diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 665ba100..898f2dc9 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -29,35 +29,28 @@ pub(super) async fn handle_command( return Ok(()); } - let (gh_team, config) = match config.get_by_name(&team_name.team) { - Some(v) => v, - None => { - let cmnt = ErrorComment::new( - &event.issue().unwrap(), - format!( - "This team (`{}`) cannot be pinged via this command; \ - it may need to be added to `triagebot.toml` on the default branch.", - team_name.team, - ), - ); - cmnt.post(&ctx.github).await?; - return Ok(()); - } + let Some((gh_team, config)) = config.get_by_name(&team_name.team) else { + let cmnt = ErrorComment::new( + event.issue().unwrap(), + format!( + "This team (`{}`) cannot be pinged via this command; \ + it may need to be added to `triagebot.toml` on the default branch.", + team_name.team, + ), + ); + cmnt.post(&ctx.github).await?; + return Ok(()); }; - let team = ctx.team.get_team(&gh_team).await?; - let team = match team { - Some(team) => team, - None => { - let cmnt = ErrorComment::new( - &event.issue().unwrap(), - format!( - "This team (`{}`) does not exist in the team repository.", - team_name.team, - ), - ); - cmnt.post(&ctx.github).await?; - return Ok(()); - } + let Some(team) = ctx.team.get_team(gh_team).await? else { + let cmnt = ErrorComment::new( + event.issue().unwrap(), + format!( + "This team (`{}`) does not exist in the team repository.", + team_name.team, + ), + ); + cmnt.post(&ctx.github).await?; + return Ok(()); }; if let Some(label) = &config.label { diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index f60ffdf8..4ae53553 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -12,22 +12,19 @@ use tracing as log; const BORS_GH_ID: u64 = 3_372_342; pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { - let body = match event.comment_body() { - Some(v) => v, + let Some(body) = event.comment_body() else { // Skip events that don't have comment bodies associated - None => return Ok(()), + return Ok(()); }; - let event = if let Event::IssueComment(e) = event { - if e.action != github::IssueCommentAction::Created { - return Ok(()); - } - - e - } else { + let Event::IssueComment(event) = event else { return Ok(()); }; + if event.action != github::IssueCommentAction::Created { + return Ok(()); + } + if !body.contains("Test successful") { return Ok(()); } @@ -45,9 +42,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let start = ""); - let (start, end) = if let (Some(start), Some(end)) = (start, end) { - (start, end) - } else { + let (Some(start), Some(end)) = (start, end) else { log::warn!("Unable to extract build completion from comment {body:?}"); return Ok(()); }; @@ -102,12 +97,9 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u let db = ctx.db.get().await; while let Some((sha, mut pr)) = to_be_resolved.pop_front() { - let mut gc = match ctx.github.rust_commit(&sha).await { - Some(c) => c, - None => { - log::error!("Could not find bors-reported sha: {:?}", sha); - continue; - } + let Some(mut gc) = ctx.github.rust_commit(&sha).await else { + log::error!("Could not find bors-reported sha: {sha:?}"); + continue; }; let parent_sha = gc.parents.remove(0).sha; @@ -121,12 +113,9 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u } } - let pr = match pr.take() { - Some(number) => number, - None => { - log::warn!("Failed to find PR number for commit {sha}"); - continue; - } + let Some(pr) = pr.take() else { + log::warn!("Failed to find PR number for commit {sha}"); + continue; }; let res = rustc_commits::record_commit( diff --git a/src/handlers/types_planning_updates.rs b/src/handlers/types_planning_updates.rs index 83f6c5a9..9c2fedd6 100644 --- a/src/handlers/types_planning_updates.rs +++ b/src/handlers/types_planning_updates.rs @@ -117,10 +117,9 @@ pub async fn request_updates( /* let mut dmed_assignee = false; for assignee in issue.assignees { - let zulip_id_and_email = zulip_id_and_email(ctx, assignee.id.unwrap()).await?; - let (zulip_id, email) = match zulip_id_and_email { - Some(id) => id, - None => continue, + let Some((zulip_id, email)) = zulip_id_and_email(ctx, assignee.id.unwrap()).await? + else { + continue; }; let message = format!( "Type team tracking issue needs an update. [Issue #{}]({})", diff --git a/src/triage.rs b/src/triage.rs index b1d3fed8..9c8d5310 100644 --- a/src/triage.rs +++ b/src/triage.rs @@ -30,14 +30,11 @@ pub async fn pulls( .per_page(100) .send() .await; - let mut page = match res { - Ok(page) => page, - Err(_) => { - return ( - StatusCode::NOT_FOUND, - Html("The repository is not found.".to_string()), - ); - } + let Ok(mut page) = res else { + return ( + StatusCode::NOT_FOUND, + Html("The repository is not found.".to_string()), + ); }; let mut base_pulls = page.take_items(); let mut next_page = page.next; From 031aa5d61e2984196b5d1236f2795cd93798832e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:30:30 +0200 Subject: [PATCH 19/59] clippy::cast_lossless --- src/handlers/concern.rs | 2 +- src/handlers/project_goals.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index 2be3942f..8f53f642 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -48,7 +48,7 @@ pub(super) async fn handle_command( match crate::rfcbot::get_all_fcps().await { Ok(fcps) => { if fcps.iter().any(|(_, fcp)| { - fcp.issue.number as u64 == issue.number + u64::from(fcp.issue.number) == issue.number && fcp.issue.repository == issue_comment.repository.full_name }) { tracing::info!( diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index f56be192..ef3082c4 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -106,7 +106,7 @@ async fn ping_project_goals_owners_automatically( zulip, team_api, false, - days_threshold as i64, + i64::from(days_threshold), &third_monday, ) .await From 554289e95b5516dede2e0cbcdaeb2b1a4decdada Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:29:51 +0200 Subject: [PATCH 20/59] documentation lints --- src/github.rs | 4 ++-- src/handlers.rs | 2 +- src/handlers/assign.rs | 2 +- src/jobs.rs | 42 +++++++++++++++++++++++------------------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/github.rs b/src/github.rs index 467a9223..a77796a5 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2409,7 +2409,7 @@ impl Event { } } - /// This will both extract from IssueComment events but also Issue events + /// This will both extract from `IssueComment` events but also `Issue` events pub fn comment_body(&self) -> Option<&str> { match self { Event::Create(_) => None, @@ -2419,7 +2419,7 @@ impl Event { } } - /// This will both extract from IssueComment events but also Issue events + /// This will both extract from `IssueComment` events but also `Issue` events pub fn comment_from(&self) -> Option<&str> { match self { Event::Create(_) => None, diff --git a/src/handlers.rs b/src/handlers.rs index 20edf2c6..4f6a104d 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -378,7 +378,7 @@ pub struct Context { pub username: String, pub octocrab: Octocrab, /// Represents the workqueue (assigned open PRs) of individual reviewers. - /// tokio's RwLock is used to avoid deadlocks, since we run on a single-threaded tokio runtime. + /// tokio's `RwLock` is used to avoid deadlocks, since we run on a single-threaded tokio runtime. pub workqueue: Arc>, pub gha_logs: Arc>, } diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index eae40e5d..02620bab 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -703,7 +703,7 @@ enum FindReviewerError { NoReviewer { initial: Vec }, /// Requested reviewer is off the review rotation (e.g. on a vacation). /// Either the username is in [users_on_vacation] in `triagebot.toml` or the user has - /// configured [RotationMode::OffRotation] in their reviewer preferences. + /// configured [`RotationMode::OffRotation`] in their reviewer preferences. ReviewerOffRotation { username: String }, /// Requested reviewer is PR author ReviewerIsPrAuthor { username: String }, diff --git a/src/jobs.rs b/src/jobs.rs index c372388f..37085c3e 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -7,12 +7,12 @@ //! job (to be used as an identifier in the database) and the function to run //! when the job runs. //! -//! The metadata is a serde_json::Value -//! Please refer to https://docs.rs/serde_json/latest/serde_json/value/fn.from_value.html +//! The metadata is a `serde_json::Value` +//! Please refer to //! on how to interpret it as an instance of type T, implementing Serialize/Deserialize. //! -//! The schedule is a cron::Schedule -//! Please refer to https://docs.rs/cron/latest/cron/struct.Schedule.html for further info +//! The schedule is a `cron::Schedule` +//! Please refer to for further info //! //! ## Example, sending a zulip message once a week //! @@ -20,26 +20,30 @@ //! Friday at 11:30am ET into #t-release with a "@T-release meeting!"" content. //! //! To begin, let's create a generic zulip message Job: -//! #[derive(Serialize, Deserialize)] -//! struct ZulipMetadata { -//! pub message: String -//! pub channel: String, -//! } -//! struct ZulipMessageJob; -//! impl Job for ZulipMessageJob { ... } +//! ```ignore +//! #[derive(Serialize, Deserialize)] +//! struct ZulipMetadata { +//! pub message: String +//! pub channel: String, +//! } +//! struct ZulipMessageJob; +//! impl Job for ZulipMessageJob { ... } +//! ``` //! //! (Imagine that this job requires a channel and a message in the metadata.) //! //! If we wanted to have a default scheduled message, we could add the following to //! `default_jobs`: -//! JobSchedule { -//! name: ZulipMessageJob.name(), -//! schedule: Schedule::from_str("0 30 11 * * FRI *").unwrap(), -//! metadata: serde_json::value::to_value(ZulipMetadata { -//! message: "@T-release meeting!".to_string() -//! channel: "T-release".to_string(), -//! }).unwrap(), -//! } +//! ```ignore +//! JobSchedule { +//! name: ZulipMessageJob.name(), +//! schedule: Schedule::from_str("0 30 11 * * FRI *").unwrap(), +//! metadata: serde_json::value::to_value(ZulipMetadata { +//! message: "@T-release meeting!".to_string() +//! channel: "T-release".to_string(), +//! }).unwrap(), +//! } +//! ``` use std::str::FromStr; From d978fc58eec98523ccd8246d3444f8a8a534ca12 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:23:26 +0200 Subject: [PATCH 21/59] reborrow instead of slicing --- src/bin/compiler.rs | 2 +- src/bin/lang.rs | 2 +- src/bin/types.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/compiler.rs b/src/bin/compiler.rs index c217838b..ac71aed6 100644 --- a/src/bin/compiler.rs +++ b/src/bin/compiler.rs @@ -7,7 +7,7 @@ async fn main() -> anyhow::Result<()> { let args: Vec = std::env::args().collect(); if args.len() == 2 { - match &args[1][..] { + match &*args[1] { "backlog_bonanza" => { let agenda = agenda::compiler_backlog_bonanza(); print!("{}", agenda.call().await?); diff --git a/src/bin/lang.rs b/src/bin/lang.rs index 1bd34468..e8ca575c 100644 --- a/src/bin/lang.rs +++ b/src/bin/lang.rs @@ -7,7 +7,7 @@ async fn main() -> anyhow::Result<()> { let args: Vec = std::env::args().collect(); if args.len() == 2 { - match &args[1][..] { + match &*args[1] { "agenda" => { let agenda = agenda::lang(); print!("{}", agenda.call().await?); diff --git a/src/bin/types.rs b/src/bin/types.rs index 82e4739b..939e62eb 100644 --- a/src/bin/types.rs +++ b/src/bin/types.rs @@ -7,7 +7,7 @@ async fn main() -> anyhow::Result<()> { let args: Vec = std::env::args().collect(); if args.len() == 2 { - match &args[1][..] { + match &*args[1] { "planning" => { let agenda = agenda::types_planning(); print!("{}", agenda.call().await?); From d15c9318e7ea7669d4b172cdd89de2012ab1e551 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:20:58 +0200 Subject: [PATCH 22/59] add/remove semicolons clippy::{semicolon_if_nothing_returned,unnecessary_semicolon} --- src/gh_range_diff.rs | 2 +- src/github.rs | 2 +- src/handlers/issue_links.rs | 2 +- src/handlers/mentions.rs | 2 +- src/handlers/notification.rs | 2 +- src/handlers/pr_tracking.rs | 2 +- src/handlers/rustc_commits.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 7eac69f3..209a15b9 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -455,7 +455,7 @@ impl HtmlDiffPrinter<'_> { match hunk_token_status { HunkTokenStatus::Added => write!(f, "{ADDED_BLOCK_SIGN} ")?, HunkTokenStatus::Removed => write!(f, "{REMOVED_BLOCK_SIGN} ")?, - }; + } let mut words = words.peekable(); diff --git a/src/github.rs b/src/github.rs index a77796a5..6f599383 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1411,7 +1411,7 @@ impl Repository { "direction" => ordering.direction = val, "per_page" => ordering.per_page = val, _ => return true, - }; + } false }) .collect(); diff --git a/src/handlers/issue_links.rs b/src/handlers/issue_links.rs index 986ca2bb..a705fedb 100644 --- a/src/handlers/issue_links.rs +++ b/src/handlers/issue_links.rs @@ -40,7 +40,7 @@ pub(super) async fn parse_input( // configuration block to enable the handler. if config.is_none() { return Ok(None); - }; + } Ok(Some(IssueLinksInput {})) } diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 49d858c1..42b545eb 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -125,7 +125,7 @@ pub(super) async fn handle_input( Some(m) => result.push_str(m), None => match type_ { MentionsEntryType::Filename => { - write!(result, "Some changes occurred in {entry}").unwrap() + write!(result, "Some changes occurred in {entry}").unwrap(); } MentionsEntryType::Content => write!( result, diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index 920487ef..f410e597 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -60,7 +60,7 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { users_notified.extend(users.into_iter().map(|user| user.id)); } } - }; + } // We've implicitly notified the user that is submitting the notification: // they already know that they left this comment. diff --git a/src/handlers/pr_tracking.rs b/src/handlers/pr_tracking.rs index e139b89e..da1050c1 100644 --- a/src/handlers/pr_tracking.rs +++ b/src/handlers/pr_tracking.rs @@ -67,7 +67,7 @@ pub(super) async fn parse_input( // about this feature not being enabled if config.is_none() { return Ok(None); - }; + } // Execute this handler only if this is a PR ... if !event.issue.is_pr() { diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index 4ae53553..11234159 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -131,7 +131,7 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u match res { Ok(()) => { if !rustc_commits::has_commit(&db, &parent_sha).await { - to_be_resolved.push_back((parent_sha, None)) + to_be_resolved.push_back((parent_sha, None)); } } Err(e) => log::error!("Failed to record commit {e:?}"), From b331922965fe75d83f7d6968bbbac83a833395e2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:20:33 +0200 Subject: [PATCH 23/59] clippy::write_with_newline --- src/handlers/concern.rs | 2 +- src/handlers/docs_update.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index 8f53f642..f0af8fd5 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -177,7 +177,7 @@ fn markdown_content(concerns: &[Concern], bot: &str) -> String { let mut md = String::new(); - let _ = writeln!(md, ""); + let _ = writeln!(md); if active_concerns > 0 { let _ = writeln!(md, "> [!CAUTION]"); diff --git a/src/handlers/docs_update.rs b/src/handlers/docs_update.rs index 40c54df7..9c79e424 100644 --- a/src/handlers/docs_update.rs +++ b/src/handlers/docs_update.rs @@ -189,7 +189,7 @@ async fn create_commit( async fn create_pr(gh: &GithubClient, dest_repo: &Repository, updates: &[Update]) -> Result { let mut body = String::new(); for update in updates { - write!(body, "{}\n", update.pr_body).unwrap(); + writeln!(body, "{}", update.pr_body).unwrap(); } let username = WORK_REPO.split('/').next().unwrap(); From 38ba2dda6e3da25a55db43d0976448b70cff613e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:19:13 +0200 Subject: [PATCH 24/59] clippy::manual_string_new --- src/config.rs | 2 +- src/github.rs | 2 +- src/handlers/concern.rs | 2 +- src/triage.rs | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/config.rs b/src/config.rs index 0e12c2cd..a0c3629b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -346,7 +346,7 @@ impl<'de> serde::Deserialize<'de> for NotifyZulipTablesConfig { if !direct_fields.is_empty() { let direct = NotifyZulipLabelConfig::deserialize(Value::Table(direct_fields)) .map_err(Error::custom)?; - subtables.insert("".to_string(), direct); + subtables.insert(String::new(), direct); } Ok(NotifyZulipTablesConfig { subtables }) diff --git a/src/github.rs b/src/github.rs index 6f599383..cadb2b2c 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2246,7 +2246,7 @@ impl IssuesQuery for Query<'_> { let mcp_details = if include_mcp_details { let first100_comments = issue.get_first100_comments(gh_client).await?; let (zulip_link, concerns) = if first100_comments.is_empty() { - ("".to_string(), None) + (String::new(), None) } else { let split = re_zulip_link .split(&first100_comments[0].body) diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index f0af8fd5..3ed0d146 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -167,7 +167,7 @@ pub(super) async fn handle_command( fn markdown_content(concerns: &[Concern], bot: &str) -> String { if concerns.is_empty() { - return "".to_string(); + return String::new(); } let active_concerns = concerns diff --git a/src/triage.rs b/src/triage.rs index 9c8d5310..d10b7d7e 100644 --- a/src/triage.rs +++ b/src/triage.rs @@ -49,10 +49,10 @@ pub async fn pulls( let mut pulls: Vec = Vec::new(); for base_pull in base_pulls { - let assignee = base_pull.assignee.map_or("".to_string(), |v| v.login); + let assignee = base_pull.assignee.map_or(String::new(), |v| v.login); let updated_at = base_pull .updated_at - .map_or("".to_string(), |v| v.format("%Y-%m-%d").to_string()); + .map_or(String::new(), |v| v.format("%Y-%m-%d").to_string()); let yellow_line = Utc::now() - Duration::days(YELLOW_DAYS); let red_line = Utc::now() - Duration::days(RED_DAYS); @@ -67,7 +67,7 @@ pub async fn pulls( (Utc::now() - base_pull.created_at.unwrap()).num_days() }; - let labels = base_pull.labels.map_or("".to_string(), |labels| { + let labels = base_pull.labels.map_or(String::new(), |labels| { labels .iter() .map(|label| label.name.clone()) From c27e10096288abd628124da6c3d401f297adaa7c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:16:27 +0200 Subject: [PATCH 25/59] clippy::single_char_pattern --- src/github.rs | 2 +- src/handlers/assign.rs | 2 +- src/handlers/check_commits.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/github.rs b/src/github.rs index cadb2b2c..535caf4a 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2125,7 +2125,7 @@ fn quote_reply(markdown: &str) -> String { if markdown.is_empty() { String::from("*No content*") } else { - format!("\n\t> {}", markdown.replace("\n", "\n\t> ")) + format!("\n\t> {}", markdown.replace('\n', "\n\t> ")) } } diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index 02620bab..d294d7a5 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -679,7 +679,7 @@ fn strip_organization_prefix<'a>(issue: &Issue, name: &'a str) -> &'a str { let repo = issue.repository(); // @ is optional, so it is trimmed separately // both @rust-lang/compiler and rust-lang/compiler should work - name.trim_start_matches("@") + name.trim_start_matches('@') .trim_start_matches(&format!("{}/", repo.organization)) } diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index 60fd0e2b..1fa8d504 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -279,7 +279,7 @@ async fn handle_new_state( fn warning_from_warnings(warnings: &[String]) -> String { let warnings: Vec<_> = warnings .iter() - .map(|warning| warning.trim().replace("\n", "\n ")) + .map(|warning| warning.trim().replace('\n', "\n ")) .map(|warning| format!("* {warning}")) .collect(); format!(":warning: **Warning** :warning:\n\n{}", warnings.join("\n")) From 9989a85fb4d3e33a18e9ce839acc6b2fc93525c2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:46:01 +0200 Subject: [PATCH 26/59] clippy::implicit_clone --- src/handlers/note.rs | 2 +- src/handlers/prioritize.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/note.rs b/src/handlers/note.rs index c4d387b2..0029c0c3 100644 --- a/src/handlers/note.rs +++ b/src/handlers/note.rs @@ -132,7 +132,7 @@ pub(super) async fn handle_command( let current = e.data_mut(); let comment_url = String::from(event.html_url().unwrap()); - let author = event.user().login.to_owned(); + let author = event.user().login.clone(); match &cmd { NoteCommand::Summary { title } => { diff --git a/src/handlers/prioritize.rs b/src/handlers/prioritize.rs index 61b0cdf4..8dbc9c74 100644 --- a/src/handlers/prioritize.rs +++ b/src/handlers/prioritize.rs @@ -13,7 +13,7 @@ pub(super) async fn handle_command( ) -> anyhow::Result<()> { let mut labels = vec![]; labels.push(github::Label { - name: config.label.to_owned(), + name: config.label.clone(), }); event .issue() From 93a80e068fd7a8b5c2e2d9945855da4e4dd66643 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 19:13:54 +0200 Subject: [PATCH 27/59] get `command` without unwrapping --- parser/src/command/shortcut.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/parser/src/command/shortcut.rs b/parser/src/command/shortcut.rs index ed36d919..495d40f4 100644 --- a/parser/src/command/shortcut.rs +++ b/parser/src/command/shortcut.rs @@ -42,12 +42,11 @@ impl ShortcutCommand { let mut toks = input.clone(); if let Some(Token::Word(word)) = toks.peek_token()? { - if !shortcuts.contains_key(word) { + let Some(command) = shortcuts.get(word) else { return Ok(None); - } + }; toks.next_token()?; *input = toks; - let command = shortcuts.get(word).unwrap(); return Ok(Some(*command)); } Ok(None) From 1da5e7187d2199056a6d9360b9469c35879146e6 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 18:42:45 +0200 Subject: [PATCH 28/59] `write!` _inside_ `match` --- parser/src/token.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/parser/src/token.rs b/parser/src/token.rs index 64f5e80a..ec212e39 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -54,15 +54,11 @@ impl std::error::Error for ErrorKind {} impl fmt::Display for ErrorKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match self { - ErrorKind::UnterminatedString => "unterminated string", - ErrorKind::QuoteInWord => "quote in word", - ErrorKind::RawString => "raw strings are not yet supported", - } - ) + match self { + ErrorKind::UnterminatedString => write!(f, "unterminated string"), + ErrorKind::QuoteInWord => write!(f, "quote in word"), + ErrorKind::RawString => write!(f, "raw strings are not yet supported"), + } } } From e2903b57de4a093a95d78918f4c20959668af702 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 18:40:59 +0200 Subject: [PATCH 29/59] clippy::unneded_struct_pattern --- parser/src/ignore_block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/src/ignore_block.rs b/parser/src/ignore_block.rs index 7f10106f..10b0daaa 100644 --- a/parser/src/ignore_block.rs +++ b/parser/src/ignore_block.rs @@ -28,10 +28,10 @@ impl IgnoreBlocks { ignore_till_end!(TagEnd::CodeBlock); } Event::Start(Tag::Link { .. }) => { - ignore_till_end!(TagEnd::Link { .. }); + ignore_till_end!(TagEnd::Link); } Event::Start(Tag::Image { .. }) => { - ignore_till_end!(TagEnd::Image { .. }); + ignore_till_end!(TagEnd::Image); } Event::Start(Tag::BlockQuote(_)) => { let start = range.start; From 01d4d27b0c9357ef5c5b7d96db7afc727d62d645 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 18:39:12 +0200 Subject: [PATCH 30/59] clippy::manual_strip --- parser/src/command/relabel.rs | 8 ++++---- parser/src/token.rs | 5 ++++- src/handlers/relabel.rs | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/parser/src/command/relabel.rs b/parser/src/command/relabel.rs index 98c55e77..7423e732 100644 --- a/parser/src/command/relabel.rs +++ b/parser/src/command/relabel.rs @@ -68,13 +68,13 @@ impl LabelDelta { return Err(input.error(ParseError::ExpectedLabelDelta)); } }; - if delta.starts_with('+') { + if let Some(label) = delta.strip_prefix('+') { Ok(LabelDelta::Add( - Label::parse(&delta[1..]).map_err(|e| input.error(e))?, + Label::parse(label).map_err(|e| input.error(e))?, )) - } else if delta.starts_with('-') { + } else if let Some(label) = delta.strip_prefix('-') { Ok(LabelDelta::Remove( - Label::parse(&delta[1..]).map_err(|e| input.error(e))?, + Label::parse(label).map_err(|e| input.error(e))?, )) } else { Ok(LabelDelta::Add( diff --git a/parser/src/token.rs b/parser/src/token.rs index ec212e39..f4bed625 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -203,7 +203,10 @@ impl<'a> Tokenizer<'a> { }) { if self.cur().unwrap().1 == '"' { let so_far = self.str_from(start); - if so_far.starts_with('r') && so_far.chars().skip(1).all(|v| v == '#' || v == '"') { + if so_far + .strip_prefix('r') + .is_some_and(|s| s.chars().all(|v| v == '#' || v == '"')) + { return Err(self.error(ErrorKind::RawString)); } else { return Err(self.error(ErrorKind::QuoteInWord)); diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index 2cc45fe6..abafde6a 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -159,8 +159,8 @@ enum MatchPatternResult { } fn match_pattern(pattern: &str, label: &str) -> anyhow::Result { - let (pattern, inverse) = if pattern.starts_with('!') { - (&pattern[1..], true) + let (pattern, inverse) = if let Some(pat) = pattern.strip_prefix('!') { + (pat, true) } else { (pattern, false) }; From 867b95fc1c00fa6a24507ee316d8454ef0e2231a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 18:38:06 +0200 Subject: [PATCH 31/59] clippy::manual_assert --- parser/src/command.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/parser/src/command.rs b/parser/src/command.rs index f81d2a39..5dd2ad11 100644 --- a/parser/src/command.rs +++ b/parser/src/command.rs @@ -140,13 +140,12 @@ impl<'a> Input<'a> { &original_tokenizer, )); - if success.len() > 1 { - panic!( - "succeeded parsing {:?} to multiple commands: {:?}", - &self.all[self.parsed..], - success - ); - } + assert!( + success.len() <= 1, + "succeeded parsing {:?} to multiple commands: {:?}", + &self.all[self.parsed..], + success + ); let (mut tok, c) = success.pop()?; // if we errored out while parsing the command do not move the input forwards From d92c33dd4b0e2db47491060c459b137c8c3a9766 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:51:15 +0200 Subject: [PATCH 32/59] needless `into_iter` --- src/handlers/check_commits/no_merges.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/check_commits/no_merges.rs b/src/handlers/check_commits/no_merges.rs index e5e71fbe..144f04b2 100644 --- a/src/handlers/check_commits/no_merges.rs +++ b/src/handlers/check_commits/no_merges.rs @@ -41,7 +41,7 @@ pub(super) fn merges_in_commits( .unwrap_or(&get_default_message( &repository.full_name, &repository.default_branch, - merge_commits.into_iter(), + merge_commits, )) .to_string(); From 7d729ffeaee44c6e30135d89937309b73abff86c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:46:39 +0200 Subject: [PATCH 33/59] clippy::legacy_numeric_constants --- src/changelogs/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changelogs/mod.rs b/src/changelogs/mod.rs index af502e3f..d476a12c 100644 --- a/src/changelogs/mod.rs +++ b/src/changelogs/mod.rs @@ -34,7 +34,7 @@ fn render_for_github_releases<'a>(document: &'a AstNode<'a>) -> anyhow::Results for every line break in the markdown, // mangling the output. - width: std::usize::MAX, + width: usize::MAX, ..ComrakRenderOptions::default() }, From 8372962b888dab24b57449256cfb3816641fd151 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:42:26 +0200 Subject: [PATCH 34/59] clippy::inconsistent_struct_constructor --- src/db/notifications.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/notifications.rs b/src/db/notifications.rs index f66535d4..f5655eb9 100644 --- a/src/db/notifications.rs +++ b/src/db/notifications.rs @@ -110,8 +110,8 @@ pub async fn delete_ping( let deleted_notification = NotificationData { origin_url, origin_text, - time, short_description, + time, metadata, }; @@ -148,8 +148,8 @@ pub async fn delete_ping( NotificationData { origin_url, origin_text, - time, short_description, + time, metadata, } }) From efdd2a8c5d4aead940b23890b90257890f5e1ebd Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:33:42 +0200 Subject: [PATCH 35/59] clippy::redundant_closure_for_method_calls --- src/changelogs/mod.rs | 2 +- src/config.rs | 2 +- src/db/review_prefs.rs | 2 +- src/handlers/assign.rs | 2 +- src/handlers/backport.rs | 2 +- src/handlers/mentions.rs | 2 +- src/zulip.rs | 4 +--- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/changelogs/mod.rs b/src/changelogs/mod.rs index d476a12c..c1e7bbbf 100644 --- a/src/changelogs/mod.rs +++ b/src/changelogs/mod.rs @@ -21,7 +21,7 @@ impl Changelog { } pub(crate) fn version(&self, version: &str) -> Option<&str> { - self.versions.get(version).map(|s| s.as_str()) + self.versions.get(version).map(String::as_str) } } diff --git a/src/config.rs b/src/config.rs index a0c3629b..c0124906 100644 --- a/src/config.rs +++ b/src/config.rs @@ -147,7 +147,7 @@ impl AssignConfig { /// Return a "fallback" adhoc group, which is used for assigning reviewers if no other /// reviewer was found. pub(crate) fn fallback_review_group(&self) -> Option<&[String]> { - self.adhoc_groups.get("fallback").map(|v| v.as_slice()) + self.adhoc_groups.get("fallback").map(Vec::as_slice) } } diff --git a/src/db/review_prefs.rs b/src/db/review_prefs.rs index 70c97632..f92141be 100644 --- a/src/db/review_prefs.rs +++ b/src/db/review_prefs.rs @@ -107,7 +107,7 @@ pub async fn get_review_prefs_batch<'a>( .iter() .map(|name| (name.to_lowercase(), *name)) .collect(); - let lowercase_users: Vec<&str> = lowercase_map.keys().map(|s| s.as_str()).collect(); + let lowercase_users: Vec<&str> = lowercase_map.keys().map(String::as_str).collect(); // The id/user_id/max_assigned_prs/rotation_mode columns have to match the names used in // `From for ReviewPrefs`. diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index d294d7a5..e31006c5 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -1036,7 +1036,7 @@ async fn candidate_reviewers_from_names<'a>( .iter() .filter_map(|res| res.as_ref().ok().map(|s| s.name.to_string())) .collect(); - let usernames: Vec<&str> = usernames.iter().map(|s| s.as_str()).collect(); + let usernames: Vec<&str> = usernames.iter().map(String::as_str).collect(); let review_prefs = get_review_prefs_batch(db, &usernames) .await .context("cannot fetch review preferences") diff --git a/src/handlers/backport.rs b/src/handlers/backport.rs index 5a340fe0..18104eac 100644 --- a/src/handlers/backport.rs +++ b/src/handlers/backport.rs @@ -76,7 +76,7 @@ pub(super) async fn parse_input( .clone() .filter(|(_cfg_name, cfg)| { let required_pr_labels: Vec<&str> = - cfg.required_pr_labels.iter().map(|l| l.as_str()).collect(); + cfg.required_pr_labels.iter().map(String::as_str).collect(); if !contains_any(&pr_labels, &required_pr_labels) { log::warn!( "Skipping backport nomination: PR is missing one required label: {:?}", diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 42b545eb..254eba71 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -70,7 +70,7 @@ pub(super) async fn parse_input( file_paths .iter() .filter(|p| p.starts_with(path)) - .map(|p| PathBuf::from(p)) + .map(PathBuf::from) .collect() } MentionsEntryType::Content => { diff --git a/src/zulip.rs b/src/zulip.rs index ece5efa3..112e38bd 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -723,9 +723,7 @@ async fn lookup_zulip_username(ctx: &Context, gh_username: &str) -> anyhow::Resu Ok(users .into_iter() .find(|user| { - user.get_github_username() - .map(|u| u.to_lowercase()) - .as_deref() + user.get_github_username().map(str::to_lowercase).as_deref() == Some(username_lowercase.as_str()) }) .map(|u| u.user_id)) From f846986147abea3a2c53dce3fb2fde18623db3c9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:31:56 +0200 Subject: [PATCH 36/59] clippy::manual_is_variant_and --- parser/src/token.rs | 2 +- src/db/notifications.rs | 14 +++++++------- src/gh_range_diff.rs | 4 ++-- src/github.rs | 17 ++++++++--------- src/main.rs | 5 +---- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/parser/src/token.rs b/parser/src/token.rs index f4bed625..f4ba2bfe 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -92,7 +92,7 @@ impl<'a> Tokenizer<'a> { fn consume_whitespace(&mut self) { while self .cur() - .map_or(false, |c| c.1 != '\n' && c.1.is_whitespace()) + .is_some_and(|c| c.1 != '\n' && c.1.is_whitespace()) { self.advance(); } diff --git a/src/db/notifications.rs b/src/db/notifications.rs index f5655eb9..455fe824 100644 --- a/src/db/notifications.rs +++ b/src/db/notifications.rs @@ -116,7 +116,7 @@ pub async fn delete_ping( }; if let Err(e) = t.commit().await { - if e.code().map_or(false, |c| { + if e.code().is_some_and(|c| { *c == tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE }) { log::trace!("serialization failure, restarting deletion"); @@ -230,9 +230,9 @@ pub async fn move_indices( } if let Err(e) = t.commit().await { - if e.code().map_or(false, |c| { - *c == tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE - }) { + if e.code() + .is_some_and(|c| *c == tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE) + { log::trace!("serialization failure, restarting index movement"); continue; } else { @@ -294,9 +294,9 @@ pub async fn add_metadata( } if let Err(e) = t.commit().await { - if e.code().map_or(false, |c| { - *c == tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE - }) { + if e.code() + .is_some_and(|c| *c == tokio_postgres::error::SqlState::T_R_SERIALIZATION_FAILURE) + { log::trace!("serialization failure, restarting index movement"); continue; } else { diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 209a15b9..a2c96185 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -460,8 +460,8 @@ impl HtmlDiffPrinter<'_> { let mut words = words.peekable(); let first_word = words.peek(); - let is_add = first_word.map(|w| w.0.starts_with('+')).unwrap_or_default(); - let is_remove = first_word.map(|w| w.0.starts_with('-')).unwrap_or_default(); + let is_add = first_word.is_some_and(|w| w.0.starts_with('+')); + let is_remove = first_word.is_some_and(|w| w.0.starts_with('-')); // Highlight in the same was as `git range-diff` does for diff-lines // that changed. In addition we also do word highlighting. diff --git a/src/github.rs b/src/github.rs index 535caf4a..e30ef148 100644 --- a/src/github.rs +++ b/src/github.rs @@ -147,8 +147,7 @@ impl GithubClient { let rate_limit = if req .url() .path_segments() - .map(|mut segments| matches!(segments.next(), Some("search"))) - .unwrap_or(false) + .is_some_and(|mut segments| segments.next() == Some("search")) { rate_limit_response.resources.search } else { @@ -308,10 +307,10 @@ impl User { let map = permission.teams; let is_triager = map .get("wg-triage") - .map_or(false, |w| w.members.iter().any(|g| g.github == self.login)); + .is_some_and(|w| w.members.iter().any(|g| g.github == self.login)); let is_async_member = map .get("wg-async") - .map_or(false, |w| w.members.iter().any(|g| g.github == self.login)); + .is_some_and(|w| w.members.iter().any(|g| g.github == self.login)); let in_all = map["all"].members.iter().any(|g| g.github == self.login); log::trace!( "{:?} is all?={:?}, triager?={:?}, async?={:?}", @@ -600,7 +599,7 @@ impl IssueRepository { Ok(_) => Ok(true), Err(e) => { if e.downcast_ref::() - .map_or(false, |e| e.status() == Some(StatusCode::NOT_FOUND)) + .is_some_and(|e| e.status() == Some(StatusCode::NOT_FOUND)) { Ok(false) } else { @@ -1918,7 +1917,7 @@ impl Repository { { Ok(_) => return Ok(()), Err(e) => { - if e.downcast_ref::().map_or(false, |e| { + if e.downcast_ref::().is_some_and(|e| { matches!( e.status(), Some(StatusCode::UNPROCESSABLE_ENTITY | StatusCode::CONFLICT) @@ -2827,9 +2826,9 @@ impl GithubClient { return Ok(milestone); } Err(e) => { - if e.downcast_ref::().map_or(false, |e| { - matches!(e.status(), Some(StatusCode::UNPROCESSABLE_ENTITY)) - }) { + if e.downcast_ref::() + .is_some_and(|e| e.status() == Some(StatusCode::UNPROCESSABLE_ENTITY)) + { // fall-through, it already exists } else { return Err(e.context(format!( diff --git a/src/main.rs b/src/main.rs index b864bad0..4b718c97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,10 +42,7 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> { // Loading the workqueue takes ~10-15s, and it's annoying for local rebuilds. // Allow users to opt out of it. - let skip_loading_workqueue = env::var("SKIP_WORKQUEUE") - .ok() - .map(|v| v == "1") - .unwrap_or(false); + let skip_loading_workqueue = env::var("SKIP_WORKQUEUE").is_ok_and(|v| v == "1"); // Load the initial workqueue state from GitHub // In case this fails, we do not want to block triagebot, instead From 6ba8cc3db213fd3f3fd6898345473d78f5cdc5f8 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:30:37 +0200 Subject: [PATCH 37/59] clippy::needless_raw_string_hashes --- parser/src/command.rs | 2 +- src/gh_range_diff.rs | 4 +- .../check_commits/force_push_range_diff.rs | 4 +- src/handlers/major_change.rs | 50 +++++++++---------- src/handlers/project_goals.rs | 2 +- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/parser/src/command.rs b/parser/src/command.rs index 5dd2ad11..c9f57eba 100644 --- a/parser/src/command.rs +++ b/parser/src/command.rs @@ -64,7 +64,7 @@ impl<'a> Input<'a> { pub fn new(input: &'a str, bot: Vec<&'a str>) -> Input<'a> { let bots: Vec<_> = bot.iter().map(|bot| format!(r"(?:@{bot}\b)")).collect(); let bot_re = Regex::new(&format!( - r#"(?i)(?P\br\?)|{bots}"#, + r"(?i)(?P\br\?)|{bots}", bots = bots.join("|") )) .unwrap(); diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index a2c96185..22eb99b7 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -408,10 +408,10 @@ fn process_old_new( writeln!( html, - r#" + r" - "# + " )?; let mut headers = HeaderMap::new(); diff --git a/src/handlers/check_commits/force_push_range_diff.rs b/src/handlers/check_commits/force_push_range_diff.rs index 67d2bd4d..e06d65b5 100644 --- a/src/handlers/check_commits/force_push_range_diff.rs +++ b/src/handlers/check_commits/force_push_range_diff.rs @@ -88,9 +88,9 @@ fn changed_base_commit( let newbase = &compare_after.merge_base_commit.sha; let message = format!( - r#"This PR was rebased onto a different {branch} commit. Here's a [range-diff]({protocol}://{host}/gh-range-diff/{issue_repo}/{oldbase}..{oldhead}/{newbase}..{newhead}) highlighting what actually changed. + r"This PR was rebased onto a different {branch} commit. Here's a [range-diff]({protocol}://{host}/gh-range-diff/{issue_repo}/{oldbase}..{oldhead}/{newbase}..{newhead}) highlighting what actually changed. -*Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.*"# +*Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.*" ); Some(message) diff --git a/src/handlers/major_change.rs b/src/handlers/major_change.rs index 87a77877..cc99fd25 100644 --- a/src/handlers/major_change.rs +++ b/src/handlers/major_change.rs @@ -382,29 +382,29 @@ async fn handle( if new_proposal { let topic_url = zulip_req.url(&ctx.zulip); let comment = format!( - r#"> [!IMPORTANT] -> This issue is *not meant to be used for technical discussion*. There is a **Zulip [stream]** for that. -> Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed. - -
-Concerns or objections can formally be registered here by adding a comment. -

- -``` -@rustbot concern reason-for-concern - -``` -Concerns can be lifted with: -``` -@rustbot resolve reason-for-concern -``` -See documentation at [https://forge.rust-lang.org](https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#what-kinds-of-comments-should-go-on-a-mcp-in-the-compiler-team-repo) - -

-
-{} - -[stream]: {topic_url}"#, + r"> [!IMPORTANT] + > This issue is *not meant to be used for technical discussion*. There is a **Zulip [stream]** for that. + > Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed. + +
+ Concerns or objections can formally be registered here by adding a comment. +

+ + ``` + @rustbot concern reason-for-concern + + ``` + Concerns can be lifted with: + ``` + @rustbot resolve reason-for-concern + ``` + See documentation at [https://forge.rust-lang.org](https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#what-kinds-of-comments-should-go-on-a-mcp-in-the-compiler-team-repo) + +

+
+ {} + + [stream]: {topic_url}", config.open_extra_text.as_deref().unwrap_or_default(), ); issue @@ -683,11 +683,11 @@ async fn process_seconded( .post_comment( &ctx.github, &format!( -r#"The final comment period is now complete, this major change is now **accepted**. +r"The final comment period is now complete, this major change is now **accepted**. As the automated representative, I would like to thank the author for their work and everyone else who contributed to this major change proposal. -*If you think this major change shouldn't have been accepted, feel free to remove the `{}` label and reopen this issue.*"#, +*If you think this major change shouldn't have been accepted, feel free to remove the `{}` label and reopen this issue.*", &config.accept_label, ), ) diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index ef3082c4..0a00b360 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -274,7 +274,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { topic: &zulip_topic_name, }, content: &format!( - r#"New tracking issue goals#{goalnum}.\n* Goal title: {title}\n* Goal owners: {zulip_owners}"# + r"New tracking issue goals#{goalnum}.\n* Goal title: {title}\n* Goal owners: {zulip_owners}" ), }; zulip_req.send(&ctx.zulip).await?; From 5ed9adf48dc97d1d677741ec79f7a018e869b14b Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:29:43 +0200 Subject: [PATCH 38/59] clippy::question_mark --- github-graphql/src/lib.rs | 10 ++-------- parser/src/command/shortcut.rs | 2 +- src/github.rs | 8 +++----- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/github-graphql/src/lib.rs b/github-graphql/src/lib.rs index c834d008..5ef3cb9d 100644 --- a/github-graphql/src/lib.rs +++ b/github-graphql/src/lib.rs @@ -323,17 +323,11 @@ pub mod project_items { impl ProjectV2Item { pub fn status(&self) -> Option<&str> { - let Some(ref status) = self.status else { - return None; - }; - status.as_str() + self.status.as_ref()?.as_str() } pub fn date(&self) -> Option { - let Some(ref date) = self.date else { - return None; - }; - date.as_date() + self.date.as_ref()?.as_date() } } diff --git a/parser/src/command/shortcut.rs b/parser/src/command/shortcut.rs index 495d40f4..35b7dc9e 100644 --- a/parser/src/command/shortcut.rs +++ b/parser/src/command/shortcut.rs @@ -56,7 +56,7 @@ impl ShortcutCommand { #[cfg(test)] fn parse(input: &str) -> Result, Error<'_>> { let mut toks = Tokenizer::new(input); - Ok(ShortcutCommand::parse(&mut toks)?) + ShortcutCommand::parse(&mut toks) } #[test] diff --git a/src/github.rs b/src/github.rs index e30ef148..a6467da4 100644 --- a/src/github.rs +++ b/src/github.rs @@ -678,9 +678,7 @@ impl Issue { self.repository().url(client), self.number, ); - Ok(client - .json::>(client.get(&comment_url)) - .await?) + client.json::>(client.get(&comment_url)).await } pub async fn edit_body(&self, client: &GithubClient, body: &str) -> anyhow::Result<()> { @@ -1067,7 +1065,7 @@ impl Issue { "{}/compare/{before}...{after}", self.repository().url(client) )); - Ok(client.json(req).await?) + client.json(req).await }) .await?; Ok(Some(compare)) @@ -1110,7 +1108,7 @@ impl Issue { self.repository().url(client), self.number )); - Ok(client.json(req).await?) + client.json(req).await } /// Returns the GraphQL ID of this issue. From 41bde068763f3913ba8e88b36f2b6727a4175e16 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:29:02 +0200 Subject: [PATCH 39/59] construct `HashMap` from array --- parser/src/command/shortcut.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/parser/src/command/shortcut.rs b/parser/src/command/shortcut.rs index 35b7dc9e..c271276e 100644 --- a/parser/src/command/shortcut.rs +++ b/parser/src/command/shortcut.rs @@ -33,12 +33,13 @@ impl fmt::Display for ParseError { impl ShortcutCommand { pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result, Error<'a>> { - let mut shortcuts = HashMap::new(); - shortcuts.insert("ready", ShortcutCommand::Ready); - shortcuts.insert("review", ShortcutCommand::Ready); - shortcuts.insert("reviewer", ShortcutCommand::Ready); - shortcuts.insert("author", ShortcutCommand::Author); - shortcuts.insert("blocked", ShortcutCommand::Blocked); + let shortcuts = HashMap::from([ + ("ready", ShortcutCommand::Ready), + ("review", ShortcutCommand::Ready), + ("reviewer", ShortcutCommand::Ready), + ("author", ShortcutCommand::Author), + ("blocked", ShortcutCommand::Blocked), + ]); let mut toks = input.clone(); if let Some(Token::Word(word)) = toks.peek_token()? { From bc1d4ab1457db77ccee77e25ac912d00730aa241 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:26:00 +0200 Subject: [PATCH 40/59] clippy::collapsible{,_else}_if --- parser/src/command/concern.rs | 10 ++++---- parser/src/token.rs | 9 ++++---- src/github.rs | 16 ++++++------- src/handlers/assign.rs | 43 +++++++++++++++++------------------ src/handlers/autolabel.rs | 10 ++++---- src/handlers/milestone_prs.rs | 24 +++++++++---------- src/handlers/notification.rs | 20 ++++++++-------- src/handlers/relnotes.rs | 12 +++++----- src/handlers/rustc_commits.rs | 14 +++++------- src/team_data.rs | 5 ++-- 10 files changed, 79 insertions(+), 84 deletions(-) diff --git a/parser/src/command/concern.rs b/parser/src/command/concern.rs index c0922e93..5d9251d2 100644 --- a/parser/src/command/concern.rs +++ b/parser/src/command/concern.rs @@ -28,11 +28,11 @@ impl ConcernCommand { if let Some(Token::Word(mut action @ ("concern" | "resolve"))) = toks.peek_token()? { toks.next_token()?; - if action == "concern" { - if let Some(Token::Word(sub_action @ "resolve")) = toks.peek_token()? { - toks.next_token()?; - action = sub_action; - } + if action == "concern" + && let Some(Token::Word(sub_action @ "resolve")) = toks.peek_token()? + { + toks.next_token()?; + action = sub_action; } let title = toks.take_line()?.trim().to_string(); diff --git a/parser/src/token.rs b/parser/src/token.rs index f4ba2bfe..6404cb80 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -198,10 +198,11 @@ impl<'a> Tokenizer<'a> { // Attempt to consume a word from the input. // Stop if we encounter whitespace or punctuation. let start = self.cur_pos(); - while self.cur().map_or(false, |(_, ch)| { - !(self.cur_punct().is_some() || ch.is_whitespace()) - }) { - if self.cur().unwrap().1 == '"' { + while let Some((_, ch)) = self.cur() + && self.cur_punct().is_none() + && !ch.is_whitespace() + { + if ch == '"' { let so_far = self.str_from(start); if so_far .strip_prefix('r') diff --git a/src/github.rs b/src/github.rs index a6467da4..084782db 100644 --- a/src/github.rs +++ b/src/github.rs @@ -48,10 +48,10 @@ impl GithubClient { .with_context(|| format!("building reqwest {req_dbg}"))?; let mut resp = self.client.execute(req.try_clone().unwrap()).await?; - if self.retry_rate_limit { - if let Some(sleep) = Self::needs_retry(&resp).await { - resp = self.retry(req, sleep, MAX_ATTEMPTS).await?; - } + if self.retry_rate_limit + && let Some(sleep) = Self::needs_retry(&resp).await + { + resp = self.retry(req, sleep, MAX_ATTEMPTS).await?; } let maybe_err = resp.error_for_status_ref().err(); let body = resp @@ -164,10 +164,10 @@ impl GithubClient { } let resp = self.client.execute(req.try_clone().unwrap()).await?; - if let Some(sleep) = Self::needs_retry(&resp).await { - if remaining_attempts > 0 { - return self.retry(req, sleep, remaining_attempts - 1).await; - } + if let Some(sleep) = Self::needs_retry(&resp).await + && remaining_attempts > 0 + { + return self.retry(req, sleep, remaining_attempts - 1).await; } Ok(resp) diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index e31006c5..56f99777 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -160,14 +160,13 @@ pub(super) async fn handle_input( if let Some(ref mut welcome) = welcome && let Some(contrib) = &config.contributing_url - { - if matches!( + && matches!( event.issue.author_association, AuthorAssociation::FirstTimer | AuthorAssociation::FirstTimeContributor - ) { - welcome.push_str("\n\n"); - welcome.push_str(&messages::contribution_message(contrib, &ctx.username)); - } + ) + { + welcome.push_str("\n\n"); + welcome.push_str(&messages::contribution_message(contrib, &ctx.username)); } welcome } @@ -211,13 +210,13 @@ pub(super) async fn handle_input( set_assignee(ctx, &event.issue, &ctx.github, &assignee).await?; } - if let Some(welcome) = welcome { - if let Err(e) = event.issue.post_comment(&ctx.github, &welcome).await { - log::warn!( - "failed to post welcome comment to {}: {e}", - event.issue.global_id() - ); - } + if let Some(welcome) = welcome + && let Err(e) = event.issue.post_comment(&ctx.github, &welcome).await + { + log::warn!( + "failed to post welcome comment to {}: {e}", + event.issue.global_id() + ); } } @@ -297,11 +296,11 @@ They may take a while to respond." )), _ => None, }; - if let Some(warning) = warning { - if let Err(err) = issue.post_comment(&ctx.github, &warning).await { - // This is a best-effort warning, do not do anything apart from logging if it fails - log::warn!("failed to post reviewer warning comment: {err}"); - } + if let Some(warning) = warning + && let Err(err) = issue.post_comment(&ctx.github, &warning).await + { + // This is a best-effort warning, do not do anything apart from logging if it fails + log::warn!("failed to post reviewer warning comment: {err}"); } } } @@ -801,10 +800,10 @@ async fn find_reviewer_from_names( names: &[String], ) -> Result { // Fast path for self-assign, which is always allowed. - if let [name] = names { - if is_self_assign(&name, requested_by) { - return Ok(ReviewerSelection::from_name(name.clone())); - } + if let [name] = names + && is_self_assign(name, requested_by) + { + return Ok(ReviewerSelection::from_name(name.clone())); } let candidates = diff --git a/src/handlers/autolabel.rs b/src/handlers/autolabel.rs index 7261675b..dd490d09 100644 --- a/src/handlers/autolabel.rs +++ b/src/handlers/autolabel.rs @@ -139,12 +139,10 @@ pub(super) async fn parse_input( name: label.to_owned(), }); } - } else { - if cfg.new_issue && event.action == IssuesAction::Opened { - autolabels.push(Label { - name: label.to_owned(), - }); - } + } else if cfg.new_issue && event.action == IssuesAction::Opened { + autolabels.push(Label { + name: label.to_owned(), + }); } } diff --git a/src/handlers/milestone_prs.rs b/src/handlers/milestone_prs.rs index cf65c337..8444e744 100644 --- a/src/handlers/milestone_prs.rs +++ b/src/handlers/milestone_prs.rs @@ -58,18 +58,18 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { e.issue.set_milestone(&ctx.github, &version).await?; let files = e.issue.diff(&ctx.github).await?; - if let Some(files) = files { - if let Some(cargo) = files.iter().find(|fd| fd.filename == "src/tools/cargo") { - // The webhook timeout of 10 seconds can be too short, so process in - // the background. - let diff = cargo.patch.clone(); - tokio::task::spawn(async move { - let gh = GithubClient::new_from_env(); - if let Err(e) = milestone_cargo(&gh, &version, &diff).await { - log::error!("failed to milestone cargo: {e:?}"); - } - }); - } + if let Some(files) = files + && let Some(cargo) = files.iter().find(|fd| fd.filename == "src/tools/cargo") + { + // The webhook timeout of 10 seconds can be too short, so process in + // the background. + let diff = cargo.patch.clone(); + tokio::task::spawn(async move { + let gh = GithubClient::new_from_env(); + if let Err(e) = milestone_cargo(&gh, &version, &diff).await { + log::error!("failed to milestone cargo: {e:?}"); + } + }); } Ok(()) diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index f410e597..d18d795c 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -19,14 +19,14 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { return Ok(()); }; - if let Event::Issue(e) = event { - if !matches!( + if let Event::Issue(e) = event + && !matches!( e.action, github::IssuesAction::Opened | github::IssuesAction::Edited - ) { - // no change in issue's body for these events, so skip - return Ok(()); - } + ) + { + // no change in issue's body for these events, so skip + return Ok(()); } let short_description = match event { @@ -44,10 +44,10 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { if event.issue().unwrap().repository().organization == "serde-rs" { // Only add dtolnay on new issues/PRs, not on comments to old PRs and // issues. - if let Event::Issue(e) = event { - if e.action == github::IssuesAction::Opened { - caps.insert("dtolnay"); - } + if let Event::Issue(e) = event + && e.action == github::IssuesAction::Opened + { + caps.insert("dtolnay"); } } diff --git a/src/handlers/relnotes.rs b/src/handlers/relnotes.rs index 42938d07..803f954e 100644 --- a/src/handlers/relnotes.rs +++ b/src/handlers/relnotes.rs @@ -51,12 +51,12 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { if let Some(paired) = state.data.relnotes_issue { // Already has a paired release notes issue. - if let IssuesAction::Milestoned = &e.action { - if let Some(milestone) = &e.issue.milestone { - ctx.github - .set_milestone(&e.issue.repository().to_string(), &milestone, paired) - .await?; - } + if let IssuesAction::Milestoned = &e.action + && let Some(milestone) = &e.issue.milestone + { + ctx.github + .set_milestone(&e.issue.repository().to_string(), milestone, paired) + .await?; } return Ok(()); diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index 11234159..9d1a0174 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -103,14 +103,12 @@ pub async fn synchronize_commits_inner(ctx: &Context, starter: Option<(String, u }; let parent_sha = gc.parents.remove(0).sha; - if pr.is_none() { - if let Some(tail) = gc.commit.message.strip_prefix("Auto merge of #") { - if let Some(end) = tail.find(' ') { - if let Ok(number) = tail[..end].parse::() { - pr = Some(number); - } - } - } + if pr.is_none() + && let Some(tail) = gc.commit.message.strip_prefix("Auto merge of #") + && let Some((number, _)) = tail.split_once(' ') + && let Ok(number) = number.parse::() + { + pr = Some(number); } let Some(pr) = pr.take() else { diff --git a/src/team_data.rs b/src/team_data.rs index 6c078c59..af8fed98 100644 --- a/src/team_data.rs +++ b/src/team_data.rs @@ -135,10 +135,9 @@ impl CachedTeamItem { value, last_download, } = &*value + && *last_download + CACHE_DURATION > now { - if *last_download + CACHE_DURATION > now { - return Ok(value.clone()); - } + return Ok(value.clone()); } } match download::(client, base_url, &self.url_path).await { From ea0801a3a9fc74f92a66dd0f6af63dadea6e14c4 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 00:25:34 +0200 Subject: [PATCH 41/59] use `Result::ok_or` for trying out multiple things --- src/github.rs | 22 +++++----------------- src/zulip.rs | 22 ++++++++-------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/src/github.rs b/src/github.rs index 084782db..0aa41dc3 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2475,23 +2475,11 @@ impl RequestSend for RequestBuilder { /// Finds the token in the user's environment, panicking if no suitable token /// can be found. pub fn default_token_from_env() -> String { - match std::env::var("GITHUB_TOKEN") { - Ok(v) => return v, - Err(_) => (), - } - - // kept for retrocompatibility but usage is discouraged and will be deprecated - match std::env::var("GITHUB_API_TOKEN") { - Ok(v) => return v, - Err(_) => (), - } - - match get_token_from_git_config() { - Ok(v) => return v, - Err(_) => (), - } - - panic!("could not find token in GITHUB_TOKEN, GITHUB_API_TOKEN or .gitconfig/github.oath-token") + std::env::var("GITHUB_TOKEN") + // kept for retrocompatibility but usage is discouraged and will be deprecated + .or_else(|_| std::env::var("GITHUB_API_TOKEN")) + .or_else(|_| get_token_from_git_config()) + .expect("could not find token in GITHUB_TOKEN, GITHUB_API_TOKEN or .gitconfig/github.oath-token") } fn get_token_from_git_config() -> anyhow::Result { diff --git a/src/zulip.rs b/src/zulip.rs index 112e38bd..c3ad3d0e 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -137,20 +137,14 @@ pub async fn webhook( pub fn get_token_from_env() -> Result { // ZULIP_WEBHOOK_SECRET is preferred, ZULIP_TOKEN is kept for retrocompatibility but will be deprecated - match std::env::var("ZULIP_WEBHOOK_SECRET") { - Ok(v) => return Ok(v), - Err(_) => (), - } - - match std::env::var("ZULIP_TOKEN") { - Ok(v) => return Ok(v), - Err(_) => (), - } - - log::error!( - "Cannot communicate with Zulip: neither ZULIP_WEBHOOK_SECRET or ZULIP_TOKEN are set." - ); - anyhow::bail!("Cannot communicate with Zulip."); + std::env::var("ZULIP_WEBHOOK_SECRET") + .or_else(|_| std::env::var("ZULIP_TOKEN")) + .or_else(|_| { + log::error!( + "Cannot communicate with Zulip: neither ZULIP_WEBHOOK_SECRET or ZULIP_TOKEN are set." + ); + Err(anyhow::anyhow!("Cannot communicate with Zulip.")) + }) } /// Processes a Zulip webhook. From 05ecbd49f52758b2bcc88ac92e793126e7bf2076 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 15 Sep 2025 23:12:56 +0200 Subject: [PATCH 42/59] use `as_deref` to avoid allocating a String --- src/handlers/project_goals.rs | 6 ++---- src/zulip.rs | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/handlers/project_goals.rs b/src/handlers/project_goals.rs index 0a00b360..fdea630e 100644 --- a/src/handlers/project_goals.rs +++ b/src/handlers/project_goals.rs @@ -262,10 +262,8 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { return Ok(()); } let zulip_topic_name = zulip_topic_name(issue); - let zulip_owners = match zulip_owners(&ctx.team, issue).await? { - Some(names) => names, - None => format!("(no owners assigned)"), - }; + let zulip_owners = zulip_owners(&ctx.team, issue).await?; + let zulip_owners = zulip_owners.as_deref().unwrap_or("(no owners assigned)"); let title = &issue.title; let goalnum = issue.number; let zulip_req = crate::zulip::MessageApiRequest { diff --git a/src/zulip.rs b/src/zulip.rs index c3ad3d0e..8e077a02 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -385,12 +385,11 @@ async fn team_status_cmd(ctx: &Context, team_name: &str) -> anyhow::Result Date: Sun, 14 Sep 2025 14:32:14 +0200 Subject: [PATCH 43/59] `RustcFormat::store_version`: take params by reference --- src/changelogs/rustc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/changelogs/rustc.rs b/src/changelogs/rustc.rs index bf3a7026..5a09ad19 100644 --- a/src/changelogs/rustc.rs +++ b/src/changelogs/rustc.rs @@ -32,7 +32,7 @@ impl<'a> RustcFormat<'a> { if let NodeValue::Heading(NodeHeading { level: 1, .. }) = child_data.value { if let Some(h1) = self.current_h1.take() { - self.store_version(h1, section_ast)?; + self.store_version(&h1, §ion_ast)?; } let Some(h1_child_data) = child.first_child().map(|c| c.data.borrow()) else { @@ -51,16 +51,16 @@ impl<'a> RustcFormat<'a> { } } if let Some(h1) = self.current_h1.take() { - self.store_version(h1, section_ast)?; + self.store_version(&h1, §ion_ast)?; } Ok(self.result) } - fn store_version(&mut self, h1: String, body: Vec<&'a AstNode<'a>>) -> anyhow::Result<()> { + fn store_version(&mut self, h1: &str, body: &[&'a AstNode<'a>]) -> anyhow::Result<()> { // Create a document with only the contents of this section let document = self.arena.alloc(NodeValue::Document.into()); - for child in &body { + for child in body { document.append(child); } From 4ea6b2043e9aa27c8c442ec828448a63c98e8b6f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 14:46:12 +0200 Subject: [PATCH 44/59] `config`: introduce `MaybeConfig` type alias pointed out by `clippy::type_complexity` --- src/config.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/config.rs b/src/config.rs index c0124906..ed418eae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,9 +9,10 @@ use tracing as log; pub(crate) static CONFIG_FILE_NAME: &str = "triagebot.toml"; const REFRESH_EVERY: Duration = Duration::from_secs(2 * 60); // Every two minutes -static CONFIG_CACHE: LazyLock< - RwLock, ConfigurationError>, Instant)>>, -> = LazyLock::new(|| RwLock::new(HashMap::new())); +type MaybeConfig = Result, ConfigurationError>; + +static CONFIG_CACHE: LazyLock>> = + LazyLock::new(|| RwLock::new(HashMap::new())); // This struct maps each possible option of the triagebot.toml. // See documentation of options at: https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration @@ -450,10 +451,7 @@ pub(crate) struct ReviewRequestedConfig { pub(crate) add_labels: Vec, } -pub(crate) async fn get( - gh: &GithubClient, - repo: &Repository, -) -> Result, ConfigurationError> { +pub(crate) async fn get(gh: &GithubClient, repo: &Repository) -> MaybeConfig { if let Some(config) = get_cached_config(&repo.full_name) { log::trace!("returning config for {} from cache", repo.full_name); config @@ -625,7 +623,7 @@ pub(crate) struct RangeDiffConfig {} #[serde(deny_unknown_fields)] pub(crate) struct ReviewChangesSinceConfig {} -fn get_cached_config(repo: &str) -> Option, ConfigurationError>> { +fn get_cached_config(repo: &str) -> Option { let cache = CONFIG_CACHE.read().unwrap(); cache.get(repo).and_then(|(config, fetch_time)| { if fetch_time.elapsed() < REFRESH_EVERY { @@ -636,10 +634,7 @@ fn get_cached_config(repo: &str) -> Option, ConfigurationErro }) } -async fn get_fresh_config( - gh: &GithubClient, - repo: &Repository, -) -> Result, ConfigurationError> { +async fn get_fresh_config(gh: &GithubClient, repo: &Repository) -> MaybeConfig { let contents = gh .raw_file(&repo.full_name, &repo.default_branch, CONFIG_FILE_NAME) .await From 42e40375bc738c5f9b04edb5447f2b7f907eaac2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 16:20:25 +0200 Subject: [PATCH 45/59] avoid eager/useless `format!`s clippy::{format_collect,format_push_string,useless_format} --- src/handlers/check_commits/issue_links.rs | 7 +++++-- src/handlers/check_commits/no_mentions.rs | 8 ++++++-- src/handlers/check_commits/no_merges.rs | 2 +- src/handlers/ping.rs | 8 +++++--- src/handlers/types_planning_updates.rs | 12 +++++------- src/notification_listing.rs | 13 ++++++++----- src/zulip.rs | 7 ++++--- 7 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/handlers/check_commits/issue_links.rs b/src/handlers/check_commits/issue_links.rs index e0c9e85a..2787e70d 100644 --- a/src/handlers/check_commits/issue_links.rs +++ b/src/handlers/check_commits/issue_links.rs @@ -1,3 +1,4 @@ +use std::fmt::Write; use std::sync::LazyLock; use regex::Regex; @@ -30,8 +31,10 @@ pub(super) fn issue_links_in_commits( .any(|i| c.commit.message.starts_with(i)) }) .filter(|c| does_match(&c.commit.message)) - .map(|c| format!("- {}\n", c.sha)) - .collect::(); + .fold(String::new(), |mut commits, c| { + _ = writeln!(commits, "- {}", c.sha); + commits + }); if issue_links_commits.is_empty() { None diff --git a/src/handlers/check_commits/no_mentions.rs b/src/handlers/check_commits/no_mentions.rs index d06691d2..c963852f 100644 --- a/src/handlers/check_commits/no_mentions.rs +++ b/src/handlers/check_commits/no_mentions.rs @@ -1,6 +1,8 @@ //! Purpose: When opening a PR, or pushing new changes, check for github mentions //! in commits and notify the user of our no-mentions in commits policy. +use std::fmt::Write; + use crate::{config::NoMentionsConfig, github::GithubCommit}; pub(super) fn mentions_in_commits( @@ -22,8 +24,10 @@ pub(super) fn mentions_in_commits( let mentions = parser::get_mentions(&c.commit.message); !mentions.is_empty() && mentions.iter().any(|m| *m != "rustbot") }) - .map(|c| format!("- {}\n", c.sha)) - .collect::(); + .fold(String::new(), |mut commits, c| { + _ = writeln!(commits, "- {}", c.sha); + commits + }); if mentions_commits.is_empty() { None diff --git a/src/handlers/check_commits/no_merges.rs b/src/handlers/check_commits/no_merges.rs index 144f04b2..2b25990f 100644 --- a/src/handlers/check_commits/no_merges.rs +++ b/src/handlers/check_commits/no_merges.rs @@ -53,7 +53,7 @@ fn get_default_message<'a>( default_branch: &str, commits: impl IntoIterator, ) -> String { - let mut message = format!( + let mut message = String::from( "The following commits have merge commits (commits with multiple parents) in your changes. \ We have a [no merge policy](https://rustc-dev-guide.rust-lang.org/git.html#no-merge-policy) \ so these commits will need to be removed for this pull request to be merged. diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 898f2dc9..7e7dcd4d 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -4,6 +4,8 @@ //! //! Parsing is done in the `parser::command::ping` module. +use std::borrow::Cow; + use crate::{ config::PingConfig, github::{self, Event}, @@ -89,10 +91,10 @@ pub(super) async fn handle_command( } } - let ping_msg = if users.is_empty() { - format!("no known users to ping?") + let ping_msg: Cow<_> = if users.is_empty() { + "no known users to ping?".into() } else { - format!("cc {}", users.join(" ")) + format!("cc {}", users.join(" ")).into() }; let comment = format!("{}\n\n{}", config.message, ping_msg); event diff --git a/src/handlers/types_planning_updates.rs b/src/handlers/types_planning_updates.rs index 9c2fedd6..846b3a1a 100644 --- a/src/handlers/types_planning_updates.rs +++ b/src/handlers/types_planning_updates.rs @@ -27,19 +27,17 @@ impl Job for TypesPlanningMeetingThreadOpenJob { if first_monday.month() == today.month() { return Ok(()); } - let meeting_date_string = first_monday.format("%Y-%m-%d").to_string(); - let message = format!( - "\ + let meeting_date_string = first_monday.format("%Y-%m-%d"); + let message = "\ Hello @*T-types/meetings*. Monthly planning meeting in one week.\n\ This is a reminder to update the current [roadmap tracking issues](https://github.com/rust-lang/types-team/issues?q=is%3Aissue+is%3Aopen+label%3Aroadmap-tracking-issue).\n\ - Extra reminders will be sent later this week." - ); + Extra reminders will be sent later this week."; let zulip_req = crate::zulip::MessageApiRequest { recipient: Recipient::Stream { id: TYPES_MEETINGS_STREAM, topic: &format!("{meeting_date_string} planning meeting"), }, - content: &message, + content: message, }; zulip_req.send(&ctx.zulip).await?; @@ -51,7 +49,7 @@ impl Job for TypesPlanningMeetingThreadOpenJob { let noon = NaiveTime::from_hms_opt(12, 0, 0).unwrap(); let thursday_at_noon = Utc.from_utc_datetime(&thursday.and_time(noon)); let metadata = serde_json::value::to_value(PlanningMeetingUpdatesPingMetadata { - date_string: meeting_date_string, + date_string: meeting_date_string.to_string(), }) .unwrap(); schedule_job( diff --git a/src/notification_listing.rs b/src/notification_listing.rs index 1c104f3d..006f0fcb 100644 --- a/src/notification_listing.rs +++ b/src/notification_listing.rs @@ -1,3 +1,4 @@ +use std::fmt::Write; use std::sync::Arc; use anyhow::Context as _; @@ -39,7 +40,7 @@ pub async fn notifications( out.push_str(""); out.push_str(""); - out.push_str(&format!("

Pending notifications for {}

", user)); + _ = write!(out, "

Pending notifications for {user}

"); if notifications.is_empty() { out.push_str("

You have no pending notifications! :)

"); @@ -47,7 +48,8 @@ pub async fn notifications( out.push_str("
    "); for notification in notifications { out.push_str("
  1. "); - out.push_str(&format!( + _ = write!( + out, "{}", notification.origin_url, notification @@ -59,9 +61,10 @@ pub async fn notifications( .replace('>', ">") .replace('"', """) .replace('\'', "'"), - )); + ); if let Some(metadata) = ¬ification.metadata { - out.push_str(&format!( + _ = write!( + out, "
    • {}
    ", metadata .replace('&', "&") @@ -69,7 +72,7 @@ pub async fn notifications( .replace('>', ">") .replace('"', """) .replace('\'', "'"), - )); + ); } out.push_str("
  2. "); } diff --git a/src/zulip.rs b/src/zulip.rs index 8e077a02..7426e4a2 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -814,8 +814,9 @@ async fn acknowledge( } else { let mut resp = String::from("Acknowledged:\n"); for deleted in deleted { - resp.push_str(&format!( - " * [{}]({}){}\n", + _ = writeln!( + resp, + " * [{}]({}){}", deleted .short_description .as_deref() @@ -824,7 +825,7 @@ async fn acknowledge( deleted .metadata .map_or(String::new(), |m| format!(" ({m})")), - )); + ); } resp }; From 801891417cc1a2cea55aaec0254aabb3f38b8357 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 16:51:27 +0200 Subject: [PATCH 46/59] replace `std::iter::once(_)` with `[_]` much more concise --- src/github.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/github.rs b/src/github.rs index 0aa41dc3..4ea9b8d8 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1501,16 +1501,11 @@ impl Repository { let filters = filters .iter() .map(|(key, val)| format!("{key}={val}")) - .chain(std::iter::once(format!( - "labels={}", - include_labels.join(",") - ))) - .chain(std::iter::once("filter=all".to_owned())) - .chain(std::iter::once(format!("sort={}", ordering.sort,))) - .chain(std::iter::once( - format!("direction={}", ordering.direction,), - )) - .chain(std::iter::once(format!("per_page={}", ordering.per_page,))) + .chain([format!("labels={}", include_labels.join(","))]) + .chain(["filter=all".to_owned()]) + .chain([format!("sort={}", ordering.sort)]) + .chain([format!("direction={}", ordering.direction)]) + .chain([format!("per_page={}", ordering.per_page)]) .collect::>() .join("&"); format!( @@ -1533,7 +1528,7 @@ impl Repository { .map(|(key, val)| format!("{key}:{val}")) .chain(include_labels.iter().map(|label| format!("label:{label}"))) .chain(exclude_labels.iter().map(|label| format!("-label:{label}"))) - .chain(std::iter::once(format!("repo:{}", self.full_name))) + .chain([format!("repo:{}", self.full_name)]) .collect::>() .join("+"); format!( From 93ad1fa4a031840170efd949a0061a6498d9da75 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 16:53:00 +0200 Subject: [PATCH 47/59] use `Itertools::format` --- src/github.rs | 25 ++++++++++++------------- src/handlers/assign.rs | 5 +++-- src/handlers/check_commits.rs | 8 ++++---- src/handlers/concern.rs | 3 ++- src/handlers/mentions.rs | 4 ++-- src/handlers/ping.rs | 3 ++- src/handlers/relnotes.rs | 3 ++- src/handlers/types_planning_updates.rs | 3 ++- src/zulip.rs | 10 +++++----- 9 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/github.rs b/src/github.rs index 4ea9b8d8..4da9aae5 100644 --- a/src/github.rs +++ b/src/github.rs @@ -4,6 +4,7 @@ use async_trait::async_trait; use bytes::Bytes; use chrono::{DateTime, FixedOffset, Utc}; use futures::{FutureExt, future::BoxFuture}; +use itertools::Itertools; use octocrab::models::{Author, AuthorAssociation}; use regex::Regex; use reqwest::header::{AUTHORIZATION, USER_AGENT}; @@ -618,7 +619,7 @@ pub(crate) struct UnknownLabels { // NOTE: This is used to post the Github comment; make sure it's valid markdown. impl fmt::Display for UnknownLabels { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Unknown labels: {}", &self.labels.join(", ")) + write!(f, "Unknown labels: {}", self.labels.iter().format(", ")) } } @@ -1501,13 +1502,12 @@ impl Repository { let filters = filters .iter() .map(|(key, val)| format!("{key}={val}")) - .chain([format!("labels={}", include_labels.join(","))]) + .chain([format!("labels={}", include_labels.iter().format(","))]) .chain(["filter=all".to_owned()]) .chain([format!("sort={}", ordering.sort)]) .chain([format!("direction={}", ordering.direction)]) .chain([format!("per_page={}", ordering.per_page)]) - .collect::>() - .join("&"); + .format("&"); format!( "{}/repos/{}/{}?{}", client.api_url, self.full_name, endpoint, filters @@ -1529,8 +1529,7 @@ impl Repository { .chain(include_labels.iter().map(|label| format!("label:{label}"))) .chain(exclude_labels.iter().map(|label| format!("-label:{label}"))) .chain([format!("repo:{}", self.full_name)]) - .collect::>() - .join("+"); + .format("+"); format!( "{}/search/issues?q={}&sort={}&order={}&per_page={}&page={}", client.api_url, @@ -1631,7 +1630,7 @@ impl Repository { client: &GithubClient, refname: &str, ) -> anyhow::Result { - let url = format!("{}/git/ref/{}", self.url(client), refname); + let url = format!("{}/git/ref/{refname}", self.url(client)); client .json(client.get(&url)) .await @@ -2662,11 +2661,11 @@ impl GithubClient { ) -> anyhow::Result { let result: serde_json::Value = self.graphql_query_with_errors(query, vars).await?; if let Some(errors) = result["errors"].as_array() { - let messages: Vec<_> = errors + let messages = errors .iter() .map(|err| err["message"].as_str().unwrap_or_default()) - .collect(); - anyhow::bail!("error: {}", messages.join("\n")); + .format("\n"); + anyhow::bail!("error: {messages}"); } Ok(result) } @@ -2697,11 +2696,11 @@ impl GithubClient { { return Ok(None); } - let messages: Vec<_> = errors + let messages = errors .iter() .map(|err| err["message"].as_str().unwrap_or_default()) - .collect(); - anyhow::bail!("failed to query user: {}", messages.join("\n")); + .format("\n"); + anyhow::bail!("failed to query user: {messages}"); } anyhow::bail!("query for user {user} failed, no error message? {user_info:?}"); } diff --git a/src/handlers/assign.rs b/src/handlers/assign.rs index 56f99777..46525d43 100644 --- a/src/handlers/assign.rs +++ b/src/handlers/assign.rs @@ -31,6 +31,7 @@ use crate::{ interactions::EditIssueBody, }; use anyhow::{Context as _, bail}; +use itertools::Itertools; use octocrab::models::AuthorAssociation; use parser::command::assign::AssignCommand; use parser::command::{Command, Input}; @@ -736,7 +737,7 @@ impl fmt::Display for FindReviewerError { "No reviewers could be found from initial request `{}`\n\ This repo may be misconfigured.\n\ Use `r?` to specify someone else to assign.", - initial.join(",") + initial.iter().format(",") ) } FindReviewerError::ReviewerOffRotation { username } => { @@ -1084,7 +1085,7 @@ async fn candidate_reviewers_from_names<'a>( log::debug!( "Candidate reviewer results for review request `{}` on `{}`: {:?}", - names.join(", "), + names.iter().format(", "), issue.global_id(), candidates ); diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index 1fa8d504..1f0eba96 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use anyhow::Context as _; use anyhow::bail; +use itertools::Itertools; use super::Context; use crate::interactions::ErrorComment; @@ -277,12 +278,11 @@ async fn handle_new_state( // Format the warnings for user consumption on Github fn warning_from_warnings(warnings: &[String]) -> String { - let warnings: Vec<_> = warnings + let warnings = warnings .iter() .map(|warning| warning.trim().replace('\n', "\n ")) - .map(|warning| format!("* {warning}")) - .collect(); - format!(":warning: **Warning** :warning:\n\n{}", warnings.join("\n")) + .format_with("\n", |warning, f| f(&format_args!("* {warning}"))); + format!(":warning: **Warning** :warning:\n\n{warnings}") } // Calculate the label changes diff --git a/src/handlers/concern.rs b/src/handlers/concern.rs index 3ed0d146..43237620 100644 --- a/src/handlers/concern.rs +++ b/src/handlers/concern.rs @@ -1,6 +1,7 @@ use std::fmt::Write; use anyhow::{Context as _, bail}; +use itertools::Itertools; use crate::{ config::ConcernConfig, @@ -142,7 +143,7 @@ pub(super) async fn handle_command( .await { tracing::error!("unable to add concern labels: {err:?}"); - let labels = config.labels.join(", "); + let labels = config.labels.iter().format(", "); issue.post_comment( &ctx.github, &format!("*Psst, I was unable to add the labels ({labels}), could someone do it for me.*"), diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 254eba71..7fe120d3 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -133,13 +133,13 @@ pub(super) async fn handle_input( relevant_file_paths .iter() .map(|f| f.to_string_lossy()) - .join(", ") + .format(", ") ) .unwrap(), }, } if !cc.is_empty() { - write!(result, "\n\ncc {}", cc.join(", ")).unwrap(); + write!(result, "\n\ncc {}", cc.iter().format(", ")).unwrap(); } state.data.entries.push(entry); } diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 7e7dcd4d..2b76d3d6 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -12,6 +12,7 @@ use crate::{ handlers::Context, interactions::ErrorComment, }; +use itertools::Itertools; use parser::command::ping::PingCommand; pub(super) async fn handle_command( @@ -94,7 +95,7 @@ pub(super) async fn handle_command( let ping_msg: Cow<_> = if users.is_empty() { "no known users to ping?".into() } else { - format!("cc {}", users.join(" ")).into() + format!("cc {}", users.into_iter().format(" ")).into() }; let comment = format!("{}\n\n{}", config.message, ping_msg); event diff --git a/src/handlers/relnotes.rs b/src/handlers/relnotes.rs index 803f954e..326affd4 100644 --- a/src/handlers/relnotes.rs +++ b/src/handlers/relnotes.rs @@ -12,6 +12,7 @@ //! the absence of a milestone, T-release is responsible for ascertaining which release is //! associated with the issue. +use itertools::Itertools; use serde::{Deserialize, Serialize}; use crate::{ @@ -108,7 +109,7 @@ If this change is notable enough for inclusion in the blog post then this sectio ", pr_number = e.issue.number, people = [&e.issue.user].into_iter().chain(e.issue.assignees.iter()) - .map(|v| format!("@{}", v.login)).collect::>().join(", "), + .format_with(", ", |v, f| f(&format_args!("@{}", v.login))), pr_title = e.issue.title, pr_url = e.issue.html_url, ); diff --git a/src/handlers/types_planning_updates.rs b/src/handlers/types_planning_updates.rs index 846b3a1a..cb9fbab7 100644 --- a/src/handlers/types_planning_updates.rs +++ b/src/handlers/types_planning_updates.rs @@ -5,6 +5,7 @@ use crate::zulip::api::Recipient; use anyhow::Context as _; use async_trait::async_trait; use chrono::{Datelike, Duration, NaiveTime, TimeZone, Utc}; +use itertools::Itertools; use serde::{Deserialize, Serialize}; const TYPES_REPO: &str = "rust-lang/types-team"; @@ -152,7 +153,7 @@ pub async fn request_updates( issues_needs_updates.push(format!("- [Issue #{}]({})", issue.number, issue.html_url)); } - let issue_list = issues_needs_updates.join("\n"); + let issue_list = issues_needs_updates.iter().format("\n"); let message = format!("The following issues still need updates:\n\n{issue_list}"); diff --git a/src/zulip.rs b/src/zulip.rs index 7426e4a2..aad0377b 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -24,6 +24,7 @@ use axum::Json; use axum::extract::State; use axum::extract::rejection::JsonRejection; use axum::response::IntoResponse; +use itertools::Itertools; use rust_team_data::v1::{TeamKind, TeamMember}; use std::cmp::Reverse; use std::fmt::Write as _; @@ -430,7 +431,7 @@ async fn team_status_cmd(ctx: &Context, team_name: &str) -> anyhow::Result anyhow::Result>() - .join("\n"); + .format("\n"); format!( "`rust-lang/rust` PRs in your review queue ({} {}):\n{prs}\n\n", assigned_prs.len(), @@ -618,7 +618,7 @@ async fn whoami_cmd(ctx: &Context, gh_id: u64) -> anyhow::Result> } ); if !member.roles.is_empty() { - write!(entry, " (roles: {})", member.roles.join(", ")).unwrap(); + write!(entry, " (roles: {})", member.roles.iter().format(", ")).unwrap(); } entry }) From 5930e34db51ba4accab25acdfd83218740511052 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 16:54:05 +0200 Subject: [PATCH 48/59] replace `.ok_or_else(|| anyhow::anyhow!` with `.context(` --- src/github.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/github.rs b/src/github.rs index 4da9aae5..7515b19a 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1,5 +1,5 @@ use crate::team_data::TeamClient; -use anyhow::{Context, anyhow}; +use anyhow::Context; use async_trait::async_trait; use bytes::Bytes; use chrono::{DateTime, FixedOffset, Utc}; @@ -1710,13 +1710,13 @@ impl Repository { } let target = data .data - .ok_or_else(|| anyhow::anyhow!("No data returned."))? + .context("No data returned.")? .repository - .ok_or_else(|| anyhow::anyhow!("No repository."))? + .context("No repository.")? .ref_ - .ok_or_else(|| anyhow::anyhow!("No ref."))? + .context("No ref.")? .target - .ok_or_else(|| anyhow::anyhow!("No target."))?; + .context("No target.")?; let GitObject::Commit(commit) = target else { anyhow::bail!("unexpected target type {target:?}") }; @@ -2989,9 +2989,9 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests { } let repository = data .data - .ok_or_else(|| anyhow::anyhow!("No data returned."))? + .context("No data returned.")? .repository - .ok_or_else(|| anyhow::anyhow!("No repository."))?; + .context("No repository.")?; prs.extend(repository.pull_requests.nodes); let page_info = repository.pull_requests.page_info; if !page_info.has_next_page || page_info.end_cursor.is_none() { @@ -3126,15 +3126,15 @@ async fn project_items_by_status( } let items = data .data - .ok_or_else(|| anyhow!("No data returned."))? + .context("No data returned.")? .organization - .ok_or_else(|| anyhow!("Organization not found."))? + .context("Organization not found.")? .project_v2 - .ok_or_else(|| anyhow!("Project not found."))? + .context("Project not found.")? .items; let filtered = items .nodes - .ok_or_else(|| anyhow!("Malformed response."))? + .context("Malformed response.")? .into_iter() .flatten() .filter(|item| status_filter(item.status())); From 3a1133f7ffc8e2a2a26093993ae663c86e20a239 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Sep 2025 17:11:06 +0200 Subject: [PATCH 49/59] don't destructure tuple for comparison --- src/github.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/github.rs b/src/github.rs index 7515b19a..e7d51ad9 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1415,9 +1415,7 @@ impl Repository { .collect(); // `is: pull-request` indicates the query to retrieve PRs only - let is_pr = filters - .iter() - .any(|&(key, value)| key == "is" && value == "pull-request"); + let is_pr = filters.contains(&("is", "pull-request")); // There are some cases that can only be handled by the search API: // 1. When using negating label filters (exclude_labels) @@ -1524,7 +1522,7 @@ impl Repository { ) -> String { let filters = filters .iter() - .filter(|&&(key, val)| !(key == "state" && val == "all")) + .filter(|filter| **filter != ("state", "all")) .map(|(key, val)| format!("{key}:{val}")) .chain(include_labels.iter().map(|label| format!("label:{label}"))) .chain(exclude_labels.iter().map(|label| format!("-label:{label}"))) From 929f3d43d0b0bb7c48b9047754671ced3645f0e6 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 20:41:49 +0200 Subject: [PATCH 50/59] `expect` some lints --- src/bin/compiler.rs | 1 + src/bin/types.rs | 1 + src/handlers.rs | 4 ++++ src/handlers/autolabel.rs | 2 ++ src/handlers/check_commits.rs | 4 ++++ src/handlers/check_commits/validate_config.rs | 4 ++++ src/handlers/nominate.rs | 4 ++++ src/handlers/ping.rs | 8 ++++++++ src/zulip.rs | 2 ++ 9 files changed, 30 insertions(+) diff --git a/src/bin/compiler.rs b/src/bin/compiler.rs index ac71aed6..9193c656 100644 --- a/src/bin/compiler.rs +++ b/src/bin/compiler.rs @@ -7,6 +7,7 @@ async fn main() -> anyhow::Result<()> { let args: Vec = std::env::args().collect(); if args.len() == 2 { + #[expect(clippy::single_match, reason = "might add more variants later")] match &*args[1] { "backlog_bonanza" => { let agenda = agenda::compiler_backlog_bonanza(); diff --git a/src/bin/types.rs b/src/bin/types.rs index 939e62eb..58518c14 100644 --- a/src/bin/types.rs +++ b/src/bin/types.rs @@ -7,6 +7,7 @@ async fn main() -> anyhow::Result<()> { let args: Vec = std::env::args().collect(); if args.len() == 2 { + #[expect(clippy::single_match, reason = "might add more variants later")] match &*args[1] { "planning" => { let agenda = agenda::types_planning(); diff --git a/src/handlers.rs b/src/handlers.rs index 4f6a104d..10302130 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -61,6 +61,10 @@ mod shortcut; mod transfer; pub mod types_planning_updates; +#[expect( + clippy::collapsible_if, + reason = "we check the preconditions in the outer if, and handle errors inside" +)] pub async fn handle(ctx: &Context, host: &str, event: &Event) -> Vec { let config = config::get(&ctx.github, event.repo()).await; if let Err(e) = &config { diff --git a/src/handlers/autolabel.rs b/src/handlers/autolabel.rs index dd490d09..55e2d8f1 100644 --- a/src/handlers/autolabel.rs +++ b/src/handlers/autolabel.rs @@ -108,6 +108,7 @@ pub(super) async fn parse_input( let is_opened_as_draft = is_opened && event.issue.draft; let is_converted_to_draft = event.action == IssuesAction::ConvertedToDraft; + #[expect(clippy::if_same_then_else, reason = "suggested code looks ugly")] if cfg.new_pr && (is_opened_non_draft || is_ready_for_review) { autolabels.push(Label { name: label.to_owned(), @@ -120,6 +121,7 @@ pub(super) async fn parse_input( // If a PR is converted to draft or closed, remove all the "new PR" labels. // Same for "new draft" labels when the PR is ready for review or closed. + #[expect(clippy::if_same_then_else, reason = "suggested code looks ugly")] if cfg.new_pr && matches!( event.action, diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index 1f0eba96..1a603286 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -124,6 +124,10 @@ pub(super) async fn handle( warnings.extend(issue_links::issue_links_in_commits(issue_links, &commits)); } + #[expect( + clippy::collapsible_if, + reason = "we always check for `config` in the outer `if`" + )] if let Some(no_merges) = &config.no_merges { if let Some(warn) = no_merges::merges_in_commits(&event.issue.title, &event.repository, no_merges, &commits) diff --git a/src/handlers/check_commits/validate_config.rs b/src/handlers/check_commits/validate_config.rs index 50890af6..018e3069 100644 --- a/src/handlers/check_commits/validate_config.rs +++ b/src/handlers/check_commits/validate_config.rs @@ -74,6 +74,10 @@ pub(super) async fn validate_config( } /// Helper to translate a toml span to a `(line_no, col_no)` (1-based). +#[expect( + clippy::sliced_string_as_bytes, + reason = "don't know if the suggestion applies here, because of the char boundaries thing" +)] fn translate_position(input: &str, index: usize) -> (usize, usize) { if input.is_empty() { return (0, index); diff --git a/src/handlers/nominate.rs b/src/handlers/nominate.rs index 66b4c0ca..ffd144fe 100644 --- a/src/handlers/nominate.rs +++ b/src/handlers/nominate.rs @@ -17,6 +17,10 @@ pub(super) async fn handle_command( let is_team_member = matches!(event.user().is_team_member(&ctx.team).await, Ok(true)); if !is_team_member { + #[expect( + clippy::useless_format, + reason = "for consistency with the `ErrorComment` constructors below" + )] let cmnt = ErrorComment::new( event.issue().unwrap(), format!( diff --git a/src/handlers/ping.rs b/src/handlers/ping.rs index 2b76d3d6..b4367410 100644 --- a/src/handlers/ping.rs +++ b/src/handlers/ping.rs @@ -24,6 +24,10 @@ pub(super) async fn handle_command( let is_team_member = matches!(event.user().is_team_member(&ctx.team).await, Ok(true)); if !is_team_member { + #[expect( + clippy::useless_format, + reason = "for consistency with the `ErrorComment` constructors below" + )] let cmnt = ErrorComment::new( event.issue().unwrap(), format!("Only Rust team members can ping teams."), @@ -56,6 +60,10 @@ pub(super) async fn handle_command( return Ok(()); }; + #[expect( + clippy::collapsible_if, + reason = "in the outer `if`, we check for `config`" + )] if let Some(label) = &config.label { if let Err(err) = event .issue() diff --git a/src/zulip.rs b/src/zulip.rs index aad0377b..ff3169e2 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -137,6 +137,7 @@ pub async fn webhook( } pub fn get_token_from_env() -> Result { + #[expect(clippy::bind_instead_of_map, reason = "`.map_err` is suggested, but we don't really map the error")] // ZULIP_WEBHOOK_SECRET is preferred, ZULIP_TOKEN is kept for retrocompatibility but will be deprecated std::env::var("ZULIP_WEBHOOK_SECRET") .or_else(|_| std::env::var("ZULIP_TOKEN")) @@ -186,6 +187,7 @@ async fn handle_command<'a>( if message_data.stream_id.is_none() { // Handle impersonation let mut impersonated = false; + #[expect(clippy::get_first, reason = "for symmetry with `get(1)`")] if let Some(&"as") = words.get(0) { if let Some(username) = words.get(1) { let impersonated_gh_id = ctx From cee3a6a981f920d3cc57452ab743bc5978d4a933 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 21:09:07 +0200 Subject: [PATCH 51/59] clippy::field_reassign_with_default --- src/handlers/relabel.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index abafde6a..96b31091 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -166,8 +166,10 @@ fn match_pattern(pattern: &str, label: &str) -> anyhow::Result MatchPatternResult::Allow, From 284ba8c7749638694cb9499cea49c94e3c57d9d4 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 21:12:12 +0200 Subject: [PATCH 52/59] clippy::vec_init_then_push the `push` used to be conditional --- src/handlers/prioritize.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/handlers/prioritize.rs b/src/handlers/prioritize.rs index 8dbc9c74..eff0d259 100644 --- a/src/handlers/prioritize.rs +++ b/src/handlers/prioritize.rs @@ -11,10 +11,9 @@ pub(super) async fn handle_command( event: &Event, _: PrioritizeCommand, ) -> anyhow::Result<()> { - let mut labels = vec![]; - labels.push(github::Label { + let labels = vec![github::Label { name: config.label.clone(), - }); + }]; event .issue() .unwrap() From ac4d7df0a4f708368f801b3ad021ac06767462d9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 22:35:02 +0200 Subject: [PATCH 53/59] avoid `clippy::partialeq_to_none` --- src/handlers/merge_conflicts.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/handlers/merge_conflicts.rs b/src/handlers/merge_conflicts.rs index 24457b9e..8a9e0d5b 100644 --- a/src/handlers/merge_conflicts.rs +++ b/src/handlers/merge_conflicts.rs @@ -244,11 +244,11 @@ async fn scan_unknowns( ); for unknown in unknowns { let pr = repo.get_pr(gh, unknown.number).await?; - // Ignore None, we don't want to repeatedly hammer GitHub asking for the answer. - if pr.mergeable == Some(false) { - maybe_add_comment(gh, &mut db, config, &pr, possibly.as_deref()).await?; - } else if pr.mergeable == None { - log::info!("unable to determine mergeable after delay for {unknown:?}"); + match pr.mergeable { + Some(true) => {} + Some(false) => maybe_add_comment(gh, &mut db, config, &pr, possibly.as_deref()).await?, + // Ignore None, we don't want to repeatedly hammer GitHub asking for the answer. + None => log::info!("unable to determine mergeable after delay for {unknown:?}"), } } Ok(()) From b722c5f39e7c504dc2a089168c6e768229a7e05e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 22:37:07 +0200 Subject: [PATCH 54/59] clippy::manual_find --- src/handlers/mentions.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/handlers/mentions.rs b/src/handlers/mentions.rs index 7fe120d3..b435459e 100644 --- a/src/handlers/mentions.rs +++ b/src/handlers/mentions.rs @@ -155,15 +155,9 @@ pub(super) async fn handle_input( } fn patch_adds(patch: &str, needle: &str) -> bool { - for line in patch.lines() { - if !line.starts_with("+++") && line.starts_with('+') { - if line.contains(needle) { - return true; - } - } - } - - false + patch + .lines() + .any(|line| !line.starts_with("+++") && line.starts_with('+') && line.contains(needle)) } #[cfg(test)] From 4382423b76a8a8986c87ba9abb2e86380bc7dcb1 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 22:39:50 +0200 Subject: [PATCH 55/59] clippy::ptr_arg --- src/db.rs | 6 +----- src/db/jobs.rs | 2 +- src/gha_logs.rs | 2 +- src/github.rs | 18 +++++++++--------- src/handlers/assign/tests/tests_from_diff.rs | 2 +- src/handlers/check_commits.rs | 9 +++------ src/handlers/check_commits/no_merges.rs | 6 +++--- 7 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/db.rs b/src/db.rs index 251f66cb..92ead7a1 100644 --- a/src/db.rs +++ b/src/db.rs @@ -257,11 +257,7 @@ pub async fn run_scheduled_jobs(ctx: &Context) -> anyhow::Result<()> { } // Try to handle a specific job -async fn handle_job( - ctx: &Context, - name: &String, - metadata: &serde_json::Value, -) -> anyhow::Result<()> { +async fn handle_job(ctx: &Context, name: &str, metadata: &serde_json::Value) -> anyhow::Result<()> { for job in jobs() { if job.name() == name { return job.run(ctx, metadata).await; diff --git a/src/db/jobs.rs b/src/db/jobs.rs index 74f50a5a..de04768b 100644 --- a/src/db/jobs.rs +++ b/src/db/jobs.rs @@ -51,7 +51,7 @@ pub async fn delete_job(db: &DbClient, id: &Uuid) -> Result<()> { Ok(()) } -pub async fn update_job_error_message(db: &DbClient, id: &Uuid, message: &String) -> Result<()> { +pub async fn update_job_error_message(db: &DbClient, id: &Uuid, message: &str) -> Result<()> { tracing::trace!("update_job_error_message(id={id})"); db.execute( diff --git a/src/gha_logs.rs b/src/gha_logs.rs index cf8cb52e..2a1bba9a 100644 --- a/src/gha_logs.rs +++ b/src/gha_logs.rs @@ -31,7 +31,7 @@ pub struct CachedLog { } impl GitHubActionLogsCache { - pub fn get(&mut self, key: &String) -> Option> { + pub fn get(&mut self, key: &str) -> Option> { if let Some(pos) = self.entries.iter().position(|(k, _)| k == key) { // Move previously cached entry to the front let entry = self.entries.remove(pos).unwrap(); diff --git a/src/github.rs b/src/github.rs index e7d51ad9..8227a65a 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1472,8 +1472,8 @@ impl Repository { fn build_issues_url( &self, client: &GithubClient, - filters: &Vec<(&str, &str)>, - include_labels: &Vec<&str>, + filters: &[(&str, &str)], + include_labels: &[&str], ordering: Ordering<'_>, ) -> String { self.build_endpoint_url(client, "issues", filters, include_labels, ordering) @@ -1482,8 +1482,8 @@ impl Repository { fn build_pulls_url( &self, client: &GithubClient, - filters: &Vec<(&str, &str)>, - include_labels: &Vec<&str>, + filters: &[(&str, &str)], + include_labels: &[&str], ordering: Ordering<'_>, ) -> String { self.build_endpoint_url(client, "pulls", filters, include_labels, ordering) @@ -1493,8 +1493,8 @@ impl Repository { &self, client: &GithubClient, endpoint: &str, - filters: &Vec<(&str, &str)>, - include_labels: &Vec<&str>, + filters: &[(&str, &str)], + include_labels: &[&str], ordering: Ordering<'_>, ) -> String { let filters = filters @@ -1515,9 +1515,9 @@ impl Repository { fn build_search_issues_url( &self, client: &GithubClient, - filters: &Vec<(&str, &str)>, - include_labels: &Vec<&str>, - exclude_labels: &Vec<&str>, + filters: &[(&str, &str)], + include_labels: &[&str], + exclude_labels: &[&str], ordering: Ordering<'_>, ) -> String { let filters = filters diff --git a/src/handlers/assign/tests/tests_from_diff.rs b/src/handlers/assign/tests/tests_from_diff.rs index 3daf7bab..b1c31f23 100644 --- a/src/handlers/assign/tests/tests_from_diff.rs +++ b/src/handlers/assign/tests/tests_from_diff.rs @@ -3,7 +3,7 @@ use super::super::*; use std::fmt::Write; -fn test_from_diff(diff: &Vec, config: toml::Table, expected: &[&str]) { +fn test_from_diff(diff: &[FileDiff], config: toml::Table, expected: &[&str]) { let aconfig: AssignConfig = config.try_into().unwrap(); assert_eq!( find_reviewers_from_diff(&aconfig, &*diff).unwrap(), diff --git a/src/handlers/check_commits.rs b/src/handlers/check_commits.rs index 1a603286..ec3e95f7 100644 --- a/src/handlers/check_commits.rs +++ b/src/handlers/check_commits.rs @@ -290,10 +290,7 @@ fn warning_from_warnings(warnings: &[String]) -> String { } // Calculate the label changes -fn calculate_label_changes( - previous: &Vec, - current: &Vec, -) -> (Vec, Vec) { +fn calculate_label_changes(previous: &[String], current: &[String]) -> (Vec, Vec) { let previous_set: HashSet = previous.iter().cloned().collect(); let current_set: HashSet = current.iter().cloned().collect(); @@ -305,8 +302,8 @@ fn calculate_label_changes( // Calculate the error changes fn calculate_error_changes( - previous: &Vec<(String, String)>, - current: &Vec, + previous: &[(String, String)], + current: &[String], ) -> (Vec<(String, String)>, Vec) { let previous_set: HashSet<(String, String)> = previous.iter().cloned().collect(); let current_set: HashSet = current.iter().cloned().collect(); diff --git a/src/handlers/check_commits/no_merges.rs b/src/handlers/check_commits/no_merges.rs index 2b25990f..d742a6ac 100644 --- a/src/handlers/check_commits/no_merges.rs +++ b/src/handlers/check_commits/no_merges.rs @@ -12,7 +12,7 @@ pub(super) fn merges_in_commits( issue_title: &str, repository: &Repository, config: &NoMergesConfig, - commits: &Vec, + commits: &[GithubCommit], ) -> Option<(String, Vec)> { // Don't trigger if the PR has any of the excluded title segments. if config @@ -143,7 +143,7 @@ $ git push --force-with-lease let commit = dummy_commit_from_body("67c917fe5937e984f58f5003ccbb5c37e", "+ main.rs"); assert_eq!( - merges_in_commits(&title, &repository, &config, &vec![commit]), + merges_in_commits(&title, &repository, &config, &[commit]), None ); } @@ -155,7 +155,7 @@ $ git push --force-with-lease "Subtree update of rustc_custom_codegen", &repository, &config, - &vec![commit_with_merge()] + &[commit_with_merge()] ), None ); From 7443c6cba62666454e5d755dbffe6cc9ade4ac4e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 17 Sep 2025 01:02:36 +0200 Subject: [PATCH 56/59] deref `Label` to `&str` directly --- parser/src/command/relabel.rs | 6 +++--- src/handlers/relabel.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/src/command/relabel.rs b/parser/src/command/relabel.rs index 7423e732..968102cf 100644 --- a/parser/src/command/relabel.rs +++ b/parser/src/command/relabel.rs @@ -51,9 +51,9 @@ impl Label { } impl std::ops::Deref for Label { - type Target = String; - fn deref(&self) -> &String { - &self.0 + type Target = str; + fn deref(&self) -> &str { + &self.0.as_str() } } diff --git a/src/handlers/relabel.rs b/src/handlers/relabel.rs index 96b31091..de348c98 100644 --- a/src/handlers/relabel.rs +++ b/src/handlers/relabel.rs @@ -27,7 +27,7 @@ pub(super) async fn handle_command( let mut results = vec![]; let mut to_add = vec![]; for delta in &input.0 { - let name = delta.label().as_str(); + let name: &str = delta.label(); let err = match check_filter(name, config, is_member(event.user(), &ctx.team).await) { Ok(CheckFilterResult::Allow) => None, Ok(CheckFilterResult::Deny) => { From 8031a82ffe1df93c53ba4a5f3dc500b08c7c518f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 22:54:07 +0200 Subject: [PATCH 57/59] clippy::redundant_pattern_matching --- src/db.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/db.rs b/src/db.rs index 92ead7a1..641072bc 100644 --- a/src/db.rs +++ b/src/db.rs @@ -225,7 +225,10 @@ pub async fn schedule_job( anyhow::bail!("Job {} does not exist in the current job list.", job_name); } - if let Err(_) = get_job_by_name_and_scheduled_at(db, job_name, &when).await { + if get_job_by_name_and_scheduled_at(db, job_name, &when) + .await + .is_err() + { // mean there's no job already in the db with that name and scheduled_at insert_job(db, job_name, &when, &job_metadata).await?; } From 9b541d0471c1b2a68fbce3ee57d5c4996158ca7c Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 23:13:28 +0200 Subject: [PATCH 58/59] lints on FCP-related items clippy::{struct_field_names,upper_case_acronym} --- src/rfcbot.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/rfcbot.rs b/src/rfcbot.rs index e8f7b9f3..cb7adc4d 100644 --- a/src/rfcbot.rs +++ b/src/rfcbot.rs @@ -3,15 +3,15 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct FCP { +pub struct Fcp { pub id: u32, pub fk_issue: u32, pub fk_initiator: u32, pub fk_initiating_comment: u64, pub disposition: Option, pub fk_bot_tracking_comment: u64, - pub fcp_start: Option, - pub fcp_closed: bool, + pub start: Option, + pub closed: bool, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Reviewer { @@ -30,7 +30,7 @@ pub struct Concern { pub reviewer: Reviewer, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct FCPIssue { +pub struct FcpIssue { pub id: u32, pub number: u32, pub fk_milestone: Option, @@ -60,18 +60,18 @@ pub struct StatusComment { } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct FullFCP { - pub fcp: FCP, +pub struct FullFcp { + pub fcp: Fcp, pub reviews: Vec, pub concerns: Vec, - pub issue: FCPIssue, + pub issue: FcpIssue, pub status_comment: StatusComment, } -pub async fn get_all_fcps() -> anyhow::Result> { +pub async fn get_all_fcps() -> anyhow::Result> { let url = Url::parse("https://rfcbot.rs/api/all")?; - let res = reqwest::get(url).await?.json::>().await?; - let mut map: HashMap = HashMap::new(); + let res = reqwest::get(url).await?.json::>().await?; + let mut map: HashMap = HashMap::new(); for full_fcp in res { map.insert( format!( From 45d88f87d0fd444d9b287e190ac753080ded6863 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 16 Sep 2025 23:34:56 +0200 Subject: [PATCH 59/59] clippy::unused_self --- src/gh_range_diff.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gh_range_diff.rs b/src/gh_range_diff.rs index 22eb99b7..24fb6032 100644 --- a/src/gh_range_diff.rs +++ b/src/gh_range_diff.rs @@ -446,7 +446,6 @@ struct HtmlDiffPrinter<'a>(pub &'a Interner<&'a str>); impl HtmlDiffPrinter<'_> { fn handle_hunk_line<'a>( - &self, mut f: impl fmt::Write, hunk_token_status: HunkTokenStatus, words: impl Iterator, @@ -554,7 +553,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { // Process all before lines first for (diff, input) in &diffs_and_inputs { - self.handle_hunk_line( + Self::handle_hunk_line( &mut f, HunkTokenStatus::Removed, input.before.iter().enumerate().map(|(b_pos, b_token)| { @@ -565,7 +564,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { // Then process all after lines for (diff, input) in &diffs_and_inputs { - self.handle_hunk_line( + Self::handle_hunk_line( &mut f, HunkTokenStatus::Added, input.after.iter().enumerate().map(|(a_pos, a_token)| { @@ -579,7 +578,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { if let Some(&last) = before.last() { for &token in before { let token = self.0[token]; - self.handle_hunk_line( + Self::handle_hunk_line( &mut f, HunkTokenStatus::Removed, std::iter::once((token, false)), @@ -593,7 +592,7 @@ impl UnifiedDiffPrinter for HtmlDiffPrinter<'_> { if let Some(&last) = after.last() { for &token in after { let token = self.0[token]; - self.handle_hunk_line( + Self::handle_hunk_line( &mut f, HunkTokenStatus::Added, std::iter::once((token, false)),