Changes:
- Allow unit contracts to import and export the same signature.
- Add "invoke" contracts that will wrap the result of invoking a unit contract,
no wrapping occurs when a body contract is not specified
- Improve error messages
- Support for init-depend clauses in unit contracts.
- Fix documentation to refelct the above
- Overhaul of unit related tests
Handling init-depend clauses in unit contracts is a rather large and somewhat
non-backwards-compatible change to unit contracts. Unit contracts must now
specify at least as many initialization dependencies as the unit value being
contracted, but may include more. These new dependencies are now actually
specified in the unit wrapper so that they will be checked by compound-unit
expressions.
This commit also adds more information to the first-order-check
error messages. If a unit imports tagged signatures, previously the errror
message did not specify which tag was missing from the unit contract. Now
the tag is printed along with the signature name.
Documentation has been edited to reflect the changes to unit/c contracts
made by this commit.
Additionally this commit overhauls all tests for units and unit contracts.
Test cases now actually check that expected error messages are triggered when
checking contract, syntax, and runtime errors. Test forms now expand into uses
of rackunit's check-exn form so only test failures are reported and all tests in
a file are run on every run of the test file.
Progress toward making the bytecode compiler deterministic, so that a
fresh `make base` always produces exactly the same bytecode from the
same sources. Most changes involve avoiding hash-table order
dependencies and adjusting scope identity. The namespace used to load
a reader extension is also better defined. Plus many other little
changes.
The identity of a scope that is unmarshaled from a bytecode file now
incorporates the hash of the file, and the relative order of scopes is
preserved in a bytecode file. This combination allows compilation to
start with modules that loaded and compiled in different orders
(including delayed loading of bytecode fragments within one file).
Formerly, a reader extension triggered by `#lang` or `#reader` was
loaded in whatever namespace happens to be current. That's
unpredictable and can pollute a module build at the level of bytecode.
To help make builds deterministic, reader extensions are now loaded in
a root namespace of the current namespace.
Deterministic compilation in general relies on deterministic macros.
The two most common ways for a macro to be non-deterministic are by
using `gensym` (use `generate-temporaries`, instead) and by using an
unsorted hash-table traversal (don't do that).
At this point, bytecode generation is unlikely to be completely
deterministic, since I uncovered non-determinism mostly by iterating
attempts over the base collections. For now, the intent is not to
provide guarantees outside of the compilation of the base collections
--- but "more deterministic" is likely to be useful in the short run,
and we can improve further in the long run.
When a module is currently installed as bytecode, but without
corresponding source and without a "info.rkt" specification that
bytecode should be preserved without source, then `raco pkg` should
not count that module bytecode as a conflict (since `raco setup`
will remove it).
Part of the expansion to handle contracts confused internal and
external names of signature elements. The new macro expander is less
tolerant of the mistake.
Add the current definition context's scope to any expression that is
produced by macro expansion before trying to expand again, in case the
expansion needs to refer to a definition introduced by a previous
expansion.
Previously, the scope was added before any expansion and after any
expansion, but that misses intermediate points.
The old expander had this bug, too (some of the new tests fail there),
but it showed up less often and was sometimes considered correct, for
various reasons.
The revised implementation of `define-generics` for the new macro
expander wasn't right, because the macro attached to `<gen>/c` for a
given `<gen>` used a macro-introduced reference to the generic to
match up method names with the generic's methods.
When a package "p" is clone-linked and the repo for "p" changes to be
a multi-package repository (e.g., with "p-lib", "p-doc", and "p"), a
`raco update` would get confused. Unofrtunately, a plain `raco pkg
update p` can't work in that case, because the clone link would still
be a pathless repo URL; the repairs make `raco pkg update --lookup
--clone ..../p` work as is should.
Related: fix inference of package names in the early check for whether
a package is installed.
- Coalesce repeated use of the same predicate.
- Fix scoring of Exact patterns, and scoring generally.
- Use `OrderedAnd` where needed.
- Guarantee that `and` patterns match in order.
- Thread bound variable information properly in GSeq compilation.
- Warn when variables are used non-linearly with `...`
(making this behave properly was not backwards compatible).
Closes#952, which now runs in <1ms and make it a test case.
Also add margin note about `?` patterns and multiple calls.
If the selector is itself a chaperone, then doing the access once
will mean that the saved result is not `chaperone-of?` the result
of doing the access a second time, at least in some cases (such as
when the accessor uses vector contracts).
Thanks to Neil T for initial spotting, and to Robby for actually
finding the bug and suggesting the fix.
When using `compound-unit/infer` and similar, check the `link` clause
against each unit's static information for initialization dependencies.
Also, propagate dependency information in `define-compount-unit`.
Unlike `collapse-module-path`, it makes sense for
`collapse-module-path-index` to convert a relative module path index
to a plain module path. In other words, `collapse-module-path-index`
can convert a module path index to a module path.
be equal?-based contracts instead of = based contracts.
Before this change, the contract (or/c 1 2 +nan.0) was the same
contract as (or/c 1 2), because +nan.0 was the same contract as
the predicate (lambda (x) (= x +nan.0)), which is the same as
(lambda (x) #f). Now, +nan.0 and +nan.f are the only numbers
that are treated as equal?-based contracts, but this means that
(or/c 1 2 +nan.0) actually accepts +nan.0.
Not really sure about this one. The API kind of
forces my hand here and the way this works limits
the non-dep side of the dependent pair to always
be drawn from a fixed set. Not sure if that matters
in practice or not.
If the clone directory's checkout includes a target commit, then
use the clone directory directly for staging (i.e., for checking
dependencies and collisions). That way, changes made locally are
used for metadata checks.
before this commit it would copy them only when the weren't
already impersonated/chaperoned, leading to different
contract checking that can be confusing in that case
it did this because the chaperone-of? check wasn't general
enough to cope with copying always, but since commit
b05d07ad10 it now is
This required moving some tests to "racket-test", and putting them
in modules that use `rackunit`. Also, some uses of rackunit were
removed and switched to more primitive systems. Some improvements
here, particularly in "foreign-test.rktl", would still be good,
but everything passes at the moment.
The implemented default for `raco pkg update` actually depended on the
way that a package is installed, and it's difficult to reason about or
to implement the default that is suggested by the documentation.
Meanwhile, `search-ask` seems the most sensible always in interactive
mode (now that we have a way to specify batch mode).
This supports running the core tests on systems which can't run
or don't want to install all the dependencies of the "racket-test"
package.
The "racket-test-core" pkg stil depends on "sandbox-lib" because
the sandbox tests live with the core tests. Hopefully I'll be able
to fix that eventually.
A value-printing truncation discovered after a stack-overflow handle
and return could go badly, because the truncation escape wasn't
reset correctly after overflow handling (in contrast to truncation
discovered during the overflow handling, which was handled correctly).
Closes PR 14870
Packages that are installed as other than a link are not meant to be
edited, but work can get lost if a package is edited and then removed
or updated. Avoid that work loss by moving removed or updated packages
to a trash folder.
By default, the trash folder holds up to 512 packages for up to 48
hours. To disable the trash folder (for a given scope), use
raco pkg config --set max-trash-packages 0
(I expect that some variant of Greenspun's rule predicted the eventual
inclusion of "backup" management in the package system.)