On 05.09.2018 14:36, mg wrote:
I agree with Daniel here, I also don't see how this could be confusing (?).
Even if the inference mechanism falls back to inferring Object, the user
will just get an "cannot call dadadam on Object" or such compile error -
which should immediately leave to the conclusion that the type needs to
be given explicitely in this case...
Does anyone have an example that shows such a malign/confusing type
deduction case ?
Let's start easy
private foo() {
return new SomeMarkerInterface(){
def x() {1}
}
}
is the return type here SomeMarkerInterface or XYZ$1? Can I do foo().x()?
private foo() {
if (something) {
return x // of class X
} else {
return y // of class Y
}
}
if X and Y implement the interfaces Foo and Bar the common super type
would be something like Object+Foo+Bar, which cannot be an actual return
type, because the Java type system cannot properly express that type.
Which is it then? Object, or Foo or Bar? And if you think this problem
is small, you have to consider this one here as well:
private foo() {
def ret
if (something) {
ret = x // of class X
} else {
ret = y // of class Y
}
return ret
}
Same problem as before obviously, just showing that using local
variables makes it even worse.
And how about this one?
private f(List<X> l) {
if (l.size()==1) {
return l[0]
} else {
return f(l.tail())
}
}
for me it is obvious the return type is X, but a compiler must be able
to see through the recursive call and it must see that it is a recursive
call.
private f(List<X> l) {
if (l.size()==1) {
return g(l[0])
} else {
return g(f(l.tail()))
}
}
private g(X x){x}
private g(List<X> l){l}
here it gets even more complicated... g(l[0]) is easy, that will return
X, since l[0] will return X causing a call to g(X):X. But since we
currently infer f, we cannot simply know what f(l.tail()) will be, thus
we cannot easily know if we call here g(X):X or g(List<X>):List<X>.
Or let us say there is also g(Object):Object and let us assume we delete
g(X):X. Then inferring the type above successfully means obviously to
let f return Object. The change will go unnoticed in f and cause
secondary errors in callers of f. In the worst case even quite far away
from the callsite itself.
Wanting more?
private f(List<X> l) {
if (l.size()==1) {
return l[0]
} else {
return g(l.tail())
}
}
private g(List<X> l){f(l)}
to know the return type of f I need to know the return type of g, for
which I need to know the return type of f... global type inference could
solve such problems, but makes about everything else more complicated
bye Jochen