@@ -16,6 +16,7 @@ User-defined rewrite rules
16
16
This section describes the extension of Rocq's reduction mechanisms with user-defined rewrite rules,
17
17
as a means to extend definitional equality. It should not be confused with the :ref: `rewrite tactic <rewritingexpressions >`
18
18
or :ref: `setoid rewriting <generalizedrewriting >` which operate on propositional equality and other relations which are defined in Rocq.
19
+ This extension is described in :cite: `Rew24 `, following the theory developed in :cite: `TotR21 `.
19
20
20
21
Rewrite rules need to be enabled by passing the option ``-allow-rewrite-rules ``
21
22
to the Rocq program.
@@ -49,7 +50,7 @@ Rewrite rules
49
50
.. insertprodn rewrite_rule rewrite_rule
50
51
51
52
.. prodn ::
52
- rewrite_rule ::= {? @univ_decl %|- } @rw_pattern => @term
53
+ rewrite_rule ::= @rw_pattern => @term
53
54
54
55
Declares a named block of rewrite rules. The name is declared in the same namespace as constants and inductives.
55
56
@@ -89,7 +90,7 @@ and eliminations (non-base-case constructions for :n:`@rw_pattern`):
89
90
| match @rw_pattern {? as @name } {? in @pattern } {? return @rw_pattern_arg } with {? | } {*| @pattern => @rw_pattern_arg } end
90
91
rw_head_pattern ::= @ident
91
92
| @qualid {? @univ_annot }
92
- | fun {+ ({+ @name } {? : @rw_pattern_arg}) } => @rw_pattern_arg
93
+ | fun {+ ({+ @name } {? : @rw_pattern_arg}) } => @rw_pattern
93
94
| forall {+ ({+ @name } {? : @rw_pattern_arg}) }, @rw_pattern_arg
94
95
rw_pattern_arg ::= ?@name
95
96
| _
@@ -112,7 +113,7 @@ Note that if in the replacement, the context was extended with a variable bearin
112
113
this explicit substitution is inferred automatically (like for existential variable instantiations).
113
114
114
115
115
- .. rocqtop :: all warn
116
+ .. rocqtop :: reset all warn
116
117
117
118
Symbol raise : forall (A : Type), A.
118
119
Rewrite Rule raise_nat :=
@@ -128,45 +129,46 @@ Universe polymorphic rules
128
129
--------------------------
129
130
130
131
Rewrite rules support universe and sort quality polymorphism.
131
- Universe levels and sort quality variables must be declared with the notation :n: `@{q1 q2;u1 u2+|+} `
132
- (the same notation as universe instance declarations);
133
- each variable must appear exactly once in the pattern.
134
- If any universe level isn't bound in the rule,
135
- as is often the case with the level of a pattern variable when it is a type,
136
- you need to make the universe instance extensible (with the final +).
137
- Universe level constraints, as inferred from the pattern, must imply those given,
138
- which in turn must imply the constraints needed for the replacement.
139
- You can make the declared constraints extensible
140
- so all inferred constraints from the left-hand side are used for the replacement.
132
+ As with pattern variables, universe levels and sort quality variables
133
+ must appear linearly (not more than once each) in the pattern.
134
+ Sort quality variables which appear only in :term: `relevance marks <relevance mark> ` in the replacement
135
+ will be detected if they also appear in a relevance mark in the pattern, such that
136
+ they can be substituted when the rule is applied (otherwise you will get an undeclared sort quality error).
141
137
142
138
.. rocqtop :: reset all warn
143
139
144
140
#[universes(polymorphic)] Symbol raise@{q;u} : forall (A : Type@{q;u}), A.
145
141
Rewrite Rule raise_nat :=
146
- @{q;u+|+} | - raise@{q;u} (forall (x : ?A), ?P) => fun (x : ?A) => raise@{q;u} ?P.
142
+ raise@{q;u} (forall (x : ?A), ?P) => fun (x : ?A) => raise@{q;u} ?P.
147
143
148
144
Rewrite rules, type preservation, confluence and termination
149
145
------------------------------------------------------------
150
146
151
- Currently, rewrite rules do not ensure that types must be preserved.
152
- There is a superficial check that the replacement needs to be typed
153
- against the type inferred for the pattern (for an unclear definition of type of a pattern),
154
- but it is known to be incomplete and only emits a warning if failed.
155
- This then means that reductions using rewrite rules have no reason to preserve well-typedness at all.
156
- The responsibility of ensuring type preservation falls on the user entirely.
147
+ The rewrite rules are typechecked so that all substituted replacements
148
+ have the type that the term being rewritten has (as described in :cite: `Rew24 `).
149
+ This means that the check is more stringent than ensuring the two sides have a shared type.
150
+ This also means that the pattern is typechecked differently from regular terms,
151
+ with an especially more restricted unification engine,
152
+ which leads to the typechecker refusing rules that do respect the criterion.
153
+ For this reason, the typechecker only emits warnings when it fails to verify the rule,
154
+ letting the user take responsibility over the correctness of the rule.
157
155
158
- Similarly, neither confluence nor termination are checked by the compiler.
156
+ Rocq currently doesn't check for confluence of the rewrite rules,
157
+ even though it is required for the invariants that the typechecker uses.
158
+ There are plans to add a check using the triangle criterion described in :cite: `TotR21 `.
159
159
160
- There are future plans to add a check on confluence using the triangle criterion :cite: `TotR21 `
161
- and a more complete check on type preservation.
160
+ Rocq doesn't check for termination of the rewrite rules either.
161
+ Indeed, non-terminating rules are generally fine except for one thing:
162
+ the typechecker itself might not always terminate anymore.
163
+ Unlike the previous two properties, non-termination cannot cause crashes or anomalies.
162
164
163
165
Compatibility with the eta laws
164
166
-------------------------------
165
167
166
168
Currently, pattern matching against rewrite rules pattern cannot do eta-expansion or contraction,
167
169
which means that it cannot properly match against terms of functional types or primitive records.
168
- As with type preservation, a check is done to test whether this may happen,
169
- but it is not complete (false positives) and thus only emits a warning if failed .
170
+ Rocq checks whether this may happen, but the check is imperfect (it reports false positives).
171
+ Therefore, the check fails by only emitting a warning, similar to the check for type preservation .
170
172
171
173
Level of support
172
174
----------------
0 commit comments