Compare commits

..

3 Commits

Author SHA1 Message Date
Scott Morrison
c680b3f28f narrow codeowners 2024-04-24 13:07:34 +10:00
Scott Morrison
854f8ab90e typo in CODEOWNERS 2024-04-23 11:51:27 +10:00
Scott Morrison
208b03e681 chore: upstream Std material from Data/List|Array/Init 2024-04-23 11:25:58 +10:00
72 changed files with 278 additions and 1172 deletions

View File

@@ -1,57 +0,0 @@
name: Check for stage0 changes
on:
merge_group:
pull_request:
jobs:
check-stage0-on-queue:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
filter: blob:none
fetch-depth: 0
- name: Find base commit
if: github.event_name == 'pull_request'
run: echo "BASE=$(git merge-base origin/${{ github.base_ref }} HEAD)" >> "$GITHUB_ENV"
- name: Identify stage0 changes
run: |
git diff "${BASE:-HEAD^}..HEAD" --name-only -- stage0 |
grep -v -x -F $'stage0/src/stdlib_flags.h\nstage0/src/lean.mk.in' \
> "$RUNNER_TEMP/stage0" || true
if test -s "$RUNNER_TEMP/stage0"
then
echo "CHANGES=yes" >> "$GITHUB_ENV"
else
echo "CHANGES=no" >> "$GITHUB_ENV"
fi
shell: bash
- if: github.event_name == 'pull_request'
name: Set label
uses: actions/github-script@v7
with:
script: |
const { owner, repo, number: issue_number } = context.issue;
if (process.env.CHANGES == 'yes') {
await github.rest.issues.addLabels({ owner, repo, issue_number, labels: ['changes-stage0'] }).catch(() => {});
} else {
await github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'changes-stage0' }).catch(() => {});
}
- if: env.CHANGES == 'yes'
name: Report changes
run: |
echo "Found changes to stage0/, please do not merge using the merge queue." | tee "$GITHUB_STEP_SUMMARY"
# shellcheck disable=SC2129
echo '```' >> "$GITHUB_STEP_SUMMARY"
cat "$RUNNER_TEMP/stage0" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
- if: github.event_name == 'merge_group' && env.CHANGES == 'yes'
name: Fail when on the merge queue
run: exit 1

View File

@@ -6,6 +6,7 @@
/.github/ @Kha @semorrison
/RELEASES.md @semorrison
/src/Init/IO.lean @joehendrix
/src/kernel/ @leodemoura
/src/lake/ @tydeu
/src/Lean/Compiler/ @leodemoura
@@ -19,6 +20,7 @@
/src/Lean/PrettyPrinter/Delaborator/ @kmill
/src/Lean/Server/ @mhuisi
/src/Lean/Widget/ @Vtec234
/src/runtime/io.cpp @joehendrix
/src/Init/Data/ @semorrison
/src/Init/Data/Array/Lemmas.lean @digama0
/src/Init/Data/List/Lemmas.lean @digama0

View File

@@ -79,11 +79,10 @@ v4.8.0 (development in progress)
Field notation can be disabled on a function-by-function basis using the `@[pp_nodot]` attribute.
* Added options `pp.mvars` (default: true) and `pp.mvars.withType` (default: false).
When `pp.mvars` is false, expression metavariables pretty print as `?_` and universe metavariables pretty print as `_`.
When `pp.mvars.withType` is true, expression metavariables pretty print with a type ascription.
These can be set when using `#guard_msgs` to make tests not depend on the particular names of metavariables.
[#3798](https://github.com/leanprover/lean4/pull/3798) and
[#3978](https://github.com/leanprover/lean4/pull/3978).
When `pp.mvars` is false, metavariables pretty print as `?_`,
and when `pp.mvars.withType` is true, metavariables pretty print with a type ascription.
These can be set when using `#guard_msgs` to make tests not rely on the unique ids assigned to anonymous metavariables.
[#3798](https://github.com/leanprover/lean4/pull/3798).
* Added `@[induction_eliminator]` and `@[cases_eliminator]` attributes to be able to define custom eliminators
for the `induction` and `cases` tactics, replacing the `@[eliminator]` attribute.

View File

@@ -75,25 +75,14 @@ The github repository will automatically update stage0 on `master` once
If you have write access to the lean4 repository, you can also also manually
trigger that process, for example to be able to use new features in the compiler itself.
You can do that on <https://github.com/leanprover/lean4/actions/workflows/update-stage0.yml>
You can do that on <https://github.com/nomeata/lean4/actions/workflows/update-stage0.yml>
or using Github CLI with
```
gh workflow run update-stage0.yml
```
Leaving stage0 updates to the CI automation is preferable, but should you need
to do it locally, you can use `make update-stage0-commit` in `build/release` to
update `stage0` from `stage1` or `make -C stageN update-stage0-commit` to
update from another stage.
This command will automatically stage the updated files and introduce a commit,
so make sure to commit your work before that.
The CI should prevent PRs with changes to stage0 (besides `stdlib_flags.h`)
from entering `master` through the (squashing!) merge queue, and label such PRs
with the `changes-stage0` label. Such PRs should have a cleaned up history,
with separate stage0 update commits; then coordinate with the admins to merge
your PR using rebase merge, bypassing the merge queue.
Leaving stage0 updates to the CI automation is preferable, but should you need to do it locally, you can use `make update-stage0-commit` in `build/release` to update `stage0` from `stage1` or `make -C stageN update-stage0-commit` to update from another stage.
This command will automatically stage the updated files and introduce a commit, so make sure to commit your work before that. Then coordinate with the admins to not squash your PR so that stage 0 updates are preserved as separate commits.
## Further Bootstrapping Complications

View File

@@ -4,16 +4,16 @@ def ack : Nat → Nat → Nat
| 0, y => y+1
| x+1, 0 => ack x 1
| x+1, y+1 => ack x (ack (x+1) y)
termination_by x y => (x, y)
termination_by ack x y => (x, y)
def sum (a : Array Int) : Int :=
let rec go (i : Nat) :=
if _ : i < a.size then
if i < a.size then
a[i] + go (i+1)
else
0
termination_by a.size - i
go 0
termination_by go i => a.size - i
set_option pp.proofs true
#print sum.go

View File

@@ -4,42 +4,43 @@ open Lean Meta
def ctor (mvarId : MVarId) (idx : Nat) : MetaM (List MVarId) := do
/- Set `MetaM` context using `mvarId` -/
mvarId.withContext do
withMVarContext mvarId do
/- Fail if the metavariable is already assigned. -/
mvarId.checkNotAssigned `ctor
checkNotAssigned mvarId `ctor
/- Retrieve the target type, instantiateMVars, and use `whnf`. -/
let target mvarId.getType'
let target getMVarType' mvarId
let .const declName us := target.getAppFn
| throwTacticEx `ctor mvarId "target is not an inductive datatype"
let .inductInfo { ctors, .. } getConstInfo declName
| throwTacticEx `ctor mvarId "target is not an inductive datatype"
if idx = 0 then
throwTacticEx `ctor mvarId "invalid index, it must be > 0"
throwTacticEx `ctor mvarId "invalid index, it must be > 0"
else if h : idx - 1 < ctors.length then
mvarId.apply (.const ctors[idx - 1] us)
apply mvarId (.const ctors[idx - 1] us)
else
throwTacticEx `ctor mvarId "invalid index, inductive datatype has only {ctors.length} contructors"
throwTacticEx `ctor mvarId "invalid index, inductive datatype has only {ctors.length} contructors"
open Elab Tactic
elab "ctor" idx:num : tactic =>
elab "ctor" idx:num : tactic =>
liftMetaTactic (ctor · idx.getNat)
example (p : Prop) : p := by
example (p : Prop) : p := by
ctor 1 -- Error
example (h : q) : p q := by
example (h : q) : p q := by
ctor 0 -- Error
exact h
example (h : q) : p q := by
example (h : q) : p q := by
ctor 3 -- Error
exact h
example (h : q) : p q := by
example (h : q) : p q := by
ctor 2
exact h
example (h : q) : p q := by
example (h : q) : p q := by
ctor 1
exact h -- Error
exact h -- Error

View File

@@ -5,15 +5,15 @@ open Lean Meta
def ex1 (declName : Name) : MetaM Unit := do
let info getConstInfo declName
IO.println s!"{declName} : {← ppExpr info.type}"
if let some val := info.value? then
if let some val := info.value? then
IO.println s!"{declName} : {← ppExpr val}"
#eval ex1 ``Nat
def ex2 (declName : Name) : MetaM Unit := do
let info getConstInfo declName
trace[Meta.debug] "{declName} : {info.type}"
if let some val := info.value? then
if let some val := info.value? then
trace[Meta.debug] "{declName} : {val}"
#eval ex2 ``Add.add
@@ -30,9 +30,9 @@ def ex3 (declName : Name) : MetaM Unit := do
trace[Meta.debug] "{x} : {← inferType x}"
def myMin [LT α] [DecidableRel (α := α) (·<·)] (a b : α) : α :=
if a < b then
if a < b then
a
else
else
b
set_option trace.Meta.debug true in
@@ -40,7 +40,7 @@ set_option trace.Meta.debug true in
def ex4 : MetaM Unit := do
let nat := mkConst ``Nat
withLocalDeclD `a nat fun a =>
withLocalDeclD `a nat fun a =>
withLocalDeclD `b nat fun b => do
let e mkAppM ``HAdd.hAdd #[a, b]
trace[Meta.debug] "{e} : {← inferType e}"
@@ -66,17 +66,15 @@ open Elab Term
def ex5 : TermElabM Unit := do
let nat := Lean.mkConst ``Nat
withLocalDeclD `a nat fun a => do
withLocalDeclD `a nat fun a => do
withLocalDeclD `b nat fun b => do
let ab mkAppM ``HAdd.hAdd #[a, b]
let abStx exprToSyntax ab
let aStx exprToSyntax a
let stx `(fun x => if x < 10 then $abStx + x else x + $aStx)
let stx `(fun x => if x < 10 then $( exprToSyntax ab) + x else x + $( exprToSyntax a))
let e elabTerm stx none
trace[Meta.debug] "{e} : {← inferType e}"
let e := mkApp e (mkNatLit 5)
let e whnf e
trace[Meta.debug] "{e}"
set_option trace.Meta.debug true in
#eval ex5

View File

@@ -4,16 +4,16 @@ def ack : Nat → Nat → Nat
| 0, y => y+1
| x+1, 0 => ack x 1
| x+1, y+1 => ack x (ack (x+1) y)
termination_by x y => (x, y)
termination_by ack x y => (x, y)
def sum (a : Array Int) : Int :=
let rec go (i : Nat) :=
if _ : i < a.size then
if i < a.size then
a[i] + go (i+1)
else
0
termination_by a.size - i
go 0
termination_by go i => a.size - i
set_option pp.proofs true
#print sum.go

View File

@@ -1,39 +0,0 @@
#!/bin/bash
# https://chat.openai.com/share/7469c7c3-aceb-4d80-aee5-62982e1f1538
# Output CSV Header
echo '"Issue URL","Title","Days Since Creation","Days Since Last Update","Total Reactions","Assignee","Labels"'
# Get the current date in YYYY-MM-DD format
today=$(date +%Y-%m-%d)
# Fetch only open issues (excluding PRs and closed issues) from the repository 'leanprover/lean4'
issues=$(gh api repos/leanprover/lean4/issues --paginate --jq '.[] | select(.pull_request == null and .state == "open") | {url: .html_url, title: .title, created_at: (.created_at | split("T")[0]), updated_at: (.updated_at | split("T")[0]), number: .number, assignee: (.assignee.login // ""), labels: [.labels[].name] | join(",")}')
# Process each JSON object
echo "$issues" | while IFS= read -r issue; do
# Extract fields from JSON
url=$(echo "$issue" | jq -r '.url')
title=$(echo "$issue" | jq -r '.title')
created_at=$(echo "$issue" | jq -r '.created_at')
updated_at=$(echo "$issue" | jq -r '.updated_at')
issue_number=$(echo "$issue" | jq -r '.number')
assignee=$(echo "$issue" | jq -r '.assignee')
labels=$(echo "$issue" | jq -r '.labels')
# Calculate days since creation and update using macOS compatible date calculation
days_since_created=$(( ($(date -jf "%Y-%m-%d" "$today" +%s) - $(date -jf "%Y-%m-%d" "$created_at" +%s)) / 86400 ))
days_since_updated=$(( ($(date -jf "%Y-%m-%d" "$today" +%s) - $(date -jf "%Y-%m-%d" "$updated_at" +%s)) / 86400 ))
# Fetch the total number of reactions for each issue
reaction_data=$(gh api repos/leanprover/lean4/issues/$issue_number/reactions --paginate --jq 'length' 2>&1)
if [[ $reaction_data == *"Not Found"* ]]; then
total_reactions="Error fetching reactions"
else
total_reactions=$reaction_data
fi
# Format output as CSV by escaping quotes and delimiting with commas
echo "\"$url\",\"${title//\"/\"\"}\",\"$days_since_created\",\"$days_since_updated\",\"$total_reactions\",\"$assignee\",\"$labels\""
done

View File

@@ -2040,8 +2040,4 @@ class LawfulCommIdentity (op : ααα) (o : outParam α) [hc : Commuta
left_id a := Eq.trans (hc.comm o a) (right_id a)
right_id a := Eq.trans (hc.comm a o) (left_id a)
instance : Commutative Or := fun _ _ => propext or_comm
instance : Commutative And := fun _ _ => propext and_comm
instance : Commutative Iff := fun _ _ => propext iff_comm
end Std

View File

@@ -826,18 +826,13 @@ theorem ofNat_add_ofNat {n} (x y : Nat) : x#n + y#n = (x + y)#n :=
protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by
apply eq_of_toNat_eq ; simp [Nat.add_assoc]
instance : Std.Associative (α := BitVec n) (· + ·) := BitVec.add_assoc
protected theorem add_comm (x y : BitVec n) : x + y = y + x := by
simp [add_def, Nat.add_comm]
instance : Std.Commutative (α := BitVec n) (· + ·) := BitVec.add_comm
@[simp] protected theorem add_zero (x : BitVec n) : x + 0#n = x := by simp [add_def]
@[simp] protected theorem zero_add (x : BitVec n) : 0#n + x = x := by simp [add_def]
instance : Std.LawfulIdentity (α := BitVec n) (· + ·) 0#n where
left_id := BitVec.zero_add
right_id := BitVec.add_zero
theorem truncate_add (x y : BitVec w) (h : i w) :
(x + y).truncate i = x.truncate i + y.truncate i := by

View File

@@ -74,7 +74,6 @@ Added for confluence with `not_and_self` `and_not_self` on term
@[simp] theorem eq_false_and_eq_true_self : (b : Bool), (b = false b = true) False := by decide
theorem and_comm : (x y : Bool), (x && y) = (y && x) := by decide
instance : Std.Commutative (· && ·) := and_comm
theorem and_left_comm : (x y z : Bool), (x && (y && z)) = (y && (x && z)) := by decide
theorem and_right_comm : (x y z : Bool), ((x && y) && z) = ((x && z) && y) := by decide
@@ -121,7 +120,6 @@ Needed for confluence of term `(a || b) ↔ a` which reduces to `(a || b) = a` v
@[simp] theorem iff_or_self : (a b : Bool), (b = (a || b)) (a b) := by decide
theorem or_comm : (x y : Bool), (x || y) = (y || x) := by decide
instance : Std.Commutative (· || ·) := or_comm
theorem or_left_comm : (x y z : Bool), (x || (y || z)) = (y || (x || z)) := by decide
theorem or_right_comm : (x y z : Bool), ((x || y) || z) = ((x || z) || y) := by decide
@@ -188,18 +186,12 @@ in false_eq and true_eq.
@[simp] theorem true_beq : b, (true == b) = b := by decide
@[simp] theorem false_beq : b, (false == b) = !b := by decide
@[simp] theorem beq_true : b, (b == true) = b := by decide
instance : Std.LawfulIdentity (· == ·) true where
left_id := true_beq
right_id := beq_true
@[simp] theorem beq_false : b, (b == false) = !b := by decide
@[simp] theorem true_bne : (b : Bool), (true != b) = !b := by decide
@[simp] theorem false_bne : (b : Bool), (false != b) = b := by decide
@[simp] theorem bne_true : (b : Bool), (b != true) = !b := by decide
@[simp] theorem bne_false : (b : Bool), (b != false) = b := by decide
instance : Std.LawfulIdentity (· != ·) false where
left_id := false_bne
right_id := bne_false
@[simp] theorem not_beq_self : (x : Bool), ((!x) == x) = false := by decide
@[simp] theorem beq_not_self : (x : Bool), (x == !x) = false := by decide
@@ -222,7 +214,6 @@ due to `beq_iff_eq`.
@[simp] theorem not_bne_not : (x y : Bool), ((!x) != (!y)) = (x != y) := by decide
@[simp] theorem bne_assoc : (x y z : Bool), ((x != y) != z) = (x != (y != z)) := by decide
instance : Std.Associative (· != ·) := bne_assoc
@[simp] theorem bne_left_inj : (x y z : Bool), (x != y) = (x != z) y = z := by decide
@[simp] theorem bne_right_inj : (x y z : Bool), (x != z) = (y != z) x = y := by decide

View File

@@ -793,20 +793,15 @@ protected theorem mul_one (k : Fin (n + 1)) : k * 1 = k := by
protected theorem mul_comm (a b : Fin n) : a * b = b * a :=
ext <| by rw [mul_def, mul_def, Nat.mul_comm]
instance : Std.Commutative (α := Fin n) (· * ·) := Fin.mul_comm
protected theorem mul_assoc (a b c : Fin n) : a * b * c = a * (b * c) := by
apply eq_of_val_eq
simp only [val_mul]
rw [ Nat.mod_eq_of_lt a.isLt, Nat.mod_eq_of_lt b.isLt, Nat.mod_eq_of_lt c.isLt]
simp only [ Nat.mul_mod, Nat.mul_assoc]
instance : Std.Associative (α := Fin n) (· * ·) := Fin.mul_assoc
protected theorem one_mul (k : Fin (n + 1)) : (1 : Fin (n + 1)) * k = k := by
rw [Fin.mul_comm, Fin.mul_one]
instance : Std.LawfulIdentity (α := Fin (n + 1)) (· * ·) 1 where
left_id := Fin.one_mul
right_id := Fin.mul_one
protected theorem mul_zero (k : Fin (n + 1)) : k * 0 = 0 := by simp [ext_iff, mul_def]

View File

@@ -137,16 +137,12 @@ protected theorem add_comm : ∀ a b : Int, a + b = b + a
| ofNat _, -[_+1] => rfl
| -[_+1], ofNat _ => rfl
| -[_+1], -[_+1] => by simp [Nat.add_comm]
instance : Std.Commutative (α := Int) (· + ·) := Int.add_comm
@[simp] protected theorem add_zero : a : Int, a + 0 = a
| ofNat _ => rfl
| -[_+1] => rfl
@[simp] protected theorem zero_add (a : Int) : 0 + a = a := Int.add_comm .. a.add_zero
instance : Std.LawfulIdentity (α := Int) (· + ·) 0 where
left_id := Int.zero_add
right_id := Int.add_zero
theorem ofNat_add_negSucc_of_lt (h : m < n.succ) : ofNat m + -[n+1] = -[n - m+1] :=
show subNatNat .. = _ by simp [succ_sub (le_of_lt_succ h), subNatNat]
@@ -200,7 +196,6 @@ where
simp
rw [Int.add_comm, subNatNat_add_negSucc]
simp [Nat.add_comm, Nat.add_left_comm, Nat.add_assoc]
instance : Std.Associative (α := Int) (· + ·) := Int.add_assoc
protected theorem add_left_comm (a b c : Int) : a + (b + c) = b + (a + c) := by
rw [ Int.add_assoc, Int.add_comm a, Int.add_assoc]
@@ -356,7 +351,6 @@ protected theorem sub_right_inj (i j k : Int) : (i - k = j - k) ↔ i = j := by
protected theorem mul_comm (a b : Int) : a * b = b * a := by
cases a <;> cases b <;> simp [Nat.mul_comm]
instance : Std.Commutative (α := Int) (· * ·) := Int.mul_comm
theorem ofNat_mul_negOfNat (m n : Nat) : (m : Nat) * negOfNat n = negOfNat (m * n) := by
cases n <;> rfl
@@ -375,7 +369,6 @@ attribute [local simp] ofNat_mul_negOfNat negOfNat_mul_ofNat
protected theorem mul_assoc (a b c : Int) : a * b * c = a * (b * c) := by
cases a <;> cases b <;> cases c <;> simp [Nat.mul_assoc]
instance : Std.Associative (α := Int) (· * ·) := Int.mul_assoc
protected theorem mul_left_comm (a b c : Int) : a * (b * c) = b * (a * c) := by
rw [ Int.mul_assoc, Int.mul_assoc, Int.mul_comm a]
@@ -465,9 +458,6 @@ protected theorem sub_mul (a b c : Int) : (a - b) * c = a * c - b * c := by
| -[n+1] => show -[1 * n +1] = -[n+1] by rw [Nat.one_mul]
@[simp] protected theorem mul_one (a : Int) : a * 1 = a := by rw [Int.mul_comm, Int.one_mul]
instance : Std.LawfulIdentity (α := Int) (· * ·) 1 where
left_id := Int.one_mul
right_id := Int.mul_one
protected theorem mul_neg_one (a : Int) : a * -1 = -a := by rw [Int.mul_neg, Int.mul_one]

View File

@@ -187,7 +187,6 @@ protected theorem min_comm (a b : Int) : min a b = min b a := by
by_cases h₁ : a b <;> by_cases h₂ : b a <;> simp [h₁, h₂]
· exact Int.le_antisymm h₁ h₂
· cases not_or_intro h₁ h₂ <| Int.le_total ..
instance : Std.Commutative (α := Int) min := Int.min_comm
protected theorem min_le_right (a b : Int) : min a b b := by rw [Int.min_def]; split <;> simp [*]
@@ -207,7 +206,6 @@ protected theorem max_comm (a b : Int) : max a b = max b a := by
by_cases h₁ : a b <;> by_cases h₂ : b a <;> simp [h₁, h₂]
· exact Int.le_antisymm h₂ h₁
· cases not_or_intro h₁ h₂ <| Int.le_total ..
instance : Std.Commutative (α := Int) max := Int.max_comm
protected theorem le_max_left (a b : Int) : a max a b := by rw [Int.max_def]; split <;> simp [*]

View File

@@ -127,9 +127,6 @@ instance : Append (List α) := ⟨List.append⟩
| nil => rfl
| cons a as ih =>
simp_all [HAppend.hAppend, Append.append, List.append]
instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where
left_id := nil_append
right_id := append_nil
@[simp] theorem cons_append (a : α) (as bs : List α) : (a::as) ++ bs = a::(as ++ bs) := rfl
@@ -139,7 +136,6 @@ theorem append_assoc (as bs cs : List α) : (as ++ bs) ++ cs = as ++ (bs ++ cs)
induction as with
| nil => rfl
| cons a as ih => simp [ih]
instance : Std.Associative (α := List α) (· ++ ·) := append_assoc
theorem append_cons (as : List α) (b : α) (bs : List α) : as ++ b :: bs = as ++ [b] ++ bs := by
induction as with

View File

@@ -157,13 +157,6 @@ def getLastD : (as : List α) → (fallback : α) → α
| [], a₀ => a₀
| a::as, _ => getLast (a::as) (fun h => List.noConfusion h)
/--
`O(n)`. Rotates the elements of `xs` to the left such that the element at
`xs[i]` rotates to `xs[(i - n) % l.length]`.
* `rotateLeft [1, 2, 3, 4, 5] 3 = [4, 5, 1, 2, 3]`
* `rotateLeft [1, 2, 3, 4, 5] 5 = [1, 2, 3, 4, 5]`
* `rotateLeft [1, 2, 3, 4, 5] = [2, 3, 4, 5, 1]`
-/
def rotateLeft (xs : List α) (n : Nat := 1) : List α :=
let len := xs.length
if len 1 then
@@ -174,13 +167,6 @@ def rotateLeft (xs : List α) (n : Nat := 1) : List α :=
let e := xs.drop n
e ++ b
/--
`O(n)`. Rotates the elements of `xs` to the right such that the element at
`xs[i]` rotates to `xs[(i + n) % l.length]`.
* `rotateRight [1, 2, 3, 4, 5] 3 = [3, 4, 5, 1, 2]`
* `rotateRight [1, 2, 3, 4, 5] 5 = [1, 2, 3, 4, 5]`
* `rotateRight [1, 2, 3, 4, 5] = [5, 1, 2, 3, 4]`
-/
def rotateRight (xs : List α) (n : Nat := 1) : List α :=
let len := xs.length
if len 1 then
@@ -311,15 +297,6 @@ def mapMono (as : List α) (f : αα) : List α :=
Monadic generalization of `List.partition`.
This uses `Array.toList` and which isn't imported by `Init.Data.List.Basic`.
```
def posOrNeg (x : Int) : Except String Bool :=
if x > 0 then pure true
else if x < 0 then pure false
else throw "Zero is not positive or negative"
partitionM posOrNeg [-1, 2, 3] = Except.ok ([2, 3], [-1])
partitionM posOrNeg [0, 2, 3] = Except.error "Zero is not positive or negative"
```
-/
@[inline] def partitionM [Monad m] (p : α m Bool) (l : List α) : m (List α × List α) :=
go l #[] #[]

View File

@@ -137,9 +137,6 @@ instance : LawfulBEq Nat where
@[simp] protected theorem zero_add : (n : Nat), 0 + n = n
| 0 => rfl
| n+1 => congrArg succ (Nat.zero_add n)
instance : Std.LawfulIdentity (α := Nat) (· + ·) 0 where
left_id := Nat.zero_add
right_id := Nat.add_zero
theorem succ_add : (n m : Nat), (succ n) + m = succ (n + m)
| _, 0 => rfl
@@ -163,12 +160,10 @@ protected theorem add_comm : ∀ (n m : Nat), n + m = m + n
have : succ (n + m) = succ (m + n) := by apply congrArg; apply Nat.add_comm
rw [succ_add m n]
apply this
instance : Std.Commutative (α := Nat) (· + ·) := Nat.add_comm
protected theorem add_assoc : (n m k : Nat), (n + m) + k = n + (m + k)
| _, _, 0 => rfl
| n, m, succ k => congrArg succ (Nat.add_assoc n m k)
instance : Std.Associative (α := Nat) (· + ·) := Nat.add_assoc
protected theorem add_left_comm (n m k : Nat) : n + (m + k) = m + (n + k) := by
rw [ Nat.add_assoc, Nat.add_comm n m, Nat.add_assoc]
@@ -212,16 +207,12 @@ theorem succ_mul (n m : Nat) : (succ n) * m = (n * m) + m := by
protected theorem mul_comm : (n m : Nat), n * m = m * n
| n, 0 => (Nat.zero_mul n).symm (Nat.mul_zero n).symm rfl
| n, succ m => (mul_succ n m).symm (succ_mul m n).symm (Nat.mul_comm n m).symm rfl
instance : Std.Commutative (α := Nat) (· * ·) := Nat.mul_comm
@[simp] protected theorem mul_one : (n : Nat), n * 1 = n :=
Nat.zero_add
@[simp] protected theorem one_mul (n : Nat) : 1 * n = n :=
Nat.mul_comm n 1 Nat.mul_one n
instance : Std.LawfulIdentity (α := Nat) (· * ·) 1 where
left_id := Nat.one_mul
right_id := Nat.mul_one
protected theorem left_distrib (n m k : Nat) : n * (m + k) = n * m + n * k := by
induction n with
@@ -240,7 +231,6 @@ protected theorem add_mul (n m k : Nat) : (n + m) * k = n * k + m * k :=
protected theorem mul_assoc : (n m k : Nat), (n * m) * k = n * (m * k)
| n, m, 0 => rfl
| n, m, succ k => by simp [mul_succ, Nat.mul_assoc n m k, Nat.left_distrib]
instance : Std.Associative (α := Nat) (· * ·) := Nat.mul_assoc
protected theorem mul_left_comm (n m k : Nat) : n * (m * k) = m * (n * k) := by
rw [ Nat.mul_assoc, Nat.mul_comm n m, Nat.mul_assoc]

View File

@@ -54,13 +54,9 @@ theorem gcd_succ (x y : Nat) : gcd (succ x) y = gcd (y % succ x) (succ x) :=
-- `simp [gcd_succ]` produces an invalid term unless `gcd_succ` is proved with `id rfl` instead
rw [gcd_succ]
exact gcd_zero_left _
instance : Std.LawfulIdentity gcd 0 where
left_id := gcd_zero_left
right_id := gcd_zero_right
@[simp] theorem gcd_self (n : Nat) : gcd n n = n := by
cases n <;> simp [gcd_succ]
instance : Std.IdempotentOp gcd := gcd_self
theorem gcd_rec (m n : Nat) : gcd m n = gcd (n % m) m :=
match m with
@@ -101,7 +97,6 @@ theorem gcd_comm (m n : Nat) : gcd m n = gcd n m :=
Nat.dvd_antisymm
(dvd_gcd (gcd_dvd_right m n) (gcd_dvd_left m n))
(dvd_gcd (gcd_dvd_right n m) (gcd_dvd_left n m))
instance : Std.Commutative gcd := gcd_comm
theorem gcd_eq_left_iff_dvd : m n gcd m n = m :=
fun h => by rw [gcd_rec, mod_eq_zero_of_dvd h, gcd_zero_left],

View File

@@ -14,7 +14,6 @@ def lcm (m n : Nat) : Nat := m * n / gcd m n
theorem lcm_comm (m n : Nat) : lcm m n = lcm n m := by
rw [lcm, lcm, Nat.mul_comm n m, gcd_comm n m]
instance : Std.Commutative lcm := lcm_comm
@[simp] theorem lcm_zero_left (m : Nat) : lcm 0 m = 0 := by simp [lcm]
@@ -23,15 +22,11 @@ instance : Std.Commutative lcm := ⟨lcm_comm⟩
@[simp] theorem lcm_one_left (m : Nat) : lcm 1 m = m := by simp [lcm]
@[simp] theorem lcm_one_right (m : Nat) : lcm m 1 = m := by simp [lcm]
instance : Std.LawfulIdentity lcm 1 where
left_id := lcm_one_left
right_id := lcm_one_right
@[simp] theorem lcm_self (m : Nat) : lcm m m = m := by
match eq_zero_or_pos m with
| .inl h => rw [h, lcm_zero_left]
| .inr h => simp [lcm, Nat.mul_div_cancel _ h]
instance : Std.IdempotentOp lcm := lcm_self
theorem dvd_lcm_left (m n : Nat) : m lcm m n :=
n / gcd m n, by rw [ Nat.mul_div_assoc m (Nat.gcd_dvd_right m n)]; rfl
@@ -59,7 +54,6 @@ Nat.dvd_antisymm
(Nat.dvd_trans (dvd_lcm_left m n) (dvd_lcm_left (lcm m n) k))
(lcm_dvd (Nat.dvd_trans (dvd_lcm_right m n) (dvd_lcm_left (lcm m n) k))
(dvd_lcm_right (lcm m n) k)))
instance : Std.Associative lcm := lcm_assoc
theorem lcm_ne_zero (hm : m 0) (hn : n 0) : lcm m n 0 := by
intro h

View File

@@ -200,7 +200,6 @@ theorem succ_min_succ (x y) : min (succ x) (succ y) = succ (min x y) := by
| inr h => rw [Nat.min_eq_right h, Nat.min_eq_right (Nat.succ_le_succ h)]
@[simp] protected theorem min_self (a : Nat) : min a a = a := Nat.min_eq_left (Nat.le_refl _)
instance : Std.IdempotentOp (α := Nat) min := Nat.min_self
@[simp] protected theorem zero_min (a) : min 0 a = 0 := Nat.min_eq_left (Nat.zero_le _)
@@ -211,7 +210,6 @@ protected theorem min_assoc : ∀ (a b c : Nat), min (min a b) c = min a (min b
| _, 0, _ => by rw [Nat.zero_min, Nat.min_zero, Nat.zero_min]
| _, _, 0 => by rw [Nat.min_zero, Nat.min_zero, Nat.min_zero]
| _+1, _+1, _+1 => by simp only [Nat.succ_min_succ]; exact congrArg succ <| Nat.min_assoc ..
instance : Std.Associative (α := Nat) min := Nat.min_assoc
protected theorem sub_sub_eq_min : (a b : Nat), a - (a - b) = min a b
| 0, _ => by rw [Nat.zero_sub, Nat.zero_min]
@@ -251,21 +249,16 @@ protected theorem max_lt {a b c : Nat} : max a b < c ↔ a < c ∧ b < c := by
rw [ Nat.succ_le, Nat.succ_max_succ a b]; exact Nat.max_le
@[simp] protected theorem max_self (a : Nat) : max a a = a := Nat.max_eq_right (Nat.le_refl _)
instance : Std.IdempotentOp (α := Nat) max := Nat.max_self
@[simp] protected theorem zero_max (a) : max 0 a = a := Nat.max_eq_right (Nat.zero_le _)
@[simp] protected theorem max_zero (a) : max a 0 = a := Nat.max_eq_left (Nat.zero_le _)
instance : Std.LawfulIdentity (α := Nat) max 0 where
left_id := Nat.zero_max
right_id := Nat.max_zero
protected theorem max_assoc : (a b c : Nat), max (max a b) c = max a (max b c)
| 0, _, _ => by rw [Nat.zero_max, Nat.zero_max]
| _, 0, _ => by rw [Nat.zero_max, Nat.max_zero]
| _, _, 0 => by rw [Nat.max_zero, Nat.max_zero]
| _+1, _+1, _+1 => by simp only [Nat.succ_max_succ]; exact congrArg succ <| Nat.max_assoc ..
instance : Std.Associative (α := Nat) max := Nat.max_assoc
protected theorem sub_add_eq_max (a b : Nat) : a - b + b = max a b := by
match Nat.le_total a b with

View File

@@ -17,7 +17,6 @@ protected theorem min_comm (a b : Nat) : min a b = min b a := by
| .inl h => simp [Nat.min_def, h, Nat.le_of_lt, Nat.not_le_of_lt]
| .inr (.inl h) => simp [Nat.min_def, h]
| .inr (.inr h) => simp [Nat.min_def, h, Nat.le_of_lt, Nat.not_le_of_lt]
instance : Std.Commutative (α := Nat) min := Nat.min_comm
protected theorem min_le_right (a b : Nat) : min a b b := by
by_cases (a <= b) <;> simp [Nat.min_def, *]
@@ -48,7 +47,6 @@ protected theorem max_comm (a b : Nat) : max a b = max b a := by
by_cases h₁ : a b <;> by_cases h₂ : b a <;> simp [h₁, h₂]
· exact Nat.le_antisymm h₂ h₁
· cases not_or_intro h₁ h₂ <| Nat.le_total ..
instance : Std.Commutative (α := Nat) max := Nat.max_comm
protected theorem le_max_left ( a b : Nat) : a max a b := by
by_cases (a <= b) <;> simp [Nat.max_def, *]

View File

@@ -492,12 +492,9 @@ The attribute `@[deprecated]` on a declaration indicates that the declaration
is discouraged for use in new code, and/or should be migrated away from in
existing code. It may be removed in a future version of the library.
* `@[deprecated myBetterDef]` means that `myBetterDef` is the suggested replacement.
* `@[deprecated myBetterDef "use myBetterDef instead"]` allows customizing the deprecation message.
* `@[deprecated (since := "2024-04-21")]` records when the deprecation was first applied.
`@[deprecated myBetterDef]` means that `myBetterDef` is the suggested replacement.
-/
syntax (name := deprecated) "deprecated" (ppSpace ident)? (ppSpace str)?
(" (" &"since" " := " str ")")? : attr
syntax (name := deprecated) "deprecated" (ppSpace ident)? : attr
/--
The `@[coe]` attribute on a function (which should also appear in a

View File

@@ -4335,13 +4335,8 @@ def addMacroScope (mainModule : Name) (n : Name) (scp : MacroScope) : Name :=
Name.mkNum (Name.mkStr (Name.appendCore (Name.mkStr n "_@") mainModule) "_hyg") scp
/--
Appends two names `a` and `b`, propagating macro scopes from `a` or `b`, if any, to the result.
Panics if both `a` and `b` have macro scopes.
This function is used for the `Append Name` instance.
See also `Lean.Name.appendCore`, which appends names without any consideration for macro scopes.
Also consider `Lean.Name.eraseMacroScopes` to erase macro scopes before appending, if appropriate.
Append two names that may have macro scopes. The macro scopes in `b` are always erased.
If `a` has macro scopes, then they are propagated to the result of `append a b`.
-/
def Name.append (a b : Name) : Name :=
match a.hasMacroScopes, b.hasMacroScopes with

View File

@@ -103,26 +103,18 @@ end SimprocHelperLemmas
@[simp] theorem and_true (p : Prop) : (p True) = p := propext (·.1), (·, trivial)
@[simp] theorem true_and (p : Prop) : (True p) = p := propext (·.2), (trivial, ·)
instance : Std.LawfulIdentity And True where
left_id := true_and
right_id := and_true
@[simp] theorem and_false (p : Prop) : (p False) = False := eq_false (·.2)
@[simp] theorem false_and (p : Prop) : (False p) = False := eq_false (·.1)
@[simp] theorem and_self (p : Prop) : (p p) = p := propext (·.left), fun h => h, h
instance : Std.IdempotentOp And := and_self
@[simp] theorem and_not_self : ¬(a ¬a) | ha, hn => absurd ha hn
@[simp] theorem not_and_self : ¬(¬a a) := and_not_self And.symm
@[simp] theorem and_imp : (a b c) (a b c) := fun h ha hb => h ha, hb, fun h ha, hb => h ha hb
@[simp] theorem not_and : ¬(a b) (a ¬b) := and_imp
@[simp] theorem or_self (p : Prop) : (p p) = p := propext fun | .inl h | .inr h => h, .inl
instance : Std.IdempotentOp Or := or_self
@[simp] theorem or_true (p : Prop) : (p True) = True := eq_true (.inr trivial)
@[simp] theorem true_or (p : Prop) : (True p) = True := eq_true (.inl trivial)
@[simp] theorem or_false (p : Prop) : (p False) = p := propext fun (.inl h) => h, .inl
@[simp] theorem false_or (p : Prop) : (False p) = p := propext fun (.inr h) => h, .inr
instance : Std.LawfulIdentity Or False where
left_id := false_or
right_id := or_false
@[simp] theorem iff_self (p : Prop) : (p p) = True := eq_true .rfl
@[simp] theorem iff_true (p : Prop) : (p True) = p := propext (·.2 trivial), fun h => fun _ => trivial, fun _ => h
@[simp] theorem true_iff (p : Prop) : (True p) = p := propext (·.1 trivial), fun h => fun _ => h, fun _ => trivial
@@ -148,7 +140,6 @@ theorem and_congr_left (h : c → (a ↔ b)) : a ∧ c ↔ b ∧ c :=
theorem and_assoc : (a b) c a (b c) :=
Iff.intro (fun ha, hb, hc => ha, hb, hc)
(fun ha, hb, hc => ha, hb, hc)
instance : Std.Associative And := fun _ _ _ => propext and_assoc
@[simp] theorem and_self_left : a (a b) a b := by rw [propext and_assoc, and_self]
@[simp] theorem and_self_right : (a b) b a b := by rw [ propext and_assoc, and_self]
@@ -176,7 +167,6 @@ theorem Or.imp_right (f : b → c) : a b → a c := .imp id f
theorem or_assoc : (a b) c a (b c) :=
Iff.intro (.rec (.imp_right .inl) (.inr .inr))
(.rec (.inl .inl) (.imp_left .inr))
instance : Std.Associative Or := fun _ _ _ => propext or_assoc
@[simp] theorem or_self_left : a (a b) a b := by rw [propext or_assoc, or_self]
@[simp] theorem or_self_right : (a b) b a b := by rw [ propext or_assoc, or_self]
@@ -197,12 +187,8 @@ theorem or_iff_left_of_imp (hb : b → a) : (a b) ↔ a := Iff.intro (Or.r
@[simp] theorem Bool.or_false (b : Bool) : (b || false) = b := by cases b <;> rfl
@[simp] theorem Bool.or_true (b : Bool) : (b || true) = true := by cases b <;> rfl
@[simp] theorem Bool.false_or (b : Bool) : (false || b) = b := by cases b <;> rfl
instance : Std.LawfulIdentity (· || ·) false where
left_id := Bool.false_or
right_id := Bool.or_false
@[simp] theorem Bool.true_or (b : Bool) : (true || b) = true := by cases b <;> rfl
@[simp] theorem Bool.or_self (b : Bool) : (b || b) = b := by cases b <;> rfl
instance : Std.IdempotentOp (· || ·) := Bool.or_self
@[simp] theorem Bool.or_eq_true (a b : Bool) : ((a || b) = true) = (a = true b = true) := by
cases a <;> cases b <;> decide
@@ -210,20 +196,14 @@ instance : Std.IdempotentOp (· || ·) := ⟨Bool.or_self⟩
@[simp] theorem Bool.and_true (b : Bool) : (b && true) = b := by cases b <;> rfl
@[simp] theorem Bool.false_and (b : Bool) : (false && b) = false := by cases b <;> rfl
@[simp] theorem Bool.true_and (b : Bool) : (true && b) = b := by cases b <;> rfl
instance : Std.LawfulIdentity (· && ·) true where
left_id := Bool.true_and
right_id := Bool.and_true
@[simp] theorem Bool.and_self (b : Bool) : (b && b) = b := by cases b <;> rfl
instance : Std.IdempotentOp (· && ·) := Bool.and_self
@[simp] theorem Bool.and_eq_true (a b : Bool) : ((a && b) = true) = (a = true b = true) := by
cases a <;> cases b <;> decide
theorem Bool.and_assoc (a b c : Bool) : (a && b && c) = (a && (b && c)) := by
cases a <;> cases b <;> cases c <;> decide
instance : Std.Associative (· && ·) := Bool.and_assoc
theorem Bool.or_assoc (a b c : Bool) : (a || b || c) = (a || (b || c)) := by
cases a <;> cases b <;> cases c <;> decide
instance : Std.Associative (· || ·) := Bool.or_assoc
@[simp] theorem Bool.not_not (b : Bool) : (!!b) = b := by cases b <;> rfl
@[simp] theorem Bool.not_true : (!true) = false := by decide

View File

@@ -1542,7 +1542,7 @@ macro "get_elem_tactic" : tactic =>
/--
Searches environment for definitions or theorems that can be substituted in
for `exact?%` to solve the goal.
for `exact?% to solve the goal.
-/
syntax (name := Lean.Parser.Syntax.exact?) "exact?%" : term

View File

@@ -183,6 +183,7 @@ structure ParametricAttribute (α : Type) where
deriving Inhabited
structure ParametricAttributeImpl (α : Type) extends AttributeImplCore where
/-- This is used as the target for go-to-definition queries for simple attributes -/
getParam : Name Syntax AttrM α
afterSet : Name α AttrM Unit := fun _ _ _ => pure ()
afterImport : Array (Array (Name × α)) ImportM Unit := fun _ => pure ()

View File

@@ -65,36 +65,8 @@ private def printInduct (id : Name) (levelParams : List Name) (numParams : Nat)
m := m ++ Format.line ++ ctor ++ " : " ++ cinfo.type
logInfo m
open Meta in
private def printStructure (id : Name) (levelParams : List Name) (numParams : Nat) (type : Expr)
(ctor : Name) (fields : Array Name) (isUnsafe : Bool) (isClass : Bool) : CommandElabM Unit := do
let kind := if isClass then "class" else "structure"
let mut m mkHeader' kind id levelParams type isUnsafe
m := m ++ Format.line ++ "number of parameters: " ++ toString numParams
m := m ++ Format.line ++ "constructor:"
let cinfo getConstInfo ctor
m := m ++ Format.line ++ ctor ++ " : " ++ cinfo.type
m := m ++ Format.line ++ "fields:" ++ ( doFields)
logInfo m
where
doFields := liftTermElabM do
forallTelescope ( getConstInfo id).type fun params type =>
withLocalDeclD `self type fun self => do
let params := params.push self
let mut m : Format := ""
for field in fields do
match getProjFnForField? ( getEnv) id field with
| some proj =>
let field : Format := if isPrivateName proj then "private " ++ toString field else toString field
let cinfo getConstInfo proj
let ftype instantiateForall cinfo.type params
m := m ++ Format.line ++ field ++ " : " ++ ( ppExpr ftype) -- Why ppExpr here?
| none => panic! "missing structure field info"
return m
private def printIdCore (id : Name) : CommandElabM Unit := do
let env getEnv
match env.find? id with
match ( getEnv).find? id with
| ConstantInfo.axiomInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "axiom" id us t u
| ConstantInfo.defnInfo { levelParams := us, type := t, value := v, safety := s, .. } => printDefLike "def" id us t v s
| ConstantInfo.thmInfo { levelParams := us, type := t, value := v, .. } => printDefLike "theorem" id us t v
@@ -103,11 +75,7 @@ private def printIdCore (id : Name) : CommandElabM Unit := do
| ConstantInfo.ctorInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "constructor" id us t u
| ConstantInfo.recInfo { levelParams := us, type := t, isUnsafe := u, .. } => printAxiomLike "recursor" id us t u
| ConstantInfo.inductInfo { levelParams := us, numParams, type := t, ctors, isUnsafe := u, .. } =>
match getStructureInfo? env id with
| some { fieldNames, .. } =>
let [ctor] := ctors | panic! "structures have only one constructor"
printStructure id us numParams t ctor fieldNames u (isClass env id)
| none => printInduct id us numParams t ctors u
printInduct id us numParams t ctors u
| none => throwUnknownId id
private def printId (id : Syntax) : CommandElabM Unit := do

View File

@@ -68,8 +68,11 @@ def elabExact?Term : TermElab := fun stx expectedType? => do
let (_, introdGoal) goal.mvarId!.intros
introdGoal.withContext do
if let some suggestions librarySearch introdGoal then
if suggestions.isEmpty then logError "`exact?%` didn't find any relevant lemmas"
else logError "`exact?%` could not close the goal. Try `by apply` to see partial suggestions."
reportOutOfHeartbeats `library_search stx
for suggestion in suggestions do
withMCtx suggestion.2 do
addTermSuggestion stx ( instantiateMVars goal).headBeta
if suggestions.isEmpty then logError "exact?# didn't find any relevant lemmas"
mkSorry expectedType (synthetic := true)
else
addTermSuggestion stx ( instantiateMVars goal).headBeta

View File

@@ -428,18 +428,15 @@ def Result.imax : Result → Result → Result
| f, Result.imaxNode Fs => Result.imaxNode (f::Fs)
| f₁, f₂ => Result.imaxNode [f₁, f₂]
def toResult (l : Level) (mvars : Bool) : Result :=
match l with
def toResult : Level Result
| zero => Result.num 0
| succ l => Result.succ (toResult l mvars)
| max l₁ l₂ => Result.max (toResult l₁ mvars) (toResult l₂ mvars)
| imax l₁ l₂ => Result.imax (toResult l₁ mvars) (toResult l₂ mvars)
| succ l => Result.succ (toResult l)
| max l₁ l₂ => Result.max (toResult l₁) (toResult l₂)
| imax l₁ l₂ => Result.imax (toResult l₁) (toResult l₂)
| param n => Result.leaf n
| mvar n =>
if mvars then
Result.leaf <| n.name.replacePrefix `_uniq (Name.mkSimple "?u")
else
Result.leaf `_
let n := n.name.replacePrefix `_uniq (Name.mkSimple "?u");
Result.leaf n
private def parenIfFalse : Format Bool Format
| f, true => f
@@ -474,17 +471,17 @@ protected partial def Result.quote (r : Result) (prec : Nat) : Syntax.Level :=
end PP
protected def format (u : Level) (mvars : Bool) : Format :=
(PP.toResult u mvars).format true
protected def format (u : Level) : Format :=
(PP.toResult u).format true
instance : ToFormat Level where
format u := Level.format u (mvars := true)
format u := Level.format u
instance : ToString Level where
toString u := Format.pretty (format u)
toString u := Format.pretty (Level.format u)
protected def quote (u : Level) (prec : Nat := 0) (mvars : Bool := true) : Syntax.Level :=
(PP.toResult u (mvars := mvars)).quote prec
protected def quote (u : Level) (prec : Nat := 0) : Syntax.Level :=
(PP.toResult u).quote prec
instance : Quote Level `level where
quote := Level.quote

View File

@@ -15,23 +15,17 @@ register_builtin_option linter.deprecated : Bool := {
descr := "if true, generate deprecation warnings"
}
structure DeprecationEntry where
newName? : Option Name := none
text? : Option String := none
since? : Option String := none
deriving Inhabited
builtin_initialize deprecatedAttr : ParametricAttribute DeprecationEntry
builtin_initialize deprecatedAttr : ParametricAttribute (Option Name)
registerParametricAttribute {
name := `deprecated
descr := "mark declaration as deprecated",
getParam := fun _ stx => do
let `(attr| deprecated $[$id?]? $[$text?]? $[(since := $since?)]?) := stx
| throwError "invalid `[deprecated]` attribute"
let newName? id?.mapM Elab.realizeGlobalConstNoOverloadWithInfo
let text? := text?.map TSyntax.getString
let since? := since?.map TSyntax.getString
return { newName?, text?, since? }
match stx with
| `(attr| deprecated $[$id?]?) =>
let some id := id? | return none
let declNameNew Elab.realizeGlobalConstNoOverloadWithInfo id
return some declNameNew
| _ => throwError "invalid `[deprecated]` attribute"
}
def isDeprecated (env : Environment) (declName : Name) : Bool :=
@@ -40,13 +34,12 @@ def isDeprecated (env : Environment) (declName : Name) : Bool :=
def _root_.Lean.MessageData.isDeprecationWarning (msg : MessageData) : Bool :=
msg.hasTag (· == ``deprecatedAttr)
def getDeprecatedNewName (env : Environment) (declName : Name) : Option Name := do
( deprecatedAttr.getParam? env declName).newName?
def getDeprecatedNewName (env : Environment) (declName : Name) : Option Name :=
(deprecatedAttr.getParam? env declName).getD none
def checkDeprecated [Monad m] [MonadEnv m] [MonadLog m] [AddMessageContext m] [MonadOptions m] (declName : Name) : m Unit := do
if getLinterValue linter.deprecated ( getOptions) then
let some attr := deprecatedAttr.getParam? ( getEnv) declName | pure ()
logWarning <| .tagged ``deprecatedAttr <| attr.text?.getD <|
match attr.newName? with
| none => s!"`{declName}` has been deprecated"
| some newName => s!"`{declName}` has been deprecated, use `{newName}` instead"
match deprecatedAttr.getParam? ( getEnv) declName with
| none => pure ()
| some none => logWarning <| .tagged ``deprecatedAttr m!"`{declName}` has been deprecated"
| some (some newName) => logWarning <| .tagged ``deprecatedAttr m!"`{declName}` has been deprecated, use `{newName}` instead"

View File

@@ -120,13 +120,7 @@ def ofExpr (e : Expr) : MessageData :=
hasSyntheticSorry := (instantiateMVarsCore · e |>.1.hasSyntheticSorry)
}
def ofLevel (l : Level) : MessageData :=
.ofPPFormat {
pp := fun
| some ctx => ppLevel ctx l
| none => return format l
}
def ofLevel (l : Level) : MessageData := ofFormat (format l)
def ofName (n : Name) : MessageData := ofFormat (format n)
partial def hasSyntheticSorry (msg : MessageData) : Bool :=

View File

@@ -110,14 +110,6 @@ structure Config where
trackZetaDelta : Bool := false
/-- Eta for structures configuration mode. -/
etaStruct : EtaStructMode := .all
/--
When `univApprox` is set to true,
we use approximations when solving postponed universe constraints.
Examples:
- `max u ?v =?= u` is solved with `?v := u` and ignoring the solution `?v := 0`.
- `max u w =?= mav u ?v` is solved with `?v := w` ignoring the solution `?v := max u w`
-/
univApprox : Bool := true
/--
Function parameter information cache.
@@ -308,11 +300,6 @@ structure Context where
A predicate to control whether a constant can be unfolded or not at `whnf`.
Note that we do not cache results at `whnf` when `canUnfold?` is not `none`. -/
canUnfold? : Option (Config ConstantInfo CoreM Bool) := none
/--
When `Config.univApprox := true`, this flag is set to `true` when there is no
progress processing universe constraints.
-/
univApprox : Bool := false
/--
The `MetaM` monad is a core component of Lean's metaprogramming framework, facilitating the
@@ -1703,10 +1690,6 @@ partial def processPostponed (mayPostpone : Bool := true) (exceptionOnFailure :=
return true
else if numPostponed' < numPostponed then
loop
-- If we cannot pospone anymore, `Config.univApprox := true`, but we haven't tried universe approximations yet,
-- then try approximations before failing.
else if !mayPostpone && ( getConfig).univApprox && !( read).univApprox then
withReader (fun ctx => { ctx with univApprox := true }) loop
else
trace[Meta.isLevelDefEq.postponed] "no progress solving pending is-def-eq level constraints"
return mayPostpone

View File

@@ -1757,21 +1757,10 @@ private def isDefEqDeltaStep (t s : Expr) : MetaM DeltaStepResult := do
| .lt => unfold t (return .unknown) (k · s)
| .gt => unfold s (return .unknown) (k t ·)
| .eq =>
-- Remark: if `t` and `s` are both some `f`-application, we use `tryHeuristic`
-- if `f` is not a projection. The projection case generates a performance regression.
if tInfo.name == sInfo.name && !( isProjectionFn tInfo.name) then
if t.isApp && s.isApp && ( tryHeuristic t s) then
return .eq
else
unfoldBoth t s
else
unfoldBoth t s
unfold t
(unfold s (return .unknown) (k t ·))
(fun t => unfold s (k t s) (k t ·))
where
unfoldBoth (t s : Expr) : MetaM DeltaStepResult := do
unfold t
(unfold s (return .unknown) (k t ·))
(fun t => unfold s (k t s) (k t ·))
k (t s : Expr) : MetaM DeltaStepResult := do
let t whnfCore t
let s whnfCore s

View File

@@ -114,7 +114,7 @@ For example:
(The type of `inst` must not contain mvars.)
-/
private partial def computeSynthOrder (inst : Expr) : MetaM (Array Nat) :=
partial def computeSynthOrder (inst : Expr) : MetaM (Array Nat) :=
withReducible do
let instTy inferType inst

View File

@@ -16,62 +16,26 @@ namespace Lean.Meta
That is, `lvl` is a proper level subterm of some `u_i`. -/
private def strictOccursMax (lvl : Level) : Level Bool
| Level.max u v => visit u || visit v
| _ => false
| _ => false
where
visit : Level Bool
| Level.max u v => visit u || visit v
| u => u != lvl && lvl.occurs u
| u => u != lvl && lvl.occurs u
/-- `mkMaxArgsDiff mvarId (max u_1 ... (mvar mvarId) ... u_n) v` => `max v u_1 ... u_n` -/
private def mkMaxArgsDiff (mvarId : LMVarId) : Level Level Level
| Level.max u v, acc => mkMaxArgsDiff mvarId v <| mkMaxArgsDiff mvarId u acc
| l@(Level.mvar id), acc => if id != mvarId then mkLevelMax' acc l else acc
| l, acc => mkLevelMax' acc l
| l, acc => mkLevelMax' acc l
/--
Solves `?m =?= max ?m v` by creating a fresh metavariable `?n`
and assigning `?m := max ?n v`
-/
Solve `?m =?= max ?m v` by creating a fresh metavariable `?n`
and assigning `?m := max ?n v` -/
private def solveSelfMax (mvarId : LMVarId) (v : Level) : MetaM Unit := do
assert! v.isMax
let n mkFreshLevelMVar
assignLevelMVar mvarId <| mkMaxArgsDiff mvarId v n
/--
Returns true if `v` is `max u ?m` (or variant). That is, we solve `u =?= max u ?m` as `?m := u`.
This is an approximation. For example, we ignore the solution `?m := 0`.
-/
-- TODO: investigate whether we need to improve this approximation.
private def tryApproxSelfMax (u v : Level) : MetaM Bool := do
match v with
| .max v' (.mvar mvarId) => solve v' mvarId
| .max (.mvar mvarId) v' => solve v' mvarId
| _ => return false
where
solve (v' : Level) (mvarId : LMVarId) : MetaM Bool := do
if u == v' then
assignLevelMVar mvarId u
return true
else
return false
/--
Returns true if `u` of the form `max u₁ u₂` and `v` of the form `max u₁ ?w` (or variant).
That is, we solve `max u₁ u₂ =?= max u₁ ?v` as `?v := u₂`.
This is an approximation. For example, we ignore the solution `?w := max u₁ u₂`.
-/
-- TODO: investigate whether we need to improve this approximation.
private def tryApproxMaxMax (u v : Level) : MetaM Bool := do
match u, v with
| .max u₁ u₂, .max v' (.mvar mvarId) => solve u₁ u₂ v' mvarId
| .max u₁ u₂, .max (.mvar mvarId) v' => solve u₁ u₂ v' mvarId
| _, _ => return false
where
solve (u₁ u₂ v' : Level) (mvarId : LMVarId) : MetaM Bool := do
if u₁ == v' then assignLevelMVar mvarId u₂; return true
else if u₂ == v' then assignLevelMVar mvarId u₁; return true
else return false
private def postponeIsLevelDefEq (lhs : Level) (rhs : Level) : MetaM Unit := do
let ref getRef
let ctx read
@@ -118,13 +82,7 @@ mutual
match ( Meta.decLevel? v) with
| some v => Bool.toLBool <$> isLevelDefEqAux u v
| none => return LBool.undef
| _, _ =>
if ( read).univApprox then
if ( tryApproxSelfMax u v) then
return LBool.true
if ( tryApproxMaxMax u v) then
return LBool.true
return LBool.undef
| _, _ => return LBool.undef
@[export lean_is_level_def_eq]
partial def isLevelDefEqAuxImpl : Level Level MetaM Bool

View File

@@ -41,14 +41,6 @@ structure GeneratorNode where
mctx : MetavarContext
instances : Array Instance
currInstanceIdx : Nat
/--
`typeHasMVars := true` if type of `mvar` contains metavariables.
We store this information to implement an optimization that relies on the fact
that instances are "morally canonical."
That is, we need to find at most one answer for this generator node if the type
does not have metavariables.
-/
typeHasMVars : Bool
deriving Inhabited
structure ConsumerNode where
@@ -64,8 +56,8 @@ inductive Waiter where
| root : Waiter
def Waiter.isRoot : Waiter Bool
| .consumerNode _ => false
| .root => true
| Waiter.consumerNode _ => false
| Waiter.root => true
/-!
In tabled resolution, we creating a mapping from goals (e.g., `Coe Nat ?x`) to
@@ -106,10 +98,10 @@ partial def normLevel (u : Level) : M Level := do
if !u.hasMVar then
return u
else match u with
| .succ v => return u.updateSucc! ( normLevel v)
| .max v w => return u.updateMax! ( normLevel v) ( normLevel w)
| .imax v w => return u.updateIMax! ( normLevel v) ( normLevel w)
| .mvar mvarId =>
| Level.succ v => return u.updateSucc! ( normLevel v)
| Level.max v w => return u.updateMax! ( normLevel v) ( normLevel w)
| Level.imax v w => return u.updateIMax! ( normLevel v) ( normLevel w)
| Level.mvar mvarId =>
if ( getMCtx).getLevelDepth mvarId != ( getMCtx).depth then
return u
else
@@ -126,15 +118,15 @@ partial def normExpr (e : Expr) : M Expr := do
if !e.hasMVar then
pure e
else match e with
| .const _ us => return e.updateConst! ( us.mapM normLevel)
| .sort u => return e.updateSort! ( normLevel u)
| .app f a => return e.updateApp! ( normExpr f) ( normExpr a)
| .letE _ t v b _ => return e.updateLet! ( normExpr t) ( normExpr v) ( normExpr b)
| .forallE _ d b _ => return e.updateForallE! ( normExpr d) ( normExpr b)
| .lam _ d b _ => return e.updateLambdaE! ( normExpr d) ( normExpr b)
| .mdata _ b => return e.updateMData! ( normExpr b)
| .proj _ _ b => return e.updateProj! ( normExpr b)
| .mvar mvarId =>
| Expr.const _ us => return e.updateConst! ( us.mapM normLevel)
| Expr.sort u => return e.updateSort! ( normLevel u)
| Expr.app f a => return e.updateApp! ( normExpr f) ( normExpr a)
| Expr.letE _ t v b _ => return e.updateLet! ( normExpr t) ( normExpr v) ( normExpr b)
| Expr.forallE _ d b _ => return e.updateForallE! ( normExpr d) ( normExpr b)
| Expr.lam _ d b _ => return e.updateLambdaE! ( normExpr d) ( normExpr b)
| Expr.mdata _ b => return e.updateMData! ( normExpr b)
| Expr.proj _ _ b => return e.updateProj! ( normExpr b)
| Expr.mvar mvarId =>
if !( mvarId.isAssignable) then
return e
else
@@ -210,7 +202,7 @@ def getInstances (type : Expr) : MetaM (Array Instance) := do
let result := result.insertionSort fun e₁ e₂ => e₁.priority < e₂.priority
let erasedInstances getErasedInstances
let mut result result.filterMapM fun e => match e.val with
| .const constName us =>
| Expr.const constName us =>
if erasedInstances.contains constName then
return none
else
@@ -242,7 +234,6 @@ def mkGeneratorNode? (key mvar : Expr) : MetaM (Option GeneratorNode) := do
let mctx getMCtx
return some {
mvar, key, mctx, instances
typeHasMVars := mvarType.hasMVar
currInstanceIdx := instances.size
}
@@ -360,7 +351,7 @@ def tryResolve (mvar : Expr) (inst : Instance) : MetaM (Option (MetavarContext
let lctx getLCtx
let localInsts getLocalInstances
forallTelescopeReducing mvarType fun xs mvarTypeBody => do
let { subgoals, instVal, instTypeBody } getSubgoals lctx localInsts xs inst
let subgoals, instVal, instTypeBody getSubgoals lctx localInsts xs inst
withTraceNode `Meta.synthInstance.tryResolve (withMCtx ( getMCtx) do
return m!"{exceptOptionEmoji ·} {← instantiateMVars mvarTypeBody} ≟ {← instantiateMVars instTypeBody}") do
if ( isDefEq mvarTypeBody instTypeBody) then
@@ -382,7 +373,7 @@ def tryAnswer (mctx : MetavarContext) (mvar : Expr) (answer : Answer) : SynthM (
/-- Move waiters that are waiting for the given answer to the resume stack. -/
def wakeUp (answer : Answer) : Waiter SynthM Unit
| .root => do
| Waiter.root => do
/- Recall that we now use `ignoreLevelMVarDepth := true`. Thus, we should allow solutions
containing universe metavariables, and not check `answer.result.paramNames.isEmpty`.
We use `openAbstractMVarsResult` to construct the universe metavariables
@@ -392,7 +383,7 @@ def wakeUp (answer : Answer) : Waiter → SynthM Unit
else
let (_, _, answerExpr) openAbstractMVarsResult answer.result
trace[Meta.synthInstance] "skip answer containing metavariables {answerExpr}"
| .consumerNode cNode =>
| Waiter.consumerNode cNode =>
modify fun s => { s with resumeStack := s.resumeStack.push (cNode, answer) }
def isNewAnswer (oldAnswers : Array Answer) (answer : Answer) : Bool :=
@@ -423,11 +414,11 @@ def addAnswer (cNode : ConsumerNode) : SynthM Unit := do
let answer mkAnswer cNode
-- Remark: `answer` does not contain assignable or assigned metavariables.
let key := cNode.key
let { waiters, answers } getEntry key
if isNewAnswer answers answer then
let newEntry := { waiters, answers := answers.push answer }
let entry getEntry key
if isNewAnswer entry.answers answer then
let newEntry := { entry with answers := entry.answers.push answer }
modify fun s => { s with tableEntries := s.tableEntries.insert key newEntry }
waiters.forM (wakeUp answer)
entry.waiters.forM (wakeUp answer)
/--
Return `true` if a type of the form `(a_1 : A_1) → ... → (a_n : A_n) → B` has an unused argument `a_i`.
@@ -435,7 +426,7 @@ def addAnswer (cNode : ConsumerNode) : SynthM Unit := do
Remark: This is syntactic check and no reduction is performed.
-/
private def hasUnusedArguments : Expr Bool
| .forallE _ _ b _ => !b.hasLooseBVar 0 || hasUnusedArguments b
| Expr.forallE _ _ b _ => !b.hasLooseBVar 0 || hasUnusedArguments b
| _ => false
/--
@@ -548,17 +539,6 @@ def generate : SynthM Unit := do
let inst := gNode.instances.get! idx
let mctx := gNode.mctx
let mvar := gNode.mvar
/- See comment at `typeHasMVars` -/
unless gNode.typeHasMVars do
if let some entry := ( get).tableEntries.find? key then
unless entry.answers.isEmpty do
/-
We already have an answer for this node, and since its type does not have metavariables,
we can skip other solutions because we assume instances are "morally canonical".
We have added this optimization to address issue #3996.
-/
modify fun s => { s with generatorStack := s.generatorStack.pop }
return
discard do withMCtx mctx do
withTraceNode `Meta.synthInstance
(return m!"{exceptOptionEmoji ·} apply {inst.val} to {← instantiateMVars (← inferType mvar)}") do
@@ -687,7 +667,7 @@ private partial def preprocessArgs (type : Expr) (i : Nat) (args : Array Expr) (
private def preprocessOutParam (type : Expr) : MetaM Expr :=
forallTelescope type fun xs typeBody => do
match typeBody.getAppFn with
| c@(.const declName _) =>
| c@(Expr.const declName _) =>
let env getEnv
if let some outParamsPos := getOutParamPositions? env declName then
unless outParamsPos.isEmpty do
@@ -710,7 +690,7 @@ def synthInstance? (type : Expr) (maxResultSize? : Option Nat := none) : MetaM (
withTraceNode `Meta.synthInstance
(return m!"{exceptOptionEmoji ·} {← instantiateMVars type}") do
withConfig (fun config => { config with isDefEqStuckEx := true, transparency := TransparencyMode.instances,
foApprox := true, ctxApprox := true, constApprox := false, univApprox := false }) do
foApprox := true, ctxApprox := true, constApprox := false }) do
let localInsts getLocalInstances
let type instantiateMVars type
let type preprocess type
@@ -795,7 +775,8 @@ def synthInstance (type : Expr) (maxResultSize? : Option Nat := none) : MetaM Ex
private def synthPendingImp (mvarId : MVarId) : MetaM Bool := withIncRecDepth <| mvarId.withContext do
let mvarDecl mvarId.getDecl
match mvarDecl.kind with
| .syntheticOpaque => return false
| MetavarKind.syntheticOpaque =>
return false
| _ =>
/- Check whether the type of the given metavariable is a class or not. If yes, then try to synthesize
it using type class resolution. We only do it for `synthetic` and `natural` metavariables. -/

View File

@@ -86,7 +86,6 @@ builtin_initialize
ppFnsRef.set {
ppExprWithInfos := fun ctx e => ctx.runMetaM <| withoutContext <| ppExprWithInfos e,
ppTerm := fun ctx stx => ctx.runCoreM <| withoutContext <| ppTerm stx,
ppLevel := fun ctx l => return l.format (mvars := getPPMVars ctx.opts),
ppGoal := fun ctx mvarId => ctx.runMetaM <| withoutContext <| Meta.ppGoal mvarId
}

View File

@@ -71,11 +71,9 @@ def delabSort : Delab := do
match l with
| Level.zero => `(Prop)
| Level.succ .zero => `(Type)
| _ =>
let mvars getPPOption getPPMVars
match l.dec with
| some l' => `(Type $(Level.quote l' (prec := max_prec) (mvars := mvars)))
| none => `(Sort $(Level.quote l (prec := max_prec) (mvars := mvars)))
| _ => match l.dec with
| some l' => `(Type $(Level.quote l' max_prec))
| none => `(Sort $(Level.quote l max_prec))
/--
Delaborator for `const` expressions.
@@ -98,8 +96,7 @@ def delabConst : Delab := do
c := c₀
pure <| mkIdent c
else
let mvars getPPOption getPPMVars
`($(mkIdent c).{$[$(ls.toArray.map (Level.quote · (prec := 0) (mvars := mvars)))],*})
`($(mkIdent c).{$[$(ls.toArray.map quote)],*})
let stx maybeAddBlockImplicit stx
if ( getPPOption getPPTagAppFns) then

View File

@@ -82,8 +82,7 @@ register_builtin_option pp.instantiateMVars : Bool := {
register_builtin_option pp.mvars : Bool := {
defValue := true
group := "pp"
descr := "(pretty printer) display names of metavariables when true, \
and otherwise display them as '?_' (for expression metavariables) and as '_' (for universe level metavariables)"
descr := "(pretty printer) display names of metavariables when true, and otherwise display them as '?_'"
}
register_builtin_option pp.mvars.withType : Bool := {
defValue := false

View File

@@ -404,7 +404,7 @@ where
for _ in [:revComponents.length] do
match revComponents with
| [] => return none
| cmpt::rest => candidate := Name.appendCore cmpt candidate; revComponents := rest
| cmpt::rest => candidate := cmpt ++ candidate; revComponents := rest
match ( resolveGlobalName candidate) with
| [(potentialMatch, _)] => if potentialMatch == n₀ then return some candidate else continue
| _ => continue

View File

@@ -11,17 +11,17 @@ namespace Lean
namespace Expr
namespace FindImpl
unsafe abbrev FindM (m) := StateT (PtrSet Expr) m
unsafe abbrev FindM := StateT (PtrSet Expr) Id
@[inline] unsafe def checkVisited [Monad m] (e : Expr) : OptionT (FindM m) Unit := do
@[inline] unsafe def checkVisited (e : Expr) : OptionT FindM Unit := do
if ( get).contains e then
failure
modify fun s => s.insert e
unsafe def findM? [Monad m] (p : Expr m Bool) (e : Expr) : OptionT (FindM m) Expr :=
unsafe def findM? (p : Expr Bool) (e : Expr) : OptionT FindM Expr :=
let rec visit (e : Expr) := do
checkVisited e
if p e then
if p e then
pure e
else match e with
| .forallE _ d b _ => visit d <|> visit b
@@ -33,35 +33,29 @@ unsafe def findM? [Monad m] (p : Expr → m Bool) (e : Expr) : OptionT (FindM m)
| _ => failure
visit e
unsafe def findUnsafeM? {m} [Monad m] (p : Expr m Bool) (e : Expr) : m (Option Expr) :=
findM? p e |>.run' mkPtrSet
@[inline] unsafe def findUnsafe? (p : Expr Bool) (e : Expr) : Option Expr := findUnsafeM? (m := Id) p e
unsafe def findUnsafe? (p : Expr Bool) (e : Expr) : Option Expr :=
Id.run <| findM? p e |>.run' mkPtrSet
end FindImpl
@[implemented_by FindImpl.findUnsafeM?]
/- This is a reference implementation for the unsafe one above -/
def findM? [Monad m] (p : Expr m Bool) (e : Expr) : m (Option Expr) := do
if p e then
return some e
else match e with
| .forallE _ d b _ => findM? p d <||> findM? p b
| .lam _ d b _ => findM? p d <||> findM? p b
| .mdata _ b => findM? p b
| .letE _ t v b _ => findM? p t <||> findM? p v <||> findM? p b
| .app f a => findM? p f <||> findM? p a
| .proj _ _ b => findM? p b
| _ => pure none
@[implemented_by FindImpl.findUnsafe?]
def find? (p : Expr Bool) (e : Expr) : Option Expr := findM? (m := Id) p e
def find? (p : Expr Bool) (e : Expr) : Option Expr :=
/- This is a reference implementation for the unsafe one above -/
if p e then
some e
else match e with
| .forallE _ d b _ => find? p d <|> find? p b
| .lam _ d b _ => find? p d <|> find? p b
| .mdata _ b => find? p b
| .letE _ t v b _ => find? p t <|> find? p v <|> find? p b
| .app f a => find? p f <|> find? p a
| .proj _ _ b => find? p b
| _ => none
/-- Return true if `e` occurs in `t` -/
def occurs (e : Expr) (t : Expr) : Bool :=
(t.find? fun s => s == e).isSome
/--
Return type for `findExt?` function argument.
-/
@@ -72,7 +66,7 @@ inductive FindStep where
namespace FindExtImpl
unsafe def findM? (p : Expr FindStep) (e : Expr) : OptionT (FindImpl.FindM Id) Expr :=
unsafe def findM? (p : Expr FindStep) (e : Expr) : OptionT FindImpl.FindM Expr :=
visit e
where
visitApp (e : Expr) :=

View File

@@ -49,7 +49,6 @@ instance : Coe Format FormatWithInfos where
structure PPFns where
ppExprWithInfos : PPContext Expr IO FormatWithInfos
ppTerm : PPContext Term IO Format
ppLevel : PPContext Level IO Format
ppGoal : PPContext MVarId IO Format
deriving Inhabited
@@ -57,7 +56,6 @@ builtin_initialize ppFnsRef : IO.Ref PPFns ←
IO.mkRef {
ppExprWithInfos := fun _ e => return format (toString e)
ppTerm := fun ctx stx => return stx.raw.formatStx (some <| pp.raw.maxDepth.get ctx.opts)
ppLevel := fun _ l => return format l
ppGoal := fun _ _ => return "goal"
}
@@ -90,10 +88,7 @@ def ppTerm (ctx : PPContext) (stx : Term) : IO Format :=
else
pure f!"failed to pretty print term (use 'set_option pp.rawOnError true' for raw representation)"
def ppLevel (ctx : PPContext) (l : Level) : IO Format :=
ppExt.getState ctx.env |>.ppLevel ctx l
def ppGoal (ctx : PPContext) (mvarId : MVarId) : IO Format :=
ppExt.getState ctx.env |>.ppGoal ctx mvarId
ppExt.getState ctx.env |>.ppGoal ctx mvarId
end Lean

View File

@@ -8,9 +8,8 @@ import Lean.Elab.SyntheticMVars
import Lean.Elab.Command
import Lean.Meta.Tactic.Unfold
import Lean.Meta.Eval
import Lean.Compiler.ImplementedByAttr
open Lean Elab Meta Command Term Compiler
open Lean Elab Meta Command Term
syntax (name := testExternCmd) "test_extern " term : command
@@ -19,15 +18,14 @@ syntax (name := testExternCmd) "test_extern " term : command
let t elabTermAndSynthesize t none
match t.getAppFn with
| .const f _ =>
let env getEnv
if isExtern env f || (getImplementedBy? env f).isSome then
if isExtern ( getEnv) f then
let t' := ( unfold t f).expr
let r := mkApp (.const ``reduceBool []) ( mkDecide ( mkEq t t'))
let r := mkApp (.const ``reduceBool []) ( mkAppM ``BEq.beq #[t, t'])
if ! ( evalExpr Bool (.const ``Bool []) r) then
throwError
("native implementation did not agree with reference implementation!\n" ++
m!"Compare the outputs of:\n#eval {t}\n and\n#eval {t'}")
else
throwError "test_extern: {f} does not have an @[extern] attribute or @[implemented_by] attribute"
throwError "test_extern: {f} does not have an @[extern] attribute"
| _ => throwError "test_extern: expects a function application"
| _ => throwUnsupportedSyntax

View File

@@ -144,9 +144,7 @@ where
| ctx, compose d₁ d₂ => do let d₁ go nCtx ctx d₁; let d₂ go nCtx ctx d₂; pure $ d₁ ++ d₂
| ctx, group d => Format.group <$> go nCtx ctx d
| ctx, .trace data header children => do
let mut header := ( go nCtx ctx header).nest 4
if data.startTime != 0 then
header := f!"[{data.stopTime - data.startTime}] {header}"
let header := ( go nCtx ctx header).nest 4
let nodes
if data.collapsed && !children.isEmpty then
let children := children.map fun child =>

View File

@@ -174,8 +174,6 @@ def Workspace.updateAndMaterialize
liftM (m := IO) <| throw e -- only ignore manifest on a bare `lake update`
logWarning s!"{rootName}: ignoring previous manifest because it failed to load: {e}"
resolveDepsAcyclic ws.root fun pkg resolve => do
if let some pkg := ( getThe Workspace).findPackage? pkg.name then
return pkg
let inherited := pkg.name != ws.root.name
-- Materialize this package's dependencies first
let deps pkg.depConfigs.mapM fun dep => fetchOrCreate dep.name do
@@ -245,8 +243,6 @@ def Workspace.materializeDeps
let rootPkg := ws.root
let (root, ws) StateT.run (s := ws) <| StateT.run' (s := mkNameMap Package) do
resolveDepsAcyclic rootPkg fun pkg resolve => do
if let some pkg := ( getThe Workspace).findPackage? pkg.name then
return pkg
let topLevel := pkg.name = rootPkg.name
let deps := pkg.depConfigs
if topLevel then

View File

@@ -1,29 +0,0 @@
{"version": 7,
"packagesDir": ".lake/packages",
"packages":
[{"type": "path",
"name": "root",
"manifestFile": "lake-manifest.json",
"inherited": true,
"dir": "./../foo/../a/../root",
"configFile": "lakefile.lean"},
{"type": "path",
"name": "a",
"manifestFile": "lake-manifest.json",
"inherited": true,
"dir": "./../foo/../a",
"configFile": "lakefile.lean"},
{"type": "path",
"name": "b",
"manifestFile": "lake-manifest.json",
"inherited": true,
"dir": "./../foo/../b",
"configFile": "lakefile.lean"},
{"type": "path",
"name": "foo",
"manifestFile": "lake-manifest.json",
"inherited": false,
"dir": "./../foo",
"configFile": "lakefile.lean"}],
"name": "bar",
"lakeDir": ".lake"}

View File

@@ -6,11 +6,6 @@ LAKE=${LAKE:-../../.lake/build/bin/lake}
./clean.sh
$LAKE -d bar build --update
# Test that the update produces the expected manifest.
# Serves as a regression test to ensure that multiples of a package in
# the dependency tree do not produce duplicate entries in the manifest.
# https://github.com/leanprover/lean4/pull/3957
diff --strip-trailing-cr bar/lake-manifest.expected.json bar/lake-manifest.json
$LAKE -d foo build --update
./foo/.lake/build/bin/foo
@@ -34,7 +29,6 @@ test ! -d foo/.lake/build
./clean.sh
$LAKE -d bar -f lakefile.toml build --update
diff --strip-trailing-cr bar/lake-manifest.expected.json bar/lake-manifest.json
$LAKE -d foo -f lakefile.toml build --update
./foo/.lake/build/bin/foo

30
tests/lean/343.lean Normal file
View File

@@ -0,0 +1,30 @@
structure CatIsh where
Obj : Type o
Hom : Obj Obj Type m
infixr:75 " ~> " => (CatIsh.Hom _)
structure FunctorIsh (C D : CatIsh) where
onObj : C.Obj D.Obj
onHom : {s d : C.Obj}, (s ~> d) (onObj s ~> onObj d)
abbrev Catish : CatIsh :=
{
Obj := CatIsh
Hom := FunctorIsh
}
universe m o
unif_hint (mvar : CatIsh) where
Catish.{m, o} =?= mvar |- mvar.Obj =?= CatIsh.{o, m}
structure CtxSyntaxLayerParamsObj where
Ct : CatIsh
def CtxSyntaxLayerParams : CatIsh :=
{
Obj := CtxSyntaxLayerParamsObj
Hom := sorry
}
def CtxSyntaxLayerTy := CtxSyntaxLayerParams ~> Catish

View File

@@ -0,0 +1,17 @@
343.lean:24:4-24:24: warning: declaration uses 'sorry'
343.lean:30:0-30:54: error: stuck at solving universe constraint
max (?u+1) (?u+1) =?= max (?u+1) (?u+1)
while trying to unify
CatIsh.Obj.{max (max (?u + 1) (?u + 1)) ?u ?u,
max ((max (?u + 1) (?u + 1)) + 1) ((max ?u ?u) + 1)}
Catish.{max (?u + 1) (?u + 1),
max ?u ?u} : Type (max ((max (?u + 1) (?u + 1)) + 1) ((max ?u ?u) + 1))
with
CatIsh.{max ?u ?u,
max (?u + 1) (?u + 1)} : Type (max ((max ?u ?u) + 1) ((max (?u + 1) (?u + 1)) + 1))
343.lean:30:0-30:54: error: failed to solve universe constraint
max (?u+1) (?u+1) =?= max (?u+1) (?u+1)
while trying to unify
Catish.Obj : Type (max ((max (u_1 + 1) (u_2 + 1)) + 1) ((max u_3 u_4) + 1))
with
CatIsh : Type (max ((max u_4 u_3) + 1) ((max (u_4 + 1) (u_3 + 1)) + 1))

1
tests/lean/456.lean Normal file
View File

@@ -0,0 +1 @@
def A : Sort u := { s : Prop // _ }

View File

@@ -0,0 +1,6 @@
456.lean:1:18-1:35: error: failed to solve universe constraint
u =?= max 1 ?u
while trying to unify
Sort u : Type u
with
Type : Type 1

View File

@@ -17,14 +17,14 @@ def f1 (x : Nat) := x + 1
def Foo.g1 := 10
@[deprecated Foo.g1 (since := "2022-07-24")]
@[deprecated Foo.g1]
def f2 (x : Nat) := x + 1
@[deprecated g1]
def f3 (x : Nat) := x + 1
open Foo
@[deprecated g1 "use g1 instead, f4 is not a good name"]
@[deprecated g1]
def f4 (x : Nat) := x + 1
#eval f2 0 + 1

View File

@@ -7,5 +7,5 @@ deprecated.lean:23:13-23:15: error: unknown constant 'g1'
deprecated.lean:30:6-30:8: warning: `f2` has been deprecated, use `Foo.g1` instead
2
2
deprecated.lean:33:6-33:8: warning: use g1 instead, f4 is not a good name
deprecated.lean:33:6-33:8: warning: `f4` has been deprecated, use `Foo.g1` instead
2

View File

@@ -2,14 +2,10 @@ diamond1.lean:11:40-11:45: error: parent field type mismatch, field 'a' from par
αα : Type
but is expected to have type
α : Type
structure Foo : Type → Type
inductive Foo : Type → Type
number of parameters: 1
constructor:
constructors:
Foo.mk : {α : Type} → Bar (αα) → (Bool → α) → Nat → Foo α
fields:
toBar : Bar (αα)
c : Bool → α
d : Nat
def f : Nat → Foo Nat :=
fun x => { a := fun y => x + y, b := fun x x_1 => x + x_1, c := fun x_1 => x, d := x }
diamond1.lean:27:47-27:52: warning: field 'a' from 'Baz' has already been declared

View File

@@ -1,7 +1,4 @@
class Semiring.{u} : Type u → Type u
inductive Semiring.{u} : Type u → Type u
number of parameters: 1
constructor:
constructors:
Semiring.mk : {R : Type u} → [toAddCommMonoid : AddCommMonoid R] → [toMonoid : Monoid R] → Semiring R
fields:
toAddCommMonoid : AddCommMonoid R
toMonoid : Monoid R

View File

@@ -43,14 +43,6 @@ example (_ha : a > 0) (w : b c) : a * b a * c := by apply?
#guard_msgs in
example : x < x + 1 := exact?%
/-- error: `exact?%` didn't find any relevant lemmas -/
#guard_msgs in
example {α : Sort u} (x y : α) : Eq x y := exact?%
/-- error: `exact?%` could not close the goal. Try `by apply` to see partial suggestions. -/
#guard_msgs in
example (x y : Nat) : x y := exact?%
/-- info: Try this: exact p -/
#guard_msgs in
example (P : Prop) (p : P) : P := by apply?

View File

@@ -1,103 +0,0 @@
/-!
Test #print command for structures and classes
-/
/- Structure -/
/--
info: structure Prod.{u, v} : Type u → Type v → Type (max u v)
number of parameters: 2
constructor:
Prod.mk : {α : Type u} → {β : Type v} → α → β → α × β
fields:
fst : α
snd : β
-/
#guard_msgs in
#print Prod
/- Class -/
/--
info: class Inhabited.{u} : Sort u → Sort (max 1 u)
number of parameters: 1
constructor:
Inhabited.mk : {α : Sort u} → α → Inhabited α
fields:
default : α
-/
#guard_msgs in
#print Inhabited
/- Structure with private field -/
/--
info: structure Thunk.{u} : Type u → Type u
number of parameters: 1
constructor:
Thunk.mk : {α : Type u} → (Unit → α) → Thunk α
fields:
private fn : Unit → α
-/
#guard_msgs in
#print Thunk
/- Extended class -/
/--
info: class Alternative.{u, v} : (Type u → Type v) → Type (max (u + 1) v)
number of parameters: 1
constructor:
Alternative.mk : {f : Type u → Type v} →
[toApplicative : Applicative f] → ({α : Type u} → f α) → ({α : Type u} → f α → (Unit → f α) → f α) → Alternative f
fields:
toApplicative : Applicative f
failure : {α : Type u} → f α
orElse : {α : Type u} → f α → (Unit → f α) → f α
-/
#guard_msgs in
#print Alternative
/- Multiply extended class -/
/--
info: class Applicative.{u, v} : (Type u → Type v) → Type (max (u + 1) v)
number of parameters: 1
constructor:
Applicative.mk : {f : Type u → Type v} →
[toFunctor : Functor f] →
[toPure : Pure f] → [toSeq : Seq f] → [toSeqLeft : SeqLeft f] → [toSeqRight : SeqRight f] → Applicative f
fields:
toFunctor : Functor f
toPure : Pure f
toSeq : Seq f
toSeqLeft : SeqLeft f
toSeqRight : SeqRight f
-/
#guard_msgs in
#print Applicative
/- Structure with unused parameter -/
structure Weird (α β : Type _) where
a : α
/--
info: structure Weird.{u_1, u_2} : Type u_1 → Type u_2 → Type u_1
number of parameters: 2
constructor:
Weird.mk : {α : Type u_1} → {β : Type u_2} → α → Weird α β
fields:
a : α
-/
#guard_msgs in
#print Weird
/- Structure-like inductive -/
inductive Fake (α : Type _) where
| mk : (x : α) Fake α
/--
info: inductive Fake.{u_1} : Type u_1 → Type u_1
number of parameters: 1
constructors:
Fake.mk : {α : Type u_1} → α → Fake α
-/
#guard_msgs in
#print Fake

View File

@@ -1,8 +0,0 @@
/-!
Issue #2291
The following example would cause the pretty printer to panic.
-/
set_option trace.compiler.simp true in
#eval [0]

View File

@@ -1,51 +0,0 @@
set_option pp.mvars false
structure CatIsh where
Obj : Type o
Hom : Obj Obj Type m
infixr:75 " ~> " => (CatIsh.Hom _)
structure FunctorIsh (C D : CatIsh) where
onObj : C.Obj D.Obj
onHom : {s d : C.Obj}, (s ~> d) (onObj s ~> onObj d)
abbrev Catish : CatIsh :=
{
Obj := CatIsh
Hom := FunctorIsh
}
universe m o
unif_hint (mvar : CatIsh) where
Catish.{m, o} =?= mvar |- mvar.Obj =?= CatIsh.{o, m}
structure CtxSyntaxLayerParamsObj where
Ct : CatIsh
/-- warning: declaration uses 'sorry' -/
#guard_msgs in
def CtxSyntaxLayerParams : CatIsh :=
{
Obj := CtxSyntaxLayerParamsObj
Hom := sorry
}
/--
error: stuck at solving universe constraint
max (_+1) (_+1) =?= max (_+1) (_+1)
while trying to unify
CatIsh.Obj.{max (max (_ + 1) (_ + 1)) _ _, max ((max (_ + 1) (_ + 1)) + 1) ((max _ _) + 1)}
Catish.{max (_ + 1) (_ + 1), max _ _} : Type (max ((max (_ + 1) (_ + 1)) + 1) ((max _ _) + 1))
with
CatIsh.{max _ _, max (_ + 1) (_ + 1)} : Type (max ((max _ _) + 1) ((max (_ + 1) (_ + 1)) + 1))
---
error: failed to solve universe constraint
max (_+1) (_+1) =?= max (_+1) (_+1)
while trying to unify
Catish.Obj : Type (max ((max (u_1 + 1) (u_2 + 1)) + 1) ((max u_3 u_4) + 1))
with
CatIsh : Type (max ((max u_4 u_3) + 1) ((max (u_4 + 1) (u_3 + 1)) + 1))
-/
#guard_msgs in
def CtxSyntaxLayerTy := CtxSyntaxLayerParams ~> Catish

View File

@@ -1,207 +0,0 @@
section Mathlib.Logic.Function.Iterate
universe u v
variable {α : Type u}
/-- Iterate a function. -/
def Nat.iterate {α : Sort u} (op : α α) : Nat α α := sorry
notation:max f "^["n"]" => Nat.iterate f n
theorem Function.iterate_succ' (f : α α) (n : Nat) : f^[n.succ] = f f^[n] := sorry
end Mathlib.Logic.Function.Iterate
section Mathlib.Data.Quot
variable {α : Sort _}
noncomputable def Quot.out {r : α α Prop} (q : Quot r) : α := sorry
end Mathlib.Data.Quot
section Mathlib.Init.Order.Defs
universe u
variable {α : Type u}
section Preorder
class Preorder (α : Type u) extends LE α, LT α where
variable [Preorder α]
theorem lt_of_lt_of_le : {a b c : α}, a < b b c a < c := sorry
end Preorder
variable [LE α]
theorem le_total : a b : α, a b b a := sorry
end Mathlib.Init.Order.Defs
section Mathlib.Order.RelClasses
universe u
class IsWellOrder (α : Type u) (r : α α Prop) : Prop
end Mathlib.Order.RelClasses
section Mathlib.Order.SetNotation
universe u v
variable {α : Type u} {ι : Sort v}
class SupSet (α : Type _) where
def iSup [SupSet α] (s : ι α) : α := sorry
end Mathlib.Order.SetNotation
section Mathlib.SetTheory.Ordinal.Basic
noncomputable section
universe u v w
variable {α : Type u}
structure WellOrder : Type (u + 1) where
α : Type u
instance Ordinal.isEquivalent : Setoid WellOrder := sorry
def Ordinal : Type (u + 1) := Quotient Ordinal.isEquivalent
instance (o : Ordinal) : LT o.out.α := sorry
namespace Ordinal
def typein (r : α α Prop) [IsWellOrder α r] (a : α) : Ordinal := sorry
instance partialOrder : Preorder Ordinal := sorry
theorem typein_lt_self {o : Ordinal} (i : o.out.α) :
@typein _ (· < ·) sorry i < o := sorry
instance : SupSet Ordinal := sorry
end Ordinal
end
end Mathlib.SetTheory.Ordinal.Basic
section Mathlib.SetTheory.Ordinal.Arithmetic
noncomputable section
universe u v w
namespace Ordinal
def sup {ι : Type u} (f : ι Ordinal.{max u v}) : Ordinal.{max u v} :=
iSup f
def lsub {ι} (f : ι Ordinal) : Ordinal :=
sup f
def blsub₂ (o₁ o₂ : Ordinal) (op : {a : Ordinal} (a < o₁) {b : Ordinal} (b < o₂) Ordinal) :
Ordinal :=
lsub (fun x : o₁.out.α × o₂.out.α => op (typein_lt_self x.1) (typein_lt_self x.2))
theorem lt_blsub₂ {o₁ o₂ : Ordinal}
(op : {a : Ordinal} (a < o₁) {b : Ordinal} (b < o₂) Ordinal) {a b : Ordinal}
(ha : a < o₁) (hb : b < o₂) : op ha hb < blsub₂ o₁ o₂ op := sorry
end Ordinal
end
end Mathlib.SetTheory.Ordinal.Arithmetic
section Mathlib.SetTheory.Ordinal.FixedPoint
noncomputable section
universe u v
namespace Ordinal
section
variable {ι : Type u} {f : ι Ordinal.{max u v} Ordinal.{max u v}}
def nfpFamily (f : ι Ordinal Ordinal) (a : Ordinal) : Ordinal :=
sup (List.foldr f a)
end
section
variable {f : Ordinal.{u} Ordinal.{u}}
def nfp (f : Ordinal Ordinal) : Ordinal Ordinal :=
nfpFamily fun _ : Unit => f
theorem lt_nfp {a b} : a < nfp f b n, a < f^[n] b := sorry
end
end Ordinal
end
end Mathlib.SetTheory.Ordinal.FixedPoint
section Mathlib.SetTheory.Ordinal.Principal
universe u v w
namespace Ordinal
def Principal (op : Ordinal Ordinal Ordinal) (o : Ordinal) : Prop :=
a b, a < o b < o op a b < o
theorem principal_nfp_blsub₂ (op : Ordinal Ordinal Ordinal) (o : Ordinal) :
Principal op (nfp (fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b)) o) :=
fun a b ha hb => by
rw [lt_nfp] at *
rcases ha with m, hm
rcases hb with n, hn
rcases le_total
((fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b))^[m] o)
((fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b))^[n] o) with h | h
· refine n+1, ?_
rw [Function.iterate_succ']
-- after https://github.com/leanprover/lean4/pull/3965 this requires `lt_blsub₂.{u}` or we get
-- `stuck at solving universe constraint max u ?v =?= u`
-- Note that there are two solutions: 0 and u. Both of them work.
-- However, when `Meta.Config.univApprox := true`, we solve using `?v := u`
exact lt_blsub₂ (@fun a _ b _ => op a b) (lt_of_lt_of_le hm h) hn
· sorry
-- Trying again with 0
theorem principal_nfp_blsub₂' (op : Ordinal Ordinal Ordinal) (o : Ordinal) :
Principal op (nfp (fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b)) o) :=
fun a b ha hb => by
rw [lt_nfp] at *
rcases ha with m, hm
rcases hb with n, hn
rcases le_total
((fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b))^[m] o)
((fun o' => blsub₂.{u, u, u} o' o' (@fun a _ b _ => op a b))^[n] o) with h | h
· refine n+1, ?_
rw [Function.iterate_succ']
-- universe 0 also works here
exact lt_blsub₂.{0} (@fun a _ b _ => op a b) (lt_of_lt_of_le hm h) hn
· sorry
end Ordinal
end Mathlib.SetTheory.Ordinal.Principal

View File

@@ -1,98 +0,0 @@
section Mathlib.Init.Order.Defs
universe u
variable {α : Type u}
class PartialOrder (α : Type u) extends LE α, LT α where
theorem le_antisymm [PartialOrder α] : {a b : α}, a b b a a = b := sorry
end Mathlib.Init.Order.Defs
section Mathlib.Init.Data.Nat.Lemmas
namespace Nat
instance : PartialOrder Nat where
le := Nat.le
lt := Nat.lt
section Find
variable {p : Nat Prop}
private def lbp (m n : Nat) : Prop :=
m = n + 1 k n, ¬p k
variable [DecidablePred p] (H : n, p n)
private def wf_lbp {p : Nat Prop} (H : n, p n) : WellFounded (@lbp p) := sorry
protected noncomputable def findX : { n // p n m < n, ¬p m } :=
@WellFounded.fix _ (fun k => ( n < k, ¬p n) { n // p n m < n, ¬p m }) lbp (wf_lbp H)
sorry 0 sorry
protected noncomputable def find {p : Nat Prop} [DecidablePred p] (H : n, p n) : Nat :=
(Nat.findX H).1
protected theorem find_spec : p (Nat.find H) := sorry
protected theorem find_min' {m : Nat} (h : p m) : Nat.find H m := sorry
end Find
end Nat
end Mathlib.Init.Data.Nat.Lemmas
section Mathlib.Logic.Basic
theorem Exists.fst {b : Prop} {p : b Prop} : Exists p b
| h, _ => h
end Mathlib.Logic.Basic
section Mathlib.Order.Basic
open Function
def PartialOrder.lift {α β} [PartialOrder β] (f : α β) : PartialOrder α where
le x y := f x f y
lt x y := f x < f y
end Mathlib.Order.Basic
section Mathlib.Data.Fin.Basic
instance {n : Nat} : PartialOrder (Fin n) :=
PartialOrder.lift Fin.val
end Mathlib.Data.Fin.Basic
section Mathlib.Data.Fin.Tuple.Basic
universe u v
namespace Fin
variable {n : Nat}
def find : {n : Nat} (p : Fin n Prop) [DecidablePred p], Option (Fin n)
| 0, _p, _ => none
| n + 1, p, _ => by
exact
Option.casesOn (@find n (fun i p (i.castLT sorry)) _)
(if _ : p (Fin.last n) then some (Fin.last n) else none) fun i
some (i.castLT sorry)
theorem nat_find_mem_find {p : Fin n Prop} [DecidablePred p]
(h : i, hin : i < n, p i, hin) :
(Nat.find h, (Nat.find_spec h).fst : Fin n) find p := by
rcases hf : find p with f | f
· sorry
· exact Option.some_inj.2 (le_antisymm sorry (Nat.find_min' _ f.2, sorry))
end Fin
end Mathlib.Data.Fin.Tuple.Basic

View File

@@ -1,43 +0,0 @@
namespace Ex1
class A where
class B (n : Nat) where
class C where
instance test [B 10000] [C] : A where
instance Bsucc {n : Nat} [B n] : B n.succ where
instance instB0 : B 0 where
instance instB10000 : B 10000 where
/--
error: failed to synthesize
A
-/
#guard_msgs in
#synth A -- should fail quickly
end Ex1
namespace Ex2
class A where
class B (n : Nat) where
class C where
instance test' [B 10] : A where
instance test [B 0] [C] : A where
instance foo {n : Nat} [B n.succ] : B n where
instance instB (n : Nat) : B n where
/--
info: test'
-/
#guard_msgs in
#synth A
end Ex2

View File

@@ -1,12 +0,0 @@
set_option pp.mvars false
/--
error: failed to solve universe constraint
u =?= max 1 _
while trying to unify
Sort u : Type u
with
Type : Type 1
-/
#guard_msgs in
def A : Sort u := { s : Prop // _ }

View File

@@ -1,3 +1,65 @@
open Std
instance : Associative (α := Nat) HAdd.hAdd := Nat.add_assoc
instance : Commutative (α := Nat) HAdd.hAdd := Nat.add_comm
instance : LawfulCommIdentity HAdd.hAdd 0 where right_id := Nat.add_zero
instance : Associative (α := Nat) HMul.hMul := Nat.mul_assoc
instance : Commutative (α := Nat) HMul.hMul := Nat.mul_comm
instance : LawfulCommIdentity HMul.hMul 1 where right_id := Nat.mul_one
@[simp] theorem succ_le_succ_iff {x y : Nat} : x.succ y.succ x y :=
Nat.le_of_succ_le_succ, Nat.succ_le_succ
@[simp] theorem add_le_add_right_iff {x y z : Nat} : x + z y + z x y := by
induction z <;> simp_all [ Nat.add_assoc]
set_option linter.unusedVariables false in
theorem le_ext : {x y : Nat} (h : z, z x z y), x = y
| 0, 0, _ => rfl
| x+1, y+1, h => congrArg (· + 1) <| le_ext fun z => have := h (z + 1); by simp at this; assumption
| 0, y+1, h => have := h 1; by clear h; simp_all
| x+1, 0, h => have := h 1; by simp at this
theorem le_or_le : (a b : Nat), a b b a
| x+1, y+1 => by simp [le_or_le x y]
| 0, 0 | x+1, 0 | 0, y+1 => by simp
theorem le_of_not_le {a b : Nat} (h : ¬ a b) : b a :=
match le_or_le a b with | .inl ab => (h ab).rec | .inr ba => ba
@[simp] theorem le_max_iff {x y z : Nat} : x max y z x y x z := by
simp only [Nat.max_def]
split
· exact Iff.intro .inr fun | .inl xy => Nat.le_trans _ _ | .inr xz => _
· exact Iff.intro .inl fun | .inl xy => _ | .inr xz => Nat.le_trans _ (le_of_not_le _)
theorem max_assoc (n m k : Nat) : max (max n m) k = max n (max m k) :=
le_ext (by simp [or_assoc])
theorem max_comm (n m : Nat) : max n m = max m n :=
le_ext (by simp [or_comm])
theorem max_idem (n : Nat) : max n n = n := le_ext (by simp)
instance : Associative (α := Nat) max := max_assoc
instance : Commutative (α := Nat) max := max_comm
instance : IdempotentOp (α := Nat) max := max_idem
instance : LawfulCommIdentity max 0 where
right_id := Nat.max_zero
instance : Associative And := λ _p _q _r => propext λ hp, hq, hr => hp, hq, hr, λ hp, hq, hr => hp, hq, hr
instance : Commutative And := λ _p _q => propext λ hp, hq => hq, hp, λ hq, hp => hp, hq
instance : IdempotentOp And := λ _p => propext λ hp, _ => hp, λ hp => hp, hp
instance : LawfulCommIdentity And True where
right_id _p := propext λ hp, _ => hp, λ hp => hp, True.intro
instance : Associative Or := by simp [or_assoc]
instance : Commutative Or := λ_p _q => propext λ hpq => hpq.elim Or.inr Or.inl, λ hqp => hqp.elim Or.inr Or.inl
instance : IdempotentOp Or := λ_p => propext λ hp => hp.elim id id, Or.inl
instance : LawfulCommIdentity Or False where
right_id _p := propext λ hpf => hpf.elim id False.elim, Or.inl
example (x y z : Nat) : x + y + 0 + z = z + (x + y) := by ac_rfl
example (x y z : Nat) : (x + y) * (0 + z) = (x + y) * z:= by ac_rfl
@@ -34,5 +96,3 @@ example (p q : Prop) : (p p q ∧ True) = (q p) := by
-- Repro: missing withContext
example : x : Nat, x = x := by intro x; ac_rfl
example : [1, 2] ++ ([] ++ [2+4, 8] ++ [4]) = [1, 2] ++ [4+2, 8] ++ [4] := by ac_rfl

View File

@@ -1,4 +1,3 @@
import Lean.Elab.BuiltinNotation
/-!
# Testing `pp.mvars`
-/
@@ -10,12 +9,6 @@ Default values
/-- info: ?a : Nat -/
#guard_msgs in #check (?a : Nat)
/-- info: ⊢ Sort ?u.1 -/
#guard_msgs (info, drop all) in
example : (by_elab do return .sort (.mvar (.mk (.num `_uniq 1)))) := by
trace_state
sorry
/-!
Turning off `pp.mvars`
-/
@@ -28,18 +21,6 @@ set_option pp.mvars false
/-- info: ?_ : Nat -/
#guard_msgs in #check (_ : Nat)
/-- info: ⊢ Sort _ -/
#guard_msgs (info, drop all) in
example : (by_elab do return .sort (.mvar (.mk (.num `_uniq 1)))) := by
trace_state
sorry
/-- info: ⊢ Type _ -/
#guard_msgs (info, drop all) in
example : Type _ := by
trace_state
sorry
end
/-!

View File

@@ -1,20 +0,0 @@
universe u v
-- This is a mock-up of the `HasLimitsOfSize` typeclass in mathlib4.
class HLOS.{a,b} (C : Type b) where
P : Type a
-- We only have an instance when there is a "universe inequality".
instance HLOS_max : HLOS.{a} (Type max a b) := sorry
-- In mathlib4 we currently make use of the following workaround:
abbrev TypeMax := Type max u v
instance (priority := high) HLOS_max' : HLOS.{a} (TypeMax.{a, b}) := sorry
example : HLOS.{a} (TypeMax.{a, b}) := HLOS_max'.{a} -- Success
example : HLOS.{a} (TypeMax.{a, b}) := inferInstance -- Success
-- We solve the following examples using approximations
example : Type max v u = TypeMax.{v} := rfl -- Previously failed with: `max u v =?= max v ?u`
example : Type max v u = TypeMax.{u} := rfl -- Previously failed with: `max u v =?= max u ?u`

View File

@@ -1,6 +1,7 @@
import Lean.Util.TestExtern
deriving instance DecidableEq for ByteArray
instance : BEq ByteArray where
beq x y := x.data == y.data
test_extern String.toUTF8 ""
test_extern String.toUTF8 "\x00"

View File

@@ -1,16 +1,10 @@
structure Foo.{v, u_1} : {α : Sort u_1} → (α → Type v) → Sort (max u_1 (v + 1))
inductive Foo.{v, u_1} : {α : Sort u_1} → (α → Type v) → Sort (max u_1 (v + 1))
number of parameters: 2
constructor:
constructors:
Foo.mk : {α : Sort u_1} → {β : α → Type v} → (a : α) → β a → Foo β
fields:
a : α
b : β self.a
structAutoBound.lean:9:15-9:16: error: a universe level named 'u' has already been declared
structure Boo.{u, v} : Type u → Type v → Type (max u v)
inductive Boo.{u, v} : Type u → Type v → Type (max u v)
number of parameters: 2
constructor:
constructors:
Boo.mk : {α : Type u} → {β : Type v} → α → β → Boo α β
fields:
a : α
b : β
structAutoBound.lean:18:0-20:7: error: unused universe parameter 'w'

View File

@@ -1,15 +1,9 @@
import Lean.Util.TestExtern
deriving instance DecidableEq for ByteArray
instance : BEq ByteArray where
beq x y := x.data == y.data
test_extern Nat.add 12 37
test_extern 4 + 5
test_extern ByteArray.copySlice #[1,2,3] 1 #[4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 0 6
def f := 3
@[implemented_by f]
def g := 4
test_extern g

View File

@@ -1,3 +1 @@
test_extern.lean:6:0-6:17: error: test_extern: HAdd.hAdd does not have an @[extern] attribute or @[implemented_by] attribute
test_extern.lean:15:0-15:13: error: native implementation did not agree with reference implementation!
Compare the outputs of: #eval g and #eval 4
test_extern.lean:7:0-7:17: error: test_extern: HAdd.hAdd does not have an @[extern] attribute