Rollup merge of #111610 - bvanjoi:fix-99597, r=compiler-errors
fix(diagnostic): wrap parens for ref impl trait param Fixes https://github.com/rust-lang/rust/issues/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
This commit is contained in:
commit
d2e52ea127
3 changed files with 76 additions and 31 deletions
|
@ -2633,47 +2633,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Nothing,
|
Nothing,
|
||||||
}
|
}
|
||||||
let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
|
let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
|
||||||
let (sp, mut introducer) = if let Some(span) =
|
|
||||||
ast_generics.bounds_span_for_suggestions(def_id)
|
|
||||||
{
|
|
||||||
(span, Introducer::Plus)
|
|
||||||
} else if let Some(colon_span) = param.colon_span {
|
|
||||||
(colon_span.shrink_to_hi(), Introducer::Nothing)
|
|
||||||
} else {
|
|
||||||
(param.span.shrink_to_hi(), Introducer::Colon)
|
|
||||||
};
|
|
||||||
if matches!(
|
|
||||||
param.kind,
|
|
||||||
hir::GenericParamKind::Type { synthetic: true, .. },
|
|
||||||
) {
|
|
||||||
introducer = Introducer::Plus
|
|
||||||
}
|
|
||||||
let trait_def_ids: FxHashSet<DefId> = ast_generics
|
let trait_def_ids: FxHashSet<DefId> = ast_generics
|
||||||
.bounds_for_param(def_id)
|
.bounds_for_param(def_id)
|
||||||
.flat_map(|bp| bp.bounds.iter())
|
.flat_map(|bp| bp.bounds.iter())
|
||||||
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
|
.filter_map(|bound| bound.trait_ref()?.trait_def_id())
|
||||||
.collect();
|
.collect();
|
||||||
if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
|
if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
|
||||||
err.span_suggestions(
|
return;
|
||||||
sp,
|
}
|
||||||
message(format!(
|
let msg = message(format!(
|
||||||
"restrict type parameter `{}` with",
|
"restrict type parameter `{}` with",
|
||||||
param.name.ident(),
|
param.name.ident(),
|
||||||
)),
|
));
|
||||||
|
let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
|
||||||
|
if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
|
||||||
|
err.multipart_suggestions(
|
||||||
|
msg,
|
||||||
candidates.iter().map(|t| {
|
candidates.iter().map(|t| {
|
||||||
format!(
|
vec![
|
||||||
"{} {}",
|
(param.span.shrink_to_lo(), "(".to_string()),
|
||||||
match introducer {
|
(
|
||||||
Introducer::Plus => " +",
|
bounds_span.unwrap(),
|
||||||
Introducer::Colon => ":",
|
format!(" + {})", self.tcx.def_path_str(t.def_id)),
|
||||||
Introducer::Nothing => "",
|
),
|
||||||
},
|
]
|
||||||
self.tcx.def_path_str(t.def_id),
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (sp, introducer) = if let Some(span) = bounds_span {
|
||||||
|
(span, Introducer::Plus)
|
||||||
|
} else if let Some(colon_span) = param.colon_span {
|
||||||
|
(colon_span.shrink_to_hi(), Introducer::Nothing)
|
||||||
|
} else if param.is_impl_trait() {
|
||||||
|
(param.span.shrink_to_hi(), Introducer::Plus)
|
||||||
|
} else {
|
||||||
|
(param.span.shrink_to_hi(), Introducer::Colon)
|
||||||
|
};
|
||||||
|
|
||||||
|
err.span_suggestions(
|
||||||
|
sp,
|
||||||
|
msg,
|
||||||
|
candidates.iter().map(|t| {
|
||||||
|
format!(
|
||||||
|
"{} {}",
|
||||||
|
match introducer {
|
||||||
|
Introducer::Plus => " +",
|
||||||
|
Introducer::Colon => ":",
|
||||||
|
Introducer::Nothing => "",
|
||||||
|
},
|
||||||
|
self.tcx.def_path_str(t.def_id)
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Node::Item(hir::Item {
|
Node::Item(hir::Item {
|
||||||
|
|
15
tests/ui/suggestions/issue-99597.rs
Normal file
15
tests/ui/suggestions/issue-99597.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
trait T1 { }
|
||||||
|
|
||||||
|
trait T2 {
|
||||||
|
fn test(&self) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go(s: &impl T1) {
|
||||||
|
//~^ SUGGESTION (
|
||||||
|
s.test();
|
||||||
|
//~^ ERROR no method named `test`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
15
tests/ui/suggestions/issue-99597.stderr
Normal file
15
tests/ui/suggestions/issue-99597.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
|
||||||
|
--> $DIR/issue-99597.rs:11:7
|
||||||
|
|
|
||||||
|
LL | s.test();
|
||||||
|
| ^^^^ method not found in `&impl T1`
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the type parameter is bounded by the trait
|
||||||
|
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
|
||||||
|
|
|
||||||
|
LL | fn go(s: &(impl T1 + T2)) {
|
||||||
|
| + +++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
Loading…
Add table
Reference in a new issue