Migrate offset_of from a macro to builtin # syntax

This commit is contained in:
est31 2023-04-22 16:29:34 +02:00
parent 59ecbd2cea
commit 5eb29c7f49
15 changed files with 213 additions and 136 deletions

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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)
}
}
}

View File

@ -1759,7 +1759,11 @@ impl<'a> Parser<'a> {
/// Parse `builtin # ident(args,*)`.
fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> {
self.parse_builtin(|_this, _lo, _ident| {
self.parse_builtin(|this, lo, ident| {
if ident.name == sym::offset_of {
return Ok(Some(this.parse_expr_offset_of(lo)?));
}
Ok(None)
})
}
@ -1793,6 +1797,20 @@ impl<'a> Parser<'a> {
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.

View File

@ -441,6 +441,7 @@ symbols! {
breakpoint,
bridge,
bswap,
builtin_syntax,
c_str,
c_str_literals,
c_unwind,

View File

@ -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).+)
}

View File

@ -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

View File

@ -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

View File

@ -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, }

View File

@ -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: aborting due to 3 previous errors
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 7 previous errors

View File

@ -0,0 +1,44 @@
// 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, }

View File

@ -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

View File

@ -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

View File

@ -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