Add parsing for builtin # in expression and item context
This commit is contained in:
parent
4b94c23219
commit
59ecbd2cea
@ -257,6 +257,10 @@ parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are inva
|
||||
.tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
|
||||
.tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
|
||||
|
||||
parse_expected_builtin_ident = expected identifier after `builtin #`
|
||||
|
||||
parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}`
|
||||
|
||||
parse_non_string_abi_literal = non-string ABI literal
|
||||
.suggestion = specify the ABI with a string literal
|
||||
|
||||
|
@ -2644,3 +2644,18 @@ pub(crate) struct MalformedCfgAttr {
|
||||
pub span: Span,
|
||||
pub sugg: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_unknown_builtin_construct)]
|
||||
pub(crate) struct UnknownBuiltinConstruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_expected_builtin_ident)]
|
||||
pub(crate) struct ExpectedBuiltinIdent {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -1300,6 +1300,8 @@ fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
|
||||
})
|
||||
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
|
||||
self.parse_expr_array_or_repeat(Delimiter::Bracket)
|
||||
} else if self.is_builtin() {
|
||||
self.parse_expr_builtin()
|
||||
} else if self.check_path() {
|
||||
self.parse_expr_path_start()
|
||||
} else if self.check_keyword(kw::Move)
|
||||
@ -1755,6 +1757,42 @@ fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
|
||||
self.maybe_recover_from_bad_qpath(expr)
|
||||
}
|
||||
|
||||
/// Parse `builtin # ident(args,*)`.
|
||||
fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> {
|
||||
self.parse_builtin(|_this, _lo, _ident| {
|
||||
Ok(None)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn parse_builtin<T>(
|
||||
&mut self,
|
||||
parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>,
|
||||
) -> PResult<'a, T> {
|
||||
let lo = self.token.span;
|
||||
|
||||
self.bump(); // `builtin`
|
||||
self.bump(); // `#`
|
||||
|
||||
let Some((ident, false)) = self.token.ident() else {
|
||||
let err = errors::ExpectedBuiltinIdent { span: self.token.span }
|
||||
.into_diagnostic(&self.sess.span_diagnostic);
|
||||
return Err(err);
|
||||
};
|
||||
self.bump();
|
||||
|
||||
self.expect(&TokenKind::OpenDelim(Delimiter::Parenthesis))?;
|
||||
let ret = if let Some(res) = parse(self, lo, ident)? {
|
||||
Ok(res)
|
||||
} else {
|
||||
let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name }
|
||||
.into_diagnostic(&self.sess.span_diagnostic);
|
||||
return Err(err);
|
||||
};
|
||||
self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/// Returns a string literal if the next token is a string literal.
|
||||
/// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
|
||||
/// and returns `None` if the next token is not literal at all.
|
||||
@ -2824,6 +2862,10 @@ fn check_let_expr(expr: &Expr) -> (bool, bool) {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn is_builtin(&self) -> bool {
|
||||
self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
|
||||
}
|
||||
|
||||
/// Parses a `try {...}` expression (`try` token already eaten).
|
||||
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let (attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
|
@ -265,6 +265,9 @@ fn parse_item_kind(
|
||||
// UNION ITEM
|
||||
self.bump(); // `union`
|
||||
self.parse_item_union()?
|
||||
} else if self.is_builtin() {
|
||||
// BUILTIN# ITEM
|
||||
return self.parse_item_builtin();
|
||||
} else if self.eat_keyword(kw::Macro) {
|
||||
// MACROS 2.0 ITEM
|
||||
self.parse_item_decl_macro(lo)?
|
||||
@ -434,6 +437,11 @@ fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
|
||||
// To be expanded
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
/// Parses an item macro, e.g., `item!();`.
|
||||
fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
|
||||
let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
|
||||
|
@ -90,7 +90,11 @@ pub(crate) fn parse_stmt_without_recovery(
|
||||
attrs,
|
||||
errors::InvalidVariableDeclarationSub::UseLetNotVar,
|
||||
)?
|
||||
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
|
||||
} else if self.check_path()
|
||||
&& !self.token.is_qpath_start()
|
||||
&& !self.is_path_start_item()
|
||||
&& !self.is_builtin()
|
||||
{
|
||||
// We have avoided contextual keywords like `union`, items with `crate` visibility,
|
||||
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
|
||||
// that starts like a path (1 token), but it fact not a path.
|
||||
|
@ -95,6 +95,7 @@
|
||||
|
||||
// Weak keywords, have special meaning only in specific contexts.
|
||||
Auto: "auto",
|
||||
Builtin: "builtin",
|
||||
Catch: "catch",
|
||||
Default: "default",
|
||||
MacroRules: "macro_rules",
|
||||
|
7
tests/ui/parser/builtin-syntax.rs
Normal file
7
tests/ui/parser/builtin-syntax.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
builtin # foobar(); //~ ERROR unknown `builtin #` construct
|
||||
}
|
||||
|
||||
fn not_identifier() {
|
||||
builtin # {}(); //~ ERROR expected identifier after
|
||||
}
|
14
tests/ui/parser/builtin-syntax.stderr
Normal file
14
tests/ui/parser/builtin-syntax.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: unknown `builtin #` construct `foobar`
|
||||
--> $DIR/builtin-syntax.rs:2:5
|
||||
|
|
||||
LL | builtin # foobar();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected identifier after `builtin #`
|
||||
--> $DIR/builtin-syntax.rs:6:15
|
||||
|
|
||||
LL | builtin # {}();
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user