Skip to content

Commit

Permalink
feat(tactic/lint/misc): adding a linter that flags iffs with explicit…
Browse files Browse the repository at this point in the history
… variables on both sides (#11606)
  • Loading branch information
arthurpaulino committed May 6, 2022
1 parent 863a167 commit 58d83ed
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
7 changes: 4 additions & 3 deletions src/tactic/lint/default.lean
Expand Up @@ -63,10 +63,11 @@ The following linters are run by default:
21. `syn_taut` checks that declarations are not syntactic tautologies.
22. `check_reducibility` checks whether non-instances with a class as type are reducible.
23. `unprintable_interactive` checks that interactive tactics have parser documentation.
24. `to_additive_doc` checks if additive versions of lemmas have documentation
24. `to_additive_doc` checks if additive versions of lemmas have documentation.
Another linter, `doc_blame_thm`, checks for missing doc strings on lemmas and theorems.
This is not run by default.
The following linters are not run by default:
1. `doc_blame_thm`, checks for missing doc strings on lemmas and theorems.
2. `explicit_vars_of_iff` checks if there are explicit variables used on both sides of an iff.
The command `#list_linters` prints a list of the names of all available linters.
Expand Down
53 changes: 52 additions & 1 deletion src/tactic/lint/misc.lean
@@ -1,7 +1,7 @@
/-
Copyright (c) 2020 Floris van Doorn. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Floris van Doorn, Robert Y. Lewis
Authors: Floris van Doorn, Robert Y. Lewis, Arthur Paulino
-/
import data.bool.basic
import meta.rb_map
Expand Down Expand Up @@ -449,6 +449,7 @@ meta def linter.unused_haves_suffices : linter :=
"proofs appear as if they are used. ",
is_fast := ff }


/-!
## Linter for unprintable interactive tactics
-/
Expand Down Expand Up @@ -481,3 +482,53 @@ meta def linter.unprintable_interactive : linter :=
"like `?` `*>` `<*` `<*>` `<|>` and `<$>` (but not `>>=` or `do` blocks) " ++
"that automatically generate a description.",
is_fast := tt }


/-!
## Linter for iff's
-/

open binder_info

/--
Recursively consumes a Pi expression while accumulating names and the complement of de-Bruijn
indexes of explicit variables, ultimately obtaining the remaining non-Pi expression as well.
-/
meta def unravel_explicits_of_pi :
expr → ℕ → list name → list ℕ → (list name) × (list ℕ) × expr
| (pi n default _ e) i ln li := unravel_explicits_of_pi e (i + 1) (n :: ln) (i :: li)
| (pi n _ _ e) i ln li := unravel_explicits_of_pi e (i + 1) ln li
| e _ ln li := (ln, li, e)

/--
This function works as follows:
1. Call `unravel_explicits_of_pi` to obtain the names, complements of de-Bruijn indexes and the
remaining non-Pi expression;
2. Check if the remaining non-Pi expression is an iff, already obtaining the respective left and
right expressions if this is the case. Returns `none` otherwise;
3. Filter the explicit variables that appear on the left *and* right side of the iff;
4. If no variable satisfies the condition above, return `none`;
5. Return a message mentioning the variables that do, otherwise.
-/
meta def explicit_vars_of_iff (d : declaration) :
tactic (option string) := do
let (ln, li, e) := unravel_explicits_of_pi d.type 0 [] [],
match e.is_iff with
| none := return none
| some (el, er) := do
let li := li.map (λ i, d.type.pi_arity - i - 1), -- fixing for the actual de-Bruijn indexes
let l := (ln.zip li).filter (λ t, (el.has_var_idx t.2) && (er.has_var_idx t.2)),
if l = [] then return none
else return $ "The following variables are used on both sides of an iff and ".append $
"should be made implicit: ".append $ ", ".intercalate (l.map (λ t, to_string t.1))
end

/--
A linter for checking if variables appearing on both sides of an iff are explicit. Ideally, such
variables should be implicit instead.
-/
meta def linter.explicit_vars_of_iff : linter :=
{ test := explicit_vars_of_iff,
auto_decls := ff,
no_errors_found := "No explicit variables on both sides of iff",
errors_found := "EXPLICIT VARIABLES ON BOTH SIDES OF IFF" }

0 comments on commit 58d83ed

Please sign in to comment.