diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml new file mode 100644 index 0000000..7332dbc --- /dev/null +++ b/.github/workflows/rust.yaml @@ -0,0 +1,32 @@ +name: Rust + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + components: clippy, rustfmt + override: true + - name: Version + run: | + rustup --version + cargo --version + cargo clippy --version + - name: Lint + run: cargo clippy + - name: Format + run: cargo fmt -- --check + - name: Completion Scripts + run: | + for script in completions/*; do + shell=${script##*.} + cargo run -- --completions $shell > $script + done + git diff --no-ext-diff --quiet --exit-code diff --git a/man/just.1 b/man/just.1 index cdc1164..6f6d4ae 100644 --- a/man/just.1 +++ b/man/just.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11. -.TH JUST "1" "December 2019" "just 0.5.4" "JUST MANUAL" +.TH JUST "1" "January 2020" "just 0.5.4" "JUST MANUAL" .SH NAME just \- save and run commands .SH DESCRIPTION @@ -57,6 +57,10 @@ Print version information .TP Print colorful output [default: auto] [possible values: auto, always, never] +.HP +\fB\-\-completions\fR +.IP +Print shell completion script for [possible values: zsh, bash, fish, powershell, elvish] .TP \fB\-f\fR, \fB\-\-justfile\fR Use as justfile. diff --git a/rustfmt.toml b/rustfmt.toml index 346c9d2..bf1a714 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ tab_spaces = 2 -max_width = 100 +max_width = 100 diff --git a/src/analyzer.rs b/src/analyzer.rs index 8ec5d0a..16da03a 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -73,7 +73,7 @@ impl<'src> Analyzer<'src> { let mut settings = Settings::new(); - for (_, set) in self.sets.into_iter() { + for (_, set) in self.sets { match set.value { Setting::Shell(shell) => { assert!(settings.shell.is_none()); @@ -191,7 +191,7 @@ impl<'src> Analyzer<'src> { // Make sure the target recipe exists match recipes.get(alias.target.lexeme()) { - Some(target) => Ok(alias.resolve(target.clone())), + Some(target) => Ok(alias.resolve(Rc::clone(target))), None => Err(token.error(UnknownAliasTarget { alias: alias.name.lexeme(), target: alias.target.lexeme(), diff --git a/src/color.rs b/src/color.rs index a6a4b55..bcaf4e1 100644 --- a/src/color.rs +++ b/src/color.rs @@ -12,12 +12,12 @@ pub(crate) struct Color { } impl Color { - fn restyle(self, style: Style) -> Color { - Color { style, ..self } + fn restyle(self, style: Style) -> Self { + Self { style, ..self } } - fn redirect(self, stream: Stream) -> Color { - Color { + fn redirect(self, stream: Stream) -> Self { + Self { atty: atty::is(stream), ..self } @@ -31,76 +31,76 @@ impl Color { } } - pub(crate) fn fmt(fmt: &Formatter) -> Color { + pub(crate) fn fmt(fmt: &Formatter) -> Self { if fmt.alternate() { - Color::always() + Self::always() } else { - Color::never() + Self::never() } } - pub(crate) fn auto() -> Color { - Color { + pub(crate) fn auto() -> Self { + Self { use_color: UseColor::Auto, ..default() } } - pub(crate) fn always() -> Color { - Color { + pub(crate) fn always() -> Self { + Self { use_color: UseColor::Always, ..default() } } - pub(crate) fn never() -> Color { - Color { + pub(crate) fn never() -> Self { + Self { use_color: UseColor::Never, ..default() } } - pub(crate) fn stderr(self) -> Color { + pub(crate) fn stderr(self) -> Self { self.redirect(Stream::Stderr) } - pub(crate) fn stdout(self) -> Color { + pub(crate) fn stdout(self) -> Self { self.redirect(Stream::Stdout) } - pub(crate) fn doc(self) -> Color { + pub(crate) fn doc(self) -> Self { self.restyle(Style::new().fg(Blue)) } - pub(crate) fn error(self) -> Color { + pub(crate) fn error(self) -> Self { self.restyle(Style::new().fg(Red).bold()) } - pub(crate) fn warning(self) -> Color { + pub(crate) fn warning(self) -> Self { self.restyle(Style::new().fg(Yellow).bold()) } - pub(crate) fn banner(self) -> Color { + pub(crate) fn banner(self) -> Self { self.restyle(Style::new().fg(Cyan).bold()) } - pub(crate) fn command(self) -> Color { + pub(crate) fn command(self) -> Self { self.restyle(Style::new().bold()) } - pub(crate) fn parameter(self) -> Color { + pub(crate) fn parameter(self) -> Self { self.restyle(Style::new().fg(Cyan)) } - pub(crate) fn message(self) -> Color { + pub(crate) fn message(self) -> Self { self.restyle(Style::new().bold()) } - pub(crate) fn annotation(self) -> Color { + pub(crate) fn annotation(self) -> Self { self.restyle(Style::new().fg(Purple)) } - pub(crate) fn string(self) -> Color { + pub(crate) fn string(self) -> Self { self.restyle(Style::new().fg(Green)) } @@ -126,8 +126,8 @@ impl Color { } impl Default for Color { - fn default() -> Color { - Color { + fn default() -> Self { + Self { use_color: UseColor::Auto, atty: false, style: Style::new(), diff --git a/src/config.rs b/src/config.rs index 0803bea..7106cd9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -237,7 +237,7 @@ impl Config { } } - pub(crate) fn from_matches(matches: &ArgMatches) -> ConfigResult { + pub(crate) fn from_matches(matches: &ArgMatches) -> ConfigResult { let invocation_directory = env::current_dir().context(config_error::CurrentDir)?; let verbosity = Verbosity::from_flag_occurrences(matches.occurrences_of(arg::VERBOSE)); @@ -368,7 +368,7 @@ impl Config { || matches.occurrences_of(arg::SHELL) > 0 || matches.occurrences_of(arg::SHELL_ARG) > 0; - Ok(Config { + Ok(Self { dry_run: matches.is_present(arg::DRY_RUN), highlight: !matches.is_present(arg::NO_HIGHLIGHT), quiet: matches.is_present(arg::QUIET), @@ -394,7 +394,7 @@ impl Config { Search::find(&self.search_config, &self.invocation_directory).eprint(self.color)?; if self.subcommand == Edit { - return self.edit(&search); + return Self::edit(&search); } let src = fs::read_to_string(&search.justfile) @@ -415,7 +415,7 @@ impl Config { } match &self.subcommand { - Dump => self.dump(justfile), + Dump => Self::dump(justfile), Completions { shell } => Self::completions(&shell), Evaluate { overrides } => self.run(justfile, &search, overrides, &Vec::new()), Run { @@ -423,8 +423,8 @@ impl Config { overrides, } => self.run(justfile, &search, overrides, arguments), List => self.list(justfile), - Show { ref name } => self.show(&name, justfile), - Summary => self.summary(justfile), + Show { ref name } => Self::show(&name, justfile), + Summary => Self::summary(justfile), Edit | Init => unreachable!(), } } @@ -439,12 +439,12 @@ impl Config { Ok(()) } - fn dump(&self, justfile: Justfile) -> Result<(), i32> { + fn dump(justfile: Justfile) -> Result<(), i32> { println!("{}", justfile); Ok(()) } - pub(crate) fn edit(&self, search: &Search) -> Result<(), i32> { + pub(crate) fn edit(search: &Search) -> Result<(), i32> { let editor = env::var_os("VISUAL") .or_else(|| env::var_os("EDITOR")) .unwrap_or_else(|| "vim".into()); @@ -601,7 +601,7 @@ impl Config { } } - fn show(&self, name: &str, justfile: Justfile) -> Result<(), i32> { + fn show(name: &str, justfile: Justfile) -> Result<(), i32> { if let Some(alias) = justfile.get_alias(name) { let recipe = justfile.get_recipe(alias.target.name.lexeme()).unwrap(); println!("{}", alias); @@ -619,7 +619,7 @@ impl Config { } } - fn summary(&self, justfile: Justfile) -> Result<(), i32> { + fn summary(justfile: Justfile) -> Result<(), i32> { if justfile.count() == 0 { eprintln!("Justfile contains no recipes."); } else { diff --git a/src/config_error.rs b/src/config_error.rs index 052dc35..96c6337 100644 --- a/src/config_error.rs +++ b/src/config_error.rs @@ -48,8 +48,8 @@ pub(crate) enum ConfigError { } impl ConfigError { - pub(crate) fn internal(message: impl Into) -> ConfigError { - ConfigError::Internal { + pub(crate) fn internal(message: impl Into) -> Self { + Self::Internal { message: message.into(), } } diff --git a/src/enclosure.rs b/src/enclosure.rs index edeb6f8..533c295 100644 --- a/src/enclosure.rs +++ b/src/enclosure.rs @@ -1,3 +1,6 @@ +// `Self` cannot be used where type takes generic arguments +#![allow(clippy::use_self)] + use crate::common::*; pub struct Enclosure { @@ -7,7 +10,7 @@ pub struct Enclosure { impl Enclosure { pub fn tick(value: T) -> Enclosure { - Enclosure { + Self { enclosure: "`", value, } diff --git a/src/evaluator.rs b/src/evaluator.rs index 8f5d103..4030386 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -66,13 +66,14 @@ impl<'src, 'run> Evaluator<'src, 'run> { } } Expression::Call { thunk } => { + use Thunk::*; + let context = FunctionContext { dotenv: self.dotenv, invocation_directory: &self.config.invocation_directory, search: self.search, }; - use Thunk::*; match thunk { Nullary { name, function, .. } => { function(&context).map_err(|message| RuntimeError::FunctionCall { @@ -183,13 +184,12 @@ impl<'src, 'run> Evaluator<'src, 'run> { let mut rest = arguments; for parameter in parameters { let value = if rest.is_empty() { - match parameter.default { - Some(ref default) => evaluator.evaluate_expression(default)?, - None => { - return Err(RuntimeError::Internal { - message: "missing parameter without default".to_string(), - }); - } + if let Some(ref default) = parameter.default { + evaluator.evaluate_expression(default)? + } else { + return Err(RuntimeError::Internal { + message: "missing parameter without default".to_string(), + }); } } else if parameter.variadic { let value = rest.to_vec().join(" "); diff --git a/src/function.rs b/src/function.rs index 7539dc6..e7ca280 100644 --- a/src/function.rs +++ b/src/function.rs @@ -109,11 +109,12 @@ fn env_var_or_default( key: &str, default: &str, ) -> Result { + use std::env::VarError::*; + if let Some(value) = context.dotenv.get(key) { return Ok(value.clone()); } - use std::env::VarError::*; match env::var(key) { Err(NotPresent) => Ok(default.to_string()), Err(NotUnicode(os_string)) => Err(format!( diff --git a/src/interrupt_guard.rs b/src/interrupt_guard.rs index 90be44e..7f3faed 100644 --- a/src/interrupt_guard.rs +++ b/src/interrupt_guard.rs @@ -3,9 +3,9 @@ use crate::common::*; pub(crate) struct InterruptGuard; impl InterruptGuard { - pub(crate) fn new() -> InterruptGuard { + pub(crate) fn new() -> Self { InterruptHandler::instance().block(); - InterruptGuard + Self } } diff --git a/src/interrupt_handler.rs b/src/interrupt_handler.rs index 575c1ef..e24759d 100644 --- a/src/interrupt_handler.rs +++ b/src/interrupt_handler.rs @@ -7,10 +7,10 @@ pub(crate) struct InterruptHandler { impl InterruptHandler { pub(crate) fn install() -> Result<(), ctrlc::Error> { - ctrlc::set_handler(|| InterruptHandler::instance().interrupt()) + ctrlc::set_handler(|| Self::instance().interrupt()) } - pub(crate) fn instance() -> MutexGuard<'static, InterruptHandler> { + pub(crate) fn instance() -> MutexGuard<'static, Self> { lazy_static! { static ref INSTANCE: Mutex = Mutex::new(InterruptHandler::new()); } @@ -29,8 +29,8 @@ impl InterruptHandler { } } - fn new() -> InterruptHandler { - InterruptHandler { + fn new() -> Self { + Self { blocks: 0, interrupted: false, } diff --git a/src/justfile.rs b/src/justfile.rs index ee07ccc..fb21073 100644 --- a/src/justfile.rs +++ b/src/justfile.rs @@ -51,7 +51,7 @@ impl<'src> Justfile<'src> { arguments: &'run [String], ) -> RunResult<'run, ()> { let argvec: Vec<&str> = if !arguments.is_empty() { - arguments.iter().map(|argument| argument.as_str()).collect() + arguments.iter().map(String::as_str).collect() } else if let Some(recipe) = self.first() { let min_arguments = recipe.min_arguments(); if min_arguments > 0 { @@ -70,7 +70,7 @@ impl<'src> Justfile<'src> { let unknown_overrides = overrides .keys() .filter(|name| !self.assignments.contains_key(name.as_str())) - .map(|name| name.as_str()) + .map(String::as_str) .collect::>(); if !unknown_overrides.is_empty() { diff --git a/src/lexer.rs b/src/lexer.rs index f6dbca5..8372b22 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -73,15 +73,11 @@ impl<'src> Lexer<'src> { let len_utf8 = c.len_utf8(); self.token_end.offset += len_utf8; + self.token_end.column += len_utf8; - match c { - '\n' => { - self.token_end.column = 0; - self.token_end.line += 1; - } - _ => { - self.token_end.column += len_utf8; - } + if c == '\n' { + self.token_end.column = 0; + self.token_end.line += 1; } self.next = self.chars.next(); @@ -203,10 +199,7 @@ impl<'src> Lexer<'src> { CompilationError { token, kind } } - fn unterminated_interpolation_error( - &self, - interpolation_start: Token<'src>, - ) -> CompilationError<'src> { + fn unterminated_interpolation_error(interpolation_start: Token<'src>) -> CompilationError<'src> { CompilationError { token: interpolation_start, kind: UnterminatedInterpolation, @@ -275,7 +268,7 @@ impl<'src> Lexer<'src> { } if let Some(interpolation_start) = self.interpolation_start { - return Err(self.unterminated_interpolation_error(interpolation_start)); + return Err(Self::unterminated_interpolation_error(interpolation_start)); } while self.indented() { @@ -486,7 +479,7 @@ impl<'src> Lexer<'src> { self.lex_double(InterpolationEnd) } else if self.at_eol_or_eof() { // Return unterminated interpolation error that highlights the opening {{ - Err(self.unterminated_interpolation_error(interpolation_start)) + Err(Self::unterminated_interpolation_error(interpolation_start)) } else { // Otherwise lex as per normal self.lex_normal(start) diff --git a/src/lib.rs b/src/lib.rs index 6788614..0a2c43b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,37 @@ +#![deny(clippy::all, clippy::pedantic, clippy::restriction)] +#![allow( + clippy::print_stdout, + clippy::else_if_without_else, + clippy::use_debug, + clippy::implicit_return, + clippy::if_not_else, + clippy::missing_docs_in_private_items, + clippy::enum_glob_use, + clippy::integer_arithmetic, + clippy::option_unwrap_used, + clippy::indexing_slicing, + clippy::non_ascii_literal, + clippy::missing_inline_in_public_items, + clippy::option_expect_used, + clippy::comparison_chain, + clippy::wildcard_enum_match_arm, + clippy::too_many_lines, + clippy::shadow_unrelated, + clippy::needless_pass_by_value, + clippy::option_map_unwrap_or, + clippy::filter_map, + clippy::result_expect_used, + clippy::unreachable, + clippy::string_add, + clippy::panic, + clippy::match_same_arms +)] +// clippy::option_map_unwrap_or_else, +// clippy::result_expect_used, +// clippy::result_unwrap_used, +// clippy::unreachable +// )] + #[macro_use] extern crate lazy_static; diff --git a/src/list.rs b/src/list.rs index 37e949b..36da9bc 100644 --- a/src/list.rs +++ b/src/list.rs @@ -1,3 +1,6 @@ +// `Self` cannot be used where type takes generic arguments +#![allow(clippy::use_self)] + use crate::common::*; pub struct List + Clone> { @@ -70,7 +73,7 @@ impl + Clone> Display for List { write!(f, ", {} {}", self.conjunction, c)?; return Ok(()); } - _ => panic!("Iterator was fused, but returned Some after None"), + _ => unreachable!("Iterator was fused, but returned Some after None"), } } } diff --git a/src/output_error.rs b/src/output_error.rs index 977a22d..10e44a0 100644 --- a/src/output_error.rs +++ b/src/output_error.rs @@ -17,11 +17,11 @@ pub(crate) enum OutputError { impl Display for OutputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - OutputError::Code(code) => write!(f, "Process exited with status code {}", code), - OutputError::Io(ref io_error) => write!(f, "Error executing process: {}", io_error), - OutputError::Signal(signal) => write!(f, "Process terminated by signal {}", signal), - OutputError::Unknown => write!(f, "Process experienced an unknown failure"), - OutputError::Utf8(ref err) => write!(f, "Could not convert process stdout to UTF-8: {}", err), + Self::Code(code) => write!(f, "Process exited with status code {}", code), + Self::Io(ref io_error) => write!(f, "Error executing process: {}", io_error), + Self::Signal(signal) => write!(f, "Process terminated by signal {}", signal), + Self::Unknown => write!(f, "Process experienced an unknown failure"), + Self::Utf8(ref err) => write!(f, "Could not convert process stdout to UTF-8: {}", err), } } } diff --git a/src/positional.rs b/src/positional.rs index 57ee57d..b1be3ed 100644 --- a/src/positional.rs +++ b/src/positional.rs @@ -10,7 +10,7 @@ use crate::common::*; /// /// - Overrides are of the form `NAME=.*` /// -/// - After overrides comes a single optional search_directory argument. +/// - After overrides comes a single optional search directory argument. /// This is either '.', '..', or an argument that contains a `/`. /// /// If the argument contains a `/`, everything before and including @@ -40,9 +40,7 @@ pub struct Positional { } impl Positional { - pub fn from_values<'values>( - values: Option>, - ) -> Positional { + pub fn from_values<'values>(values: Option>) -> Self { let mut overrides = Vec::new(); let mut search_directory = None; let mut arguments = Vec::new(); @@ -71,7 +69,7 @@ impl Positional { } } - Positional { + Self { overrides, search_directory, arguments, diff --git a/src/recipe.rs b/src/recipe.rs index 0abcdf9..169b1ba 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -50,7 +50,7 @@ impl<'src, D> Recipe<'src, D> { pub(crate) fn max_arguments(&self) -> usize { if self.parameters.iter().any(|p| p.variadic) { - usize::MAX - 1 + usize::max_value() - 1 } else { self.parameters.len() } diff --git a/src/recipe_resolver.rs b/src/recipe_resolver.rs index 57ac719..07dea6e 100644 --- a/src/recipe_resolver.rs +++ b/src/recipe_resolver.rs @@ -76,7 +76,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> { recipe: UnresolvedRecipe<'src>, ) -> CompilationResult<'src, Rc>> { if let Some(resolved) = self.resolved_recipes.get(recipe.name()) { - return Ok(resolved.clone()); + return Ok(Rc::clone(resolved)); } stack.push(recipe.name()); @@ -87,7 +87,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> { if let Some(resolved) = self.resolved_recipes.get(name) { // dependency already resolved - dependencies.push(resolved.clone()); + dependencies.push(Rc::clone(&resolved)); } else if stack.contains(&name) { let first = stack[0]; stack.push(first); @@ -114,7 +114,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> { } let resolved = Rc::new(recipe.resolve(dependencies)?); - self.resolved_recipes.insert(resolved.clone()); + self.resolved_recipes.insert(Rc::clone(&resolved)); stack.pop(); Ok(resolved) } diff --git a/src/runtime_error.rs b/src/runtime_error.rs index f683ed8..09f3059 100644 --- a/src/runtime_error.rs +++ b/src/runtime_error.rs @@ -72,8 +72,8 @@ pub(crate) enum RuntimeError<'src> { impl<'src> Error for RuntimeError<'src> { fn code(&self) -> i32 { match *self { - Self::Code { code, .. } => code, - Self::Backtick { + Self::Code { code, .. } + | Self::Backtick { output_error: OutputError::Code(code), .. } => code, diff --git a/src/search.rs b/src/search.rs index 70c7e6b..8d62a6d 100644 --- a/src/search.rs +++ b/src/search.rs @@ -14,14 +14,14 @@ impl Search { pub(crate) fn find( search_config: &SearchConfig, invocation_directory: &Path, - ) -> SearchResult { + ) -> SearchResult { match search_config { SearchConfig::FromInvocationDirectory => { let justfile = Self::justfile(&invocation_directory)?; let working_directory = Self::working_directory_from_justfile(&justfile)?; - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -34,7 +34,7 @@ impl Search { let working_directory = Self::working_directory_from_justfile(&justfile)?; - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -45,7 +45,7 @@ impl Search { let working_directory = Self::working_directory_from_justfile(&justfile)?; - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -54,7 +54,7 @@ impl Search { SearchConfig::WithJustfileAndWorkingDirectory { justfile, working_directory, - } => Ok(Search { + } => Ok(Self { justfile: Self::clean(invocation_directory, justfile), working_directory: Self::clean(invocation_directory, working_directory), }), @@ -64,14 +64,14 @@ impl Search { pub(crate) fn init( search_config: &SearchConfig, invocation_directory: &Path, - ) -> SearchResult { + ) -> SearchResult { match search_config { SearchConfig::FromInvocationDirectory => { let working_directory = Self::project_root(&invocation_directory)?; let justfile = working_directory.join(FILENAME); - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -84,7 +84,7 @@ impl Search { let justfile = working_directory.join(FILENAME); - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -95,7 +95,7 @@ impl Search { let working_directory = Self::working_directory_from_justfile(&justfile)?; - Ok(Search { + Ok(Self { justfile, working_directory, }) @@ -104,7 +104,7 @@ impl Search { SearchConfig::WithJustfileAndWorkingDirectory { justfile, working_directory, - } => Ok(Search { + } => Ok(Self { justfile: Self::clean(invocation_directory, justfile), working_directory: Self::clean(invocation_directory, working_directory), }), diff --git a/src/table.rs b/src/table.rs index 217c993..9fe886e 100644 --- a/src/table.rs +++ b/src/table.rs @@ -85,6 +85,7 @@ impl<'table, V: Keyed<'table> + 'table> IntoIterator for &'table Table<'table, V type Item = (&'table &'table str, &'table V); type IntoIter = btree_map::Iter<'table, &'table str, V>; + #[must_use] fn into_iter(self) -> btree_map::Iter<'table, &'table str, V> { self.map.iter() } diff --git a/src/verbosity.rs b/src/verbosity.rs index 843feb3..61aefea 100644 --- a/src/verbosity.rs +++ b/src/verbosity.rs @@ -8,7 +8,7 @@ pub(crate) enum Verbosity { } impl Verbosity { - pub(crate) fn from_flag_occurrences(flag_occurences: u64) -> Verbosity { + pub(crate) fn from_flag_occurrences(flag_occurences: u64) -> Self { match flag_occurences { 0 => Taciturn, 1 => Loquacious, @@ -19,15 +19,13 @@ impl Verbosity { pub(crate) fn loquacious(self) -> bool { match self { Taciturn => false, - Loquacious => true, - Grandiloquent => true, + Loquacious | Grandiloquent => true, } } pub(crate) fn grandiloquent(self) -> bool { match self { - Taciturn => false, - Loquacious => false, + Taciturn | Loquacious => false, Grandiloquent => true, } }