Skip to content

Add a suggestion to replace parentheses with angle brackets on associated trait constraint #97656

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID};
Expand Down Expand Up @@ -901,7 +901,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::TypeBinding<'hir> {
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);

// lower generic arguments of identifier in constraint
let gen_args = if let Some(ref gen_args) = constraint.gen_args {
let gen_args_ctor = match gen_args {
Expand All @@ -914,12 +913,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.0
}
GenericArgs::Parenthesized(ref data) => {
let mut err = self.sess.struct_span_err(
gen_args.span(),
"parenthesized generic arguments cannot be used in associated type constraints"
);
// FIXME: try to write a suggestion here
err.emit();
self.assoc_ty_contraint_param_error_emit(data);
self.lower_angle_bracketed_parameter_data(
&data.as_angle_bracketed_args(),
ParamMode::Explicit,
Expand Down Expand Up @@ -1033,6 +1027,42 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

fn assoc_ty_contraint_param_error_emit(&self, data: &ParenthesizedArgs) -> () {
let mut err = self.sess.struct_span_err(
data.span,
"parenthesized generic arguments cannot be used in associated type constraints",
);
// Suggest removing empty parentheses: "Trait()" -> "Trait"
if data.inputs.is_empty() {
let parentheses_span =
data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi());
err.multipart_suggestion(
"remove these parentheses",
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
);
}
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
else {
// Start of parameters to the 1st argument
let open_param = data.inputs_span.shrink_to_lo().to(data
.inputs
.first()
.unwrap()
.span
.shrink_to_lo());
// End of last argument to end of parameters
let close_param =
data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());
err.multipart_suggestion(
&format!("use angle brackets instead",),
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
err.emit();
}

fn lower_generic_arg(
&mut self,
arg: &ast::GenericArg,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
//~| ERROR this associated type takes 0 generic arguments but 1 generic argument
//~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments


fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
//~^ ERROR: parenthesized generic arguments cannot be used
//~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ error: parenthesized generic arguments cannot be used in associated type constra
|
LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
| ^^^^^
|
help: use angle brackets instead
|
LL | fn foo<'a>(arg: Box<dyn X<Y<'a> = &'a ()>>) {}
| ~ ~

error: parenthesized generic arguments cannot be used in associated type constraints
--> $DIR/gat-trait-path-parenthesised-args.rs:14:27
|
LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
| ^--
| |
| help: remove these parentheses

error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:7:27
Expand Down Expand Up @@ -40,6 +53,22 @@ note: associated type defined here, with 0 generic parameters
LL | type Y<'a>;
| ^

error: aborting due to 4 previous errors
error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:14:27
|
LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
| ^ expected 1 lifetime argument
|
note: associated type defined here, with 1 lifetime parameter: `'a`
--> $DIR/gat-trait-path-parenthesised-args.rs:4:8
|
LL | type Y<'a>;
| ^ --
help: add missing lifetime argument
|
LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {}
| ++

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0107`.