fix issue-144595

This commit is contained in:
b1yd
2026-05-26 11:20:51 +00:00
parent 31a9463c6e
commit 92194469a0
4 changed files with 72 additions and 4 deletions
+25
View File
@@ -4639,3 +4639,28 @@ pub(crate) struct ReservedMultihashLint {
)]
pub suggestion: Span,
}
#[derive(Subdiagnostic)]
#[suggestion(
"if you meant to write a path, use a double colon:",
code = "::",
applicability = "maybe-incorrect"
)]
pub(crate) struct UseDoubleColonSuggestion {
#[primary_span]
pub colon: Span,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
"if you meant to create a regular struct, use curly braces:",
applicability = "maybe-incorrect"
)]
pub(crate) struct UseRegularStructSuggestion {
#[suggestion_part(code = "{{")]
pub open: Span,
#[suggestion_part(code = "}}")]
pub close: Span,
#[suggestion_part(code = "")]
pub semicolon: Option<Span>,
}
+23 -4
View File
@@ -23,7 +23,10 @@
AllowConstBlockItems, AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect,
Parser, PathStyle, Recovered, Trailing, UsePreAttrPos,
};
use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
use crate::errors::{
self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField,
UseDoubleColonSuggestion, UseRegularStructSuggestion,
};
use crate::exp;
impl<'a> Parser<'a> {
@@ -2084,10 +2087,11 @@ fn parse_unsafe_field(&mut self) -> Safety {
Safety::Default
}
}
/// This is the case where we find `struct Foo<T>(T) where T: Copy;`
/// Unit like structs are handled in parse_item_struct function
pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
// Unit like structs are handled in parse_item_struct function
let openparen_span = self.token.span;
let mut encountered_colon = false;
self.parse_paren_comma_seq(|p| {
let attrs = p.parse_outer_attributes()?;
p.collect_tokens(None, attrs, ForceCollect::No, |p, attrs| {
@@ -2109,6 +2113,8 @@ pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef
}
};
let mut_restriction = p.parse_mut_restriction()?;
encountered_colon |=
p.token.is_ident() && p.look_ahead(1, |tok| tok == &token::Colon);
// Unsafe fields are not supported in tuple structs, as doing so would result in a
// parsing ambiguity for `struct X(unsafe fn())`.
let ty = match p.parse_ty() {
@@ -2156,6 +2162,19 @@ pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef
})
})
.map(|(r, _)| r)
.map_err(|mut error| {
if encountered_colon {
error.subdiagnostic(UseDoubleColonSuggestion { colon: self.token.span });
self.eat_to_tokens(&[exp!(CloseParen)]);
self.bump();
error.subdiagnostic(UseRegularStructSuggestion {
open: openparen_span,
close: self.prev_token.span,
semicolon: if self.token == token::Semi { Some(self.token.span) } else { None },
});
}
error
})
}
/// Parses an element of a struct declaration.
@@ -0,0 +1,6 @@
// Provide diagnostics when the user writes field names in tuple struct.(issue#144595)
struct Foo(a:u8,b:u8);
//~^ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:`
//~| HELP if you meant to write a path, use a double colon:
//~| HELP if you meant to create a regular struct, use curly braces:
@@ -0,0 +1,18 @@
error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:`
--> $DIR/field-name-in-tuple-struct.rs:3:13
|
LL | struct Foo(a:u8,b:u8);
| ^ expected one of 7 possible tokens
|
help: if you meant to write a path, use a double colon:
|
LL | struct Foo(a::u8,b:u8);
| +
help: if you meant to create a regular struct, use curly braces:
|
LL - struct Foo(a:u8,b:u8);
LL + struct Foo{a:u8,b:u8}
|
error: aborting due to 1 previous error