plt/racket — pull request #812 by takikawa (2014-10-31 16:04:14+00:00)
Title: New opaque object/class contracts

This PR modifies the semantics of class contracts in a backwards incompatible way for the `#:opaque` feature. This feature pretty much exists only for TR, so I doubt this will affect many users though.

Currently, the opaque keyword just makes the class contract reject methods/fields that are not mentioned in the contract as a first-order check. The new behavior hides the methods/fields instead as if they were never defined. This is still safe (in that it upholds the same guarantees for typed code), but may produce "method not found" errors later where the previous behavior would have produced a contract error earlier.

The motivation for this change is to work better with recursive contracts like the following example:

````
(define foo%/c
(recursive-contract (class/c #:opaque
[m (-> (instanceof/c foo%/c))])))
````

With the previous behavior, this would immediately error if `m` is invoked and `m` returns an object that contains more methods/fields (say via a subclass of `foo%`). The new behavior makes more sense for this situation and also makes it easier to import classes in Typed Racket (you don't have to specify all of the method types upfront).

It does rule out `#:opaque` object/class contracts from being chaperone contracts though, and it's definitely not a pair-of-projections-style contract.

@sstrickl @rfindler any opinions about this?

(Credit: @sstrickl had the original idea to re-implement opaque contracts like this. Any design/implementation mistakes are mine though.)