Started writing on phantom types as witnesses for invariants

This commit is contained in:
Georges Dupéron 2017-01-01 21:03:03 +01:00
parent 48bc1ed2f9
commit e951c7b26f
6 changed files with 125 additions and 38 deletions

View File

@ -1,14 +1,14 @@
<!-- Tufts VUE 3.3.0 concept-map (Graph-notes-copy2.vue) 2016-12-29 -->
<!-- Tufts VUE 3.3.0 concept-map (Graph-notes-copy2.vue) 2016-12-30 -->
<!-- Tufts VUE: http://vue.tufts.edu/ -->
<!-- Do Not Remove: VUE mapping @version(1.1) jar:file:/nix/store/z92y35qgs6g3cvvh0i4f14mg5n47zvvi-vue-3.3.0/share/vue/vue.jar!/tufts/vue/resources/lw_mapping_1_1.xml -->
<!-- Do Not Remove: Saved date Thu Dec 29 22:27:01 CET 2016 by georges on platform Linux 4.4.38 in JVM 1.8.0_122-04 -->
<!-- Do Not Remove: Saved date Fri Dec 30 22:07:05 CET 2016 by georges on platform Linux 4.4.38 in JVM 1.8.0_122-04 -->
<!-- Do Not Remove: Saving version @(#)VUE: built October 8 2015 at 1724 by tomadm on Linux 2.6.32-504.23.4.el6.x86_64 i386 JVM 1.7.0_21-b11(bits=32) -->
<?xml version="1.0" encoding="US-ASCII"?>
<LW-MAP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="none" ID="0"
label="Graph-notes-copy2.vue" created="1479309847604" x="0.0"
y="0.0" width="1.4E-45" height="1.4E-45" strokeWidth="0.0" autoSized="false">
<resource referenceCreated="1483046821901" size="202869"
<resource referenceCreated="1483132025205" size="204773"
spec="/home/georges/phc/racket-packages/phc-graph/Graph-notes-copy2.vue"
type="1" xsi:type="URLResource">
<title>Graph-notes-copy2.vue</title>
@ -1046,8 +1046,8 @@
<shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/>
</child>
<child ID="215" label="Structural invariant" layerID="1"
created="1479312437302" x="-526.0517" y="296.2496" width="162.0"
height="86.75" strokeWidth="1.0" autoSized="true" xsi:type="node">
created="1479312437302" x="-526.0517" y="273.2496" width="162.0"
height="107.0" strokeWidth="1.0" autoSized="true" xsi:type="node">
<fillColor>#F2AE45</fillColor>
<strokeColor>#000000</strokeColor>
<textColor>#000000</textColor>
@ -1083,6 +1083,16 @@
<URIString>http://vue.tufts.edu/rdf/resource/6e13f9e943a6be970d2ffe25a12d6061</URIString>
<shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/>
</child>
<child ID="537" label="a.c = count(a.b)" created="1483131981450"
x="34.0" y="83.75" width="118.0" height="23.0"
strokeWidth="1.0" autoSized="true" xsi:type="node">
<fillColor>#F2AE45</fillColor>
<strokeColor>#776D6D</strokeColor>
<textColor>#000000</textColor>
<font>SansSerif-plain-12</font>
<URIString>http://vue.tufts.edu/rdf/resource/518eb6ce534430712734d86a5ed52578</URIString>
<shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/>
</child>
<shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/>
</child>
<child ID="216" label="Fill in auto fields" layerID="1"
@ -1516,16 +1526,16 @@
<ID1 xsi:type="node">216</ID1>
<ID2 xsi:type="node">269</ID2>
</child>
<child ID="273" layerID="1" created="1479315784203" x="-550.9628"
y="268.6448" width="41.538574" height="28.104797"
<child ID="273" layerID="1" created="1479315784203" x="-547.75836"
y="268.64478" width="22.596802" height="13.172211"
strokeWidth="1.0" autoSized="false" controlCount="0"
arrowState="2" xsi:type="link">
<strokeColor>#000000</strokeColor>
<textColor>#404040</textColor>
<font>SansSerif-plain-11</font>
<URIString>http://vue.tufts.edu/rdf/resource/6e18c7e043a6be970d2ffe25213bebda</URIString>
<point1 x="-550.4628" y="269.1448"/>
<point2 x="-509.92426" y="296.2496"/>
<point1 x="-547.25836" y="269.1448"/>
<point2 x="-525.66156" y="281.31702"/>
<ID1 xsi:type="node">269</ID1>
<ID2 xsi:type="node">215</ID2>
</child>
@ -1614,16 +1624,16 @@
<ID1 xsi:type="node">278</ID1>
<ID2 xsi:type="node">264</ID2>
</child>
<child ID="286" layerID="1" created="1479316060242" x="-444.86713"
y="59.84375" width="4.7231445" height="236.90625"
<child ID="286" layerID="1" created="1479316060242" x="-444.6682"
y="59.84375" width="4.5158997" height="213.90625"
strokeWidth="1.0" autoSized="false" controlCount="0"
arrowState="2" xsi:type="link">
<strokeColor>#000000</strokeColor>
<textColor>#404040</textColor>
<font>SansSerif-plain-11</font>
<URIString>http://vue.tufts.edu/rdf/resource/6e1c69c643a6be970d2ffe2578e91de4</URIString>
<point1 x="-440.64398" y="60.34375"/>
<point2 x="-444.36713" y="296.25"/>
<point1 x="-440.65234" y="60.34375"/>
<point2 x="-444.16824" y="273.25"/>
<ID1 xsi:type="node">280</ID1>
<ID2 xsi:type="node">215</ID2>
</child>
@ -2015,10 +2025,9 @@
<ID2 xsi:type="node">335</ID2>
</child>
<child ID="342"
label="Define a wrapper, which may alter the input and input types, and the output and output types"
label="Define a wrapper, which may alter the input value and input types, and the output value and output types"
layerID="1" created="1479326681064" x="347.9707" y="1262.2448"
width="683.25" height="202.25" strokeWidth="1.0"
autoSized="true" xsi:type="node">
width="726.0" height="202.25" strokeWidth="1.0" autoSized="true" xsi:type="node">
<fillColor>#F2AE45</fillColor>
<strokeColor>#776D6D</strokeColor>
<textColor>#000000</textColor>
@ -2130,15 +2139,15 @@
</child>
<shape arcwidth="20.0" archeight="20.0" xsi:type="roundRect"/>
</child>
<child ID="345" layerID="1" created="1479326900002" x="219.06221"
y="1077.2448" width="304.619" height="185.5" strokeWidth="1.0"
<child ID="345" layerID="1" created="1479326900002" x="219.88948"
y="1077.2448" width="317.8918" height="185.5" strokeWidth="1.0"
autoSized="false" controlCount="0" arrowState="2" xsi:type="link">
<strokeColor>#404040</strokeColor>
<textColor>#404040</textColor>
<font>SansSerif-plain-11</font>
<URIString>http://vue.tufts.edu/rdf/resource/6ec139aac0a80026616d92397220832f</URIString>
<point1 x="219.56223" y="1077.7448"/>
<point2 x="523.1812" y="1262.2448"/>
<point1 x="220.3895" y="1077.7448"/>
<point2 x="537.2813" y="1262.2448"/>
<ID1 xsi:type="node">293</ID1>
<ID2 xsi:type="node">342</ID2>
</child>
@ -3704,7 +3713,7 @@
<URIString>http://vue.tufts.edu/rdf/resource/6dbf6b15c0a80026548592b8d2f3fee2</URIString>
</layer>
<userZoom>1.0</userZoom>
<userOrigin x="-1573.3625" y="-374.75525"/>
<userOrigin x="-1829.3625" y="-403.75525"/>
<presentationBackground>#FFFFFF</presentationBackground>
<PathwayList currentPathway="0" revealerIndex="-1">
<pathway ID="0" label="Chemin sans nom" created="1479309847603"

View File

@ -11,7 +11,8 @@
"srfi-lite-lib"
"delay-pure"
"backport-template-pr1514"
"typed-map"))
"typed-map"
"scribble-lib"))
(define build-deps '("scribble-lib"
"racket-doc"
"remember"

View File

@ -1,15 +1,19 @@
#lang aful/unhygienic hyper-literate type-expander/lang
@title[#;#:style #;(with-html5 manual-doc-style)
#:tag "invariants-phantom"
#:tag-prefix "phc-graph/invariants-phantom"]{Tracking checked contracts
@require[scribble-math
scribble-enhanced/doc
"notations.rkt"]
@title[#:style (with-html5 manual-doc-style)
#:tag "inv-phantom"
#:tag-prefix "phc-graph/inv-phantom"]{Tracking checked contracts
via phantom types}
@(chunks-toc-prefix
'("(lib phc-graph/scribblings/phc-graph-implementation.scrbl)"
"phc-graph/invariants-phantom"))
"phc-graph/inv-phantom"))
@section{Overview}
@section{Introduction}
The cautious compiler writer will no doubt want to check that the graph used
to represent the program verifies some structural properties. For example, the
@ -18,6 +22,8 @@ property is that the @racket[in-method] field of an instruction points back to
the method containing it. We will use this second property as a running
example in this section.
@section{Implementation overview}
It is possible to express with Typed/Racket that a @racket[Method] should
contain a list of @racket[Instruction]s, and that @racket[Instruction]s should
point to a @racket[Method]@note{We are not concerned here about the ability to
@ -86,13 +92,80 @@ to wrap it in a struct type which is only accessible by the graph library:
(code:comment "provide only the type, not the constructor or accessor")
(provide Flag-Wrapper)]
@; size → use a dummy function which errors when called
@; (accepts an opaque token to prevent calling)
We would like to be able to indicate that a graph node has validated several
invariants. For that, we need a way to represent the type of a "set" of
invariant witnesses. We also want some subtyping relationship between the
sets: a set @${s₁} with more invariant witnesses should be a subtype of a
subset @${s₂ s₁}. We can order the invariant witnesses and use @racket[Rec]
to build the type of a list of invariant witnesses, where some may be missing:
@; Subtyping: multiple contracts with case→
@chunk[<invariant-set-as-List+Rec>
(define-type At-Least-InvB+InvD
(Rec R₁ (U (Pairof Any R₁)
(Pairof 'InvB (Rec R₂ (U (Pairof Any R₂)
(Pairof 'InvD (Listof Any))))))))]
@; Subtyping: when C1 ⇒ C2,
@; make the marker for C1 a subtype of the marker for C2
@chunk[<invariant-set-as-List+Rec-use>
(ann '(InvA InvB InvC InvD InvE) At-Least-InvB+InvD)
(ann '(InvB InvD) At-Least-InvB+InvD)
(code:comment "Rejected, because it lacks 'InvD")
(code:comment "(ann '(InvB InvC InvE) At-Least-InvB+InvD)")
(code:comment "The elements must be in the right order,")
(code:comment "this would be rejected by the typechecker:")
(code:comment "(ann '(InvD InvB) At-Least-InvB+InvD)")]
Another solution is to group the witnesses in an untagged union with
@racket[U], and place it in a contravariant position:
@chunk[<invariant-set-as-contravariant-U>
(define-type At-Least-InvB+InvD
( (U 'InvB 'InvD) Void))]
This solution also has the advantage that the size of the run-time witness is
constant, and does not depend on the number of checked contracts (unlike the
representation using a list). In practice the function should never be called.
It can however simply be implemented in a way which pleases the type checked
as a function accepting anything and returning void.
In addition to testifying that a graph node was checked against multiple,
separate contracts, there might be some contracts which check stronger
properties than others. A way to encode this relationship in the type system
is to have subtyping relationships between the contract witnesses, so that
@; TODO: get rid of the mathit
@${\mathit{P}(x) \mathit{P}(x) \mathit{Inv} @texsubtype \mathit{Inv}}:
@chunk[<invariant-contract-subtyping>
(struct InvWeak ())
(struct InvStrong InvWeak ())]
If the witnesses must appear in a contravariant position (when using
@racket[U] to group them), the relationship must be reversed:
@chunk[<invariant-contract-subtyping>
(struct InvStrongContra ())
(struct InvWeakContra InvStrongContra ())]
Alternatively, it is possible to use a second contravariant position to
reverse the subtyping relationship again:
@chunk[<invariant-contract-subtyping>
(struct InvWeak ())
(struct InvStrong InvWeak ())
(define InvWeakContra ( InvWeak Void))
(define InvStrongContra ( InvStrong Void))]
Finally, we note that the invariants should always be represented using a
particular struct type, instead of using a symbol, so that name clashes are
not a problem.
@section{Types for some graph contracts}
@chunk[<structural>
( [a : Nd] (get a f1 f2))
( [a : Nd] (get a f1 f2))
( [a : Nd] (get a f1 f2))
( [a : Nd] (get a (* f1 f2 f3 f4) (* f5 f6)))]
@chunk[<*>
(void)]

7
notations.rkt Normal file
View File

@ -0,0 +1,7 @@
#lang racket
(require scribble/base)
(provide texsubtype)
(define texsubtype "<:")

View File

@ -22,15 +22,13 @@
[struct struct-field ] )))]))
(gs bt-fields
257
16
(a b c)
[sab a b]
[sbc b c]
[sabc a b c])
;(define-type btac (bt-fields a c))
#|
(define-type btac (bt-fields a c))
(check-equal?:
(~> (ann (with-c (sab→tree 1 2) 'nine)
@ -78,5 +76,4 @@
(call-with-values
(tree→sbc (without-a (with-c (sab→tree 1 2) 3)))
list)
'(2 3))
|#
'(2 3))