diff --git a/check-clippy.sh b/check-clippy.sh new file mode 100755 index 0000000000..20ac595851 --- /dev/null +++ b/check-clippy.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -euo pipefail + +# Usage: check-clippy.sh [--install] + +if cargo install --list | tee /dev/null | grep -q "^clippy v0"; then + exit 0 +else + exit 1 +fi diff --git a/clippy-all.sh b/clippy-all.sh new file mode 100755 index 0000000000..6ec2fd1411 --- /dev/null +++ b/clippy-all.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail + +# Check all sources with clippy. +# In the cton-util crate (root dir) clippy will only work with nightly cargo - +# there is a bug where it will reject the commands passed to it by cargo 0.25.0 +cargo +nightly clippy --all diff --git a/cranelift/clippy.toml b/cranelift/clippy.toml new file mode 100644 index 0000000000..caabf12b77 --- /dev/null +++ b/cranelift/clippy.toml @@ -0,0 +1 @@ +doc-valid-idents = [ "WebAssembly", "NaN", "SetCC" ] diff --git a/cranelift/src/cat.rs b/cranelift/src/cat.rs index 3ae9c843d8..4d3d73ac2c 100644 --- a/cranelift/src/cat.rs +++ b/cranelift/src/cat.rs @@ -7,7 +7,7 @@ use cton_reader::parse_functions; use CommandResult; use utils::read_to_string; -pub fn run(files: Vec) -> CommandResult { +pub fn run(files: &[String]) -> CommandResult { for (i, f) in files.into_iter().enumerate() { if i != 0 { println!(); @@ -17,7 +17,7 @@ pub fn run(files: Vec) -> CommandResult { Ok(()) } -fn cat_one(filename: String) -> CommandResult { +fn cat_one(filename: &str) -> CommandResult { let buffer = read_to_string(&filename).map_err( |e| format!("{}: {}", filename, e), )?; diff --git a/cranelift/src/compile.rs b/cranelift/src/compile.rs index 9047f055fe..a1cc244f5d 100644 --- a/cranelift/src/compile.rs +++ b/cranelift/src/compile.rs @@ -49,23 +49,23 @@ impl binemit::RelocSink for PrintRelocs { pub fn run( files: Vec, flag_print: bool, - flag_set: Vec, - flag_isa: String, + flag_set: &[String], + flag_isa: &str, ) -> Result<(), String> { let parsed = parse_sets_and_isa(flag_set, flag_isa)?; for filename in files { let path = Path::new(&filename); let name = String::from(path.as_os_str().to_string_lossy()); - handle_module(flag_print, path.to_path_buf(), name, parsed.as_fisa())?; + handle_module(flag_print, &path.to_path_buf(), &name, parsed.as_fisa())?; } Ok(()) } fn handle_module( flag_print: bool, - path: PathBuf, - name: String, + path: &PathBuf, + name: &str, fisa: FlagsOrIsa, ) -> Result<(), String> { let buffer = read_to_string(&path).map_err( diff --git a/cranelift/src/cton-util.rs b/cranelift/src/cton-util.rs index 54d7d38d4d..216eae458b 100644 --- a/cranelift/src/cton-util.rs +++ b/cranelift/src/cton-util.rs @@ -86,15 +86,20 @@ fn cton_util() -> CommandResult { // Find the sub-command to execute. let result = if args.cmd_test { - cton_filetests::run(args.flag_verbose, args.arg_file).map(|_time| ()) + cton_filetests::run(args.flag_verbose, &args.arg_file).map(|_time| ()) } else if args.cmd_cat { - cat::run(args.arg_file) + cat::run(&args.arg_file) } else if args.cmd_filecheck { - rsfilecheck::run(args.arg_file, args.flag_verbose) + rsfilecheck::run(&args.arg_file, args.flag_verbose) } else if args.cmd_print_cfg { - print_cfg::run(args.arg_file) + print_cfg::run(&args.arg_file) } else if args.cmd_compile { - compile::run(args.arg_file, args.flag_print, args.flag_set, args.flag_isa) + compile::run( + args.arg_file, + args.flag_print, + &args.flag_set, + &args.flag_isa, + ) } else if args.cmd_wasm { wasm::run( args.arg_file, @@ -102,8 +107,8 @@ fn cton_util() -> CommandResult { args.flag_just_decode, args.flag_check_translation, args.flag_print, - args.flag_set, - args.flag_isa, + &args.flag_set, + &args.flag_isa, args.flag_print_size, ) } else { diff --git a/cranelift/src/print_cfg.rs b/cranelift/src/print_cfg.rs index 08ab439d05..65242cc8f8 100644 --- a/cranelift/src/print_cfg.rs +++ b/cranelift/src/print_cfg.rs @@ -8,7 +8,7 @@ use cretonne::cfg_printer::CFGPrinter; use cton_reader::parse_functions; use utils::read_to_string; -pub fn run(files: Vec) -> CommandResult { +pub fn run(files: &[String]) -> CommandResult { for (i, f) in files.into_iter().enumerate() { if i != 0 { println!(); @@ -18,8 +18,8 @@ pub fn run(files: Vec) -> CommandResult { Ok(()) } -fn print_cfg(filename: String) -> CommandResult { - let buffer = read_to_string(&filename).map_err( +fn print_cfg(filename: &str) -> CommandResult { + let buffer = read_to_string(filename).map_err( |e| format!("{}: {}", filename, e), )?; let items = parse_functions(&buffer).map_err( diff --git a/cranelift/src/rsfilecheck.rs b/cranelift/src/rsfilecheck.rs index 57b9bb9e8f..58b9cb9e53 100644 --- a/cranelift/src/rsfilecheck.rs +++ b/cranelift/src/rsfilecheck.rs @@ -7,7 +7,7 @@ use utils::read_to_string; use filecheck::{CheckerBuilder, Checker, NO_VARIABLES}; use std::io::{self, Read}; -pub fn run(files: Vec, verbose: bool) -> CommandResult { +pub fn run(files: &[String], verbose: bool) -> CommandResult { if files.is_empty() { return Err("No check files".to_string()); } diff --git a/cranelift/src/utils.rs b/cranelift/src/utils.rs index 7e45e99436..dc4f501893 100644 --- a/cranelift/src/utils.rs +++ b/cranelift/src/utils.rs @@ -41,10 +41,7 @@ impl OwnedFlagsOrIsa { } /// Parse "set" and "isa" commands. -pub fn parse_sets_and_isa( - flag_set: Vec, - flag_isa: String, -) -> Result { +pub fn parse_sets_and_isa(flag_set: &[String], flag_isa: &str) -> Result { let mut flag_builder = settings::builder(); parse_options( flag_set.iter().map(|x| x.as_str()), diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 3ab877bf34..efd93df77f 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -1,6 +1,7 @@ //! CLI tool to use the functions provided by the [cretonne-wasm](../cton_wasm/index.html) crate. //! //! Reads Wasm binary files, translates the functions' code to Cretonne IL. +#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments, cyclomatic_complexity))] use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment}; use std::path::PathBuf; @@ -38,8 +39,8 @@ pub fn run( flag_just_decode: bool, flag_check_translation: bool, flag_print: bool, - flag_set: Vec, - flag_isa: String, + flag_set: &[String], + flag_isa: &str, flag_print_size: bool, ) -> Result<(), String> { let parsed = parse_sets_and_isa(flag_set, flag_isa)?; @@ -53,8 +54,8 @@ pub fn run( flag_check_translation, flag_print, flag_print_size, - path.to_path_buf(), - name, + &path.to_path_buf(), + &name, parsed.as_fisa(), )?; } @@ -67,8 +68,8 @@ fn handle_module( flag_check_translation: bool, flag_print: bool, flag_print_size: bool, - path: PathBuf, - name: String, + path: &PathBuf, + name: &str, fisa: FlagsOrIsa, ) -> Result<(), String> { let mut terminal = term::stdout().unwrap(); @@ -153,29 +154,27 @@ fn handle_module( context.func = func.clone(); if flag_check_translation { context.verify(fisa).map_err(|err| { - pretty_verifier_error(&context.func, fisa.isa, err) + pretty_verifier_error(&context.func, fisa.isa, &err) })?; - } else { - if let Some(isa) = fisa.isa { - let compiled_size = context.compile(isa).map_err(|err| { - pretty_error(&context.func, fisa.isa, err) - })?; - if flag_print_size { - println!( - "Function #{} code size: {} bytes", - func_index, - compiled_size - ); - total_module_code_size += compiled_size; - println!( - "Function #{} bytecode size: {} bytes", - func_index, - dummy_environ.func_bytecode_sizes[func_index] - ); - } - } else { - return Err(String::from("compilation requires a target isa")); + } else if let Some(isa) = fisa.isa { + let compiled_size = context.compile(isa).map_err(|err| { + pretty_error(&context.func, fisa.isa, err) + })?; + if flag_print_size { + println!( + "Function #{} code size: {} bytes", + func_index, + compiled_size + ); + total_module_code_size += compiled_size; + println!( + "Function #{} bytecode size: {} bytes", + func_index, + dummy_environ.func_bytecode_sizes[func_index] + ); } + } else { + return Err(String::from("compilation requires a target isa")); } if flag_print { vprintln!(flag_verbose, ""); @@ -194,10 +193,7 @@ fn handle_module( if !flag_check_translation && flag_print_size { println!("Total module code size: {} bytes", total_module_code_size); - let total_bytecode_size = dummy_environ.func_bytecode_sizes.iter().fold( - 0, - |sum, x| sum + x, - ); + let total_bytecode_size: usize = dummy_environ.func_bytecode_sizes.iter().sum(); println!("Total module bytecode size: {} bytes", total_bytecode_size); } diff --git a/cranelift/test-all.sh b/cranelift/test-all.sh index 2b4e2eba01..572bf5de7b 100755 --- a/cranelift/test-all.sh +++ b/cranelift/test-all.sh @@ -55,4 +55,12 @@ cargo test --all --release banner "Rust documentation: $topdir/target/doc/cretonne/index.html" cargo doc +# Run clippy if we have it. +banner "Rust linter" +if $topdir/check-clippy.sh; then + $topdir/clippy-all.sh --write-mode=diff +else + echo "\`cargo +nightly install clippy\` for optional rust linting" +fi + banner "OK" diff --git a/cranelift/tests/filetests.rs b/cranelift/tests/filetests.rs index 97fbeb296f..6b5e392c76 100644 --- a/cranelift/tests/filetests.rs +++ b/cranelift/tests/filetests.rs @@ -3,5 +3,5 @@ extern crate cton_filetests; #[test] fn filetests() { // Run all the filetests in the following directories. - cton_filetests::run(false, vec!["filetests".into(), "docs".into()]).expect("test harness"); + cton_filetests::run(false, &["filetests".into(), "docs".into()]).expect("test harness"); } diff --git a/lib/cretonne/meta/gen_settings.py b/lib/cretonne/meta/gen_settings.py index b5f0de3488..373c9cb1a9 100644 --- a/lib/cretonne/meta/gen_settings.py +++ b/lib/cretonne/meta/gen_settings.py @@ -28,7 +28,7 @@ def gen_enum_types(sgrp, fmt): if not isinstance(setting, EnumSetting): continue ty = camel_case(setting.name) - fmt.doc_comment('Values for {}.'.format(setting)) + fmt.doc_comment('Values for `{}`.'.format(setting)) fmt.line('#[derive(Debug, PartialEq, Eq)]') with fmt.indented('pub enum {} {{'.format(ty), '}'): for v in setting.values: diff --git a/lib/cretonne/src/bforest/path.rs b/lib/cretonne/src/bforest/path.rs index e52c8e897e..34f165d86c 100644 --- a/lib/cretonne/src/bforest/path.rs +++ b/lib/cretonne/src/bforest/path.rs @@ -437,7 +437,7 @@ impl Path { // Discard the root node if it has shrunk to a single sub-tree. let mut ns = 0; - while let &NodeData::Inner { size: 0, ref tree, .. } = &pool[self.node[ns]] { + while let NodeData::Inner { size: 0, ref tree, .. } = pool[self.node[ns]] { ns += 1; self.node[ns] = tree[0]; } @@ -529,12 +529,11 @@ impl Path { // current entry[level] was one off the end of the node, it will now point at a proper // entry. debug_assert!(usize::from(self.entry[level]) < pool[self.node[level]].entries()); - } else { + + } else if usize::from(self.entry[level]) >= pool[self.node[level]].entries() { // There's no right sibling at this level, so the node can't be rebalanced. // Check if we are in an off-the-end position. - if usize::from(self.entry[level]) >= pool[self.node[level]].entries() { - self.size = 0; - } + self.size = 0; } } diff --git a/lib/cretonne/src/bforest/pool.rs b/lib/cretonne/src/bforest/pool.rs index 481271c8db..54a1f81cef 100644 --- a/lib/cretonne/src/bforest/pool.rs +++ b/lib/cretonne/src/bforest/pool.rs @@ -57,6 +57,7 @@ impl NodePool { pub fn free_tree(&mut self, node: Node) { if let NodeData::Inner { size, tree, .. } = self[node] { // Note that we have to capture `tree` by value to avoid borrow checker trouble. + #[cfg_attr(feature = "cargo-clippy", allow(needless_range_loop))] for i in 0..usize::from(size + 1) { // Recursively free sub-trees. This recursion can never be deeper than `MAX_PATH`, // and since most trees have less than a handful of nodes, it is worthwhile to diff --git a/lib/cretonne/src/binemit/relaxation.rs b/lib/cretonne/src/binemit/relaxation.rs index b0bf6196c6..24a78ceebd 100644 --- a/lib/cretonne/src/binemit/relaxation.rs +++ b/lib/cretonne/src/binemit/relaxation.rs @@ -76,14 +76,13 @@ pub fn relax_branches(func: &mut Function, isa: &TargetIsa) -> Result(&self, isa: &TargetIsa) -> verifier::Result { + pub fn verify_locations(&self, isa: &TargetIsa) -> verifier::Result { verifier::verify_locations(isa, &self.func, None) } /// Run the locations verifier only if the `enable_verifier` setting is true. - pub fn verify_locations_if<'a>(&self, isa: &TargetIsa) -> CtonResult { + pub fn verify_locations_if(&self, isa: &TargetIsa) -> CtonResult { if isa.flags().enable_verifier() { self.verify_locations(isa).map_err(Into::into) } else { diff --git a/lib/cretonne/src/cursor.rs b/lib/cretonne/src/cursor.rs index ed2528d5be..42f5e1e741 100644 --- a/lib/cretonne/src/cursor.rs +++ b/lib/cretonne/src/cursor.rs @@ -744,8 +744,9 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> { if !self.srcloc.is_default() { self.func.srclocs[inst] = self.srcloc; } - // Assign an encoding. + // XXX Is there a way to describe this error to the user? + #[cfg_attr(feature = "cargo-clippy", allow(match_wild_err_arm))] match self.isa.encode( &self.func.dfg, &self.func.dfg[inst], diff --git a/lib/cretonne/src/ir/extname.rs b/lib/cretonne/src/ir/extname.rs index b7bcc7d94f..b37e40086c 100644 --- a/lib/cretonne/src/ir/extname.rs +++ b/lib/cretonne/src/ir/extname.rs @@ -16,7 +16,7 @@ const TESTCASE_NAME_LENGTH: usize = 16; /// to keep track of a sy mbol table. /// /// External names are primarily used as keys by code using Cretonne to map -/// from a cretonne::ir::FuncRef or similar to additional associated data. +/// from a `cretonne::ir::FuncRef` or similar to additional associated data. /// /// External names can also serve as a primitive testing and debugging tool. /// In particular, many `.cton` test files use function names to identify diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 0e6e010e7c..2f4c378edd 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -428,7 +428,7 @@ impl Layout { } /// Return an iterator over all EBBs in layout order. - pub fn ebbs<'f>(&'f self) -> Ebbs<'f> { + pub fn ebbs(&self) -> Ebbs { Ebbs { layout: self, next: self.first_ebb, @@ -611,7 +611,7 @@ impl Layout { } /// Iterate over the instructions in `ebb` in layout order. - pub fn ebb_insts<'f>(&'f self, ebb: Ebb) -> Insts<'f> { + pub fn ebb_insts(&self, ebb: Ebb) -> Insts { Insts { layout: self, head: self.ebbs[ebb].first_inst.into(), diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index f317ed9f85..0f731b9620 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -4,13 +4,44 @@ trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="clippy", + plugin(clippy(conf_file="../../clippy.toml")))] + +#![cfg_attr(feature="cargo-clippy", allow( +// Rustfmt 0.9.0 is at odds with this lint: + block_in_if_condition_stmt, +// Produces only a false positive: + while_let_loop, +// Produces many false positives, but did produce some valid lints, now fixed: + needless_lifetimes, +// Generated code makes some style transgressions, but readability doesn't suffer much: + many_single_char_names, + identity_op, + needless_borrow, + cast_lossless, + unreadable_literal, + assign_op_pattern, + empty_line_after_outer_attr, +// Hard to avoid in generated code: + cyclomatic_complexity, + too_many_arguments, +// Code generator doesn't have a way to collapse identical arms: + match_same_arms, +// These are relatively minor style issues, but would be easy to fix: + new_without_default, + new_without_default_derive, + should_implement_trait, + redundant_field_names, + useless_let_if_seq, + len_without_is_empty))] + pub use context::Context; pub use legalizer::legalize_function; pub use verifier::verify_function; pub use write::write_function; /// Version number of the cretonne crate. -pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); #[macro_use] pub mod dbg; diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index e767fc838b..7887a39e4e 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -150,6 +150,7 @@ fn remove_loop_invariant_instructions( loop_values.insert(*val); } pos.goto_top(*ebb); + #[cfg_attr(feature = "cargo-clippy", allow(block_in_if_condition_stmt))] while let Some(inst) = pos.next_inst() { if pos.func.dfg.has_results(inst) && pos.func.dfg.inst_args(inst).into_iter().all(|arg| { diff --git a/lib/cretonne/src/partition_slice.rs b/lib/cretonne/src/partition_slice.rs index 7a94a9fe0d..dd0aff5da6 100644 --- a/lib/cretonne/src/partition_slice.rs +++ b/lib/cretonne/src/partition_slice.rs @@ -6,7 +6,7 @@ /// The order of elements is not preserved, unless the slice is already partitioned. /// /// Returns the number of elements where `p(t)` is true. -pub fn partition_slice<'a, T: 'a, F>(s: &'a mut [T], mut p: F) -> usize +pub fn partition_slice(s: &mut [T], mut p: F) -> usize where F: FnMut(&T) -> bool, { diff --git a/lib/cretonne/src/predicates.rs b/lib/cretonne/src/predicates.rs index 63d2e79af3..618369291d 100644 --- a/lib/cretonne/src/predicates.rs +++ b/lib/cretonne/src/predicates.rs @@ -7,7 +7,7 @@ //! bound is implemented by all the native integer types as well as `Imm64`. //! //! Some of these predicates may be unused in certain ISA configurations, so we suppress the -//! dead_code warning. +//! dead code warning. /// Check that `x` is the same as `y`. #[allow(dead_code)] diff --git a/lib/cretonne/src/preopt.rs b/lib/cretonne/src/preopt.rs index f5e8b3a7fe..698631316e 100644 --- a/lib/cretonne/src/preopt.rs +++ b/lib/cretonne/src/preopt.rs @@ -114,7 +114,7 @@ fn package_up_divrem_info( fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { let idata: &InstructionData = &dfg[inst]; - if let &InstructionData::BinaryImm { opcode, arg, imm } = idata { + if let InstructionData::BinaryImm { opcode, arg, imm } = *idata { let (isSigned, isRem) = match opcode { Opcode::UdivImm => (false, false), Opcode::UremImm => (false, true), @@ -132,7 +132,7 @@ fn get_div_info(inst: Inst, dfg: &DataFlowGraph) -> Option { // that some previous constant propagation pass has pushed all such // immediates to their use points, creating BinaryImm instructions // instead? For now we take the conservative approach. - if let &InstructionData::Binary { opcode, args } = idata { + if let InstructionData::Binary { opcode, args } = *idata { let (isSigned, isRem) = match opcode { Opcode::Udiv => (false, false), Opcode::Urem => (false, true), @@ -484,7 +484,7 @@ fn get_const(value: Value, dfg: &DataFlowGraph) -> Option { match dfg.value_def(value) { ValueDef::Result(definingInst, resultNo) => { let definingIData: &InstructionData = &dfg[definingInst]; - if let &InstructionData::UnaryImm { opcode, imm } = definingIData { + if let InstructionData::UnaryImm { opcode, imm } = *definingIData { if opcode == Opcode::Iconst && resultNo == 0 { return Some(imm.into()); } diff --git a/lib/cretonne/src/print_errors.rs b/lib/cretonne/src/print_errors.rs index abd22f3e6b..1bc61cfb59 100644 --- a/lib/cretonne/src/print_errors.rs +++ b/lib/cretonne/src/print_errors.rs @@ -10,7 +10,7 @@ use std::fmt::Write; pub fn pretty_verifier_error( func: &ir::Function, isa: Option<&TargetIsa>, - err: verifier::Error, + err: &verifier::Error, ) -> String { let mut msg = err.to_string(); match err.location { @@ -26,7 +26,7 @@ pub fn pretty_verifier_error( /// Pretty-print a Cretonne error. pub fn pretty_error(func: &ir::Function, isa: Option<&TargetIsa>, err: CtonError) -> String { if let CtonError::Verifier(e) = err { - pretty_verifier_error(func, isa, e) + pretty_verifier_error(func, isa, &e) } else { err.to_string() } diff --git a/lib/cretonne/src/ref_slice.rs b/lib/cretonne/src/ref_slice.rs index b9dbd55dd1..251b601d00 100644 --- a/lib/cretonne/src/ref_slice.rs +++ b/lib/cretonne/src/ref_slice.rs @@ -1,6 +1,6 @@ //! Functions for converting a reference into a singleton slice. //! -//! See also the ref_slice crate on crates.io. +//! See also the [`ref_slice` crate](https://crates.io/crates/ref_slice). //! //! We define the functions here to avoid external dependencies, and to ensure that they are //! inlined in this crate. diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index e0abf76d37..8c40809310 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -197,9 +197,9 @@ impl<'a> fmt::Display for DisplayAllocatableSet<'a> { "{}", bank.names .get(offset as usize) - .and_then(|name| name.chars().skip(1).next()) - .unwrap_or( - char::from_digit(u32::from(offset % 10), 10).unwrap(), + .and_then(|name| name.chars().nth(1)) + .unwrap_or_else( + || char::from_digit(u32::from(offset % 10), 10).unwrap(), ) )?; } diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index dbde52f05d..2d66b010f7 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -276,33 +276,31 @@ impl GenLiveRange { } else { return first_time_livein; } - } else { + } else if let Some((_, end)) = c.prev() { // There's no interval beginning at `ebb`, but we could still be live-in at `ebb` with // a coalesced interval that begins before and ends after. - if let Some((_, end)) = c.prev() { - if order.cmp(end, ebb) == Ordering::Greater { - // Yep, the previous interval overlaps `ebb`. - first_time_livein = false; - if order.cmp(end, to) == Ordering::Less { - *c.value_mut().unwrap() = to; - } else { - return first_time_livein; - } + if order.cmp(end, ebb) == Ordering::Greater { + // Yep, the previous interval overlaps `ebb`. + first_time_livein = false; + if order.cmp(end, to) == Ordering::Less { + *c.value_mut().unwrap() = to; } else { - first_time_livein = true; - // The current interval does not overlap `ebb`, but it may still be possible to - // coalesce with it. - if order.is_ebb_gap(end, ebb) { - *c.value_mut().unwrap() = to; - } else { - c.insert(ebb, to); - } + return first_time_livein; } } else { - // There is no existing interval before `ebb`. first_time_livein = true; - c.insert(ebb, to); + // The current interval does not overlap `ebb`, but it may still be possible to + // coalesce with it. + if order.is_ebb_gap(end, ebb) { + *c.value_mut().unwrap() = to; + } else { + c.insert(ebb, to); + } } + } else { + // There is no existing interval before `ebb`. + first_time_livein = true; + c.insert(ebb, to); } // Now `c` to left pointing at an interval that ends in `to`. diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 63e7354453..106830bc19 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -306,14 +306,12 @@ impl<'a> Context<'a> { let args = self.cur.func.dfg.inst_args(inst); for (argidx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() { - if op.kind != ConstraintKind::Stack { - if self.liveness[arg].affinity.is_stack() { - self.candidates.push(ReloadCandidate { - argidx, - value: arg, - regclass: op.regclass, - }) - } + if op.kind != ConstraintKind::Stack && self.liveness[arg].affinity.is_stack() { + self.candidates.push(ReloadCandidate { + argidx, + value: arg, + regclass: op.regclass, + }) } } diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index 7824444eec..3559623ae4 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -299,6 +299,7 @@ impl Move { } /// Get the "from" register and register class, if possible. + #[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))] fn from_reg(&self) -> Option<(RegClass, RegUnit)> { match *self { Move::Reg { rc, from, .. } | diff --git a/lib/cretonne/src/regalloc/virtregs.rs b/lib/cretonne/src/regalloc/virtregs.rs index 097a66cccd..8069a0b69b 100644 --- a/lib/cretonne/src/regalloc/virtregs.rs +++ b/lib/cretonne/src/regalloc/virtregs.rs @@ -101,8 +101,10 @@ impl VirtRegs { where 'a: 'b, { - self.get(*value).map(|vr| self.values(vr)).unwrap_or( - ref_slice(value), + self.get(*value).map(|vr| self.values(vr)).unwrap_or_else( + || { + ref_slice(value) + }, ) } @@ -371,7 +373,7 @@ impl VirtRegs { let vreg = self.get(leader).unwrap_or_else(|| { // Allocate a vreg for `leader`, but leave it empty. let vr = self.alloc(); - if let &mut Some(ref mut vec) = &mut new_vregs { + if let Some(ref mut vec) = new_vregs { vec.push(vr); } self.value_vregs[leader] = vr.into(); diff --git a/lib/cretonne/src/scoped_hash_map.rs b/lib/cretonne/src/scoped_hash_map.rs index d5acf2ecb6..ded42672ab 100644 --- a/lib/cretonne/src/scoped_hash_map.rs +++ b/lib/cretonne/src/scoped_hash_map.rs @@ -1,4 +1,4 @@ -//! ScopedHashMap +//! `ScopedHashMap` //! //! This module defines a struct `ScopedHashMap` which defines a `HashMap`-like //! container that has a concept of scopes that can be entered and exited, such that diff --git a/lib/cretonne/src/timing.rs b/lib/cretonne/src/timing.rs index 7a7572f5c7..647e0a07aa 100644 --- a/lib/cretonne/src/timing.rs +++ b/lib/cretonne/src/timing.rs @@ -11,7 +11,7 @@ pub use self::details::{TimingToken, PassTimes, take_current, add_to_current}; // // This macro defines: // -// - A C-style enum containing all the pass names and a `NoPass` variant. +// - A C-style enum containing all the pass names and a `None` variant. // - A usize constant with the number of defined passes. // - A const array of pass descriptions. // - A public function per pass used to start the timing of that pass. @@ -21,9 +21,9 @@ macro_rules! define_passes { } => { #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] - enum $enum { $($pass,)+ NoPass } + enum $enum { $($pass,)+ None} - const $num_passes: usize = $enum::NoPass as usize; + const $num_passes: usize = $enum::None as usize; const $descriptions: [&str; $num_passes] = [ $($desc),+ ]; @@ -164,7 +164,7 @@ mod details { /// Information about passes in a single thread. thread_local!{ - static CURRENT_PASS: Cell = Cell::new(Pass::NoPass); + static CURRENT_PASS: Cell = Cell::new(Pass::None); static PASS_TIME: RefCell = RefCell::new(Default::default()); } @@ -204,7 +204,7 @@ mod details { } /// Add `timings` to the accumulated timings for the current thread. - pub fn add_to_current(times: PassTimes) { + pub fn add_to_current(times: &PassTimes) { PASS_TIME.with(|rc| for (a, b) in rc.borrow_mut().pass.iter_mut().zip( ×.pass, ) @@ -221,7 +221,7 @@ mod test { #[test] fn display() { - assert_eq!(Pass::NoPass.to_string(), ""); + assert_eq!(Pass::None.to_string(), ""); assert_eq!(Pass::regalloc.to_string(), "Register allocation"); } } diff --git a/lib/cretonne/src/verifier/liveness.rs b/lib/cretonne/src/verifier/liveness.rs index 95691625c8..8f971e2d05 100644 --- a/lib/cretonne/src/verifier/liveness.rs +++ b/lib/cretonne/src/verifier/liveness.rs @@ -86,16 +86,14 @@ impl<'a> LivenessVerifier<'a> { self.isa.encoding_info().display(encoding) ); } - } else { + } else if !lr.affinity.is_none() { // A non-encoded instruction can only define ghost values. - if !lr.affinity.is_none() { - return err!( - inst, - "{} is a real {} value defined by a ghost instruction", - val, - lr.affinity.display(&self.isa.register_info()) - ); - } + return err!( + inst, + "{} is a real {} value defined by a ghost instruction", + val, + lr.affinity.display(&self.isa.register_info()) + ); } } @@ -109,16 +107,14 @@ impl<'a> LivenessVerifier<'a> { return err!(inst, "{} is not live at this use", val); } - if encoding.is_legal() { - // A legal instruction is not allowed to depend on ghost values. - if lr.affinity.is_none() { - return err!( - inst, - "{} is a ghost value used by a real [{}] instruction", - val, - self.isa.encoding_info().display(encoding) - ); - } + // A legal instruction is not allowed to depend on ghost values. + if encoding.is_legal() && lr.affinity.is_none() { + return err!( + inst, + "{} is a ghost value used by a real [{}] instruction", + val, + self.isa.encoding_info().display(encoding) + ); } } } diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 26eb9a53d9..b19510a485 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -34,7 +34,7 @@ //! For polymorphic opcodes, determine the controlling type variable first. //! - Branches and jumps must pass arguments to destination EBBs that match the //! expected types exactly. The number of arguments must match. -//! - All EBBs in a jump_table must take no arguments. +//! - All EBBs in a jump table must take no arguments. //! - Function calls are type checked against their signature. //! - The entry block must take arguments that match the signature of the current //! function. @@ -871,50 +871,47 @@ impl<'a> Verifier<'a> { // Check special-purpose type constraints that can't be expressed in the normal opcode // constraints. fn typecheck_special(&self, inst: Inst, ctrl_type: Type) -> Result { - match self.func.dfg[inst] { - ir::InstructionData::Unary { opcode, arg } => { - let arg_type = self.func.dfg.value_type(arg); - match opcode { - Opcode::Bextend | Opcode::Uextend | Opcode::Sextend | Opcode::Fpromote => { - if arg_type.lane_count() != ctrl_type.lane_count() { - return err!( - inst, - "input {} and output {} must have same number of lanes", - arg_type, - ctrl_type - ); - } - if arg_type.lane_bits() >= ctrl_type.lane_bits() { - return err!( - inst, - "input {} must be smaller than output {}", - arg_type, - ctrl_type - ); - } + if let ir::InstructionData::Unary { opcode, arg } = self.func.dfg[inst] { + let arg_type = self.func.dfg.value_type(arg); + match opcode { + Opcode::Bextend | Opcode::Uextend | Opcode::Sextend | Opcode::Fpromote => { + if arg_type.lane_count() != ctrl_type.lane_count() { + return err!( + inst, + "input {} and output {} must have same number of lanes", + arg_type, + ctrl_type + ); } - Opcode::Breduce | Opcode::Ireduce | Opcode::Fdemote => { - if arg_type.lane_count() != ctrl_type.lane_count() { - return err!( - inst, - "input {} and output {} must have same number of lanes", - arg_type, - ctrl_type - ); - } - if arg_type.lane_bits() <= ctrl_type.lane_bits() { - return err!( - inst, - "input {} must be larger than output {}", - arg_type, - ctrl_type - ); - } + if arg_type.lane_bits() >= ctrl_type.lane_bits() { + return err!( + inst, + "input {} must be smaller than output {}", + arg_type, + ctrl_type + ); } - _ => {} } + Opcode::Breduce | Opcode::Ireduce | Opcode::Fdemote => { + if arg_type.lane_count() != ctrl_type.lane_count() { + return err!( + inst, + "input {} and output {} must have same number of lanes", + arg_type, + ctrl_type + ); + } + if arg_type.lane_bits() <= ctrl_type.lane_bits() { + return err!( + inst, + "input {} must be larger than output {}", + arg_type, + ctrl_type + ); + } + } + _ => {} } - _ => {} } Ok(()) } diff --git a/lib/filetests/src/concurrent.rs b/lib/filetests/src/concurrent.rs index 6a18bb2390..1ddf643258 100644 --- a/lib/filetests/src/concurrent.rs +++ b/lib/filetests/src/concurrent.rs @@ -70,7 +70,7 @@ impl ConcurrentRunner { assert!(self.request_tx.is_none(), "must shutdown before join"); for h in self.handles.drain(..) { match h.join() { - Ok(t) => timing::add_to_current(t), + Ok(t) => timing::add_to_current(&t), Err(e) => println!("worker panicked: {:?}", e), } } diff --git a/lib/filetests/src/lib.rs b/lib/filetests/src/lib.rs index 36d321358c..a6a43d4437 100644 --- a/lib/filetests/src/lib.rs +++ b/lib/filetests/src/lib.rs @@ -3,6 +3,11 @@ //! This crate contains the main test driver as well as implementations of the //! available filetest commands. +#![cfg_attr(feature="cargo-clippy", allow( + type_complexity, +// Rustfmt 0.9.0 is at odds with this lint: + block_in_if_condition_stmt))] + #[macro_use(dbg)] extern crate cretonne; extern crate cton_reader; @@ -44,7 +49,7 @@ type TestResult = Result; /// Directories are scanned recursively for test cases ending in `.cton`. These test cases are /// executed on background threads. /// -pub fn run(verbose: bool, files: Vec) -> TestResult { +pub fn run(verbose: bool, files: &[String]) -> TestResult { let mut runner = TestRunner::new(verbose); for path in files.iter().map(Path::new) { diff --git a/lib/filetests/src/runner.rs b/lib/filetests/src/runner.rs index ff40ed81e2..49078cff8e 100644 --- a/lib/filetests/src/runner.rs +++ b/lib/filetests/src/runner.rs @@ -45,7 +45,7 @@ impl Display for QueueEntry { f, "{}.{:03} {}", dur.as_secs(), - dur.subsec_nanos() / 1000000, + dur.subsec_nanos() / 1_000_000, p ) } @@ -135,7 +135,7 @@ impl TestRunner { // This lets us skip spurious extensionless files without statting everything // needlessly. if !dir.is_file() { - self.path_error(dir, err); + self.path_error(&dir, &err); } } Ok(entries) => { @@ -149,7 +149,7 @@ impl TestRunner { // libstd/sys/unix/fs.rs seems to suggest that breaking now would // be a good idea, or the iterator could keep returning the same // error forever. - self.path_error(dir, err); + self.path_error(&dir, &err); break; } Ok(entry) => { @@ -172,7 +172,7 @@ impl TestRunner { } /// Report an error related to a path. - fn path_error(&mut self, path: PathBuf, err: E) { + fn path_error(&mut self, path: &PathBuf, err: &E) { self.errors += 1; println!("{}: {}", path.to_string_lossy(), err); } diff --git a/lib/filetests/src/runone.rs b/lib/filetests/src/runone.rs index fcc01e4f95..dab44ff920 100644 --- a/lib/filetests/src/runone.rs +++ b/lib/filetests/src/runone.rs @@ -132,7 +132,7 @@ fn run_one_test<'a>( if !context.verified && test.needs_verifier() { verify_function(&func, context.flags_or_isa()).map_err( |e| { - pretty_verifier_error(&func, isa, e) + pretty_verifier_error(&func, isa, &e) }, )?; context.verified = true; diff --git a/lib/filetests/src/subtest.rs b/lib/filetests/src/subtest.rs index a9cf657d8e..39812ed228 100644 --- a/lib/filetests/src/subtest.rs +++ b/lib/filetests/src/subtest.rs @@ -1,4 +1,4 @@ -//! SubTest trait. +//! `SubTest` trait. use std::result; use std::borrow::Cow; diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index de89698f15..8cd2c5cc82 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -400,7 +400,7 @@ where /// /// This can be used to insert SSA code that doesn't need to access locals and that doesn't /// need to know about `FunctionBuilder` at all. - pub fn cursor<'f>(&'f mut self) -> FuncCursor<'f> { + pub fn cursor(&mut self) -> FuncCursor { self.ensure_inserted_ebb(); FuncCursor::new(self.func) .with_srcloc(self.srcloc) @@ -548,6 +548,8 @@ where /// Returns a displayable object for the function as it is. /// /// Useful for debug purposes. Use it with `None` for standard printing. + // Clippy thinks the lifetime that follows is needless, but rustc needs it + #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))] pub fn display<'b, I: Into>>(&'b self, isa: I) -> DisplayFunction { self.func.display(isa) } diff --git a/lib/frontend/src/lib.rs b/lib/frontend/src/lib.rs index f5b4514e56..1f2c2e0db8 100644 --- a/lib/frontend/src/lib.rs +++ b/lib/frontend/src/lib.rs @@ -131,6 +131,9 @@ trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="cargo-clippy", + allow(new_without_default, redundant_field_names))] + extern crate cretonne; pub use frontend::{FunctionBuilderContext, FunctionBuilder}; diff --git a/lib/reader/src/lexer.rs b/lib/reader/src/lexer.rs index ca315d3b58..4b1a952d1b 100644 --- a/lib/reader/src/lexer.rs +++ b/lib/reader/src/lexer.rs @@ -53,7 +53,7 @@ pub struct LocatedToken<'a> { } /// Wrap up a `Token` with the given location. -fn token<'a>(token: Token<'a>, loc: Location) -> Result, LocatedError> { +fn token(token: Token, loc: Location) -> Result { Ok(LocatedToken { token, location: loc, diff --git a/lib/reader/src/lib.rs b/lib/reader/src/lib.rs index 85ea048950..d6c23cfa81 100644 --- a/lib/reader/src/lib.rs +++ b/lib/reader/src/lib.rs @@ -1,6 +1,6 @@ //! Cretonne file reader library. //! -//! The cton_reader library supports reading .cton files. This functionality is needed for testing +//! The `cton_reader` library supports reading .cton files. This functionality is needed for testing //! Cretonne, but is not essential for a JIT compiler. #![deny(missing_docs, diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index a9568942ed..2e320b31a7 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -37,7 +37,7 @@ pub fn parse_functions(text: &str) -> Result> { /// Parse the entire `text` as a test case file. /// /// The returned `TestFile` contains direct references to substrings of `text`. -pub fn parse_test<'a>(text: &'a str) -> Result> { +pub fn parse_test(text: &str) -> Result { let _tt = timing::parse_text(); let mut parser = Parser::new(text); // Gather the preamble comments. @@ -277,6 +277,10 @@ impl<'a> Parser<'a> { // Get the current lookahead token, after making sure there is one. fn token(&mut self) -> Option> { + // clippy says self.lookahead is immutable so this loop is either infinite or never + // running. I don't think this is true - self.lookahead is mutated in the loop body - so + // maybe this is a clippy bug? Either way, disable clippy for this. + #[cfg_attr(feature = "cargo-clippy", allow(while_immutable_condition))] while self.lookahead == None { match self.lex.next() { Some(Ok(lexer::LocatedToken { token, location })) => { @@ -957,7 +961,7 @@ impl<'a> Parser<'a> { isa.register_info() .parse_regunit(name) .map(ArgumentLoc::Reg) - .ok_or(self.error("invalid register name")) + .ok_or_else(|| self.error("invalid register name")) } else { err!(self.loc, "argument location requires exactly one isa") } @@ -1392,12 +1396,12 @@ impl<'a> Parser<'a> { match self.token() { Some(Token::Arrow) => { self.consume(); - self.parse_value_alias(results, ctx)?; + self.parse_value_alias(&results, ctx)?; } Some(Token::Equal) => { self.consume(); self.parse_instruction( - results, + &results, srcloc, encoding, result_locations, @@ -1408,7 +1412,7 @@ impl<'a> Parser<'a> { _ if !results.is_empty() => return err!(self.loc, "expected -> or ="), _ => { self.parse_instruction( - results, + &results, srcloc, encoding, result_locations, @@ -1512,7 +1516,7 @@ impl<'a> Parser<'a> { isa.register_info() .parse_regunit(name) .map(ValueLoc::Reg) - .ok_or(self.error("invalid register value location")) + .ok_or_else(|| self.error("invalid register value location")) } else { err!(self.loc, "value location requires exactly one isa") } @@ -1601,7 +1605,7 @@ impl<'a> Parser<'a> { // // value_alias ::= [inst-results] "->" Value(v) // - fn parse_value_alias(&mut self, results: Vec, ctx: &mut Context) -> Result<()> { + fn parse_value_alias(&mut self, results: &[Value], ctx: &mut Context) -> Result<()> { if results.len() != 1 { return err!(self.loc, "wrong number of aliases"); } @@ -1621,7 +1625,7 @@ impl<'a> Parser<'a> { // fn parse_instruction( &mut self, - results: Vec, + results: &[Value], srcloc: ir::SourceLoc, encoding: Option, result_locations: Option>, @@ -1629,7 +1633,7 @@ impl<'a> Parser<'a> { ebb: Ebb, ) -> Result<()> { // Define the result values. - for val in &results { + for val in results { ctx.map.def_value(*val, &self.loc)?; } @@ -1674,7 +1678,7 @@ impl<'a> Parser<'a> { let num_results = ctx.function.dfg.make_inst_results_for_parser( inst, ctrl_typevar, - &results, + results, ); ctx.function.layout.append_inst(inst, ebb); ctx.map.def_entity(inst.into(), &opcode_loc).expect( @@ -1784,11 +1788,9 @@ impl<'a> Parser<'a> { opcode ); } - } else { - // Treat it as a syntax error to speficy a typevar on a non-polymorphic opcode. - if ctrl_type != VOID { - return err!(self.loc, "{} does not take a typevar", opcode); - } + // Treat it as a syntax error to speficy a typevar on a non-polymorphic opcode. + } else if ctrl_type != VOID { + return err!(self.loc, "{} does not take a typevar", opcode); } Ok(ctrl_type) diff --git a/lib/reader/src/sourcemap.rs b/lib/reader/src/sourcemap.rs index 704c097855..36fb954fd9 100644 --- a/lib/reader/src/sourcemap.rs +++ b/lib/reader/src/sourcemap.rs @@ -13,7 +13,7 @@ use lexer::split_entity_name; use std::collections::HashMap; /// Mapping from entity names to source locations. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct SourceMap { // Store locations for entities, including instructions. locations: HashMap, diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 940725600a..42d232e6f5 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -36,6 +36,8 @@ use environ::{FuncEnvironment, GlobalValue}; use std::{i32, u32}; use std::vec::Vec; +// Clippy warns about "flags: _" but its important to document that the flags field is ignored +#[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] /// Translates wasm operators into Cretonne IL instructions. Returns `true` if it inserted /// a return. pub fn translate_operator( @@ -45,7 +47,7 @@ pub fn translate_operator( environ: &mut FE, ) { if !state.reachable { - return translate_unreachable_operator(op, builder, state); + return translate_unreachable_operator(&op, builder, state); } // This big match treats all Wasm code operators. @@ -198,9 +200,8 @@ pub fn translate_operator( builder.switch_to_block(frame.following_code()); builder.seal_block(frame.following_code()); // If it is a loop we also have to seal the body loop block - match frame { - ControlStackFrame::Loop { header, .. } => builder.seal_block(header), - _ => {} + if let ControlStackFrame::Loop { header, .. } = frame { + builder.seal_block(header) } state.stack.truncate(frame.original_stack_size()); state.stack.extend_from_slice( @@ -857,15 +858,17 @@ pub fn translate_operator( } } +// Clippy warns us of some fields we are deliberately ignoring +#[cfg_attr(feature = "cargo-clippy", allow(unneeded_field_pattern))] /// Deals with a Wasm instruction located in an unreachable portion of the code. Most of them /// are dropped but special ones like `End` or `Else` signal the potential end of the unreachable /// portion so the translation state muts be updated accordingly. fn translate_unreachable_operator( - op: Operator, + op: &Operator, builder: &mut FunctionBuilder, state: &mut TranslationState, ) { - match op { + match *op { Operator::If { ty: _ } => { // Push a placeholder control stack entry. The if isn't reachable, // so we don't have any branches anywhere. @@ -877,27 +880,25 @@ fn translate_unreachable_operator( } Operator::Else => { let i = state.control_stack.len() - 1; - match state.control_stack[i] { - ControlStackFrame::If { - branch_inst, - ref mut reachable_from_top, - .. - } => { - if *reachable_from_top { - // We have a branch from the top of the if to the else. - state.reachable = true; - // And because there's an else, there can no longer be a - // branch from the top directly to the end. - *reachable_from_top = false; + if let ControlStackFrame::If { + branch_inst, + ref mut reachable_from_top, + .. + } = state.control_stack[i] + { + if *reachable_from_top { + // We have a branch from the top of the if to the else. + state.reachable = true; + // And because there's an else, there can no longer be a + // branch from the top directly to the end. + *reachable_from_top = false; - // We change the target of the branch instruction - let else_ebb = builder.create_ebb(); - builder.change_jump_destination(branch_inst, else_ebb); - builder.seal_block(else_ebb); - builder.switch_to_block(else_ebb); - } + // We change the target of the branch instruction + let else_ebb = builder.create_ebb(); + builder.change_jump_destination(branch_inst, else_ebb); + builder.seal_block(else_ebb); + builder.switch_to_block(else_ebb); } - _ => {} } } Operator::End => { @@ -1057,10 +1058,10 @@ fn translate_br_if( builder.ins().brnz(val, br_destination, inputs); } -fn translate_br_if_args<'state>( +fn translate_br_if_args( relative_depth: u32, - state: &'state mut TranslationState, -) -> (ir::Ebb, &'state [ir::Value]) { + state: &mut TranslationState, +) -> (ir::Ebb, &[ir::Value]) { let i = state.control_stack.len() - 1 - (relative_depth as usize); let (return_count, br_destination) = { let frame = &mut state.control_stack[i]; diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index de941f3b9a..c99afd32d9 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -121,7 +121,7 @@ impl DummyEnvironment { } } -/// The FuncEnvironment implementation for use by the `DummyEnvironment`. +/// The `FuncEnvironment` implementation for use by the `DummyEnvironment`. pub struct DummyFuncEnvironment<'dummy_environment> { pub mod_info: &'dummy_environment DummyModuleInfo, } diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 6e9a6a365a..f2a1adb7cb 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -12,6 +12,10 @@ #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![cfg_attr(feature="clippy", + plugin(clippy(conf_file="../../clippy.toml")))] +#![cfg_attr(feature="cargo-clippy", + allow(new_without_default, redundant_field_names))] extern crate wasmparser; extern crate cton_frontend; diff --git a/lib/wasm/tests/wasm_testsuite.rs b/lib/wasm/tests/wasm_testsuite.rs index 824a7606da..5d969c9cc2 100644 --- a/lib/wasm/tests/wasm_testsuite.rs +++ b/lib/wasm/tests/wasm_testsuite.rs @@ -25,7 +25,7 @@ fn testsuite() { // Ignore files starting with `.`, which could be editor temporary files if let Some(stem) = p.path().file_stem() { if let Some(stemstr) = stem.to_str() { - return !stemstr.starts_with("."); + return !stemstr.starts_with('.'); } } false @@ -35,7 +35,7 @@ fn testsuite() { let flags = Flags::new(&settings::builder()); for path in paths { let path = path.path(); - handle_module(path, &flags); + handle_module(&path, &flags); } } @@ -44,7 +44,7 @@ fn return_at_end() { let mut flag_builder = settings::builder(); flag_builder.enable("return_at_end").unwrap(); let flags = Flags::new(&flag_builder); - handle_module(PathBuf::from("../../wasmtests/return_at_end.wat"), &flags); + handle_module(&PathBuf::from("../../wasmtests/return_at_end.wat"), &flags); } fn read_wasm_file(path: PathBuf) -> Result, io::Error> { @@ -54,7 +54,7 @@ fn read_wasm_file(path: PathBuf) -> Result, io::Error> { Ok(buf) } -fn handle_module(path: PathBuf, flags: &Flags) { +fn handle_module(path: &PathBuf, flags: &Flags) { let data = match path.extension() { None => { panic!("the file extension is not wasm or wat"); @@ -103,7 +103,7 @@ fn handle_module(path: PathBuf, flags: &Flags) { translate_module(&data, &mut dummy_environ).unwrap(); for func in &dummy_environ.info.function_bodies { verifier::verify_function(func, flags) - .map_err(|err| panic!(pretty_verifier_error(func, None, err))) + .map_err(|err| panic!(pretty_verifier_error(func, None, &err))) .unwrap(); } }