summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs3
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl4
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/offset_of.rs99
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs15
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs61
-rw-r--r--compiler/rustc_parse/src/parser/item.rs8
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--library/core/src/mem/mod.rs6
-rw-r--r--tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff16
-rw-r--r--tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff8
-rw-r--r--tests/ui/feature-gates/feature-gate-builtin_syntax.rs7
-rw-r--r--tests/ui/feature-gates/feature-gate-builtin_syntax.stderr12
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.rs14
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.stderr59
-rw-r--r--tests/ui/offset-of/offset-of-builtin.rs44
-rw-r--r--tests/ui/offset-of/offset-of-builtin.stderr65
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr3
-rw-r--r--tests/ui/offset-of/offset-of-unstable.stderr5
-rw-r--r--tests/ui/parser/builtin-syntax.rs9
-rw-r--r--tests/ui/parser/builtin-syntax.stderr14
25 files changed, 333 insertions, 136 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index b960671bf6e..3d5056d82c5 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -603,6 +603,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(yeet_expr, "`do yeet` expression is experimental");
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
gate_all!(const_closures, "const closures are experimental");
+ gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index b74c59bca30..87c32ffce12 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -556,8 +556,7 @@ impl<'a> State<'a> {
self.pclose();
}
ast::ExprKind::OffsetOf(container, fields) => {
- // FIXME: This should have its own syntax, distinct from a macro invocation.
- self.word("offset_of!");
+ self.word("builtin # offset_of");
self.popen();
self.rbox(0, Inconsistent);
self.print_type(container);
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 0d7cf7cdb26..3b458b1d30b 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -150,10 +150,6 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
*[more] arguments
} in format string, but {$desc}
-builtin_macros_offset_of_expected_field = expected field
-
-builtin_macros_offset_of_expected_two_args = expected 2 arguments
-
builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c7da61d72b3..4e5edb4d6b1 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -44,7 +44,6 @@ mod format;
mod format_foreign;
mod global_allocator;
mod log_syntax;
-mod offset_of;
mod source_util;
mod test;
mod trace_macros;
@@ -92,7 +91,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
line: source_util::expand_line,
log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod,
- offset_of: offset_of::expand_offset_of,
option_env: env::expand_option_env,
core_panic: edition_panic::expand_panic,
std_panic: edition_panic::expand_panic,
diff --git a/compiler/rustc_builtin_macros/src/offset_of.rs b/compiler/rustc_builtin_macros/src/offset_of.rs
deleted file mode 100644
index 0ef3e000e41..00000000000
--- a/compiler/rustc_builtin_macros/src/offset_of.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use rustc_ast as ast;
-use rustc_ast::ptr::P;
-use rustc_ast::token;
-use rustc_ast::tokenstream::TokenStream;
-use rustc_errors::PResult;
-use rustc_expand::base::{self, *};
-use rustc_macros::Diagnostic;
-use rustc_parse::parser::Parser;
-use rustc_span::{symbol::Ident, Span};
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_offset_of_expected_field)]
-struct ExpectedField {
- #[primary_span]
- span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_offset_of_expected_two_args)]
-struct ExpectedTwoArgs {
- #[primary_span]
- span: Span,
-}
-
-fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> {
- let token = p.token.uninterpolate();
- let field = match token.kind {
- token::Ident(name, _) => Ident::new(name, token.span),
- token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => {
- Ident::new(symbol, token.span)
- }
- _ => return Err(cx.create_err(ExpectedField { span: p.token.span })),
- };
-
- p.bump();
-
- Ok(field)
-}
-
-fn parse_args<'a>(
- cx: &mut ExtCtxt<'a>,
- sp: Span,
- tts: TokenStream,
-) -> PResult<'a, (P<ast::Ty>, P<[Ident]>)> {
- let mut p = cx.new_parser_from_tts(tts);
-
- let container = p.parse_ty()?;
-
- p.expect(&token::Comma)?;
-
- if p.eat(&token::Eof) {
- return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
- }
-
- let mut fields = Vec::new();
-
- loop {
- let field = parse_field(cx, &mut p)?;
- fields.push(field);
-
- if p.eat(&token::Dot) {
- continue;
- }
-
- p.eat(&token::Comma);
-
- if !p.eat(&token::Eof) {
- return Err(cx.create_err(ExpectedTwoArgs { span: sp }));
- }
-
- break;
- }
-
- Ok((container, fields.into()))
-}
-
-pub fn expand_offset_of<'cx>(
- cx: &'cx mut ExtCtxt<'_>,
- sp: Span,
- tts: TokenStream,
-) -> Box<dyn base::MacResult + 'cx> {
- match parse_args(cx, sp, tts) {
- Ok((container, fields)) => {
- let expr = P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- kind: ast::ExprKind::OffsetOf(container, fields),
- span: sp,
- attrs: ast::AttrVec::new(),
- tokens: None,
- });
-
- MacEager::expr(expr)
- }
- Err(mut err) => {
- err.emit();
- DummyResult::any(sp)
- }
- }
-}
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 27d30c315af..f4615445f8e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -313,6 +313,8 @@ declare_features! (
(active, async_closure, "1.37.0", Some(62290), None),
/// Allows async functions to be declared, implemented, and used in traits.
(active, async_fn_in_trait, "1.66.0", Some(91611), None),
+ /// Allows builtin # foo() syntax
+ (active, builtin_syntax, "CURRENT_RUSTC_VERSION", Some(110680), None),
/// Allows `c"foo"` literals.
(active, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
/// Treat `extern "C"` function as nounwind.
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index cd296dca133..711447a0af0 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -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
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 010a13aefa4..0810f0efef9 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -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,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 018eddea4b0..887e155426f 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1300,6 +1300,8 @@ impl<'a> Parser<'a> {
})
} 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)
@@ -1766,6 +1768,61 @@ impl<'a> Parser<'a> {
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| {
+ if ident.name == sym::offset_of {
+ return Ok(Some(this.parse_expr_offset_of(lo)?));
+ }
+
+ 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.sess.gated_spans.gate(sym::builtin_syntax, ident.span);
+ 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
+ }
+
+ pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+ let container = self.parse_ty()?;
+ self.expect(&TokenKind::Comma)?;
+
+ let seq_sep = SeqSep { sep: Some(token::Dot), trailing_sep_allowed: false };
+ let (fields, _trailing, _recovered) = self.parse_seq_to_before_end(
+ &TokenKind::CloseDelim(Delimiter::Parenthesis),
+ seq_sep,
+ Parser::parse_field_name,
+ )?;
+ let span = lo.to(self.token.span);
+ Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.to_vec().into())))
+ }
+
/// 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.
@@ -2835,6 +2892,10 @@ impl<'a> Parser<'a> {
})
}
+ 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()?;
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 49e05efd39d..840cfe90899 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -265,6 +265,9 @@ impl<'a> Parser<'a> {
// 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 @@ impl<'a> Parser<'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`
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 1c17de337e8..a0bd086053e 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -90,7 +90,11 @@ impl<'a> Parser<'a> {
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.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index b97ec6c684b..117e2774bd8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -95,6 +95,7 @@ symbols! {
// Weak keywords, have special meaning only in specific contexts.
Auto: "auto",
+ Builtin: "builtin",
Catch: "catch",
Default: "default",
MacroRules: "macro_rules",
@@ -440,6 +441,7 @@ symbols! {
breakpoint,
bridge,
bswap,
+ builtin_syntax,
c_str,
c_str_literals,
c_unwind,
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 7d2f2971523..4913a6de918 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1315,9 +1315,9 @@ impl<T> SizedTypeProperties for T {}
///
/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
/// ```
-#[unstable(feature = "offset_of", issue = "106655")]
-#[rustc_builtin_macro]
#[cfg(not(bootstrap))]
+#[unstable(feature = "offset_of", issue = "106655")]
+#[allow_internal_unstable(builtin_syntax)]
pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
- /* compiler built-in */
+ builtin # offset_of($Container, $($fields).+)
}
diff --git a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff
index e768a47a96d..e3757941c8c 100644
--- a/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff
+++ b/tests/mir-opt/const_prop/offset_of.concrete.ConstProp.diff
@@ -22,17 +22,17 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/offset_of.rs:+1:9: +1:10
-- _1 = OffsetOf(Alpha, [0]); // scope 0 at $DIR/offset_of.rs:+1:13: +1:33
-+ _1 = const 4_usize; // scope 0 at $DIR/offset_of.rs:+1:13: +1:33
+- _1 = OffsetOf(Alpha, [0]); // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
++ _1 = const 4_usize; // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_2); // scope 1 at $DIR/offset_of.rs:+2:9: +2:10
-- _2 = OffsetOf(Alpha, [1]); // scope 1 at $DIR/offset_of.rs:+2:13: +2:33
-+ _2 = const 0_usize; // scope 1 at $DIR/offset_of.rs:+2:13: +2:33
+- _2 = OffsetOf(Alpha, [1]); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
++ _2 = const 0_usize; // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_3); // scope 2 at $DIR/offset_of.rs:+3:9: +3:11
-- _3 = OffsetOf(Alpha, [2, 0]); // scope 2 at $DIR/offset_of.rs:+3:14: +3:36
-+ _3 = const 2_usize; // scope 2 at $DIR/offset_of.rs:+3:14: +3:36
+- _3 = OffsetOf(Alpha, [2, 0]); // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
++ _3 = const 2_usize; // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_4); // scope 3 at $DIR/offset_of.rs:+4:9: +4:11
-- _4 = OffsetOf(Alpha, [2, 1]); // scope 3 at $DIR/offset_of.rs:+4:14: +4:36
-+ _4 = const 3_usize; // scope 3 at $DIR/offset_of.rs:+4:14: +4:36
+- _4 = OffsetOf(Alpha, [2, 1]); // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
++ _4 = const 3_usize; // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
_0 = const (); // scope 0 at $DIR/offset_of.rs:+0:15: +5:2
StorageDead(_4); // scope 3 at $DIR/offset_of.rs:+5:1: +5:2
StorageDead(_3); // scope 2 at $DIR/offset_of.rs:+5:1: +5:2
diff --git a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff
index e40fdbd79d8..4a655604cd1 100644
--- a/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff
+++ b/tests/mir-opt/const_prop/offset_of.generic.ConstProp.diff
@@ -22,13 +22,13 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/offset_of.rs:+1:9: +1:11
- _1 = OffsetOf(Gamma<T>, [0]); // scope 0 at $DIR/offset_of.rs:+1:14: +1:37
+ _1 = OffsetOf(Gamma<T>, [0]); // scope 0 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_2); // scope 1 at $DIR/offset_of.rs:+2:9: +2:11
- _2 = OffsetOf(Gamma<T>, [1]); // scope 1 at $DIR/offset_of.rs:+2:14: +2:37
+ _2 = OffsetOf(Gamma<T>, [1]); // scope 1 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_3); // scope 2 at $DIR/offset_of.rs:+3:9: +3:11
- _3 = OffsetOf(Delta<T>, [1]); // scope 2 at $DIR/offset_of.rs:+3:14: +3:37
+ _3 = OffsetOf(Delta<T>, [1]); // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
StorageLive(_4); // scope 3 at $DIR/offset_of.rs:+4:9: +4:11
- _4 = OffsetOf(Delta<T>, [2]); // scope 3 at $DIR/offset_of.rs:+4:14: +4:37
+ _4 = OffsetOf(Delta<T>, [2]); // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
_0 = const (); // scope 0 at $DIR/offset_of.rs:+0:17: +5:2
StorageDead(_4); // scope 3 at $DIR/offset_of.rs:+5:1: +5:2
StorageDead(_3); // scope 2 at $DIR/offset_of.rs:+5:1: +5:2
diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.rs b/tests/ui/feature-gates/feature-gate-builtin_syntax.rs
new file mode 100644
index 00000000000..832bb5a96bc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-builtin_syntax.rs
@@ -0,0 +1,7 @@
+struct Foo {
+ v: u8,
+ w: u8,
+}
+fn main() {
+ builtin # offset_of(Foo, v); //~ ERROR `builtin #` syntax is unstable
+}
diff --git a/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr b/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr
new file mode 100644
index 00000000000..3bc7848f66d
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-builtin_syntax.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `builtin #` syntax is unstable
+ --> $DIR/feature-gate-builtin_syntax.rs:6:15
+ |
+LL | builtin # offset_of(Foo, v);
+ | ^^^^^^^^^
+ |
+ = note: see issue #110680 <https://github.com/rust-lang/rust/issues/110680> for more information
+ = help: add `#![feature(builtin_syntax)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index 163b07454ec..5e66e33f8a2 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -3,7 +3,15 @@
use std::mem::offset_of;
fn main() {
- offset_of!(NotEnoughArguments); //~ ERROR expected one of
- offset_of!(NotEnoughArgumentsWithAComma, ); //~ ERROR expected 2 arguments
- offset_of!(Container, field, too many arguments); //~ ERROR expected 2 arguments
+ offset_of!(NotEnoughArguments); //~ ERROR unexpected end of macro invocation
+ offset_of!(NotEnoughArgumentsWithAComma, ); //~ ERROR unexpected end of macro invocation
+ offset_of!(Container, field, too many arguments); //~ ERROR no rules expected the token `too`
+ offset_of!(S, f); // compiles fine
+ offset_of!(S, f,); // also compiles fine
+ offset_of!(S, f.); //~ ERROR unexpected end of macro invocation
+ offset_of!(S, f.,); //~ ERROR expected identifier
+ offset_of!(S, f..); //~ ERROR no rules expected the token
+ offset_of!(S, f..,); //~ ERROR no rules expected the token
}
+
+struct S { f: u8, }
diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr
index ebecc982c51..4275a89545f 100644
--- a/tests/ui/offset-of/offset-of-arg-count.stderr
+++ b/tests/ui/offset-of/offset-of-arg-count.stderr
@@ -1,20 +1,59 @@
-error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `<eof>`
- --> $DIR/offset-of-arg-count.rs:6:16
+error: unexpected end of macro invocation
+ --> $DIR/offset-of-arg-count.rs:6:34
|
LL | offset_of!(NotEnoughArguments);
- | ^^^^^^^^^^^^^^^^^^ expected one of `!`, `(`, `+`, `,`, `::`, or `<`
+ | ^ missing tokens in macro arguments
+ |
+note: while trying to match `,`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-error: expected 2 arguments
- --> $DIR/offset-of-arg-count.rs:7:5
+error: unexpected end of macro invocation
+ --> $DIR/offset-of-arg-count.rs:7:45
|
LL | offset_of!(NotEnoughArgumentsWithAComma, );
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^ missing tokens in macro arguments
+ |
+note: while trying to match meta-variable `$fields:tt`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-error: expected 2 arguments
- --> $DIR/offset-of-arg-count.rs:8:5
+error: no rules expected the token `too`
+ --> $DIR/offset-of-arg-count.rs:8:34
|
LL | offset_of!(Container, field, too many arguments);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^ no rules expected this token in macro call
+ |
+ = note: while trying to match sequence end
+
+error: unexpected end of macro invocation
+ --> $DIR/offset-of-arg-count.rs:11:21
+ |
+LL | offset_of!(S, f.);
+ | ^ missing tokens in macro arguments
+ |
+note: while trying to match meta-variable `$fields:tt`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+
+error: expected identifier, found `,`
+ --> $DIR/offset-of-arg-count.rs:12:21
+ |
+LL | offset_of!(S, f.,);
+ | ^ expected identifier
+
+error: no rules expected the token `..`
+ --> $DIR/offset-of-arg-count.rs:13:20
+ |
+LL | offset_of!(S, f..);
+ | ^^ no rules expected this token in macro call
+ |
+ = note: while trying to match sequence start
+
+error: no rules expected the token `..`
+ --> $DIR/offset-of-arg-count.rs:14:20
+ |
+LL | offset_of!(S, f..,);
+ | ^^ no rules expected this token in macro call
+ |
+ = note: while trying to match sequence start
-error: aborting due to 3 previous errors
+error: aborting due to 7 previous errors
diff --git a/tests/ui/offset-of/offset-of-builtin.rs b/tests/ui/offset-of/offset-of-builtin.rs
new file mode 100644
index 00000000000..1be9899887b
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-builtin.rs
@@ -0,0 +1,44 @@
+#![feature(builtin_syntax)]
+
+// For the exposed macro we already test these errors in the other files,
+// but this test helps to make sure the builtin construct also errors.
+// This has the same examples as offset-of-arg-count.rs
+
+fn main() {
+ builtin # offset_of(NotEnoughArguments); //~ ERROR expected one of
+}
+fn t1() {
+ // Already errored upon at the macro level. Yielding an error would require
+ // extra effort.
+ builtin # offset_of(NotEnoughArgumentsWithAComma, );
+}
+fn t2() {
+ builtin # offset_of(Container, field, too many arguments); //~ ERROR expected identifier, found
+ //~| ERROR found `,`
+ //~| ERROR found `many`
+ //~| ERROR found `arguments`
+}
+fn t3() {
+ builtin # offset_of(S, f); // compiles fine
+}
+fn t4() {
+ // Already errored upon at the macro level. Yielding an error would require
+ // extra effort.
+ builtin # offset_of(S, f);
+}
+fn t5() {
+ builtin # offset_of(S, f.); //~ ERROR expected identifier
+}
+fn t6() {
+ builtin # offset_of(S, f.,); //~ ERROR expected identifier
+}
+fn t7() {
+ builtin # offset_of(S, f..); //~ ERROR expected one of
+}
+fn t8() {
+ // Already errored upon at the macro level. Yielding an error would require
+ // extra effort.
+ builtin # offset_of(S, f..,);
+}
+
+struct S { f: u8, }
diff --git a/tests/ui/offset-of/offset-of-builtin.stderr b/tests/ui/offset-of/offset-of-builtin.stderr
new file mode 100644
index 00000000000..1a1f33cc613
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-builtin.stderr
@@ -0,0 +1,65 @@
+error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `)`
+ --> $DIR/offset-of-builtin.rs:8:43
+ |
+LL | builtin # offset_of(NotEnoughArguments);
+ | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `<`
+
+error: expected identifier, found `,`
+ --> $DIR/offset-of-builtin.rs:16:41
+ |
+LL | builtin # offset_of(Container, field, too many arguments);
+ | ^
+ | |
+ | expected identifier
+ | help: remove this comma
+
+error: expected one of `)` or `.`, found `,`
+ --> $DIR/offset-of-builtin.rs:16:41
+ |
+LL | builtin # offset_of(Container, field, too many arguments);
+ | ^
+ | |
+ | expected one of `)` or `.`
+ | help: missing `.`
+
+error: expected one of `)` or `.`, found `many`
+ --> $DIR/offset-of-builtin.rs:16:47
+ |
+LL | builtin # offset_of(Container, field, too many arguments);
+ | -^^^^ expected one of `)` or `.`
+ | |
+ | help: missing `.`
+
+error: expected one of `)` or `.`, found `arguments`
+ --> $DIR/offset-of-builtin.rs:16:52
+ |
+LL | builtin # offset_of(Container, field, too many arguments);
+ | -^^^^^^^^^ expected one of `)` or `.`
+ | |
+ | help: missing `.`
+
+error: expected identifier, found `)`
+ --> $DIR/offset-of-builtin.rs:30:30
+ |
+LL | builtin # offset_of(S, f.);
+ | ^ expected identifier
+
+error: expected identifier, found `,`
+ --> $DIR/offset-of-builtin.rs:33:30
+ |
+LL | builtin # offset_of(S, f.,);
+ | ^ expected identifier
+
+error: expected one of `)` or `.`, found `..`
+ --> $DIR/offset-of-builtin.rs:36:29
+ |
+LL | builtin # offset_of(S, f..);
+ | ^^ expected one of `)` or `.`
+ |
+help: if you meant to bind the contents of the rest of the array pattern into `f`, use `@`
+ |
+LL | builtin # offset_of(S, f @ ..);
+ | +
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index 8e88015b07a..e6e0f499236 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -5,6 +5,7 @@ LL | offset_of!(Alpha, z);
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:31:5
@@ -13,6 +14,7 @@ LL | offset_of!(Beta, z);
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `Extern` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:32:5
@@ -21,6 +23,7 @@ LL | offset_of!(Gamma, z);
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `Extern`
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr
index 25811a061d7..c39882519a5 100644
--- a/tests/ui/offset-of/offset-of-unstable.stderr
+++ b/tests/ui/offset-of/offset-of-unstable.stderr
@@ -33,6 +33,7 @@ LL | | );
| |_____^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/offset-of-unstable.rs:18:5
@@ -41,6 +42,7 @@ LL | offset_of!(StableWithUnstableField, unstable);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/offset-of-unstable.rs:20:5
@@ -49,6 +51,7 @@ LL | offset_of!(StableWithUnstableFieldType, stable.unstable);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/offset-of-unstable.rs:21:5
@@ -61,6 +64,7 @@ LL | | );
| |_____^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/offset-of-unstable.rs:26:5
@@ -73,6 +77,7 @@ LL | | );
| |_____^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+ = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 8 previous errors
diff --git a/tests/ui/parser/builtin-syntax.rs b/tests/ui/parser/builtin-syntax.rs
new file mode 100644
index 00000000000..897dab8ec50
--- /dev/null
+++ b/tests/ui/parser/builtin-syntax.rs
@@ -0,0 +1,9 @@
+#![feature(builtin_syntax)]
+
+fn main() {
+ builtin # foobar(); //~ ERROR unknown `builtin #` construct
+}
+
+fn not_identifier() {
+ builtin # {}(); //~ ERROR expected identifier after
+}
diff --git a/tests/ui/parser/builtin-syntax.stderr b/tests/ui/parser/builtin-syntax.stderr
new file mode 100644
index 00000000000..ee3764a6221
--- /dev/null
+++ b/tests/ui/parser/builtin-syntax.stderr
@@ -0,0 +1,14 @@
+error: unknown `builtin #` construct `foobar`
+ --> $DIR/builtin-syntax.rs:4:5
+ |
+LL | builtin # foobar();
+ | ^^^^^^^^^^^^^^^^
+
+error: expected identifier after `builtin #`
+ --> $DIR/builtin-syntax.rs:8:15
+ |
+LL | builtin # {}();
+ | ^
+
+error: aborting due to 2 previous errors
+