-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support reflective calls for structural refinements of js.Any types #4886
Comments
This was of course considered many years ago, when we faced the issue of reflective calls for JS objects. Besides the problem of If we support it for The indirection you write by hand solves this problem, because you tell the compiler in advance which one of the schemes it's supposed to use. |
Why do we need to dynamically type-test the receiver? I was naively thinking that we would look at the definition of Is this not similar to how native JS traits work? I was presuming in that case we look at Why can't we limit this to JS refinements? In other words we check that the component type preceeding the refinement has an upper bound of |
Because you can assign |
I think I get what you are saying now. The thing is that LSP is alread being violated with the current implementation. In the original example of:
A more complete example showing the various cases:
My suggestion is that only for the case of This would improve the situation with regards to LSP as you can see here:
So yeah it isn't going to improve the case of |
I realized this morning that this can be implemented in user-space in Scala 3: object JSReflectiveCalls:
import scala.language.implicitConversions
final class Wrapper(private val x: js.Any) extends AnyVal with Selectable:
@inline def selectDynamic(propName: String): Any =
x.asInstanceOf[js.Dynamic].selectDynamic(propName)
@inline def applyDynamic(propName: String)(args: Any*): Any =
x.asInstanceOf[js.Dynamic].applyDynamic(propName)(args.asInstanceOf[Seq[js.Any]]*)
end Wrapper
implicit def toJSReflectiveCalls(x: js.Any): Wrapper =
new Wrapper(x)
end JSReflectiveCalls
import JSReflectiveCalls.toJSReflectiveCalls
type T = js.Any { def foo(x: Int): String; val bar: Int }
def print(obj: T): String = obj.foo(100 obj.bar)
object Foo extends js.Object {
def foo(x: Int): String = x.toString
val bar: Int = 5
}
print(Foo) |
I've been thinking about this, and the only reason I see not to add better support for |
I've read the Reflexive calls section but something feels like it is still missing.
My understanding is that for the example:
Will fail at runtime with:
However with some indirection we can do:
Which will succeed at runtime.
It seems to me like we ought to be able to have reflexive calls work provided that the structural refinement is on a
js.Any
(likeT
in this last example).We don't need to generate the forwarder methods, we can treat it exactly the same as we would for a native JS trait, i.e. no name translation.
It of course relies on you getting the names in the structural refinement correct but that is the same with native JS traits. The one limitation is that you can't use a
@JSName
annotation within the structural refinement but I don't think that should be a blocker.In short, I think this should work:
The text was updated successfully, but these errors were encountered: