[racket-dev] Blame and re-provided bindings

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Sat Jan 15 08:21:32 EST 2011

On Sat, Jan 15, 2011 at 6:53 AM, Robby Findler
<robby at eecs.northwestern.edu> wrote:
> On Fri, Jan 14, 2011 at 9:13 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:
>>> I think that most of the time that you re-provide something you really
>>> wanted to put the same contract on it, so it seems like we should make
>>> that easy.
>>
>> On the other hand, that means the number of requires and provides can
>> seriously impact a program's performance if a function has a
>> computationally intensive contract.  I don't think we really want to
>> put hidden "gotchas" into the module system.
>
> The contract system should be able to be smart enough to avoid putting
> the redundant contracts on. After all, they are eq? to each other
> (altho I agree some care will have to be taken to make sure this
> happens).

I don't think that's possible in general.  For instance, the listof
contract has to traverse the entire list, recursively applying the
element contract to each part.  There's no way to avoid rewrapping
there.  Granted, providing a list of functions is not common, but any
contract can be implemented that way.  The whole contract need not be
preserved after the projection has been applied.  Our contract system
is too flexible to make hard guarantees about the effects of applying
the same contract twice.

>> Also, I occasionally make use of the fact that re-provides are
>> considered "the same binding" by the module system.  So if A exports
>> X, and B re-exports that X, C can require both A and B.  The duplicate
>> import of X doesn't cause an error because it's the same X.  Changing
>> module exports is a little bit easier because of this -- for instance,
>> more than once I have used this property to keep (planet cce/scheme)
>> compatible with changes to the core that added overlapping bindings.
>> Adding a new contract means you suddenly have a different binding,
>> which can be less convenient.
>
> Wait a sec: I don't see how 'the same binding' can be on the table for
> one option and not the other? It seems like 'the same binding' in the
> current world can do two different things (specifically either include
> the 'via' message or not when there is an error).
>
> I tried this out with racket/load and the bindings were the same, but
> there was no via message. Maybe that is just part of the bug we're
> dealing with, tho?

I'm not talking about "via" messages in contract errors.  I'm talking
about syntax errors.  The following program compiles and runs:

#lang racket/load
(module A racket (define x 5) (provide x))
(module B racket (require 'A) (provide x))
(module C racket (require 'A) (require 'B))

But this program does not:

#lang racket/load
(module A racket (define x 5) (provide/contract [x any/c]))
(module B racket (require 'A) (provide/contract [x any/c]))
(module C racket (require 'A) (require 'B))

The resulting error message:

module: identifier already imported from a different source in:
  x
  (quote B)
  (quote A)

--Carl


Posted on the dev mailing list.