Relaxed MJ rejects the following class:
public class X {
public static class Y{}
public static class Z{}
public abstract static void f(X _);
public static void f(X@Y _) {}
public static void f(X@Z _) {}
}
The error message:
X.java:5:11 error: Method "f" has an illegal
combination of modifiers: abstract cannot be
combined with private, static, final, native,
strictfp, or synchronized [JLS 8.4.3]
In ordinary Java, abstract static methods don't
make any sense.
In ordinary MJ, you can later fill in cases for such
methods, but you always need to provide the
default case. So, abstract static methods have a
natural dynamic interpretation, but are statically
illegal.
In RMJ, the static restriction on top-level abstract
external generic functions goes away. So,
abstract static methods should be legal, and
should be typechecked like abstract external
generic functions.
Logged In: YES
user_id=724721
You say "In RMJ, the static restriction on top-level abstract
external generic functions goes away." If you mean that a
static method can be abstract in RMJ, then I've never
intended this to be so. You could make a case that it
should be allowed, but we'd have to think about it first.
However, it is the case that RMJ intends to allow both
internal and external methods to be abstract, even for
concrete receiver classes. However, the current RMJ
implementation does not yet support abstract internal
methods of concrete receiver classes (because the mjc
compiler hasn't been relaxed enough yet; the RMJ loader
would handle it fine). This is one of the known limitations
of the current RMJ implementation; see others in the
relaxed/TODO file. Your test case is using internal
methods, so it's not going to be allowed (yet),
independently of the static keyword.
Logged In: YES
user_id=26937
Right, by "static restriction on top-level abstract
external generic functions", I meant static in the
sense of static typechecking, not the Java static
keyword. In other words, MJ typechecking disallows
abstract external generic functions, whereas RMJ
does not.
Since I consider MJ static methods to be the "moral
equivalent" of external generic functions wrapped
inside a namespace, I assumed that RMJ would
support abstract static methods as well. I see no
countervailing language design or translation
strategy issues (the simplest translation strategy:
generate a concrete static method that forwards the
call to a specially named external gf).
The language design issues are relatively simple:
+ How to typecheck abstract static methods? I claim
any static method
Class.Method(Arg1 a1, ..., ArgN aN)
can be typechecked identically to an external generic
function named
Arg1.mangle$Class$Method(Arg2 a2, ..., ArgN aN)
Note that this illuminates the fact that no-argument
static methods cannot be abstract. This restriction
makes sense since, the programmer could not
provide any implementing cases.
+ How to declare overriding cases of static methods?
I propose 2 mechanisms:
(1) declare a static overriding case in a subclass:
class A { abstract static void f(A a); }
class B extends A { static void f(A@B b) {} }
(2) mark an external overriding case with the "static"
keyword; the "receiver" position should be named for
the static method's introducing class:
static void A.f(A@B b) {}
Case (1) actually introduces a new kind of syntactic
ambiguity---what if B introduces a new static method
f(A), which is legal in Java?
class B extends A {
static void f(A a) {}
static void f(A@B b) {} // what does this override?
}
In order to allow programmers to resolve this
ambiguity, we can expand the syntax:
static void A.f(A@B b) {} // what does this override?
or simply require that programmers declare such
overriding cases externally.
Obviously, I don't need these features now. They're
not really fundamental RMJ design issues either.
But I've actually wanted to write static multimethods
with abstract cases.
Logged In: YES
user_id=724721
Static methods are not inherited from one class to another,
unlike top-level methods, so I don't think they're the same
thing. At least not in regular Java or MJ. So I don't want
to change that model and have static methods be inherited
in RMJ. It's still fair to allow static methods (just like
regular methods) to be abstract, if additional multimethods
are provided in the same class to handle all the concrete
subclasses that are known (and that will be loaded at
run-time). But this is exactly the case of internal
abstract methods that isn't handled yet by the RMJ compiler.