#542 Compiler - Internal class cast error

tactics Sun 19 Apr 2009

I think I found a bug in the compiler. Not sure exactly what's up with it.

class Test
{  
  Str:Obj bindings := [
    "printLine": |Obj[] args|
    {
      str := ""
      args.each |arg|
      {
        str += arg
      }
    }
  ]  
}

This produces the error

ERROR: cannot compile script
sys::CastErr: java.lang.ClassCastException: fan.compiler.FieldDef cannot be cast
to fan.compiler.MethodDef
compiler::ResolveExpr.resolveLocal (ResolveExpr.fan:720)
compiler::ResolveExpr.resolveVar (ResolveExpr.fan:340)
compiler::ResolveExpr.resolveExpr (ResolveExpr.fan:162)
compiler::ResolveExpr.visitExpr (ResolveExpr.fan:123)
compiler::Expr.walk (Expr.fan:220)
compiler::Expr.walkExpr (Expr.fan:230)
compiler::CallExpr.walkChildren (Expr.fan:758)
compiler::Expr.walk (Expr.fan:219)
compiler::Stmt.walkExpr (Stmt.fan:55)
compiler::ExprStmt.walkChildren (Stmt.fan:107)
compiler::Stmt.walk (Stmt.fan:42)
compiler::Block.walk (Block.fan:81)
fan.sys.List.each (List.java:509)
compiler::Block.walk (Block.fan:79)
compiler::MethodDef.walk (MethodDef.fan:160)
compiler::TypeDef.walk (TypeDef.fan:297)
fan.sys.List.each (List.java:509)
compiler::TypeDef.walk (TypeDef.fan:297)
compiler::Visitor.walk (Visitor.fan:31)
More...

brian Mon 20 Apr 2009

Promoted to ticket #542 and assigned to brian

brian Wed 22 Apr 2009

Ticket resolved in 1.0.42

The problem here is use of enclosed locals in nested closures in a field initializer. Although I support closures in field initializers, I don't support the more complicated aspects of what I call "cvars" (enclosed local variables). We could potentially support that, although it ripples thru the compiler pipeline as a fairly complicated boundary condition because the actual enclosing method is the object's constructor for field initializers.

So for now I am going to say we don't support that feature. What I did was detect this case and report a sensible error message: "Nested closures not supported in field initializer" instead of throwing an CastErr.

Work arounds include:

// use non-nested closure
Str:Obj bindings := ["printLine": |Obj[] args->Str| { args.join }]

// use curried method
Str:Obj bindings := ["printLine": &printLine]
static Str printLine(Obj[] args) { args.join }

Login or Signup to reply.