about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-17 16:34:47 +0100
committerGitHub <noreply@github.com>2025-03-17 16:34:47 +0100
commit9adf2189f55b6e20ab8b490cc75438ba5ef2e793 (patch)
treee9bd055031b655bbd005e0e89a28c00c6360ff8e /src
parent3d3f817ff92a9a59e6f2ed50ff76c01800614654 (diff)
parente250bd16da5d3016c45e91431fd7b97822f771c0 (diff)
downloadrust-9adf2189f55b6e20ab8b490cc75438ba5ef2e793.tar.gz
rust-9adf2189f55b6e20ab8b490cc75438ba5ef2e793.zip
Rollup merge of #137449 - compiler-errors:control-flow, r=Amanieu,lnicola
Denote `ControlFlow` as `#[must_use]`

I've repeatedly hit bugs in the compiler due to `ControlFlow` not being marked `#[must_use]`. There seems to be an accepted ACP to make the type `#[must_use]` (https://github.com/rust-lang/libs-team/issues/444), so this PR implements that part of it.

Most of the usages in the compiler that trigger this new warning are "root" usages (calling into an API that uses control-flow internally, but for which the callee doesn't really care) and have been suppressed by `let _ = ...`, but I did legitimately find one instance of a missing `?` and one for a never-used `ControlFlow` value in #137448.

Presumably this needs an FCP too, so I'm opening this and nominating it for T-libs-api.

This PR also touches the tools (incl. rust-analyzer), but if this went into FCP, I'd split those out into separate PRs which can land before this one does.

r? libs-api
`@rustbot` label: T-libs-api I-libs-api-nominated
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/length_limit/tests.rs46
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs4
16 files changed, 45 insertions, 45 deletions
diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs
index 2185c034890..4ebecfd5f24 100644
--- a/src/librustdoc/html/length_limit/tests.rs
+++ b/src/librustdoc/html/length_limit/tests.rs
@@ -9,41 +9,41 @@ fn empty() {
 #[test]
 fn basic() {
     let mut buf = HtmlWithLimit::new(60);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "Hello <em>world</em>!");
 }
 
 #[test]
 fn no_tags() {
     let mut buf = HtmlWithLimit::new(60);
-    buf.push("Hello");
-    buf.push(" world!");
+    let _ = buf.push("Hello");
+    let _ = buf.push(" world!");
     assert_eq!(buf.finish(), "Hello world!");
 }
 
 #[test]
 fn limit_0() {
     let mut buf = HtmlWithLimit::new(0);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "");
 }
 
 #[test]
 fn exactly_limit() {
     let mut buf = HtmlWithLimit::new(12);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "Hello <em>world</em>!");
 }
 
@@ -51,11 +51,11 @@ fn exactly_limit() {
 fn multiple_nested_tags() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("This is a ");
+    let _ = buf.push("This is a ");
     buf.open_tag("em");
-    buf.push("paragraph");
+    let _ = buf.push("paragraph");
     buf.open_tag("strong");
-    buf.push("!");
+    let _ = buf.push("!");
     buf.close_tag();
     buf.close_tag();
     buf.close_tag();
@@ -66,11 +66,11 @@ fn multiple_nested_tags() {
 fn forgot_to_close_tags() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("This is a ");
+    let _ = buf.push("This is a ");
     buf.open_tag("em");
-    buf.push("paragraph");
+    let _ = buf.push("paragraph");
     buf.open_tag("strong");
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "<p>This is a <em>paragraph<strong>!</strong></em></p>");
 }
 
@@ -78,10 +78,10 @@ fn forgot_to_close_tags() {
 fn past_the_limit() {
     let mut buf = HtmlWithLimit::new(20);
     buf.open_tag("p");
-    (0..10).try_for_each(|n| {
+    let _ = (0..10).try_for_each(|n| {
         buf.open_tag("strong");
-        buf.push("word#")?;
-        buf.push(&n.to_string())?;
+        let _ = buf.push("word#")?;
+        let _ = buf.push(&n.to_string())?;
         buf.close_tag();
         ControlFlow::Continue(())
     });
@@ -100,8 +100,8 @@ fn past_the_limit() {
 fn quickly_past_the_limit() {
     let mut buf = HtmlWithLimit::new(6);
     buf.open_tag("p");
-    buf.push("Hello");
-    buf.push(" World");
+    let _ = buf.push("Hello");
+    let _ = buf.push(" World");
     // intentionally not closing <p> before finishing
     assert_eq!(buf.finish(), "<p>Hello</p>");
 }
@@ -110,7 +110,7 @@ fn quickly_past_the_limit() {
 fn close_too_many() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("Hello");
+    let _ = buf.push("Hello");
     buf.close_tag();
     // This call does not panic because there are valid cases
     // where `close_tag()` is called with no tags left to close.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 079651e8603..b067dbf750e 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1568,7 +1568,7 @@ fn markdown_summary_with_limit(
 
     let mut buf = HtmlWithLimit::new(length_limit);
     let mut stopped_early = false;
-    p.try_for_each(|event| {
+    let _ = p.try_for_each(|event| {
         match &event {
             Event::Text(text) => {
                 let r =
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index fb5d49a1004..5afcf51167d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -129,7 +129,7 @@ impl BreakAfterExprVisitor {
         };
 
         get_enclosing_block(cx, hir_id).is_some_and(|block| {
-            visitor.visit_block(block);
+            let _ = visitor.visit_block(block);
             visitor.break_after_expr
         })
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
index c9251c1b849..fe999a3b5f8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
@@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
         // We've checked that `call` is a call to `Stdin::read_line()` with the right receiver,
         // now let's check if the first use of the string passed to `::read_line()`
         // is used for operations that will always fail (e.g. parsing "6\n" into a number)
-        for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
+        let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
                     if args.is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 320c0286bb7..0a8e2885648 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -141,7 +141,7 @@ impl PassByRefOrValue {
         // Gather all the lifetimes found in the output type which may affect whether
         // `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
         let mut output_regions = FxHashSet::default();
-        for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
+        let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
             output_regions.insert(region);
             ControlFlow::Continue(())
         });
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index a443043bef9..51c7d6fce31 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -381,7 +381,7 @@ impl UnconditionalRecursion {
                 implemented_ty_id,
                 method_span,
             };
-            walk_body(&mut c, body);
+            let _ = walk_body(&mut c, body);
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 67fb73696f7..65fb342f752 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -145,19 +145,19 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         let mut result = vec![];
         if fps.is_empty() {
             debug!("Unrestricted search for {:?} impls...", trait_);
-            self.for_trait_impls(trait_, self_ty_fp, |impls| {
+            let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| {
                 result.extend(impls.for_trait(trait_).map(id_to_chalk));
                 ControlFlow::Continue(())
-            })
+            });
         } else {
-            self.for_trait_impls(trait_, self_ty_fp, |impls| {
+            let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| {
                 result.extend(
                     fps.iter().flat_map(move |fp| {
                         impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
                     }),
                 );
                 ControlFlow::Continue(())
-            })
+            });
         };
 
         debug!("impls_for_trait returned {} impls", result.len());
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 6a01579bccc..e042c35d0c6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -116,7 +116,7 @@ pub fn dyn_compatibility_of_trait_query(
     trait_: TraitId,
 ) -> Option<DynCompatibilityViolation> {
     let mut res = None;
-    dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| {
+    let _ = dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| {
         res = Some(osv);
         ControlFlow::Break(())
     });
@@ -597,7 +597,7 @@ fn contains_illegal_impl_trait_in_trait(
 
     let ret = sig.skip_binders().ret();
     let mut visitor = OpaqueTypeCollector(FxHashSet::default());
-    ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST);
+    let _ = ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST);
 
     // Since we haven't implemented RPITIT in proper way like rustc yet,
     // just check whether `ret` contains RPIT for now
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
index 3060b610bb6..50851325bd5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
@@ -53,7 +53,7 @@ fn check_dyn_compatibility<'a>(
             continue;
         };
         let mut osvs = FxHashSet::default();
-        dyn_compatibility_with_callback(&db, trait_id, &mut |osv| {
+        let _ = dyn_compatibility_with_callback(&db, trait_id, &mut |osv| {
             osvs.insert(match osv {
                 DynCompatibilityViolation::SizedSelf => SizedSelf,
                 DynCompatibilityViolation::SelfReferential => SelfReferential,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 556091c4046..3e0ce7f1933 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1143,7 +1143,7 @@ impl<'a> InferenceContext<'a> {
             non_assocs: FxHashMap::default(),
         };
         for ty in tait_candidates {
-            ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
+            let _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
         }
 
         // Non-assoc TAITs can be define-used everywhere as long as they are
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 624767cedf8..cc02b71f05c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -1033,7 +1033,7 @@ where
     T: ?Sized + TypeVisitable<Interner>,
 {
     let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() };
-    value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+    let _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
     collector.placeholders.into_iter().collect()
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index db94351dcc9..c7228005271 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -596,7 +596,7 @@ pub(crate) fn iterate_method_candidates<T>(
     mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>,
 ) -> Option<T> {
     let mut slot = None;
-    iterate_method_candidates_dyn(
+    let _ = iterate_method_candidates_dyn(
         ty,
         db,
         env,
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index 4351a34e822..4e45b5a250e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -260,7 +260,7 @@ fn resolve_impl_trait_item(
     // attributes here. Use path resolution directly instead.
     //
     // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
-    method_resolution::iterate_path_candidates(
+    let _ = method_resolution::iterate_path_candidates(
         &canonical,
         db,
         environment,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index a8075509474..29f45846650 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -2911,7 +2911,7 @@ impl Trait {
         db: &dyn HirDatabase,
     ) -> Option<Vec<DynCompatibilityViolation>> {
         let mut violations = vec![];
-        hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
+        let _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
             violations.push(violation);
             ControlFlow::Continue(())
         });
@@ -5497,7 +5497,7 @@ impl Type {
             .generic_def()
             .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
 
-        method_resolution::iterate_method_candidates_dyn(
+        let _ = method_resolution::iterate_method_candidates_dyn(
             &canonical,
             db,
             environment,
@@ -5584,7 +5584,7 @@ impl Type {
             .generic_def()
             .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
 
-        method_resolution::iterate_path_candidates(
+        let _ = method_resolution::iterate_path_candidates(
             &canonical,
             db,
             environment,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 330587e0dbf..6f4b886a28d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -750,7 +750,7 @@ impl FunctionBody {
                         ast::Stmt::Item(_) => (),
                         ast::Stmt::LetStmt(stmt) => {
                             if let Some(pat) = stmt.pat() {
-                                walk_pat(&pat, &mut |pat| {
+                                let _ = walk_pat(&pat, &mut |pat| {
                                     cb(pat);
                                     std::ops::ControlFlow::<(), ()>::Continue(())
                                 });
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
index 0b2e8aa6836..56a66070ef7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -121,7 +121,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) {
         match ast::Stmt::cast(node.clone()) {
             Some(ast::Stmt::LetStmt(l)) => {
                 if let Some(pat) = l.pat() {
-                    walk_pat(&pat, &mut |pat| {
+                    let _ = walk_pat(&pat, &mut |pat| {
                         cb(pat);
                         ControlFlow::<(), ()>::Continue(())
                     });
@@ -159,7 +159,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) {
                     }
                 } else if let Some(pat) = ast::Pat::cast(node) {
                     preorder.skip_subtree();
-                    walk_pat(&pat, &mut |pat| {
+                    let _ = walk_pat(&pat, &mut |pat| {
                         cb(pat);
                         ControlFlow::<(), ()>::Continue(())
                     });