Enforce the static symbol order.

By making the proc macro abort if any symbols are out of order.

The commit also changes the proc macro collect multiple errors (of order
or duplicated symbols) and prints them at the end, which is useful if
you have multiple errors.
This commit is contained in:
Nicholas Nethercote 2020-07-10 09:46:38 +10:00
parent e2e29de5e8
commit fd8f177234
2 changed files with 146 additions and 118 deletions

View File

@ -87,18 +87,29 @@ pub fn symbols(input: TokenStream) -> TokenStream {
let mut prefill_stream = quote! {}; let mut prefill_stream = quote! {};
let mut counter = 0u32; let mut counter = 0u32;
let mut keys = HashSet::<String>::new(); let mut keys = HashSet::<String>::new();
let mut prev_key: Option<String> = None;
let mut errors = Vec::<String>::new();
let mut check_dup = |str: &str| { let mut check_dup = |str: &str, errors: &mut Vec<String>| {
if !keys.insert(str.to_string()) { if !keys.insert(str.to_string()) {
panic!("Symbol `{}` is duplicated", str); errors.push(format!("Symbol `{}` is duplicated", str));
} }
}; };
let mut check_order = |str: &str, errors: &mut Vec<String>| {
if let Some(ref prev_str) = prev_key {
if str < prev_str {
errors.push(format!("Symbol `{}` must precede `{}`", str, prev_str));
}
}
prev_key = Some(str.to_string());
};
// Generate the listed keywords. // Generate the listed keywords.
for keyword in &input.keywords.0 { for keyword in &input.keywords.0 {
let name = &keyword.name; let name = &keyword.name;
let value = &keyword.value; let value = &keyword.value;
check_dup(&value.value()); check_dup(&value.value(), &mut errors);
prefill_stream.extend(quote! { prefill_stream.extend(quote! {
#value, #value,
}); });
@ -116,7 +127,8 @@ pub fn symbols(input: TokenStream) -> TokenStream {
Some(value) => value.value(), Some(value) => value.value(),
None => name.to_string(), None => name.to_string(),
}; };
check_dup(&value); check_dup(&value, &mut errors);
check_order(&name.to_string(), &mut errors);
prefill_stream.extend(quote! { prefill_stream.extend(quote! {
#value, #value,
}); });
@ -131,7 +143,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
// Generate symbols for the strings "0", "1", ..., "9". // Generate symbols for the strings "0", "1", ..., "9".
for n in 0..10 { for n in 0..10 {
let n = n.to_string(); let n = n.to_string();
check_dup(&n); check_dup(&n, &mut errors);
prefill_stream.extend(quote! { prefill_stream.extend(quote! {
#n, #n,
}); });
@ -141,6 +153,13 @@ pub fn symbols(input: TokenStream) -> TokenStream {
counter += 1; counter += 1;
} }
if !errors.is_empty() {
for error in errors.into_iter() {
eprintln!("error: {}", error)
}
panic!("errors in `Keywords` and/or `Symbols`");
}
let tt = TokenStream::from(quote! { let tt = TokenStream::from(quote! {
macro_rules! keywords { macro_rules! keywords {
() => { () => {

View File

@ -19,6 +19,7 @@ use crate::{Span, DUMMY_SP, SESSION_GLOBALS};
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
// The proc macro code for this is in `src/librustc_macros/src/symbols.rs`.
symbols! { symbols! {
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`, // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order. // this should be rarely necessary though if the keywords are kept in alphabetic order.
@ -113,8 +114,78 @@ symbols! {
// As well as the symbols listed, there are symbols for the the strings // As well as the symbols listed, there are symbols for the the strings
// "0", "1", ..., "9", which are accessible via `sym::integer`. // "0", "1", ..., "9", which are accessible via `sym::integer`.
// //
// Keep this list in sorted order, as defined by the Unix `sort` utility. // The proc macro will abort if symbols are not in alphabetical order (as
// defined by `impl Ord for str`) or if any symbols are duplicated. Vim
// users can sort the list by selecting it and executing the command
// `:'<,'>!LC_ALL=C sort`.
//
// There is currently no checking that all symbols are used; that would be
// nice to have.
Symbols { Symbols {
Arc,
ArgumentV1,
Arguments,
C,
Clone,
Copy,
Debug,
Decodable,
Default,
Encodable,
Eq,
Equal,
Err,
From,
Future,
FxHashMap,
FxHashSet,
GlobalAlloc,
Hash,
HashMap,
HashSet,
Input,
IntoIterator,
Iterator,
Layout,
LintPass,
None,
Ok,
Option,
Ord,
Ordering,
Output,
PartialEq,
PartialOrd,
Pending,
Pin,
Poll,
ProcMacroHack,
ProceduralMasqueradeDummyType,
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
Rc,
Ready,
Result,
Return,
RustcDecodable,
RustcEncodable,
Send,
Some,
Sync,
Target,
Try,
Ty,
TyCtxt,
TyKind,
Vec,
Yield,
_Self,
__next,
_task_context,
aarch64_target_feature, aarch64_target_feature,
abi, abi,
abi_amdgpu_kernel, abi_amdgpu_kernel,
@ -131,8 +202,8 @@ symbols! {
aborts, aborts,
add, add,
add_assign, add_assign,
address,
add_with_overflow, add_with_overflow,
address,
advanced_slice_patterns, advanced_slice_patterns,
adx_target_feature, adx_target_feature,
alias, alias,
@ -141,28 +212,26 @@ symbols! {
alignstack, alignstack,
all, all,
alloc, alloc,
allocator,
allocator_internals,
alloc_error_handler, alloc_error_handler,
alloc_layout, alloc_layout,
alloc_zeroed, alloc_zeroed,
allocator,
allocator_internals,
allow, allow,
allowed,
allow_fail, allow_fail,
allow_internal_unsafe, allow_internal_unsafe,
allow_internal_unstable, allow_internal_unstable,
allow_internal_unstable_backcompat_hack, allow_internal_unstable_backcompat_hack,
allowed,
always, always,
and, and,
any, any,
arbitrary_enum_discriminant, arbitrary_enum_discriminant,
arbitrary_self_types, arbitrary_self_types,
Arc,
Arguments,
ArgumentV1,
arith_offset, arith_offset,
arm_target_feature, arm_target_feature,
array, array,
as_str,
asm, asm,
assert, assert,
assert_inhabited, assert_inhabited,
@ -173,16 +242,15 @@ symbols! {
associated_type_bounds, associated_type_bounds,
associated_type_defaults, associated_type_defaults,
associated_types, associated_types,
as_str,
assume, assume,
assume_init, assume_init,
async_await, async_await,
async_closure, async_closure,
atomics, atomics,
attr,
attributes,
attr_literals,
att_syntax, att_syntax,
attr,
attr_literals,
attributes,
augmented_assignments, augmented_assignments,
automatically_derived, automatically_derived,
avx512_target_feature, avx512_target_feature,
@ -210,11 +278,11 @@ symbols! {
braced_empty_structs, braced_empty_structs,
breakpoint, breakpoint,
bswap, bswap,
C, c_variadic,
call, call,
caller_location,
call_mut, call_mut,
call_once, call_once,
caller_location,
cdylib, cdylib,
ceilf32, ceilf32,
ceilf64, ceilf64,
@ -232,7 +300,6 @@ symbols! {
char, char,
clippy, clippy,
clone, clone,
Clone,
clone_closures, clone_closures,
clone_from, clone_from,
closure_to_fn_coercion, closure_to_fn_coercion,
@ -274,7 +341,6 @@ symbols! {
context, context,
convert, convert,
copy, copy,
Copy,
copy_closures, copy_closures,
copy_nonoverlapping, copy_nonoverlapping,
copysignf32, copysignf32,
@ -303,18 +369,14 @@ symbols! {
custom_derive, custom_derive,
custom_inner_attributes, custom_inner_attributes,
custom_test_frameworks, custom_test_frameworks,
c_variadic,
dead_code, dead_code,
dealloc, dealloc,
debug, debug,
Debug,
debug_assertions, debug_assertions,
debug_trait, debug_trait,
declare_lint_pass,
decl_macro, decl_macro,
Decodable, declare_lint_pass,
decode, decode,
Default,
default_lib_allocator, default_lib_allocator,
default_type_parameter_fallback, default_type_parameter_fallback,
default_type_params, default_type_params,
@ -339,8 +401,8 @@ symbols! {
doc_masked, doc_masked,
doctest, doctest,
document_private_items, document_private_items,
dotdoteq_in_patterns,
dotdot_in_tuple_patterns, dotdot_in_tuple_patterns,
dotdoteq_in_patterns,
double_braced_closure: "{{closure}}", double_braced_closure: "{{closure}}",
double_braced_constant: "{{constant}}", double_braced_constant: "{{constant}}",
double_braced_constructor: "{{constructor}}", double_braced_constructor: "{{constructor}}",
@ -349,24 +411,20 @@ symbols! {
double_braced_misc: "{{misc}}", double_braced_misc: "{{misc}}",
double_braced_opaque: "{{opaque}}", double_braced_opaque: "{{opaque}}",
drop, drop,
dropck_eyepatch,
dropck_parametricity,
drop_in_place, drop_in_place,
drop_types_in_const, drop_types_in_const,
dropck_eyepatch,
dropck_parametricity,
dylib, dylib,
dyn_trait, dyn_trait,
eh_catch_typeinfo, eh_catch_typeinfo,
eh_personality, eh_personality,
enable, enable,
enclosing_scope, enclosing_scope,
Encodable,
encode, encode,
env, env,
eq, eq,
Eq,
Equal,
err, err,
Err,
exact_div, exact_div,
except, except,
exchange_malloc, exchange_malloc,
@ -382,12 +440,12 @@ symbols! {
export_name, export_name,
expr, expr,
extern_absolute_paths, extern_absolute_paths,
external_doc,
extern_crate_item_prelude, extern_crate_item_prelude,
extern_crate_self, extern_crate_self,
extern_in_paths, extern_in_paths,
extern_prelude, extern_prelude,
extern_types, extern_types,
external_doc,
f16c_target_feature, f16c_target_feature,
f32, f32,
f32_runtime, f32_runtime,
@ -424,7 +482,6 @@ symbols! {
freeze, freeze,
frem_fast, frem_fast,
from, from,
From,
from_desugaring, from_desugaring,
from_error, from_error,
from_generator, from_generator,
@ -436,29 +493,22 @@ symbols! {
fsub_fast, fsub_fast,
fundamental, fundamental,
future, future,
Future,
future_trait, future_trait,
FxHashMap,
FxHashSet,
ge, ge,
generator,
generators,
generator_state,
generic_associated_types,
generic_param_attrs,
gen_future, gen_future,
gen_kill, gen_kill,
generator,
generator_state,
generators,
generic_associated_types,
generic_param_attrs,
get_context, get_context,
GlobalAlloc,
global_allocator, global_allocator,
global_asm, global_asm,
globs, globs,
gt, gt,
half_open_range_patterns, half_open_range_patterns,
hash, hash,
Hash,
HashMap,
HashSet,
hexagon_target_feature, hexagon_target_feature,
hidden, hidden,
homogeneous_aggregate, homogeneous_aggregate,
@ -493,10 +543,8 @@ symbols! {
inlateout, inlateout,
inline, inline,
inout, inout,
Input,
intel, intel,
into_iter, into_iter,
IntoIterator,
into_result, into_result,
intrinsics, intrinsics,
irrefutable_let_patterns, irrefutable_let_patterns,
@ -508,7 +556,6 @@ symbols! {
item_context: "ItemContext", item_context: "ItemContext",
item_like_imports, item_like_imports,
iter, iter,
Iterator,
keyword, keyword,
kind, kind,
label, label,
@ -516,7 +563,6 @@ symbols! {
lang, lang,
lang_items, lang_items,
lateout, lateout,
Layout,
lazy_normalization_consts, lazy_normalization_consts,
le, le,
let_chains, let_chains,
@ -527,14 +573,13 @@ symbols! {
likely, likely,
line, line,
link, link,
linkage,
link_args, link_args,
link_cfg, link_cfg,
link_llvm_intrinsics, link_llvm_intrinsics,
link_name, link_name,
link_ordinal, link_ordinal,
link_section, link_section,
LintPass, linkage,
lint_reasons, lint_reasons,
literal, literal,
llvm_asm, llvm_asm,
@ -543,9 +588,9 @@ symbols! {
log10f64, log10f64,
log2f32, log2f32,
log2f64, log2f64,
log_syntax,
logf32, logf32,
logf64, logf64,
log_syntax,
loop_break_value, loop_break_value,
lt, lt,
macro_at_most_once_rep, macro_at_most_once_rep,
@ -554,9 +599,9 @@ symbols! {
macro_lifetime_matcher, macro_lifetime_matcher,
macro_literal_matcher, macro_literal_matcher,
macro_reexport, macro_reexport,
macros_in_extern,
macro_use, macro_use,
macro_vis_matcher, macro_vis_matcher,
macros_in_extern,
main, main,
managed_boxes, managed_boxes,
manually_drop, manually_drop,
@ -567,23 +612,23 @@ symbols! {
match_default_bindings, match_default_bindings,
maxnumf32, maxnumf32,
maxnumf64, maxnumf64,
may_dangle,
maybe_uninit, maybe_uninit,
maybe_uninit_uninit, maybe_uninit_uninit,
maybe_uninit_zeroed, maybe_uninit_zeroed,
may_dangle,
member_constraints,
memory,
mem_uninitialized, mem_uninitialized,
mem_zeroed, mem_zeroed,
member_constraints,
memory,
message, message,
meta, meta,
min_align_of, min_align_of,
min_align_of_val, min_align_of_val,
min_const_fn, min_const_fn,
min_const_unsafe_fn, min_const_unsafe_fn,
min_specialization,
minnumf32, minnumf32,
minnumf64, minnumf64,
min_specialization,
mips_target_feature, mips_target_feature,
miri_start_panic, miri_start_panic,
mmx_target_feature, mmx_target_feature,
@ -615,7 +660,6 @@ symbols! {
never_type, never_type,
never_type_fallback, never_type_fallback,
new, new,
__next,
next, next,
nll, nll,
no, no,
@ -629,47 +673,41 @@ symbols! {
no_link, no_link,
no_main, no_main,
no_mangle, no_mangle,
nomem,
non_ascii_idents,
None,
none_error,
non_exhaustive,
no_niche, no_niche,
non_modrs_mods,
nontemporal_store,
nontrapping_dash_fptoint: "nontrapping-fptoint",
noreturn,
no_sanitize, no_sanitize,
nostack,
no_stack_check, no_stack_check,
no_start, no_start,
no_std, no_std,
nomem,
non_ascii_idents,
non_exhaustive,
non_modrs_mods,
none_error,
nontemporal_store,
nontrapping_dash_fptoint: "nontrapping-fptoint",
noreturn,
nostack,
not, not,
note, note,
object_safe_for_dispatch, object_safe_for_dispatch,
offset, offset,
Ok,
omit_gdb_pretty_printer_section, omit_gdb_pretty_printer_section,
on, on,
on_unimplemented, on_unimplemented,
oom, oom,
opaque, opaque,
ops, ops,
opt_out_copy,
optimize, optimize,
optimize_attribute, optimize_attribute,
optin_builtin_traits, optin_builtin_traits,
option, option,
Option,
option_env, option_env,
options,
option_type, option_type,
opt_out_copy, options,
or, or,
Ord,
Ordering,
or_patterns, or_patterns,
out, out,
Output,
overlapping_marker_traits, overlapping_marker_traits,
owned_box, owned_box,
packed, packed,
@ -686,17 +724,13 @@ symbols! {
param_attrs, param_attrs,
parent_trait, parent_trait,
partial_cmp, partial_cmp,
PartialEq,
partial_ord, partial_ord,
PartialOrd,
passes, passes,
pat, pat,
path, path,
pattern_parentheses, pattern_parentheses,
Pending,
phantom_data, phantom_data,
pin, pin,
Pin,
pinned, pinned,
platform_intrinsics, platform_intrinsics,
plugin, plugin,
@ -704,15 +738,14 @@ symbols! {
plugins, plugins,
pointer, pointer,
poll, poll,
Poll,
post_dash_lto: "post-lto", post_dash_lto: "post-lto",
powerpc_target_feature, powerpc_target_feature,
powf32, powf32,
powf64, powf64,
powif32, powif32,
powif64, powif64,
precise_pointer_size_matching,
pre_dash_lto: "pre-lto", pre_dash_lto: "pre-lto",
precise_pointer_size_matching,
pref_align_of, pref_align_of,
prefetch_read_data, prefetch_read_data,
prefetch_read_instruction, prefetch_read_instruction,
@ -723,14 +756,12 @@ symbols! {
preserves_flags, preserves_flags,
primitive, primitive,
proc_dash_macro: "proc-macro", proc_dash_macro: "proc-macro",
ProceduralMasqueradeDummyType,
proc_macro, proc_macro,
proc_macro_attribute, proc_macro_attribute,
proc_macro_def_site, proc_macro_def_site,
proc_macro_derive, proc_macro_derive,
proc_macro_expr, proc_macro_expr,
proc_macro_gen, proc_macro_gen,
ProcMacroHack,
proc_macro_hygiene, proc_macro_hygiene,
proc_macro_internals, proc_macro_internals,
proc_macro_mod, proc_macro_mod,
@ -747,18 +778,11 @@ symbols! {
quad_precision_float, quad_precision_float,
question_mark, question_mark,
quote, quote,
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
raw_dylib, raw_dylib,
raw_identifiers, raw_identifiers,
raw_ref_op, raw_ref_op,
Rc, re_rebalance_coherence,
readonly, readonly,
Ready,
realloc, realloc,
reason, reason,
receiver, receiver,
@ -779,11 +803,8 @@ symbols! {
repr_packed, repr_packed,
repr_simd, repr_simd,
repr_transparent, repr_transparent,
re_rebalance_coherence,
result, result,
Result,
result_type, result_type,
Return,
rhs, rhs,
rintf32, rintf32,
rintf64, rintf64,
@ -799,6 +820,10 @@ symbols! {
rust_2015_preview, rust_2015_preview,
rust_2018_preview, rust_2018_preview,
rust_begin_unwind, rust_begin_unwind,
rust_eh_personality,
rust_eh_register_frames,
rust_eh_unregister_frames,
rust_oom,
rustc, rustc,
rustc_allocator, rustc_allocator,
rustc_allocator_nounwind, rustc_allocator_nounwind,
@ -810,7 +835,6 @@ symbols! {
rustc_const_stable, rustc_const_stable,
rustc_const_unstable, rustc_const_unstable,
rustc_conversion_suggestion, rustc_conversion_suggestion,
RustcDecodable,
rustc_def_path, rustc_def_path,
rustc_deprecated, rustc_deprecated,
rustc_diagnostic_item, rustc_diagnostic_item,
@ -820,7 +844,6 @@ symbols! {
rustc_dump_env_program_clauses, rustc_dump_env_program_clauses,
rustc_dump_program_clauses, rustc_dump_program_clauses,
rustc_dump_user_substs, rustc_dump_user_substs,
RustcEncodable,
rustc_error, rustc_error,
rustc_expected_cgu_reuse, rustc_expected_cgu_reuse,
rustc_if_this_changed, rustc_if_this_changed,
@ -857,19 +880,15 @@ symbols! {
rustc_then_this_would_need, rustc_then_this_would_need,
rustc_unsafe_specialization_marker, rustc_unsafe_specialization_marker,
rustc_variance, rustc_variance,
rust_eh_personality,
rustfmt, rustfmt,
rust_oom,
rvalue_static_promotion, rvalue_static_promotion,
sanitize, sanitize,
sanitizer_runtime, sanitizer_runtime,
saturating_add, saturating_add,
saturating_sub, saturating_sub,
_Self,
self_in_typedefs, self_in_typedefs,
self_struct_ctor, self_struct_ctor,
semitransparent, semitransparent,
Send,
send_trait, send_trait,
shl, shl,
shl_assign, shl_assign,
@ -937,9 +956,9 @@ symbols! {
sinf32, sinf32,
sinf64, sinf64,
size, size,
sized,
size_of, size_of,
size_of_val, size_of_val,
sized,
slice, slice,
slice_alloc, slice_alloc,
slice_patterns, slice_patterns,
@ -947,7 +966,6 @@ symbols! {
slice_u8_alloc, slice_u8_alloc,
slicing_syntax, slicing_syntax,
soft, soft,
Some,
specialization, specialization,
speed, speed,
sqrtf32, sqrtf32,
@ -957,9 +975,9 @@ symbols! {
staged_api, staged_api,
start, start,
static_in_const, static_in_const,
staticlib,
static_nobundle, static_nobundle,
static_recursion, static_recursion,
staticlib,
std, std,
std_inject, std_inject,
stmt, stmt,
@ -970,10 +988,10 @@ symbols! {
stringify, stringify,
struct_field_attributes, struct_field_attributes,
struct_inherit, struct_inherit,
struct_variant,
structural_match, structural_match,
structural_peq, structural_peq,
structural_teq, structural_teq,
struct_variant,
sty, sty,
sub, sub,
sub_assign, sub_assign,
@ -981,9 +999,7 @@ symbols! {
suggestion, suggestion,
sym, sym,
sync, sync,
Sync,
sync_trait, sync_trait,
Target,
target_arch, target_arch,
target_endian, target_endian,
target_env, target_env,
@ -998,7 +1014,6 @@ symbols! {
target_thread_local, target_thread_local,
target_vendor, target_vendor,
task, task,
_task_context,
tbm_target_feature, tbm_target_feature,
termination, termination,
termination_trait, termination_trait,
@ -1024,7 +1039,6 @@ symbols! {
trivial_bounds, trivial_bounds,
truncf32, truncf32,
truncf64, truncf64,
Try,
try_blocks, try_blocks,
try_trait, try_trait,
tt, tt,
@ -1032,9 +1046,6 @@ symbols! {
tuple_indexing, tuple_indexing,
two_phase, two_phase,
ty, ty,
Ty,
TyCtxt,
TyKind,
type_alias_enum_variants, type_alias_enum_variants,
type_alias_impl_trait, type_alias_impl_trait,
type_ascription, type_ascription,
@ -1082,21 +1093,20 @@ symbols! {
unwind, unwind,
unwind_attributes, unwind_attributes,
unwrap_or, unwrap_or,
used,
use_extern_macros, use_extern_macros,
use_nested_groups, use_nested_groups,
used,
usize, usize,
v1, v1,
va_arg, va_arg,
va_copy, va_copy,
va_end, va_end,
val,
va_list, va_list,
va_start,
val,
var, var,
variant_count, variant_count,
va_start,
vec, vec,
Vec,
vec_type, vec_type,
version, version,
vis, vis,
@ -1117,7 +1127,6 @@ symbols! {
wrapping_mul, wrapping_mul,
wrapping_sub, wrapping_sub,
write_bytes, write_bytes,
Yield,
} }
} }