diff --git a/Cargo.toml b/Cargo.toml index 77f6b89..608dfdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,48 +86,54 @@ unexpected_cfgs = { level = "warn", check-cfg = [ unused_qualifications = "warn" [workspace.lints.clippy] -# The counts were generated with this command: -# cargo clippy --all-targets --workspace --message-format=json --quiet \ -# | jq -r '.message.code.code | select(. != null and startswith("clippy::"))' \ -# | sort | uniq -c | sort -h -r -# +# Groups all = { level = "warn", priority = -1 } cargo = { level = "warn", priority = -1 } pedantic = { level = "warn", priority = -1 } -print_stdout = "warn" # restriction: forbid print/println macros -print_stderr = "warn" # restriction: forbid eprint/eprintln macros -use_self = "warn" # nursery lint -cargo_common_metadata = "allow" # 3240 -multiple_crate_versions = "allow" # 2882 -missing_errors_doc = "allow" # 1572 -missing_panics_doc = "allow" # 946 -must_use_candidate = "allow" # 322 -match_same_arms = "allow" # 204 -cast_possible_truncation = "allow" # 122 -too_many_lines = "allow" # 101 -cast_possible_wrap = "allow" # 78 -cast_sign_loss = "allow" # 70 -struct_excessive_bools = "allow" # 68 -cast_precision_loss = "allow" # 52 -cast_lossless = "allow" # 35 -ignored_unit_patterns = "allow" # 21 -similar_names = "allow" # 20 -needless_pass_by_value = "allow" # 16 -float_cmp = "allow" # 12 -items_after_statements = "allow" # 11 -return_self_not_must_use = "allow" # 8 -inline_always = "allow" # 6 -fn_params_excessive_bools = "allow" # 6 -used_underscore_items = "allow" # 2 -should_panic_without_expect = "allow" # 2 +perf = { level = "warn", priority = -1 } -doc_markdown = "allow" -unused_self = "allow" -enum_glob_use = "allow" -unnested_or_patterns = "allow" -implicit_hasher = "allow" -doc_link_with_quotes = "allow" +# Restrictions +print_stderr = "warn" +print_stdout = "warn" + +# Casts; TODO: replace with fancy std methods when available +cast_lossless = "allow" +cast_possible_truncation = "allow" +cast_possible_wrap = "allow" +cast_precision_loss = "allow" +cast_sign_loss = "allow" + +# Others (mostly, curated nursery lints) +assigning_clones = "warn" +branches_sharing_code = "warn" +fallible_impl_from = "warn" +imprecise_flops = "warn" +iter_on_empty_collections = "warn" +iter_on_single_items = "warn" +large_stack_frames = "warn" +missing_const_for_fn = "warn" +needless_collect = "warn" +set_contains_or_insert = "warn" +use_self = "warn" +useless_let_if_seq = "warn" + +# Shut up +cargo_common_metadata = "allow" +fn_params_excessive_bools = "allow" format_push_string = "allow" -flat_map_option = "allow" -from_iter_instead_of_collect = "allow" -large_types_passed_by_value = "allow" +ignored_unit_patterns = "allow" +inline_always = "allow" +items_after_statements = "allow" +match_same_arms = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" +multiple_crate_versions = "allow" +must_use_candidate = "allow" +needless_pass_by_value = "allow" +return_self_not_must_use = "allow" +should_panic_without_expect = "allow" +struct_excessive_bools = "allow" +too_many_lines = "allow" +undocumented_unsafe_blocks = "allow" +unnested_or_patterns = "allow" +unused_self = "allow" diff --git a/interpreter/src/builtins.rs b/interpreter/src/builtins.rs index dedd7bf..99f08c5 100644 --- a/interpreter/src/builtins.rs +++ b/interpreter/src/builtins.rs @@ -32,7 +32,7 @@ pub(crate) enum BuiltinError { } impl BuiltinError { - pub(crate) fn into_interpreter_error(self, span: AriadneSpan) -> InterpreterError { + pub(crate) const fn into_interpreter_error(self, span: AriadneSpan) -> InterpreterError { match self { Self::Arity { expected, given } => { InterpreterError::ArityMismatch(span, expected, given) @@ -123,7 +123,7 @@ impl<'a> Interpreter<'a> { } } -fn require_args<'a, 'b>( +const fn require_args<'a, 'b>( args: &'b [Value<'a>], min: u8, max: u8, diff --git a/interpreter/src/ir.rs b/interpreter/src/ir.rs index ee41391..9b70ba8 100644 --- a/interpreter/src/ir.rs +++ b/interpreter/src/ir.rs @@ -165,7 +165,7 @@ impl Instruction { } } - fn br(condition: Reg, then_label: Label) -> Self { + const fn br(condition: Reg, then_label: Label) -> Self { Self::Branch { then_label, else_label: Label(0), condition } } @@ -375,7 +375,7 @@ impl Display for Instruction { } impl Instruction { - fn display_name(self) -> &'static str { + const fn display_name(self) -> &'static str { match self { Self::LoadF { .. } => "fload", Self::Negation { .. } => "not", diff --git a/interpreter/src/ir/lower.rs b/interpreter/src/ir/lower.rs index 643b5f2..43938c0 100644 --- a/interpreter/src/ir/lower.rs +++ b/interpreter/src/ir/lower.rs @@ -186,7 +186,7 @@ impl<'a> CodeGen<'a> { Statement::If { condition, then_body, else_body, metadata } => { self.with_metadata(*metadata, |this| { let state = this.regs.clone(); - let (if_label, _) = + let (if_label, ()) = this.emit_branch(condition, |this| this.lower_body(then_body)); if let Some(else_body) = else_body { @@ -831,7 +831,7 @@ impl<'a> CodeGen<'a> { } fn lower_and_into(&mut self, lhs: &Expr<'_>, rhs: &Expr<'_>, dest: Reg) { - let (if_label, _) = self.emit_branch(lhs, |this| { + let (if_label, ()) = self.emit_branch(lhs, |this| { this.scoped_reg(|this, rhs_reg| { this.lower_expr_into(rhs, rhs_reg); this.truthify(dest, rhs_reg); @@ -845,7 +845,7 @@ impl<'a> CodeGen<'a> { } fn lower_or_into(&mut self, lhs: &Expr<'_>, rhs: &Expr<'_>, dest: Reg) { - let (if_label, _) = self.emit_branch(lhs, |this| { + let (if_label, ()) = self.emit_branch(lhs, |this| { let (arg, ty) = TypedArg::new_imm(1).into_arg(); this.emit(Instruction::CopyP { dest, arg, ty }); }); @@ -1015,19 +1015,19 @@ impl<'a> Bytecode<'a> { &mut self.code[label.0 as usize] } - pub fn begin_code(&self) -> CodeRange { + pub const fn begin_code(&self) -> CodeRange { CodeRange(self.begin_label.0..self.begin_file_label.0) } - pub fn begin_file_code(&self) -> CodeRange { + pub const fn begin_file_code(&self) -> CodeRange { CodeRange(self.begin_file_label.0..self.end_file_label.0) } - pub fn end_file_code(&self) -> CodeRange { + pub const fn end_file_code(&self) -> CodeRange { CodeRange(self.end_file_label.0..self.end_label.0) } - pub fn end_code(&self) -> CodeRange { + pub const fn end_code(&self) -> CodeRange { CodeRange(self.end_label.0..self.rules_label.0) } @@ -1035,13 +1035,13 @@ impl<'a> Bytecode<'a> { CodeRange(self.rules_label.0..self.len()) } - pub fn funs_code(&self) -> CodeRange { + pub const fn funs_code(&self) -> CodeRange { CodeRange(self.funs_label.0..self.begin_label.0) } } impl Instruction { - pub(super) fn from_unary(op: UnaryOperator, dest: Reg, arg: TypedArg) -> Self { + pub(super) const fn from_unary(op: UnaryOperator, dest: Reg, arg: TypedArg) -> Self { let (arg, ty) = arg.into_arg(); match op { UnaryOperator::Record => Self::LoadF { dest, arg, ty }, @@ -1076,7 +1076,7 @@ impl Instruction { } } -fn lower_assign_ops(op: BinaryPlaceOperator) -> Option { +const fn lower_assign_ops(op: BinaryPlaceOperator) -> Option { match op { BinaryPlaceOperator::Assignment => None, BinaryPlaceOperator::AddAssign => Some(BinaryOperator::Add), diff --git a/interpreter/src/ir/lower/utils.rs b/interpreter/src/ir/lower/utils.rs index 8e53d2f..d9a0d0f 100644 --- a/interpreter/src/ir/lower/utils.rs +++ b/interpreter/src/ir/lower/utils.rs @@ -43,7 +43,7 @@ pub enum Operand { } impl LinearReg { - pub fn into_inner(self) -> Reg { + pub const fn into_inner(self) -> Reg { let inner = self.0; forget(self); inner @@ -74,7 +74,7 @@ impl TypedArg { TypedPlace::new_is(var).into() } - pub fn new_imm(imm: i32) -> Self { + pub const fn new_imm(imm: i32) -> Self { Self(Arg { imm }, ArgTy::Imm) } @@ -92,7 +92,7 @@ impl TypedArg { TypedPlace::new_reg(reg).into() } - pub fn as_reg(self) -> Option { + pub const fn as_reg(self) -> Option { if matches!(self.1, ArgTy::Reg) { // SAFETY: has been type-checked. Some(unsafe { self.0.reg }) @@ -262,7 +262,7 @@ impl From for LinearReg { impl TypedArg { #[inline(always)] - pub fn into_arg(self) -> (Arg, ArgTy) { + pub const fn into_arg(self) -> (Arg, ArgTy) { (self.0, self.1) } } @@ -274,7 +274,7 @@ impl TypedPlace { } #[inline(always)] - pub fn into_place(self) -> (Arg, PlaceTy) { + pub const fn into_place(self) -> (Arg, PlaceTy) { (self.0, self.1) } } diff --git a/interpreter/src/vm.rs b/interpreter/src/vm.rs index 750cddb..b9a1302 100644 --- a/interpreter/src/vm.rs +++ b/interpreter/src/vm.rs @@ -100,7 +100,7 @@ pub struct Consts<'a>(pub(crate) Vec<'a, Value<'a>>); #[derive(Debug, Clone)] pub struct CodeRange(pub(crate) Range); -/// Newtype of (Arg, PlaceTy). +/// Newtype of `(Arg, PlaceTy)`. #[derive(Clone, Copy)] struct Place { arg: Arg, @@ -296,7 +296,7 @@ impl<'a> Interpreter<'a> { } Instruction::LoadA { dest, arg, start, end, ty } => { let key = self.make_array_key(start, end); - let val = self.array_elem_get(Place::new(arg, ty), key, metadata)?; + let val = self.array_elem_get(Place::new(arg, ty), &key, metadata)?; self.write_reg(dest, val); } @@ -344,13 +344,13 @@ impl<'a> Interpreter<'a> { } Instruction::In { dest, lhs, rhs, tyr, tyl } => { let key = self.get_val(rhs, tyr, metadata, Value::to_string)?; - let val = self.has_array_elem(Place::new(lhs, tyl), key, metadata)?; + let val = self.has_array_elem(Place::new(lhs, tyl), &key, metadata)?; self.write_reg(dest, val); } Instruction::InA { dest, arg, start, end, ty } => { let key = self.make_array_key(start, end); - let val = self.has_array_elem(Place::new(arg, ty), key, metadata)?; + let val = self.has_array_elem(Place::new(arg, ty), &key, metadata)?; self.write_reg(dest, val); } @@ -459,7 +459,7 @@ impl<'a> Interpreter<'a> { fn array_elem_get( &mut self, place: Place, - key: String, + key: &str, metadata: &[MetaId], ) -> Result> { place @@ -493,7 +493,7 @@ impl<'a> Interpreter<'a> { .ok_or_else(|| InterpreterError::ArrayUseOfScalar(self.get_span(metadata))) } - fn has_array_elem(&mut self, place: Place, key: String, metadata: &[MetaId]) -> Result { + fn has_array_elem(&mut self, place: Place, key: &str, metadata: &[MetaId]) -> Result { place .array(self) .and_then(|arr| arr.has_array_elem(key)) @@ -665,7 +665,7 @@ impl<'a> Registers<'a> { } } #[inline(always)] - fn index_of(reg: Reg, offset: IxWidth) -> usize { + const fn index_of(reg: Reg, offset: IxWidth) -> usize { reg.0 as usize + offset as usize } #[inline(always)] @@ -803,7 +803,7 @@ impl Arg { impl Place { #[inline(always)] - fn new(arg: Arg, ty: PlaceTy) -> Self { + const fn new(arg: Arg, ty: PlaceTy) -> Self { Self { arg, ty } } diff --git a/interpreter/src/vm/symbols.rs b/interpreter/src/vm/symbols.rs index e8d834c..386ebae 100644 --- a/interpreter/src/vm/symbols.rs +++ b/interpreter/src/vm/symbols.rs @@ -293,7 +293,7 @@ impl Record { let len = self.raw.len(); let buf = self.fields.get_or_insert_default(); buf.clear(); - buf.push(Span::from(0..self.raw.len())); // $0 + buf.push(Span::from(0..len)); // $0 // Aren't iterators beautiful? regex::automaton(symbols.fs.to_string().as_bytes(), mode, false)? @@ -351,7 +351,7 @@ impl Record { self.write_record_raw(val); Ok(()) } else { - self.write_field_raw(val, n, symbols, mode) + self.write_field_raw(&val, n, symbols, mode) } } @@ -365,7 +365,7 @@ impl Record { /// the public function for more details. fn write_field_raw( &mut self, - val: Value<'_>, + val: &Value<'_>, n: usize, symbols: &mut SymbolTable<'_>, mode: ExecMode, diff --git a/interpreter/src/vm/types.rs b/interpreter/src/vm/types.rs index 3b554d4..4d8e33f 100644 --- a/interpreter/src/vm/types.rs +++ b/interpreter/src/vm/types.rs @@ -21,7 +21,7 @@ use hashbrown::HashMap; use crate::{ExecMode, vm::regex}; #[inline(always)] -fn likely(b: bool) -> bool { +const fn likely(b: bool) -> bool { if !b { cold_path(); } @@ -128,13 +128,13 @@ impl<'a> Value<'a> { Some(()) } - pub fn get_array_elem(&mut self, key: String) -> Option { + pub fn get_array_elem(&mut self, key: &str) -> Option { self.as_array() - .map(|arr| arr.borrow().get(&key).cloned().unwrap_or(Self::Untyped)) + .map(|arr| arr.borrow().get(key).cloned().unwrap_or(Self::Untyped)) } - pub fn has_array_elem(&mut self, key: String) -> Option { - self.as_array().map(|arr| arr.borrow().get(&key).is_some()) + pub fn has_array_elem(&mut self, key: &str) -> Option { + self.as_array().map(|arr| arr.borrow().get(key).is_some()) } pub fn array_elem_mdim(&mut self, key: String) -> Option { diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index 32a2538..b6d2b32 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -647,11 +647,11 @@ impl<'a> Identifier<'a> { } } -fn accept_expression(lex: &mut Lexer<'_>) { +const fn accept_expression(lex: &mut Lexer<'_>) { lex.extras.ctx = Context::AcceptExpression; } -fn accept_operator(lex: &mut Lexer<'_>) { +const fn accept_operator(lex: &mut Lexer<'_>) { lex.extras.ctx = Context::AcceptOperator; } @@ -733,7 +733,7 @@ impl Ord for Slice<'_> { } impl Extra { - fn arena<'a>(&self) -> &'a Bump { + const fn arena<'a>(&self) -> &'a Bump { // SAFETY: lives for as long as self because it's the same lifetime as // the source being lexed; Logos just can't take lifetimes on extras. unsafe { self.arena.as_ref() } diff --git a/parser/src/ast.rs b/parser/src/ast.rs index d252d86..f125e2c 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -176,7 +176,7 @@ pub enum Place<'a> { ChainedIndex(Variable<'a>, Vec<'a, Vec<'a, Expr<'a>>>), } -/// GNU docs: https://www.gnu.org/software/gawk/manual/html_node/Redirection.html +/// GNU docs: #[derive(Clone, Copy)] #[repr(u8)] pub enum Redirection { @@ -334,31 +334,31 @@ impl<'a> Expr<'a> { } impl UnaryOperator { - pub fn expr(self, a: Expr<'_>) -> ExprNode<'_> { + pub const fn expr(self, a: Expr<'_>) -> ExprNode<'_> { ExprNode::UnaryOperation(self, a) } } impl BinaryOperator { - pub fn expr<'a>(self, a: Expr<'a>, b: Expr<'a>) -> ExprNode<'a> { + pub const fn expr<'a>(self, a: Expr<'a>, b: Expr<'a>) -> ExprNode<'a> { ExprNode::BinaryOperation(self, a, b) } } impl UnaryPlaceOperator { - pub fn expr(self, a: Place<'_>) -> ExprNode<'_> { + pub const fn expr(self, a: Place<'_>) -> ExprNode<'_> { ExprNode::UnaryPlaceOperation(self, a) } } impl BinaryPlaceOperator { - pub fn expr<'a>(self, a: Place<'a>, b: Expr<'a>) -> ExprNode<'a> { + pub const fn expr<'a>(self, a: Place<'a>, b: Expr<'a>) -> ExprNode<'a> { ExprNode::BinaryPlaceOperation(self, a, b) } } impl ArrayOperator { - pub fn expr<'a>(self, a: Variable<'a>, b: Vec<'a, Expr<'a>>) -> ExprNode<'a> { + pub const fn expr<'a>(self, a: Variable<'a>, b: Vec<'a, Expr<'a>>) -> ExprNode<'a> { ExprNode::ArrayOperation(self, a, b) } } @@ -443,7 +443,7 @@ impl<'a> BinaryOperator { } impl UnaryPlaceOperator { - pub fn parse_prefix(value: &Token<'_>, span: Span) -> Result { + pub const fn parse_prefix(value: &Token<'_>, span: Span) -> Result { match value { Token::Increment => Ok(Self::IncrementL), Token::Decrement => Ok(Self::DecrementL), @@ -451,7 +451,7 @@ impl UnaryPlaceOperator { } } - pub fn parse_suffix(value: &Token<'_>, span: Span) -> Result { + pub const fn parse_suffix(value: &Token<'_>, span: Span) -> Result { match value { Token::Increment => Ok(Self::IncrementR), Token::Decrement => Ok(Self::DecrementR), @@ -517,7 +517,7 @@ impl<'a> Place<'a> { } impl Redirection { - pub fn parse(value: &Token) -> Option { + pub const fn parse(value: &Token) -> Option { match value { Token::GreaterThan => Some(Self::WriteFile), Token::AppendPipe => Some(Self::AppendFile), @@ -529,7 +529,7 @@ impl Redirection { } impl WriteKind { - pub fn parse(value: &Token) -> Option { + pub const fn parse(value: &Token) -> Option { match value { Token::Pipe => Some(Self::Pipe), Token::DoublePipe => Some(Self::Coprocess), @@ -537,7 +537,7 @@ impl WriteKind { } } - pub fn expr_getline<'a>(self, var: Option>, expr: Expr<'a>) -> Getline<'a> { + pub const fn expr_getline<'a>(self, var: Option>, expr: Expr<'a>) -> Getline<'a> { match self { Self::Pipe => Getline::PipeOut(var, expr), Self::Coprocess => Getline::CoprocessOut(var, expr), diff --git a/parser/src/diagnostics.rs b/parser/src/diagnostics.rs index 626d3a6..f60aca1 100644 --- a/parser/src/diagnostics.rs +++ b/parser/src/diagnostics.rs @@ -75,7 +75,7 @@ impl DiagnosticStore { Ok(()) } - pub fn is_unrecoverable(&self) -> bool { + pub const fn is_unrecoverable(&self) -> bool { self.unrecoverable } @@ -163,7 +163,7 @@ pub enum ParsingError { } impl ParsingError { - pub fn span(&self) -> Option { + pub const fn span(&self) -> Option { match self { Self::LexingError(LexingError::Unknown | LexingError::UnexpectedEof) => None, &Self::LexingError(LexingError::Unexpected(span, _)) @@ -209,7 +209,7 @@ impl ParsingError { | &Self::CommandDoubleCall(span, _) => Some(span), } } - fn hint(&self) -> Option<&'static str> { + const fn hint(&self) -> Option<&'static str> { match self { Self::DuplicatedArgument(_, _, _) => Some("Consider giving the argument another name."), Self::ExpectedStatementEnd(_) => Some( diff --git a/parser/src/lex.rs b/parser/src/lex.rs index e496b7b..e83a765 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -152,7 +152,7 @@ impl<'a> Lexer<'a> { } } - pub fn span(&self) -> Span { + pub const fn span(&self) -> Span { self.span } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d2977dd..ab2879b 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -630,7 +630,7 @@ impl<'a> Parser<'a> { args } else { let mut args = Vec::new_in(self.arena); - self.parse_command_args(lex, &mut args).map(|_| args)? + self.parse_command_args(lex, &mut args).map(|()| args)? }; let redirection = self.parse_command_redirection(lex)?; let metadata = self.gen_metadata(lex.span().since(start)); diff --git a/parser/src/pratt.rs b/parser/src/pratt.rs index 6bea512..81002fe 100644 --- a/parser/src/pratt.rs +++ b/parser/src/pratt.rs @@ -31,7 +31,7 @@ pub struct Pratt<'a, 'b> { } impl<'a, 'b> Pratt<'a, 'b> { - pub fn new(parser: &'b mut Parser<'a>, typed_regex: bool) -> Self { + pub const fn new(parser: &'b mut Parser<'a>, typed_regex: bool) -> Self { Self { parser, typed_regex } } @@ -612,7 +612,7 @@ impl<'a, 'b> Pratt<'a, 'b> { } /// Errors if `expr` is a typed regex. - fn typecheck(&self, lex: &mut Lexer<'a>, expr: &Expr<'a>) -> Result<()> { + const fn typecheck(&self, lex: &mut Lexer<'a>, expr: &Expr<'a>) -> Result<()> { if matches!(expr, Expr::Leaf(Atom::TypedRegex(_), _)) { Err(ParsingError::UnexpectedTypedRegex(lex.span())) } else { diff --git a/src/event.rs b/src/event.rs index 0d1f9ef..23d4faf 100644 --- a/src/event.rs +++ b/src/event.rs @@ -28,7 +28,7 @@ pub struct AwkRt<'a> { } impl<'a> AwkRt<'a> { - pub fn new( + pub const fn new( intrp: Interpreter<'a>, bc: Bytecode<'a>, queue: &'a [ArgQueueItem], @@ -120,7 +120,7 @@ impl<'a> AwkRt<'a> { fn perform_io(&mut self, req: &IoRequest) -> Result { match req { IoRequest::FileWrite { buf, at: FilePath::Stdout } => { - stdout().lock().write_all(buf).map(|_| IoResponse::Empty) + stdout().lock().write_all(buf).map(|()| IoResponse::Empty) } _ => todo!(), } diff --git a/src/utils.rs b/src/utils.rs index 7c2af11..f42d2db 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,7 +27,7 @@ fn install_abort_hook() { /// Ensures exit code 2 on panics, which is GNU's behavior. Also installs /// color-eyre's panic hook. -/// https://www.gnu.org/software/gawk/manual/html_node/Exit-Status.html +/// #[inline(always)] // Hide from stack trace on panics. pub fn ensure_consistent_panic(f: impl UnwindSafe + FnOnce() -> T) -> T { if cfg!(panic = "abort") {