Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 56c68e7

Browse files
Rollup merge of #145853 - JonathanBrouwer:fix-lit-parsing, r=jdonszelmann
Improve error messages around invalid literals in attribute arguments r? `@jdonszelmann` This previously created two errors, which is a bit ugly and the second one didn't add any value Blocked on #143193
2 parents 9e4a283 + e0bdc46 commit 56c68e7

File tree

5 files changed

+64
-71
lines changed

5 files changed

+64
-71
lines changed

‎compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use rustc_ast::token::{self, Delimiter, MetaVarKind};
1010
use rustc_ast::tokenstream::TokenStream;
1111
use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
1212
use rustc_ast_pretty::pprust;
13-
use rustc_errors::PResult;
13+
use rustc_errors::{Diag,PResult};
1414
use rustc_hir::{self as hir, AttrPath};
1515
use rustc_parse::exp;
1616
use rustc_parse::parser::{Parser, PathStyle, token_descr};
17-
use rustc_session::errors::report_lit_error;
17+
use rustc_session::errors::{create_lit_error,report_lit_error};
1818
use rustc_session::parse::ParseSess;
1919
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
2020
use thin_vec::ThinVec;
@@ -379,22 +379,23 @@ struct MetaItemListParserContext<'a, 'sess> {
379379

380380
impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
381381
fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'sess, MetaItemLit> {
382-
let uninterpolated_span = self.parser.token_uninterpolated_span();
383-
let Some(token_lit) = self.parser.eat_token_lit() else {
384-
return self.parser.handle_missing_lit(Parser::mk_meta_item_lit_char);
385-
};
382+
let Some(token_lit) = self.parser.eat_token_lit() else { return Err(self.expected_lit()) };
383+
self.unsuffixed_meta_item_from_lit(token_lit)
384+
}
386385

386+
fn unsuffixed_meta_item_from_lit(
387+
&mut self,
388+
token_lit: token::Lit,
389+
) -> PResult<'sess, MetaItemLit> {
387390
let lit = match MetaItemLit::from_token_lit(token_lit, self.parser.prev_token.span) {
388391
Ok(lit) => lit,
389392
Err(err) => {
390-
let guar =
391-
report_lit_error(&self.parser.psess, err, token_lit, uninterpolated_span);
392-
// Pack possible quotes and prefixes from the original literal into
393-
// the error literal's symbol so they can be pretty-printed faithfully.
394-
let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
395-
let symbol = Symbol::intern(&suffixless_lit.to_string());
396-
let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
397-
MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
393+
return Err(create_lit_error(
394+
&self.parser.psess,
395+
err,
396+
token_lit,
397+
self.parser.prev_token_uninterpolated_span(),
398+
));
398399
}
399400
};
400401

@@ -448,16 +449,28 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
448449
}
449450

450451
fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser<'static>> {
451-
match self.parse_unsuffixed_meta_item_lit() {
452-
Ok(lit) => return Ok(MetaItemOrLitParser::Lit(lit)),
453-
Err(err) => err.cancel(), // we provide a better error below
454-
}
455-
456-
match self.parse_attr_item() {
457-
Ok(mi) => return Ok(MetaItemOrLitParser::MetaItemParser(mi)),
458-
Err(err) => err.cancel(), // we provide a better error below
452+
if let Some(token_lit) = self.parser.eat_token_lit() {
453+
// If a literal token is parsed, we commit to parsing a MetaItemLit for better errors
454+
Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?))
455+
} else {
456+
let prev_pros = self.parser.approx_token_stream_pos();
457+
match self.parse_attr_item() {
458+
Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)),
459+
Err(err) => {
460+
// If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
461+
// If it didn't make progress we use the `expected_lit` from below
462+
if self.parser.approx_token_stream_pos() != prev_pros {
463+
Err(err)
464+
} else {
465+
err.cancel();
466+
Err(self.expected_lit())
467+
}
468+
}
469+
}
459470
}
471+
}
460472

473+
fn expected_lit(&mut self) -> Diag<'sess> {
461474
let mut err = InvalidMetaItem {
462475
span: self.parser.token.span,
463476
descr: token_descr(&self.parser.token),
@@ -492,7 +505,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
492505
self.parser.bump();
493506
}
494507

495-
Err(self.parser.dcx().create_err(err))
508+
self.parser.dcx().create_err(err)
496509
}
497510

498511
fn parse(

‎compiler/rustc_parse/src/parser/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,7 +2077,7 @@ impl<'a> Parser<'a> {
20772077
(token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
20782078
}
20792079

2080-
pubfn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
2080+
fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
20812081
ast::MetaItemLit {
20822082
symbol: name,
20832083
suffix: None,
@@ -2086,7 +2086,7 @@ impl<'a> Parser<'a> {
20862086
}
20872087
}
20882088

2089-
pubfn handle_missing_lit<L>(
2089+
fn handle_missing_lit<L>(
20902090
&mut self,
20912091
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
20922092
) -> PResult<'a, L> {

‎compiler/rustc_session/src/errors.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ pub fn report_lit_error(
384384
lit: token::Lit,
385385
span: Span,
386386
) -> ErrorGuaranteed {
387+
create_lit_error(psess, err, lit, span).emit()
388+
}
389+
390+
pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> {
387391
// Checks if `s` looks like i32 or u1234 etc.
388392
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
389393
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
@@ -414,32 +418,32 @@ pub fn report_lit_error(
414418
let dcx = psess.dcx();
415419
match err {
416420
LitError::InvalidSuffix(suffix) => {
417-
dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
421+
dcx.create_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
418422
}
419423
LitError::InvalidIntSuffix(suffix) => {
420424
let suf = suffix.as_str();
421425
if looks_like_width_suffix(&['i', 'u'], suf) {
422426
// If it looks like a width, try to be helpful.
423-
dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
427+
dcx.create_err(InvalidIntLiteralWidth { span, width: suf[1..].into() })
424428
} else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) {
425-
dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed })
429+
dcx.create_err(InvalidNumLiteralBasePrefix { span, fixed })
426430
} else {
427-
dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
431+
dcx.create_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() })
428432
}
429433
}
430434
LitError::InvalidFloatSuffix(suffix) => {
431435
let suf = suffix.as_str();
432436
if looks_like_width_suffix(&['f'], suf) {
433437
// If it looks like a width, try to be helpful.
434-
dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
438+
dcx.create_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })
435439
} else {
436-
dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
440+
dcx.create_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() })
437441
}
438442
}
439443
LitError::NonDecimalFloat(base) => match base {
440-
16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }),
441-
8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }),
442-
2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }),
444+
16 => dcx.create_err(HexadecimalFloatLiteralNotSupported { span }),
445+
8 => dcx.create_err(OctalFloatLiteralNotSupported { span }),
446+
2 => dcx.create_err(BinaryFloatLiteralNotSupported { span }),
443447
_ => unreachable!(),
444448
},
445449
LitError::IntTooLarge(base) => {
@@ -450,7 +454,7 @@ pub fn report_lit_error(
450454
16 => format!("{max:#x}"),
451455
_ => format!("{max}"),
452456
};
453-
dcx.emit_err(IntLiteralTooLarge { span, limit })
457+
dcx.create_err(IntLiteralTooLarge { span, limit })
454458
}
455459
}
456460
}

‎tests/ui/parser/bad-lit-suffixes.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ fn g() {}
3838

3939
#[link(name = "string"suffix)]
4040
//~^ ERROR suffixes on string literals are invalid
41-
//~| ERROR malformed `link` attribute input
4241
extern "C" {}
4342

4443
#[rustc_layout_scalar_valid_range_start(0suffix)]
4544
//~^ ERROR invalid suffix `suffix` for number literal
46-
//~| ERROR malformed `rustc_layout_scalar_valid_range_start` attribute input
4745
struct S;
46+
47+
impl S {
48+
#[rustc_confusables("blah"suffix)]
49+
//~^ ERROR suffixes on string literals are invalid
50+
fn woof() { }
51+
}

‎tests/ui/parser/bad-lit-suffixes.stderr

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -160,48 +160,20 @@ error: suffixes on string literals are invalid
160160
LL | #[link(name = "string"suffix)]
161161
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
162162

163-
error[E0539]: malformed `link` attribute input
164-
--> $DIR/bad-lit-suffixes.rs:39:1
165-
|
166-
LL | #[link(name = "string"suffix)]
167-
| ^^^^^^^---------------------^^
168-
| |
169-
| expected this to be of the form `name = "..."`
170-
|
171-
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
172-
help: try changing it to one of the following valid forms of the attribute
173-
|
174-
LL - #[link(name = "string"suffix)]
175-
LL + #[link(name = "...")]
176-
|
177-
LL - #[link(name = "string"suffix)]
178-
LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
179-
|
180-
LL - #[link(name = "string"suffix)]
181-
LL + #[link(name = "...", kind = "dylib|static|...")]
182-
|
183-
LL - #[link(name = "string"suffix)]
184-
LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
185-
|
186-
= and 1 other candidate
187-
188163
error: invalid suffix `suffix` for number literal
189-
--> $DIR/bad-lit-suffixes.rs:44:41
164+
--> $DIR/bad-lit-suffixes.rs:43:41
190165
|
191166
LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
192167
| ^^^^^^^ invalid suffix `suffix`
193168
|
194169
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
195170

196-
error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
197-
--> $DIR/bad-lit-suffixes.rs:44:1
171+
error: suffixes on string literals are invalid
172+
--> $DIR/bad-lit-suffixes.rs:48:25
198173
|
199-
LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
200-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
201-
| | |
202-
| | expected an integer literal here
203-
| help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
174+
LL | #[rustc_confusables("blah"suffix)]
175+
| ^^^^^^^^^^^^ invalid suffix `suffix`
204176

205-
error: aborting due to 23 previous errors; 2 warnings emitted
177+
error: aborting due to 22 previous errors; 2 warnings emitted
206178

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /