Skip to content

Commit

Permalink
Add skeleton and tests for the lint
Browse files Browse the repository at this point in the history
Will close use-ink#2073
  • Loading branch information
jubnzv committed Jan 25, 2024
1 parent 8b5b497 commit 7a063bd
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 22 deletions.
50 changes: 28 additions & 22 deletions linting/extra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,36 @@ scale-info = { version = "2.6", default-features = false, features = ["derive"]
#
# Those files require the ink! dependencies though, by having
# them as examples here, they inherit the `dev-dependencies`.
# [[example]]
# name = "primitive_topic_pass"
# path = "ui/pass/primitive_topic.rs"
# [[example]]
# name = "primitive_topic_fail"
# path = "ui/fail/primitive_topic.rs"
# [[example]]
# name = "storage_never_freed_pass"
# path = "ui/pass/storage_never_freed.rs"
# [[example]]
# name = "storage_never_freed_fail"
# path = "ui/fail/storage_never_freed.rs"
# [[example]]
# name = "strict_balance_equality_pass"
# path = "ui/pass/strict_balance_equality.rs"
# [[example]]
# name = "strict_balance_equality_fail"
# path = "ui/fail/strict_balance_equality.rs"
# [[example]]
# name = "non_fallible_api_pass"
# path = "ui/pass/non_fallible_api.rs"
# [[example]]
# name = "non_fallible_api_fail"
# path = "ui/fail/non_fallible_api.rs"
[[example]]
name = "primitive_topic_pass"
path = "ui/pass/primitive_topic.rs"
name = "divide_before_multiply_pass"
path = "ui/pass/divide_before_multiply.rs"
[[example]]
name = "primitive_topic_fail"
path = "ui/fail/primitive_topic.rs"
[[example]]
name = "storage_never_freed_pass"
path = "ui/pass/storage_never_freed.rs"
[[example]]
name = "storage_never_freed_fail"
path = "ui/fail/storage_never_freed.rs"
[[example]]
name = "strict_balance_equality_pass"
path = "ui/pass/strict_balance_equality.rs"
[[example]]
name = "strict_balance_equality_fail"
path = "ui/fail/strict_balance_equality.rs"
[[example]]
name = "non_fallible_api_pass"
path = "ui/pass/non_fallible_api.rs"
[[example]]
name = "non_fallible_api_fail"
path = "ui/fail/non_fallible_api.rs"
name = "divide_before_multiply_fail"
path = "ui/fail/divide_before_multiply.rs"

[package.metadata.rust-analyzer]
rustc_private = true
Expand Down
61 changes: 61 additions & 0 deletions linting/extra/src/divide_before_multiply.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (C) Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use if_chain::if_chain;
use rustc_hir::Expr;
use rustc_lint::{
LateContext,
LateLintPass,
};
use rustc_session::{
declare_lint,
declare_lint_pass,
};

declare_lint! {
/// ## What it does
/// Highlights arithmetic expressions in which division is performed before multiplication.
///
/// ## Why is this bad?
/// Integer division might unexpectedly result with 0.
///
/// ## Example
/// Bad:
///
/// ```rust
/// let a: u32 = 2;
/// let b: u32 = 4;
/// let c: u32 = a / b * 8; // c == 0
/// ```
///
/// Use the following:
///
/// ```rust
/// let a: u32 = 2;
/// let b: u32 = 4;
/// let c: u32 = a * 8 / b; // c == 4
/// ```
///
pub DIVIDE_BEFORE_MULTIPLY,
Warn,
"division before multiplication"
}

declare_lint_pass!(DivideBeforeMultiply => [DIVIDE_BEFORE_MULTIPLY]);

impl<'tcx> LateLintPass<'tcx> for DivideBeforeMultiply {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
todo!()
}
}
4 changes: 4 additions & 0 deletions linting/extra/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_type_ir;

mod divide_before_multiply;
mod non_fallible_api;
mod primitive_topic;
mod storage_never_freed;
Expand All @@ -48,12 +49,15 @@ pub fn register_lints(
storage_never_freed::STORAGE_NEVER_FREED,
strict_balance_equality::STRICT_BALANCE_EQUALITY,
non_fallible_api::NON_FALLIBLE_API,
divide_before_multiply::DIVIDE_BEFORE_MULTIPLY,
]);
lint_store.register_late_pass(|_| Box::new(primitive_topic::PrimitiveTopic));
lint_store.register_late_pass(|_| Box::new(storage_never_freed::StorageNeverFreed));
lint_store
.register_late_pass(|_| Box::new(strict_balance_equality::StrictBalanceEquality));
lint_store.register_late_pass(|_| Box::new(non_fallible_api::NonFallibleAPI));
lint_store
.register_late_pass(|_| Box::new(divide_before_multiply::DivideBeforeMultiply));
}

#[test]
Expand Down
56 changes: 56 additions & 0 deletions linting/extra/ui/fail/divide_before_multiply.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#![cfg_attr(not(feature = "std"), no_main)]

pub type TyAlias1 = u32;
pub type TyAlias2 = TyAlias1;

#[ink::contract]
pub mod divide_before_multiply {

const CONST_1: u32 = 1;
const CONST_2: u32 = 2;
const CONST_3: u32 = 3;

#[ink(storage)]
pub struct DivideBeforeMultiply {}

impl DivideBeforeMultiply {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

fn return_1(&self) -> u32 {
1
}

fn return_2(&self) -> u32 {
2
}

#[ink(message)]
pub fn test_lint(&mut self) {
// Constants
let _ = CONST_1 / CONST_2 * CONST_3;

// Variables
let a: u32 = 1;
let b: u32 = 2;
let _ = a / b * (4 + 4);
let _ = a / b * CONST_3;
let _ = a / b * a;

// Function calls
let _ = self.return_1() / self.return_2() * self.return_1();
let _ = a / self.return_2() * 2;
let _ = self.return_1() / CONST_1 * b;

// Type aliases
let c: crate::TyAlias2 = 4;
let _ = c / b * 4;
let _ = a / c * CONST_3;
let _ = a / b * c;
}
}
}

fn main() {}
70 changes: 70 additions & 0 deletions linting/extra/ui/pass/divide_before_multiply.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#![cfg_attr(not(feature = "std"), no_main)]

pub type TyAlias1 = u32;
pub type TyAlias2 = TyAlias1;

#[ink::contract]
pub mod divide_before_multiply {

const CONST_1: u32 = 1;
const CONST_2: u32 = 2;
const CONST_3: u32 = 3;

#[ink(storage)]
pub struct DivideBeforeMultiply {}

impl DivideBeforeMultiply {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

fn return_1(&self) -> u32 {
1
}

fn return_2(&self) -> u32 {
2
}

#[ink(message)]
pub fn test_lint(&mut self) {
// Constants
let _ = CONST_1 * CONST_3 / CONST_2;
let _ = CONST_1 / (CONST_2 * CONST_3);

// Variables
let a: u32 = 1;
let b: u32 = 2;
let _ = a * (4 + 4) / b;
let _ = a * CONST_3 / b;
let _ = a * a / b;
let _ = a / (b * (4 + 4));
let _ = a / (b * CONST_3);
let _ = a / (b * a);

// Function calls
let _ = self.return_1() * self.return_1() / self.return_2();
let _ = a * 2 / self.return_2();
let _ = self.return_1() * b / CONST_1;
let _ = self.return_1() / (self.return_2() * self.return_1());
let _ = a / (self.return_2() * 2);
let _ = self.return_1() / (CONST_1 * b);

// Type aliases
let c: crate::TyAlias2 = 4;
let _ = c * 4 / b;
let _ = a * CONST_3 / c;
let _ = a * c / b;
let _ = c / (b * 4);
let _ = a / (c * CONST_3);
let _ = a / (b * c);

// Test if suppressions work
#[cfg_attr(dylint_lib = "ink_linting", allow(divide_before_multiply))]
let _ = a / b * c;
}
}
}

fn main() {}

0 comments on commit 7a063bd

Please sign in to comment.