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 counter = 0u32;
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()) {
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.
for keyword in &input.keywords.0 {
let name = &keyword.name;
let value = &keyword.value;
check_dup(&value.value());
check_dup(&value.value(), &mut errors);
prefill_stream.extend(quote! {
#value,
});
@ -116,7 +127,8 @@ pub fn symbols(input: TokenStream) -> TokenStream {
Some(value) => value.value(),
None => name.to_string(),
};
check_dup(&value);
check_dup(&value, &mut errors);
check_order(&name.to_string(), &mut errors);
prefill_stream.extend(quote! {
#value,
});
@ -131,7 +143,7 @@ pub fn symbols(input: TokenStream) -> TokenStream {
// Generate symbols for the strings "0", "1", ..., "9".
for n in 0..10 {
let n = n.to_string();
check_dup(&n);
check_dup(&n, &mut errors);
prefill_stream.extend(quote! {
#n,
});
@ -141,6 +153,13 @@ pub fn symbols(input: TokenStream) -> TokenStream {
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! {
macro_rules! keywords {
() => {

View File

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