about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2024-12-11 03:30:44 -0500
committerGitHub <noreply@github.com>2024-12-11 03:30:44 -0500
commitf1030765f32a3ed31f25345ad2775dca76c05388 (patch)
tree280e85f2790b3b49493902a98abefa82bdf3fffb /compiler/rustc_trait_selection/src
parent16b64938c203ca8f63f5c6b82870423caa5cdccf (diff)
parente134c74904bc83c1c92584fad388c20343a8be37 (diff)
downloadrust-f1030765f32a3ed31f25345ad2775dca76c05388.tar.gz
rust-f1030765f32a3ed31f25345ad2775dca76c05388.zip
Rollup merge of #134142 - compiler-errors:paren-sug, r=jieyouxu
Rudimentary heuristic to insert parentheses when needed for RPIT overcaptures lint

We don't have basically any preexisting machinery to detect when parentheses are needed for *types*. AFAICT, all of the diagnostics we have for opaques just... fail when they suggest `+ 'a` when that's ambiguous.

Fixes #132853
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs35
1 files changed, 30 insertions, 5 deletions
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index afac6fc6004..68fe90f0de2 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -10,7 +10,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{Visitor, walk_ty};
-use rustc_hir::{FnRetTy, GenericParamKind};
+use rustc_hir::{FnRetTy, GenericParamKind, Node};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
 use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
@@ -1888,10 +1888,35 @@ pub fn impl_trait_overcapture_suggestion<'tcx>(
         .collect::<Vec<_>>()
         .join(", ");
 
-    suggs.push((
-        tcx.def_span(opaque_def_id).shrink_to_hi(),
-        format!(" + use<{concatenated_bounds}>"),
-    ));
+    let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
+    // FIXME: This is a bit too conservative, since it ignores parens already written in AST.
+    let (lparen, rparen) = match tcx
+        .hir()
+        .parent_iter(opaque_hir_id)
+        .nth(1)
+        .expect("expected ty to have a parent always")
+        .1
+    {
+        Node::PathSegment(segment)
+            if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
+        {
+            ("(", ")")
+        }
+        Node::Ty(ty) => match ty.kind {
+            rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
+            // FIXME: RPITs are not allowed to be nested in `impl Fn() -> ...`,
+            // but we eventually could support that, and that would necessitate
+            // making this more sophisticated.
+            _ => ("", ""),
+        },
+        _ => ("", ""),
+    };
+
+    let rpit_span = tcx.def_span(opaque_def_id);
+    if !lparen.is_empty() {
+        suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
+    }
+    suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
 
     Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
 }