[MLton] front-end error message

Stephen Weeks MLton@mlton.org
Thu, 14 Apr 2005 09:20:13 -0700

> > The Error.bug "missing flexInst" at line 1492 of elaborate/type-env.fun 
> > is triggered by the following program:
> How does this look for a fix:

It looks like an improvement to me.

> My (possibly inaccurate) reasoning is that the "missing flexInst"
> only arises when the program already has an earlier type-error, 


> and it corresponds to a situation where the to-be-instantiated type
> has internal flexes that aren't actually present in the type. 

Yes.  Flexes are used to handle the case when a variable, x, must be
generalized, but we aren't yet sure of all of the fields in the
flexrecord types that appear in x's type.  When generalizing, we save
all unresolved flexes that don't appear in the type environment so
that we can get the field names once they have been determined and add
a type variable for each such field to the type scheme of x.  If a
flexrecord type doesn't appear in the type environment and doesn't
appear in the type of x, then it's obviously missed its chance to be
determined, and will get reported as an error.

> So, no one will miss the instantiated flexes in the external type.

The only thing to worry about is cascading errors.  Using
-show-def-use and reading each use of Scheme.instantiate, all the uses
but one produce a result that will only be used if MLton proceeds to
process CoreML, which won't happen in the case of a type error.  The
only problematic use is the call to strArgs on line 2913 of
elaborate-env.fun.  The call runs during type checking, and must be
what's causing the current problem.  The call is in the cut function,
which is why this bug only shows up when there's signature matching.
Changing the code as you suggest will cause strArgs to return a
shorter vector of types, which might cause the "0 <" test to fail,
which might cause the "else" branch to be visited, which seems
harmless enough.

To help with cascading, it could be worth exposing the failure in
Scheme.instantiate, changing

  val instantiate: t -> {args: unit -> Type.t vector,
                         instance: Type.t}


  val instantiate: t -> {args: unit -> Type.t vector option,
                         instance: Type.t}

But I don't object to your simpler fix.