Skip to content

Commit d2e52ea

Browse files
authored
Rollup merge of rust-lang#111610 - bvanjoi:fix-99597, r=compiler-errors
fix(diagnostic): wrap parens for ref impl trait param Fixes rust-lang#99597 When parameters are an `impl_trait` which it needed to add trait, and it is a reference, add parentheses to the type of the parameter in the suggestion
2 parents 20f6aa1 + b2b2be1 commit d2e52ea

File tree

3 files changed

+76
-31
lines changed

3 files changed

+76
-31
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+46-31
Original file line numberDiff line numberDiff line change
@@ -2633,47 +2633,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26332633
Nothing,
26342634
}
26352635
let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
2636-
let (sp, mut introducer) = if let Some(span) =
2637-
ast_generics.bounds_span_for_suggestions(def_id)
2638-
{
2639-
(span, Introducer::Plus)
2640-
} else if let Some(colon_span) = param.colon_span {
2641-
(colon_span.shrink_to_hi(), Introducer::Nothing)
2642-
} else {
2643-
(param.span.shrink_to_hi(), Introducer::Colon)
2644-
};
2645-
if matches!(
2646-
param.kind,
2647-
hir::GenericParamKind::Type { synthetic: true, .. },
2648-
) {
2649-
introducer = Introducer::Plus
2650-
}
26512636
let trait_def_ids: FxHashSet<DefId> = ast_generics
26522637
.bounds_for_param(def_id)
26532638
.flat_map(|bp| bp.bounds.iter())
26542639
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
26552640
.collect();
2656-
if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2657-
err.span_suggestions(
2658-
sp,
2659-
message(format!(
2660-
"restrict type parameter `{}` with",
2661-
param.name.ident(),
2662-
)),
2641+
if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
2642+
return;
2643+
}
2644+
let msg = message(format!(
2645+
"restrict type parameter `{}` with",
2646+
param.name.ident(),
2647+
));
2648+
let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
2649+
if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
2650+
err.multipart_suggestions(
2651+
msg,
26632652
candidates.iter().map(|t| {
2664-
format!(
2665-
"{} {}",
2666-
match introducer {
2667-
Introducer::Plus => " +",
2668-
Introducer::Colon => ":",
2669-
Introducer::Nothing => "",
2670-
},
2671-
self.tcx.def_path_str(t.def_id),
2672-
)
2653+
vec![
2654+
(param.span.shrink_to_lo(), "(".to_string()),
2655+
(
2656+
bounds_span.unwrap(),
2657+
format!(" + {})", self.tcx.def_path_str(t.def_id)),
2658+
),
2659+
]
26732660
}),
26742661
Applicability::MaybeIncorrect,
26752662
);
2663+
return;
26762664
}
2665+
2666+
let (sp, introducer) = if let Some(span) = bounds_span {
2667+
(span, Introducer::Plus)
2668+
} else if let Some(colon_span) = param.colon_span {
2669+
(colon_span.shrink_to_hi(), Introducer::Nothing)
2670+
} else if param.is_impl_trait() {
2671+
(param.span.shrink_to_hi(), Introducer::Plus)
2672+
} else {
2673+
(param.span.shrink_to_hi(), Introducer::Colon)
2674+
};
2675+
2676+
err.span_suggestions(
2677+
sp,
2678+
msg,
2679+
candidates.iter().map(|t| {
2680+
format!(
2681+
"{} {}",
2682+
match introducer {
2683+
Introducer::Plus => " +",
2684+
Introducer::Colon => ":",
2685+
Introducer::Nothing => "",
2686+
},
2687+
self.tcx.def_path_str(t.def_id)
2688+
)
2689+
}),
2690+
Applicability::MaybeIncorrect,
2691+
);
26772692
return;
26782693
}
26792694
Node::Item(hir::Item {

tests/ui/suggestions/issue-99597.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![allow(dead_code)]
2+
3+
trait T1 { }
4+
5+
trait T2 {
6+
fn test(&self) { }
7+
}
8+
9+
fn go(s: &impl T1) {
10+
//~^ SUGGESTION (
11+
s.test();
12+
//~^ ERROR no method named `test`
13+
}
14+
15+
fn main() { }
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
2+
--> $DIR/issue-99597.rs:11:7
3+
|
4+
LL | s.test();
5+
| ^^^^ method not found in `&impl T1`
6+
|
7+
= help: items from traits can only be used if the type parameter is bounded by the trait
8+
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
9+
|
10+
LL | fn go(s: &(impl T1 + T2)) {
11+
| + +++++
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)