effekt-lang / effekt

A research language with effect handlers and lightweight effect polymorphism

Home Page:https://effekt-lang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unhelpful error message on missing braces in an interface implementation

jiribenes opened this issue · comments

When trying to write an instance of an interface:

interface Eff {
  def op(): Int
}

def e: Eff = new Eff {
  def op() = println("42"); 42
}

shows an error: "Operation Eff is not part of interface Eff."

Here's a screenshot:
Screenshot 2024-01-23 at 17 19 27

One way to work around this is to add braces into the method body:

interface Eff {
  def op(): Int
}

def e: Eff = new Eff {
  def op() = { println("42"); 42 }
}

TBH it took me quite a while to understand this error...

The parser parses it as

def e: Eff = new Eff { () =>
  def op() = println("42")
  42
}

which is our syntax for singleton operations and thus shorthand for:

def e: Eff = new Eff { 
  def Eff() = {
    def op() = println("42")
    42
  }
}

@jiribenes what would you expect as an error message? We could also forbid parsing it as single operation in case it starts with def

I wouldn't know an elegant way to prevent it though.

lazy val implementation: P[Implementation] =
( interfaceType ~ (`{` ~> many(defClause) <~ `}`) ^^ {
case effect ~ clauses =>
Implementation(effect, clauses)
}
| idRef ~ maybeTypeParams ~ implicitResume ~ functionArg ^^ {
case id ~ tparams ~ resume ~ BlockLiteral(_, vparams, _, body) =>
val synthesizedId = IdRef(id.name)
val interface = BlockTypeRef(id, Nil) withPositionOf id
Implementation(interface, List(OpClause(synthesizedId, tparams, vparams, None, body, resume) withPositionOf id))
}
)

The parser for implementation reuses functionArg which admits the program you wrote.