[GHC] #5624: Delay Errors Until Runtime

GHC cvs-ghc at haskell.org
Fri Nov 11 11:41:47 CET 2011


#5624: Delay Errors Until Runtime
---------------------------------+------------------------------------------
    Reporter:  atnnn             |        Owner:  atnnn       
        Type:  feature request   |       Status:  new         
    Priority:  high              |    Milestone:  7.6.1       
   Component:  Compiler          |      Version:  7.3         
    Keywords:                    |     Testcase:              
   Blockedby:                    |   Difficulty:              
          Os:  Unknown/Multiple  |     Blocking:              
Architecture:  Unknown/Multiple  |      Failure:  None/Unknown
---------------------------------+------------------------------------------

Comment(by simonpj):

 Good work `atnnn`.  I wonder who you really are?  People have asked me
 about this, and I had a cunning plan, but I never thought of your
 approach.  So far as I can see, your plan is:
  1. Typecheck the program
  2. For each error message,
     * Take the `SrcSpan` of each error
     * Find a sub-expression (of type `HsExpr`) ''in the original input
 program'' that has (exactly?) that `SrcSpan`
     * Replace it with `error "...the message..."`
  3. Repeat from step 1 with the transformed program

 You have a conter to stop an infinite loop in this procedure.

 Assuming I'm right there are lots of details I don't understand.
  * I don't really grok the types of `findIn` etc
  * What if the `SrcSpan` doesn't match exactly?
  * What happens if you have an error in a type signature, or a type
 declaration; then there is no obvious expression to replace.

 What I like about your approach is that it's brutally simple and direct.
 But I'd like to tell you about my cunning plan.  Here's how it goes.

 When the typechecker looks at, say,
 {{{
   (f x)

 where    f :: ty1 -> Int
          x :: ty2
 }}}
 it generate an ''equality constraint'' that looks like
 {{{
   g :: ty2 ~ ty1
 }}}
 Moreover, the post-typechecked expression looks like
 {{{
   (f (x |> g))
 }}}
 That is, the argument `x` is cast by the ''evidence'' `g`, which converts
 a value of type `ty2` to a value of type `ty2`.  Later on, the typechecker
 solves the constraint, and create a binding for `g`, somthing like
 {{{
   g = Refl ty
 }}}
 The point is this.  If `ty1` turns out to be different to `ty2` (say they
 turn out to be `Int` and `Bool`), then today the typecheck emits an error
 message. But it'd be rather easy to make it emit a binding
 {{{
   g = error "...the error message..."
 }}}
 IMHO this is rather elegant: '''precisely when the runtime execution needs
 evidence that `ty1` = `ty2`, and no sooner,  you'll get the error'''.
 Like, if `f` happens not to use its argument, you can run `(f x)` without
 getting the error.

 Moreover, failing type-class constraints work just the same way.

 I think this is the Right Way to solve your problem.  If you are
 interested, I can help point you at the right places.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5624#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler



More information about the Glasgow-haskell-bugs mailing list