1
Fork 0

Improve diagnostic for E0178 (bad + in type)

Namely, use a more sensical primary span.
Don't pretty-print AST nodes for the diagnostic message. Why:
* It's lossy (e.g., it doesn't replicate trailing `+`s in trait objects.
* It's prone to leak error nodes (printed as `(/*ERROR*/)`) since
  the LHS can easily represent recovered code (e.g., `fn(i32?) + T`).
This commit is contained in:
León Orell Valerian Liehr 2025-04-15 07:44:24 +02:00
parent 8887af72a0
commit 6242335fdb
No known key found for this signature in database
GPG key ID: D17A07215F68E713
14 changed files with 51 additions and 52 deletions

View file

@ -543,7 +543,7 @@ parse_maybe_recover_from_bad_qpath_stage_2 =
.suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
parse_maybe_recover_from_bad_type_plus =
expected a path on the left-hand side of `+`, not `{$ty}`
expected a path on the left-hand side of `+`
parse_maybe_report_ambiguous_plus =
ambiguous `+` in a type

View file

@ -30,7 +30,6 @@ pub(crate) struct AmbiguousPlus {
#[derive(Diagnostic)]
#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)]
pub(crate) struct BadTypePlus {
pub ty: String,
#[primary_span]
pub span: Span,
#[subdiagnostic]

View file

@ -1636,19 +1636,19 @@ impl<'a> Parser<'a> {
self.bump(); // `+`
let _bounds = self.parse_generic_bounds()?;
let sum_span = ty.span.to(self.prev_token.span);
let sub = match &ty.kind {
TyKind::Ref(_lifetime, mut_ty) => {
let lo = mut_ty.ty.span.shrink_to_lo();
let hi = self.prev_token.span.shrink_to_hi();
BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } }
}
TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span },
_ => BadTypePlusSub::ExpectPath { span: sum_span },
TyKind::Ptr(..) | TyKind::BareFn(..) => {
BadTypePlusSub::ForgotParen { span: ty.span.to(self.prev_token.span) }
}
_ => BadTypePlusSub::ExpectPath { span: ty.span },
};
self.dcx().emit_err(BadTypePlus { ty: pprust::ty_to_string(ty), span: sum_span, sub });
self.dcx().emit_err(BadTypePlus { span: ty.span, sub });
Ok(())
}

View file

@ -1,41 +1,43 @@
error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:6:8
|
LL | w: &'a Foo + Copy,
| ^^^^^^^^^^^^^^
| ^^^^^^^
|
help: try adding parentheses
|
LL | w: &'a (Foo + Copy),
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:7:8
|
LL | x: &'a Foo + 'a,
| ^^^^^^^^^^^^
| ^^^^^^^
|
help: try adding parentheses
|
LL | x: &'a (Foo + 'a),
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:8:8
|
LL | y: &'a mut Foo + 'a,
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^
|
help: try adding parentheses
|
LL | y: &'a mut (Foo + 'a),
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/E0178.rs:9:8
|
LL | z: fn() -> Foo + 'a,
| ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
| ^^^^^^^^^^^-----
| |
| perhaps you forgot parentheses?
error: aborting due to 4 previous errors

View file

@ -1,19 +1,19 @@
error[E0178]: expected a path on the left-hand side of `+`, not `&Copy`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
|
LL | let _: &Copy + 'static;
| ^^^^^^^^^^^^^^^
| ^^^^^
|
help: try adding parentheses
|
LL | let _: &(Copy + 'static);
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12
|
LL | let _: &'static Copy + 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
help: try adding parentheses
|

View file

@ -27,7 +27,7 @@ type A = fn() -> impl A + B;
type A = fn() -> dyn A + B;
//~^ ERROR ambiguous `+` in a type
type A = fn() -> A + B;
//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A`
//~^ ERROR expected a path on the left-hand side of `+`
type A = Fn() -> impl A +;
//~^ ERROR ambiguous `+` in a type
@ -44,6 +44,6 @@ type A = &impl A + B;
type A = &dyn A + B;
//~^ ERROR ambiguous `+` in a type
type A = &A + B;
//~^ ERROR expected a path on the left-hand side of `+`, not `&A`
//~^ ERROR expected a path on the left-hand side of `+`
fn main() {}

View file

@ -31,11 +31,13 @@ help: try adding parentheses
LL | type A = fn() -> (dyn A + B);
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/impl-trait-plus-priority.rs:29:10
|
LL | type A = fn() -> A + B;
| ^^^^^^^^^^^^^ perhaps you forgot parentheses?
| ^^^^^^^^^----
| |
| perhaps you forgot parentheses?
error: ambiguous `+` in a type
--> $DIR/impl-trait-plus-priority.rs:32:18
@ -103,11 +105,11 @@ help: try adding parentheses
LL | type A = &(dyn A + B);
| + +
error[E0178]: expected a path on the left-hand side of `+`, not `&A`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/impl-trait-plus-priority.rs:46:10
|
LL | type A = &A + B;
| ^^^^^^
| ^^
|
help: try adding parentheses
|

View file

@ -12,7 +12,7 @@ mac!('a);
// avoid false positives
fn y<'a>(y: &mut 'a + Send) {
//~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a`
//~^ ERROR expected a path on the left-hand side of `+`
//~| ERROR at least one trait is required for an object type
let z = y as &mut 'a + Send;
//~^ ERROR expected value, found trait `Send`

View file

@ -10,11 +10,11 @@ LL - fn x<'a>(x: &mut 'a i32){}
LL + fn x<'a>(x: &'a mut i32){}
|
error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/issue-73568-lifetime-after-mut.rs:14:13
|
LL | fn y<'a>(y: &mut 'a + Send) {
| ^^^^^^^^^^^^^^
| ^^^^^^^
|
help: try adding parentheses
|

View file

@ -5,12 +5,8 @@
auto trait Auto {}
fn main() {
let _: Box<((Auto)) + Auto>;
//~^ ERROR expected a path on the left-hand side of `+`, not `((Auto))`
let _: Box<(Auto + Auto) + Auto>;
//~^ ERROR expected a path on the left-hand side of `+`, not `(Auto + Auto)`
let _: Box<(Auto +) + Auto>;
//~^ ERROR expected a path on the left-hand side of `+`, not `(Auto)`
let _: Box<(dyn Auto) + Auto>;
//~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Auto)`
let _: Box<((Auto)) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
let _: Box<(Auto + Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
let _: Box<(Auto +) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
let _: Box<(dyn Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+`
}

View file

@ -1,26 +1,26 @@
error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-bad-parens.rs:8:16
|
LL | let _: Box<((Auto)) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
| ^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
--> $DIR/trait-object-bad-parens.rs:10:16
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-bad-parens.rs:9:16
|
LL | let _: Box<(Auto + Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^^^^ expected a path
| ^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
--> $DIR/trait-object-bad-parens.rs:12:16
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-bad-parens.rs:10:16
|
LL | let _: Box<(Auto +) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
| ^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
--> $DIR/trait-object-bad-parens.rs:14:16
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-bad-parens.rs:11:16
|
LL | let _: Box<(dyn Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^ expected a path
| ^^^^^^^^^^ expected a path
error: aborting due to 4 previous errors

View file

@ -28,11 +28,11 @@ error: expected type, found lifetime
LL | let _: Box<('a) + Trait>;
| ^^ expected type
error[E0178]: expected a path on the left-hand side of `+`, not `((/*ERROR*/))`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-lifetime-parens.rs:16:16
|
LL | let _: Box<('a) + Trait>;
| ^^^^^^^^^^^^ expected a path
| ^^^^ expected a path
error[E0782]: expected a type, found a trait
--> $DIR/trait-object-lifetime-parens.rs:12:16

View file

@ -4,6 +4,6 @@ trait Trait<'a> {}
fn main() {
let _: &for<'a> Trait<'a> + 'static;
//~^ ERROR expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
//~^ ERROR expected a path on the left-hand side of `+`
//~| HELP try adding parentheses
}

View file

@ -1,8 +1,8 @@
error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
error[E0178]: expected a path on the left-hand side of `+`
--> $DIR/trait-object-polytrait-priority.rs:6:12
|
LL | let _: &for<'a> Trait<'a> + 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^
|
help: try adding parentheses
|