Skip to content

feat: implementation of @[use_set_notation]#37347

Open
JovanGerb wants to merge 1 commit intoleanprover-community:masterfrom
JovanGerb:Jovan-subset-le-impl
Open

feat: implementation of @[use_set_notation]#37347
JovanGerb wants to merge 1 commit intoleanprover-community:masterfrom
JovanGerb:Jovan-subset-le-impl

Conversation

@JovanGerb
Copy link
Copy Markdown
Contributor

This PR is the implementation part of #32983, without using the feature yet.


Open in Gitpod

@github-actions
Copy link
Copy Markdown

PR summary e885514426

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference
Mathlib.Tactic 1

Declarations diff

+ delabGe
+ delabGt
+ delabLe
+ delabLt
+ elabSsubsetStx'
+ elabSsupsetStx'
+ elabSubsetLike
+ elabSubsetStx'
+ elabSupsetStx'
+ useSetNotationFor

You can run this locally as follows
## summary with just the declaration names:
./scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
./scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh contains some details about this script.


No changes to technical debt.

You can run this locally as

./scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@github-actions github-actions bot added the t-meta Tactics, attributes or user commands label Mar 29, 2026
Copy link
Copy Markdown
Contributor

@thorimur thorimur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! :) My comments here are mostly administrative or minor; the content of the metaprogramming looks solid. I've gone through carefully and ensured all names and syntax precedences line up, and everything checks out. :)

Also, could you please copy-paste most of the PR description from #32983 into this PR? I think it would be helpful to have it available in the git blame for this file.


/-- Delaborate `x ≤ y` into `x ⊆ y` if the type is tagged with `@[use_set_notation]`. -/
@[app_delab LE.le]
def delabLe : Delab := whenNotPPOption getPPExplicit <| whenPPOption getPPNotation do
Copy link
Copy Markdown
Contributor

@thorimur thorimur Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably namespace these under some appropriate SetNotation-related namespace, but see the file-level suggestion on naming.

let x ← withNaryArg 2 delab
let y ← withNaryArg 3 delab
let stx ← `($x ⊆ $y)
annotateGoToDef stx `Mathlib.Meta.delabLe
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Here and below, to make this stable under refactors)

Suggested change
annotateGoToDef stx `Mathlib.Meta.delabLe
annotateGoToDef stx decl_name%


/-! ## Elaboration -/

/-- This relation is an implementation detail of the `⊆` elatorator. -/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
/-- This relation is an implementation detail of the `⊆` elatorator. -/
/-- This relation is an implementation detail of the `⊆` elaborator. -/

/-- Elaborate a notation like `a ⊆ b` by elaborating `a` and `b`, and then deciding
based on their type whether to return `a ⊆ b` or `a ≤ b`.
Use `a ≤ b` whenever `useSetNotationFor` returns true for the type.
If the type is not known, elaboration of this term is postponed. -/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If the type is not known, elaboration of this term is postponed. -/
If the type is not known, elaboration of this term is postponed.
We assume that `le` and `sub` are names for declarations of exactly the form
`decl.{u} {α : Type u} [Cls.{u} α] (a b : α) : Prop`, and that likewise `leCls` and `subCls` are
names for declarations of exactly the form `Cls.{u} (α : Type u) : Type u`. -/

Copy link
Copy Markdown
Contributor

@thorimur thorimur Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about calling this file SetlikeOrderNotation, and renaming the definitions in it accordingly? E.g. @[setlike_order_notation].

I know there are plans to expand this functionality; do they all have to do with using setlike notation for order-related operations, or do some have to do with {}, {|}, complementation, and ? That's the ambiguity in the phrase "set notation" I'm trying to eliminate here; SetNotation is by itself a bit broad!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sound good to me, indeed it seems that all set notations involved are about order. (Note that for complements, we already use the same constant for sets and boolean algebras)

Comment on lines +118 to +123
if ← useSetNotationFor α then
let inst ← mkInstMVar <| .app (.const leCls f.constLevels!) α
return mkApp4 (.const le f.constLevels!) α inst x y
else
let inst ← mkInstMVar <| .app (.const subCls f.constLevels!) α
return mkApp4 (.const sub f.constLevels!) α inst x y
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I wonder if it's worth adding hover info to the subset token specifically to show which relation it wound up elaborating to. 🤔 However, command-clicking brings up the instances, so I think this is likely fine as-is, and my experiments in adding hover info to the token actually interfere with that command-clicking on the broader term. Let me know if you have thoughts here, though.


/-- Elaborator for `x ⊂ y` notation. -/
@[term_elab ssubsetStx']
def elabSsubsetStx' : TermElab
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Following HasSSubset)

Suggested change
def elabSsubsetStx' : TermElab
def elabSSubsetStx' : TermElab


/-- Elaborator for `x ⊃ y` notation. -/
@[term_elab ssupsetStx']
def elabSsupsetStx' : TermElab
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Following HasSSubset)

Suggested change
def elabSsupsetStx' : TermElab
def elabSSupsetStx' : TermElab

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please

  1. Move this file out of Delab, and name it analogously to the source file it's testing
  2. Include tests for the elaborating/delaborating the other 3 relations? It's alright if they're minimal (or combined in a single statement!), I just want to make sure we test them since I anticipate they won't be used very much (and so it might not be obvious if they break).


/-- Whether to use set notation for the given type or not. -/
def useSetNotationFor (type : Expr) : MetaM Bool := do
let .const n _ := (← whnfR type).getAppFn | return false
Copy link
Copy Markdown
Contributor

@thorimur thorimur Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is probably appropriate, especially given that we might use it after synthesizeSyntheticMVars* later on:

Suggested change
let .const n _ := (← whnfR type).getAppFn | return false
let .const n _ := (← whnfR <| ← instantiateMVars type).getAppFn | return false

@thorimur
Copy link
Copy Markdown
Contributor

thorimur commented Apr 3, 2026

Here's a half-thought re: the simp_rw ... _ ≤ _ issue that comes up in the application PR. Currently if α contains a metavariable we just default to using Subset. Could we instead allow the class to be solved by unification in that case, somehow? (This might require some thought, and intuition says delayed-assigned mvars might be involved. This option might wind up being too fragile once explored, too, if it even works.)

@JovanGerb
Copy link
Copy Markdown
Contributor Author

Note that these issues arise in simp_rw and not in rw. This is because simp_rw has to fully elaborate the term beforehand.

Another solution would be to default to LE.le when the type is a metavariable. I think it could work, but is not a very principled solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

t-meta Tactics, attributes or user commands

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants