OLD | NEW |
---|---|
1 \documentclass[fleqn, draft]{article} | 1 \documentclass[fleqn, draft]{article} |
2 \usepackage{proof, amsmath, amssymb, ifthen} | 2 \usepackage{proof, amsmath, amssymb, ifthen} |
3 \input{macros.tex} | 3 \input{macros.tex} |
4 | 4 |
5 % types | 5 % types |
6 \newcommand{\Arrow}[3][-]{#2 \overset{#1}{\rightarrow} #3} | 6 \newcommand{\Arrow}[3][-]{#2 \overset{#1}{\rightarrow} #3} |
7 \newcommand{\Bool}{\mathbf{bool}} | 7 \newcommand{\Bool}{\mathbf{bool}} |
8 \newcommand{\Bottom}{\mathbf{bottom}} | 8 \newcommand{\Bottom}{\mathbf{bottom}} |
9 \newcommand{\Dynamic}{\mathbf{dynamic}} | 9 \newcommand{\Dynamic}{\mathbf{dynamic}} |
10 \newcommand{\Null}{\mathbf{Null}} | 10 \newcommand{\Null}{\mathbf{Null}} |
11 \newcommand{\Num}{\mathbf{num}} | 11 \newcommand{\Num}{\mathbf{num}} |
12 \newcommand{\Object}{\mathbf{Object}} | 12 \newcommand{\Object}{\mathbf{Object}} |
13 \newcommand{\TApp}[2]{#1\mathrm{<}#2\mathrm{>}} | 13 \newcommand{\TApp}[2]{#1\mathrm{<}#2\mathrm{>}} |
14 \newcommand{\Type}{\mathbf{Type}} | 14 \newcommand{\Type}{\mathbf{Type}} |
15 \newcommand{\Weak}[1]{\mathbf{\{#1\}}} | |
16 \newcommand{\Sig}{\mathit{Sig}} | |
15 | 17 |
16 % expressions | 18 % expressions |
17 \newcommand{\eassign}[2]{#1 = #2} | 19 \newcommand{\eassign}[2]{#1 = #2} |
18 \newcommand{\eas}[2]{#1\ \mathbf{as}\ #2} | 20 \newcommand{\eas}[2]{#1\ \mathbf{as}\ #2} |
19 \newcommand{\echeck}[2]{\kwop{check}(#1, #2)} | 21 \newcommand{\echeck}[2]{\kwop{check}(#1, #2)} |
20 \newcommand{\ecall}[2]{#1(#2)} | 22 \newcommand{\ecall}[2]{#1(#2)} |
21 \newcommand{\edcall}[2]{\kwop{dcall}(#1, #2)} | 23 \newcommand{\edcall}[2]{\kwop{dcall}(#1, #2)} |
22 \newcommand{\edload}[2]{\kwop{dload}(#1, #2)} | 24 \newcommand{\edload}[2]{\kwop{dload}(#1, #2)} |
23 \newcommand{\eff}{\mathrm{ff}} | 25 \newcommand{\eff}{\mathrm{ff}} |
24 \newcommand{\eis}[2]{#1\ \mathbf{is}\ #2} | 26 \newcommand{\eis}[2]{#1\ \mathbf{is}\ #2} |
(...skipping 22 matching lines...) Expand all Loading... | |
47 \newcommand{\kwthen}{\kw{then}} | 49 \newcommand{\kwthen}{\kw{then}} |
48 \newcommand{\kwvar}{\kw{var}} | 50 \newcommand{\kwvar}{\kw{var}} |
49 | 51 |
50 % declarations | 52 % declarations |
51 \newcommand{\dclass}[3]{\kwclass\ #1\ \kwextends\ #2\ \{#3\}} | 53 \newcommand{\dclass}[3]{\kwclass\ #1\ \kwextends\ #2\ \{#3\}} |
52 \newcommand{\dfun}[4]{#2(#3):#1 = #4} | 54 \newcommand{\dfun}[4]{#2(#3):#1 = #4} |
53 \newcommand{\dvar}[2]{\kwvar\ #1\ =\ #2} | 55 \newcommand{\dvar}[2]{\kwvar\ #1\ =\ #2} |
54 | 56 |
55 | 57 |
56 \newcommand{\fieldDecl}[2]{\kwvar\ #1 : #2} | 58 \newcommand{\fieldDecl}[2]{\kwvar\ #1 : #2} |
57 \newcommand{\methodDecl}[2]{\kwfun\ #1 : #2} | 59 \newcommand{\methodDecl}[3]{\kwfun\ #1 : \iftrans{#2 \triangleleft} #3} |
58 | 60 |
59 % statements | 61 % statements |
60 \newcommand{\sifthenelse}[3]{\kwif\ (#1)\ \kwthen\ #2\ \kwelse\ #3} | 62 \newcommand{\sifthenelse}[3]{\kwif\ (#1)\ \kwthen\ #2\ \kwelse\ #3} |
61 \newcommand{\sreturn}[1]{\kwreturn\ #1} | 63 \newcommand{\sreturn}[1]{\kwreturn\ #1} |
62 | 64 |
63 % programs | 65 % programs |
64 \newcommand{\program}[2]{\kwlet\ #1\ \kwin\ #2} | 66 \newcommand{\program}[2]{\kwlet\ #1\ \kwin\ #2} |
65 | 67 |
66 % relational operators | 68 % relational operators |
67 \newcommand{\sub}{\mathbin{<:}} | 69 \newcommand{\sub}{\mathbin{<:}} |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 \newcommand{\axiom}[2][]{ | 104 \newcommand{\axiom}[2][]{ |
103 \[ | 105 \[ |
104 \axiomm[#1]{#2} | 106 \axiomm[#1]{#2} |
105 \] | 107 \] |
106 } | 108 } |
107 | 109 |
108 % judgements and relations | 110 % judgements and relations |
109 \newboolean{show_translation} | 111 \newboolean{show_translation} |
110 \setboolean{show_translation}{false} | 112 \setboolean{show_translation}{false} |
111 \newcommand{\iftrans}[1]{\ifthenelse{\boolean{show_translation}}{#1}{}} | 113 \newcommand{\iftrans}[1]{\ifthenelse{\boolean{show_translation}}{#1}{}} |
114 \newcommand{\ifnottrans}[1]{\ifthenelse{\boolean{show_translation}}{#1}} | |
112 | 115 |
113 \newcommand{\blockOk}[4]{#1 \vdash #2 \col #3\iftrans{\, \Uparrow\, #4}} | 116 \newcommand{\blockOk}[4]{#1 \vdash #2 \col #3\iftrans{\, \Uparrow\, #4}} |
114 \newcommand{\declOk}[5][]{#2 \vdash_{#1} #3 \, \Uparrow\, \iftrans{#4\, :\,} #5} | 117 \newcommand{\declOk}[5][]{#2 \vdash_{#1} #3 \, \Uparrow\, \iftrans{#4\, :\,} #5} |
115 \newcommand{\extends}[4][:]{#2[#3\ #1\ #4]} | 118 \newcommand{\extends}[4][:]{#2[#3\ #1\ #4]} |
116 \newcommand{\fieldLookup}[4]{#1 \vdash #2.#3\, \leadsto_f\, #4} | 119 \newcommand{\fieldLookup}[4]{#1 \vdash #2.#3\, \leadsto_f\, #4} |
117 \newcommand{\methodLookup}[4]{#1 \vdash #2.#3\, \leadsto_m\, #4} | 120 \newcommand{\methodLookup}[5]{#1 \vdash #2.#3\, \leadsto_m\, \iftrans{#4 \triang leleft} #5} |
121 \newcommand{\fieldAbsent}[3]{#1 \vdash #3 \notin #2} | |
122 \newcommand{\methodAbsent}[3]{#1 \vdash #3 \notin #2} | |
118 \newcommand{\hastype}[3]{#1 \vdash #2 \, : \, #3} | 123 \newcommand{\hastype}[3]{#1 \vdash #2 \, : \, #3} |
119 \newcommand{\stmtOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow \iftrans{#4\, :\,} #5 } | 124 \newcommand{\stmtOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow \iftrans{#4\, :\,} #5 } |
120 \newcommand{\subst}[2]{[#1/#2]} | 125 \newcommand{\subst}[2]{[#1/#2]} |
121 \newcommand{\subtypeOfOpt}[5][?]{#2 \vdash\ #3 \sub^{#1} #4\, \Uparrow\, #5} | 126 \newcommand{\subtypeOfOpt}[5][?]{#2 \vdash\ #3 \sub^{#1} #4\, \Uparrow\, #5} |
122 \newcommand{\subtypeOf}[4][]{#2 \vdash\ #3 \sub^{#1} #4} | 127 \newcommand{\subtypeOf}[4][]{#2 \vdash\ #3 \sub^{#1} #4} |
123 \newcommand{\yieldsOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow\, \iftrans{#4\, :\, } #5} | 128 \newcommand{\yieldsOk}[5]{#1 \vdash #2 \, : \, #3\, \Uparrow\, \iftrans{#4\, :\, } #5} |
129 \newcommand{\programOk}[3]{#1 \vdash #2\iftrans{\, \Uparrow\, #3}} | |
130 \newcommand{\ok}[2]{#1 \vdash #2\, \mbox{\textbf{ok}}} | |
131 \newcommand{\overrideOk}[4]{#1 \vdash #2\,\kwextends\, #3 \Leftarrow\, #4} | |
124 | 132 |
125 | 133 \newcommand{\down}[1]{\ensuremath{\downharpoonleft\!\!#1\!\!\downharpoonright}} |
134 \newcommand{\up}[1]{\ensuremath{\upharpoonleft\!\!#1\!\!\upharpoonright}} | |
135 \newcommand{\sigof}[1]{\mathit{sigof}(#1)} | |
126 \newcommand{\sstext}[2]{\ifthenelse{\boolean{show_translation}}{#2}{#1}} | 136 \newcommand{\sstext}[2]{\ifthenelse{\boolean{show_translation}}{#2}{#1}} |
127 | 137 |
128 | 138 |
129 | 139 |
130 \title{Dart strong mode definition} | 140 \title{Dart strong mode definition} |
131 | 141 |
132 \begin{document} | 142 \begin{document} |
133 | 143 |
134 \textbf{\large PRELIMINARY DRAFT} | 144 \textbf{\large PRELIMINARY DRAFT} |
135 | 145 |
(...skipping 25 matching lines...) Expand all Loading... | |
161 \alt \Arrow[k]{\many{\tau}}{\sigma} \alt \TApp{C}{\many{\tau}} \\ | 171 \alt \Arrow[k]{\many{\tau}}{\sigma} \alt \TApp{C}{\many{\tau}} \\ |
162 % | 172 % |
163 \text{Optional type ($[\tau]$)} & ::= & \_ \alt \tau \\ | 173 \text{Optional type ($[\tau]$)} & ::= & \_ \alt \tau \\ |
164 % | 174 % |
165 \text{Term identifiers} & ::= & a, b, x, y, m, n, \ldots \\ | 175 \text{Term identifiers} & ::= & a, b, x, y, m, n, \ldots \\ |
166 % | 176 % |
167 \text{Primops ($\phi$)} & ::= & \mathrm{+}, \mathrm{-} \ldots \mathrm{||} \ldots \\ | 177 \text{Primops ($\phi$)} & ::= & \mathrm{+}, \mathrm{-} \ldots \mathrm{||} \ldots \\ |
168 % | 178 % |
169 \text{Expressions $e$} & ::= & | 179 \text{Expressions $e$} & ::= & |
170 x \alt i \alt \ett \alt \eff \alt \enull \alt \ethis \\&& | 180 x \alt i \alt \ett \alt \eff \alt \enull \alt \ethis \\&& |
171 \alt \elambda{\many{x:\opt{\tau}}}{\opt{\sigma}}{e} | 181 \alt \elambda{\many{x:\opt{\tau}}}{\opt{\sigma}}{s} |
172 \alt \enew{C}{\many{\tau}}{} \\&& | 182 \alt \enew{C}{\many{\tau}}{} \\&& |
173 \alt \eprimapp{\eprim}{\many{e}} \alt \ecall{e}{\many{e}} | 183 \alt \eprimapp{\eprim}{\many{e}} \alt \ecall{e}{\many{e}} |
174 \alt \edcall{e}{\many{e}} \\&& | 184 \alt \edcall{e}{\many{e}} \\&& |
175 \alt \eload{e}{m} \alt \edload{e}{m} \alt \eload{\ethis}{x} \\&& | 185 \alt \eload{e}{m} \alt \edload{e}{m} \alt \eload{\ethis}{x} \\&& |
176 \alt \eassign{x}{e} \alt \eset{\ethis}{x}{e} \\&& | 186 \alt \eassign{x}{e} \alt \eset{\ethis}{x}{e} \\&& |
177 \alt \ethrow \alt \eas{e}{\tau} \alt \eis{e}{\tau} \alt \echeck{e}{\tau}\\ | 187 \alt \ethrow \alt \eas{e}{\tau} \alt \eis{e}{\tau} \alt \echeck{e}{\tau}\\ |
178 % | 188 % |
179 \text{Declaration ($\mathit{vd}$)} & ::= & | 189 \text{Declaration ($\mathit{vd}$)} & ::= & |
180 \dvar{x:\opt{\tau}}{e} \alt \dfun{\tau}{f}{\many{x:\tau}}{s} \\ | 190 \dvar{x:\opt{\tau}}{e} \alt \dfun{\tau}{f}{\many{x:\tau}}{s} \\ |
181 % | 191 % |
182 \text{Statements ($s$)} & ::= & \mathit{vd} \alt e \alt \sifthenelse{e}{s_1}{s_2 } | 192 \text{Statements ($s$)} & ::= & \mathit{vd} \alt e \alt \sifthenelse{e}{s_1}{s_2 } |
183 \alt \sreturn{e} \alt s;s \\ | 193 \alt \sreturn{e} \alt s;s \\ |
184 % | 194 % |
185 \text{Class decl ($\mathit{cd}$)} & ::= & \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\ many{S}}}{\many{\mathit{vd}}} \\ | 195 \text{Class decl ($\mathit{cd}$)} & ::= & \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\ many{\tau}}}{\many{\mathit{vd}}} \\ |
186 % | 196 % |
187 \text{Toplevel decl ($\mathit{td}$)} & ::= & \mathit{vd} \alt \mathit{cd}\\ | 197 \text{Toplevel decl ($\mathit{td}$)} & ::= & \mathit{vd} \alt \mathit{cd}\\ |
188 % | 198 % |
189 \text{Program ($P$)} & ::= & \program{\many{\mathit{td}}}{s} | 199 \text{Program ($P$)} & ::= & \program{\many{\mathit{td}}}{s} |
190 \end{array} | 200 \end{array} |
191 \] | 201 \] |
192 | 202 |
193 | 203 |
194 Type contexts map type variables to their bounds. | 204 Type contexts map type variables to their bounds. |
195 | 205 |
196 Class signatures describe the methods and fields in an object, along with the | 206 Class signatures describe the methods and fields in an object, along with the |
197 super class of the class. There are no static methods or fields. | 207 super class of the class. There are no static methods or fields. |
198 | 208 |
199 The class hierararchy records the classes with their signatures. | 209 The class hierararchy records the classes with their signatures. |
200 | 210 |
201 The term context maps term variables to their types. I also abuse notation and | 211 The term context maps term variables to their types. I also abuse notation and |
202 allow for the attachment of an optional type to term contexts as follows: | 212 allow for the attachment of an optional type to term contexts as follows: |
203 $\Gamma_\sigma$ refers to a term context within the body of a method whose class | 213 $\Gamma_\sigma$ refers to a term context within the body of a method whose class |
204 type is $\sigma$. | 214 type is $\sigma$. |
205 | 215 |
206 \[ | 216 \[ |
207 \begin{array}{lcl} | 217 \begin{array}{lcl} |
208 \text{Type context ($\Delta$)} & ::= & \epsilon \alt \Delta, T \sub \tau \\ | 218 \text{Type context ($\Delta$)} & ::= & \epsilon \alt \Delta, T \sub \tau \\ |
209 \text{Class element ($\mathit{ce}$)} & ::= & | 219 \text{Class element ($\mathit{ce}$)} & ::= & |
210 \fieldDecl{x}{\tau} \alt \methodDecl{f}{\tau} \\ | 220 \fieldDecl{x}{\tau} \alt \methodDecl{f}{\tau}{\sigma} \\ |
211 \text{Class signature ($\mathit{Sig}$)} & ::= & | 221 \text{Class signature ($\Sig$)} & ::= & |
212 \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{S}}}{\many{\mathit{ce}}} \\ | 222 \dclass{\TApp{C}{\many{T}}}{\TApp{G}{\many{\tau}}}{\many{\mathit{ce}}} \\ |
213 \text{Class hierarchy ($\Phi$)} & ::= & \epsilon \alt \Phi, C\ :\ \mathit{Sig} \\ | 223 \text{Class hierarchy ($\Phi$)} & ::= & \epsilon \alt \Phi, C\ :\ \Sig \\ |
214 \text{Term context ($\Gamma$)} & ::= & \epsilon \alt \Gamma, x\ :\ \tau | 224 \text{Term context ($\Gamma$)} & ::= & \epsilon \alt \Gamma, x\ :\ \tau |
215 \end{array} | 225 \end{array} |
216 \] | 226 \] |
217 | 227 |
218 | 228 |
219 \section*{Subtyping} | 229 \section*{Subtyping} |
220 | 230 |
221 \subsection*{Variant Subtyping} | 231 \subsection*{Variant Subtyping} |
222 | 232 |
223 We include a special kind of covariant function space to model certain dart | 233 We include a special kind of covariant function space to model certain dart |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
264 {\subtypeOf{\Phi, \Delta} | 274 {\subtypeOf{\Phi, \Delta} |
265 {\TApp{C}{\tau_0, \ldots, \tau_n}} | 275 {\TApp{C}{\tau_0, \ldots, \tau_n}} |
266 {\TApp{C}{\sigma_0, \ldots, \sigma_n}}} | 276 {\TApp{C}{\sigma_0, \ldots, \sigma_n}}} |
267 | 277 |
268 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\ldots}) \in \Phi \\ | 278 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\ldots}) \in \Phi \\ |
269 \subtypeOf{\Phi, \Delta}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_ n}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}}{\TApp{G}{\sigma_0, \ldots, \sigma _m}}} | 279 \subtypeOf{\Phi, \Delta}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_ n}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}}{\TApp{G}{\sigma_0, \ldots, \sigma _m}}} |
270 {\subtypeOf{\Phi, \Delta} | 280 {\subtypeOf{\Phi, \Delta} |
271 {\TApp{C}{\tau_0, \ldots, \tau_n}} | 281 {\TApp{C}{\tau_0, \ldots, \tau_n}} |
272 {\TApp{G}{\sigma_0, \ldots, \sigma_m}}} | 282 {\TApp{G}{\sigma_0, \ldots, \sigma_m}}} |
273 | 283 |
274 \section*{Field and Method lookup} | |
275 | |
276 \subsection*{Field lookup} | |
277 | |
278 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\many{\mathit{ce}}}) \in \Phi \\ | |
279 \fieldDecl{x}{\tau} \in \many{\mathit{ce}} | |
280 } | |
281 {\fieldLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{x}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}} | |
282 } | |
283 | |
284 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad x \notin \many{\mathit{ce}} \\ | |
285 \fieldLookup{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{x}{\tau} | |
286 } | |
287 {\fieldLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{x}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}} | |
288 } | |
289 | |
290 \subsection*{Method lookup} | |
291 | |
292 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\many{\mathit{ce}}}) \in \Phi \\ | |
293 \methodDecl{m}{\tau} \in \many{\mathit{ce}} | |
294 } | |
295 {\methodLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{m}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}} | |
296 } | |
297 | |
298 \infrule{(C : \dclass{\TApp{C}{T_0,\ldots,T_n}}{\TApp{C'}{\upsilon_0, \ldots, \u psilon_k}}{\many{\mathit{ce}}}) \in \Phi \quad m \notin \many{\mathit{ce}} \\ | |
299 \methodLookup{\Phi}{\TApp{C'}{\upsilon_0, \ldots, \upsilon_k}}{m}{\tau} | |
300 } | |
301 {\methodLookup{\Phi}{\TApp{C}{\tau_0, \ldots, \tau_n}}{m}{\subst{\tau_0, \ldots, \tau_n}{T_0, \ldots, T_n}{\tau}} | |
302 } | |
303 | |
304 | 284 |
305 | 285 |
306 \section*{Typing} | 286 \section*{Typing} |
307 \input{static-semantics} | 287 \input{static-semantics} |
308 | 288 |
289 \pagebreak | |
309 \section*{Elaboration} | 290 \section*{Elaboration} |
291 \setboolean{show_translation}{true} | |
310 | 292 |
311 These are the same rules, extended with a translated term which corresponds to | 293 Elaboration is a type driven translation which maps a source Dart term to a |
312 the original term with the additional dynamic type checks inserted to reify the | 294 translated term which corresponds to the original term with additional dynamic |
313 static unsoundness as runtime type errors. | 295 type checks inserted to reify the static unsoundness as runtime type errors. |
296 For the translation, we extend the source language slightly as follows. | |
297 \[ | |
298 \begin{array}{lcl} | |
299 \text{Expressions $e$} & ::= & \ldots | |
300 \alt \edcall{e}{\many{e}} \alt \edload{e}{m} \alt \echeck{e}{\tau}\\ | |
301 \end{array} | |
302 \] | |
314 | 303 |
315 \setboolean{show_translation}{true} | 304 The expression language is extended with an explicitly checked dynamic call |
305 operation, and explicitly checked dynamic method load operation, and a runtime | |
vsm
2015/07/28 15:44:32
"dynamic method load operation" -> "dynamic load o
Leaf
2015/07/28 20:34:29
The syntax is a little deceptive - there are reall
| |
306 type test. Note that while a user level cast throws an exception on failure, | |
307 the runtime type test term introduced here produces a hard type error which | |
308 cannot be caught programmatically. | |
309 | |
310 We also extend typing contexts slightly by adding an internal type to method sig natures. | |
311 \[ | |
312 \begin{array}{lcl} | |
313 \text{Class element ($\mathit{ce}$)} & ::= & | |
314 \fieldDecl{x}{\tau} \alt \methodDecl{f}{\tau}{\sigma} \\ | |
315 \end{array} | |
316 \] | |
317 A method signature of the form $\methodDecl{f}{\tau}{\sigma}$ describes a method | |
318 whose public interface is described by $\sigma$, but which has an internal type | |
319 $\tau$ which is a subtype of $\sigma$, but which is properly covariant in any | |
320 type parameters. The elaboration introduces runtime type checks to mediate | |
321 between the two types. This is discussed further in the translation of classes | |
322 below. | |
323 | |
316 \input{static-semantics} | 324 \input{static-semantics} |
317 | 325 |
318 | 326 |
319 \end{document} | 327 \end{document} |
OLD | NEW |