[Types-sig] recursive types, type safety, and flow analysis

Greg Stein gstein@lyra.org
Tue, 21 Dec 1999 20:06:28 -0800 (PST)

On Tue, 21 Dec 1999, Guido van Rossum wrote:
> I'm giving up on responding point-by-point -- let's just agree that we
> differ in opinion on this matter.

I'm not sure that I'm there yet :-)

Basically, I think your request to find and report on
use-before-definition is "intractable" *when* you're talking about
multiple bodies of code (e.g. two functions, or the global space and a

[ by "intractable", I mean within the scope of what I believe we want to
  build; the problem is certainly doable but I believe it would involve
  complex, global, control-flow analysis. ]

> > But it does not allow:
> > 
> > def f(x: Foo):
> >   ...
> > class Foo:
> >   ...
> If there's only one Foo (which is usually the case) I still think this
> is too strict, and I don't see a technical reason why it would be
> necessary.

I want compile time checks, but I also want function objects to contain
typedecl information at runtime. I'm not talking about runtime type
checks, just recording more information with the function objects.

For example, I'd like to be able to say something like:

for i in range(func.func_code.co_argcount):
  print func.func_code.co_varnames[i], ':', func.func_argtypes[i]

> > I believe the compiler should be recording information about the function
> > arguments' typedecls. Unless the compiler is going to have multiple passes
> > then the name should be defined before usage.
> > 
> > Or rather, let's assume that the function argument information is
> > constructed and recorded at runtime (as part of the standard function
> > object construction at runtime). Then you really have to ensure that name
> > is available, so the appropriate value can be stored into the function
> > object.
> OK, this is why we disagree.  I am only interested in compile time
> type checking; I can admit that some run time checking is necessary,
> but only in order to assert certain invariants that are assumed by the
> compile time checker.

Actually, I'm assuming that runtime checks are *only* present to verify
parameter values and when the type-assert operator is used. I do not
believe we would ever insert them outside of these two cases.

Asserting the types of parameters could be arguable.

Back to the point: I think we're in agreement on compile-time vs run-time
checks. The difference is that I have one more requirement: the typedecl
information should be available at runtime (for introspection purposes).

> A form of type checking that happens completely at run time (the way
> you describe it) is uninteresting to me, and using such a system as
> the semantic basis for a type checker seems to be a mistake.

Sorry, I have been unclear if this was the result. I do not want a
runtime-based type checker. I want compile time (*).

The runtime checks for function parameters are just assertions to ensure
that non-type-checked code does not pass the wrong thing. The runtime
check for the type-assert operator is present because the person requested

[ although it possible that the compiler can optimize away the assertion
  generatd by the type-assert operator if the compiler can determine that
  it will always fail or that it will never fail. ]

Neither of these two classes of runtime checks are intended to replace any
compile-time type checks.

(*) strictly speaking, I don't care about compile-time checks, as I'm in
    this for (OPT) :-), but I'm attempting to design a solution that
    encompasses (ERR), too.

> Yes,
> this follows Python's semantics closer than what I am proposing.  But
> I don't think that it is closer to what the user expects the type
> checker to do.

I agree with you.

> Here's the crux of my argument:
>     Python's dynamic semantics can often be surprising.  Compile time
>     checking should warn the user about these surprises, it shouldn't
>     try to assume that these surprises are what the user wanted!


> (I've skipped the rest of what you wrote, because of the agreement to
> disagree.)

Our difference lies in two items:

* I do not believe that you can do cross-function, compile-time checks to
  determine if a name is undefined.
  [ or if a name has different types over time, which type it may be ]

* I am requiring the ability to associate typedecl objects with a function
  object at runtime. This imposes the requirement on a typedecl name (such
  as a class' name) being defined at the point that a function is defined.
  [ I also want typedecl objects associated with a class object and a
    module object so that we can reflect on their interface at runtime ]

We can agree to disagree on the first item (I'll let you write the code
to do that :-). I'd like your opinion on the second.


Greg Stein, http://www.lyra.org/