about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-08 09:59:09 +0000
committerbors <bors@rust-lang.org>2024-08-08 09:59:09 +0000
commitd3a393932eeafa4638ae22f5ecbc38bf38760d0e (patch)
tree53dfce2310acc7557a9b2508cc4f7cfa438348ec
parent9337f7afa6fda07e60d6aa5ee88e692878446782 (diff)
parent15982b2fcae0fba61816dbd31617bc6604e36af5 (diff)
downloadrust-d3a393932eeafa4638ae22f5ecbc38bf38760d0e.tar.gz
rust-d3a393932eeafa4638ae22f5ecbc38bf38760d0e.zip
Auto merge of #128465 - GrigorenkoPV:128200, r=estebank
Some `const { }` asserts for #128200

The correctness of code in #128200 relies on an array being sorted (so that it can be used in binary search later), which is currently enforced with `// tidy-alphabetical` (and characters being written in `\u{XXXX}` form), as well as lack of duplicate entries with conflicting keys, which is not currently enforced.

This PR changes it to using a `const{ }` assertion (and also checks for duplicate entries). Sadly, we cannot use the recently-stabilized `is_sorted_by_key` here, because it is not const (but it would not allow us to check for uniqueness anyways). Instead, let's write a manual loop.

Alternative approach (perfect hash function): #128463

r? `@ghost`
-rw-r--r--compiler/rustc_errors/src/emitter.rs22
1 files changed, 15 insertions, 7 deletions
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 88ed3128164..b83d9e63d3e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2595,9 +2595,7 @@ fn num_decimal_digits(num: usize) -> usize {
 
 // We replace some characters so the CLI output is always consistent and underlines aligned.
 // Keep the following list in sync with `rustc_span::char_width`.
-// ATTENTION: keep lexicografically sorted so that the binary search will work
 const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
-    // tidy-alphabetical-start
     // In terminals without Unicode support the following will be garbled, but in *all* terminals
     // the underlying codepoint will be as well. We could gate this replacement behind a "unicode
     // support" gate.
@@ -2610,7 +2608,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
     ('\u{0006}', "␆"),
     ('\u{0007}', "␇"),
     ('\u{0008}', "␈"),
-    ('\u{0009}', "    "), // We do our own tab replacement
+    ('\t', "    "), // We do our own tab replacement
     ('\u{000b}', "␋"),
     ('\u{000c}', "␌"),
     ('\u{000d}', "␍"),
@@ -2643,13 +2641,23 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
     ('\u{2067}', "�"),
     ('\u{2068}', "�"),
     ('\u{2069}', "�"),
-    // tidy-alphabetical-end
 ];
 
 fn normalize_whitespace(s: &str) -> String {
-    // Scan the input string for a character in the ordered table above. If it's present, replace
-    // it with it's alternative string (it can be more than 1 char!). Otherwise, retain the input
-    // char. At the end, allocate all chars into a string in one operation.
+    const {
+        let mut i = 1;
+        while i < OUTPUT_REPLACEMENTS.len() {
+            assert!(
+                OUTPUT_REPLACEMENTS[i - 1].0 < OUTPUT_REPLACEMENTS[i].0,
+                "The OUTPUT_REPLACEMENTS array must be sorted (for binary search to work) \
+                and must contain no duplicate entries"
+            );
+            i += 1;
+        }
+    }
+    // Scan the input string for a character in the ordered table above.
+    // If it's present, replace it with its alternative string (it can be more than 1 char!).
+    // Otherwise, retain the input char.
     s.chars().fold(String::with_capacity(s.len()), |mut s, c| {
         match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) {
             Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1),