Closed
Description
The current semantics of inline override
is inconsistent and confusing.
Current state
class Greeting {
def greet(name: String): String = "Greetings " + name
}
class Hello extends Greeting {
inline override def greet(name: String): String = "Hello " + name
}
object App {
val greeting: Greeting = new Greeting
val hello1: Hello = new Hello
val hello2: Greeting = hello1
println(greeting.greet("World")) // prints: Greetings World
println(hello1.greet("World")) // prints: Hello World
// Inlined Hello.greet directly
println(hello2.greet("World")) // prints: Greetings World
// Not inlined as it is statically calling Greeting.greet, so far so good
// It should have dynamically call Hello.greet, but inline method are erased!
}
Semantically coherent version
object App {
val greeting: Greeting = new Greeting
val hello1: Hello = new Hello
val hello2: Greeting = hello1
println(greeting.greet("World")) // prints: Greetings World
println(hello1.greet("World")) // prints: Hello World
// Inlined as we call Hello.greet directly
println(hello2.greet("World")) // prints: Hello World
// Not inlined as it is statiacally calling Greeting.greet.
// Dynamically calls Hello.greet
}
How to make this happen
class Hello extends Greeting {
inline override def greet(name: String): String = "Hello " + name
}
should become
class Hello extends Greeting {
override def greet(name: String): String = "Hello " + name
}
and
class Hello extends Greeting {
inline override def greet(name: String): String = ${ myHello('name) }
}
would become
class Hello extends Greeting {
override def greet(name: String): String = ${ myHello('name) } // where macro is evaluated in place
}