The `identifier-binding` function is now senstive to the "macro
introduction" scope that's on an indentifier provided to a currently
expanding macro. Unit tests for TR need to use
`syntax-local-intorduce` to remove it, in the same way that `tc-setup`
already does.
Also, recognize a class expansion when it's wrapped with
`#%expression`, since `class` now expands that way sometimes.
The `quote-syntax` form now suports a `#:local` option, which is
used for type annotations to preserve binding context.
Since `letrec-syntaxes+values` is now removed by `local-expand`,
some patterns must be adjusted, including the pattern used
for type annotations.
Using the enclosing module's context for the `#f` part of the
`(module* _ #f ....)` would generally enable a compact encoding of
bindings for the purposes of `module->namespace`. Disabling
`module->namespace` for the generated submodules seems more reliable,
and it seems unlikely that anyone will miss the extra debugging
capability (which is all that is lost for these submodules whose
content is, I think, unspecified).
This patch addresses two issues with `typed/racket/class`:
1. For multiple private fields declared with `define-values`, type
information does not propagate from the values produced by the
initialization expression to the declared fields. This breaks soundness
of private fields: A field can be annotated with a type that does not
contain the field's initial value.
This was resolved by keeping a table of temporary bindings introduced in
the expansion of the initializer along with their types. The field
setter's type is then checked against that of the corresponding
temporary.
2. The class body typechecker assumes that the `expr` of
a `define-values` clause will expand to a bare `(values vs ...)`.
This was resolved by generalizing the template for matching an expanded
`define-values` initializer and extracting the type information from the
`expr` instead of each element in `(vs ...)`.
In conjunction with a small change to syntax/parse, this means
that `typed/racket/base` no longer depends on `racket/set`,
`racket/contract/base`, or `racket/generic`.
Timings on my machine go from ~200ms for `#lang typed/racket/base`
as the whole file, to ~100ms. For comparison, `racket/base` is 30ms
and `#lang racket` is 150ms. `#lang typed/racket` is ~200ms with
this change.
Changes include:
- not using `in-syntax`
- switching to `syntax/parse/pre`
- avoiding `template` from `syntax/parse`
Previously the restriction didn't account for traversing
the object type with the given path. This also relies on
the previous commit that adds subtyping on filters.
(because this change seems to introduce filters which
only differ by an unrolling of a recursive type, but
the old subtyping only worked for identical types)
There are several new files: one for structure prims, one for
annotation-related prims, one for contract related ones. The prims-contract
file uses trickery with submodules to avoid a direct dependency
on `racket/contract`.
Additionally, the rewritten versions of `for/set` et al now use
a submodule to avoid a direct dependency on `racket/set`.
With the current macro expander, either should work, but
`free-id=?` is arguably the right choice for determining
that two identifiers refer to the same binding.
This allows the main TR module not to explicitly
depend on the contract library. Each exported name
can be redirected to either the original name (for a
typed client) or to another macro (for an untyped
client) which expands to a `local-require` for the
relevant submodule (named `#%contract-defs`).
Thanks to Matthew for the initial idea and an
implementation in plai-typed that this is based on.
Previously, TR only recognized a subset of the syntax that
the class macro accepts for method definitions (and errored
unhelpfully on other cases). Though that subset was sufficient
for most methods, macros will sometimes produce unusual forms.