1 #![deny(clippy::all, clippy::pedantic)]
2 #![allow(
3     // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
4     clippy::nonstandard_macro_braces,
5     clippy::option_if_let_else,
6 )]
7 
8 use std::fmt::Display;
9 use thiserror::Error;
10 
11 // Some of the elaborate cases from the rcc codebase, which is a C compiler in
12 // Rust. https://github.com/jyn514/rcc/blob/0.8.0/src/data/error.rs
13 #[derive(Error, Debug)]
14 pub enum CompilerError {
15     #[error("cannot shift {} by {maximum} or more bits (got {current})", if *.is_left { "left" } else { "right" })]
16     TooManyShiftBits {
17         is_left: bool,
18         maximum: u64,
19         current: u64,
20     },
21 
22     #[error("#error {}", (.0).iter().copied().collect::<Vec<_>>().join(" "))]
23     User(Vec<&'static str>),
24 
25     #[error("overflow while parsing {}integer literal",
26         if let Some(signed) = .is_signed {
27             if *signed { "signed "} else { "unsigned "}
28         } else {
29             ""
30         }
31     )]
32     IntegerOverflow { is_signed: Option<bool> },
33 
34     #[error("overflow while parsing {}integer literal", match .is_signed {
35         Some(true) => "signed ",
36         Some(false) => "unsigned ",
37         None => "",
38     })]
39     IntegerOverflow2 { is_signed: Option<bool> },
40 }
41 
42 // Examples drawn from Rustup.
43 #[derive(Error, Debug)]
44 pub enum RustupError {
45     #[error(
46         "toolchain '{name}' does not contain component {component}{}",
47         .suggestion
48             .as_ref()
49             .map_or_else(String::new, |s| format!("; did you mean '{}'?", s)),
50     )]
51     UnknownComponent {
52         name: String,
53         component: String,
54         suggestion: Option<String>,
55     },
56 }
57 
58 fn assert<T: Display>(expected: &str, value: T) {
59     assert_eq!(expected, value.to_string());
60 }
61 
62 #[test]
63 fn test_rcc() {
64     assert(
65         "cannot shift left by 32 or more bits (got 50)",
66         CompilerError::TooManyShiftBits {
67             is_left: true,
68             maximum: 32,
69             current: 50,
70         },
71     );
72 
73     assert("#error A B C", CompilerError::User(vec!["A", "B", "C"]));
74 
75     assert(
76         "overflow while parsing signed integer literal",
77         CompilerError::IntegerOverflow {
78             is_signed: Some(true),
79         },
80     );
81 }
82 
83 #[test]
84 fn test_rustup() {
85     assert(
86         "toolchain 'nightly' does not contain component clipy; did you mean 'clippy'?",
87         RustupError::UnknownComponent {
88             name: "nightly".to_owned(),
89             component: "clipy".to_owned(),
90             suggestion: Some("clippy".to_owned()),
91         },
92     );
93 }
94