Skip to content

Commit

Permalink
Ignore null in generic lambda tparams
Browse files Browse the repository at this point in the history
Because of the way lambdas are synthesized by the JVM, at the call-site,
it is not possible to know which generic types do lambdas have via the
current reflection API.

Related but not strictly reasons why this happens can be found in JDK's
issue tracker: https://bugs.openjdk.java.net/browse/JDK-8178523?jql=text%20%7E%20%22lambda%20generic%20type%22

As a result, we ignore nulls that are returned by
`getGenericParameterTypes`.

Fixes sbt#389.
  • Loading branch information
jvican committed Sep 28, 2017
1 parent 8c4b996 commit bff7df1
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,14 @@ object ClassToAPI {
accumulate(t).filterNot(_ == null).distinct
}

@deprecated("No longer used", "0.13.0")
def parents(c: Class[_]): Seq[api.Type] = types(allSuperTypes(c))
def types(ts: Seq[Type]): Array[api.Type] = (ts filter (_ ne null) map reference).toArray
def types(ts: Seq[Type]): Array[api.Type] =
ts.filter(_ ne null).map(reference).toArray
def upperBounds(ts: Array[Type]): api.Type =
api.Structure.of(lzy(types(ts)), lzyEmptyDefArray, lzyEmptyDefArray)

@deprecated("No longer used", "0.13.0")
def parents(c: Class[_]): Seq[api.Type] = types(allSuperTypes(c))

@deprecated("Use fieldToDef[4] instead", "0.13.9")
def fieldToDef(enclPkg: Option[String])(f: Field): api.FieldLike = {
val c = f.getDeclaringClass
Expand Down Expand Up @@ -496,12 +498,18 @@ object ClassToAPI {
api.Projection.of(api.Singleton.of(pathFromString(p)), cls)
}
}

// sbt/zinc#389: Ignore nulls coming from generic parameter types of lambdas
private[this] def ignoreNulls[T: scala.reflect.ClassTag](genericTypes: Array[T]): Array[T] =
genericTypes.filter(_ != null)

def referenceP(t: ParameterizedType): api.Parameterized = {
val targs = t.getActualTypeArguments
val targs = ignoreNulls(t.getActualTypeArguments)
val args = if (targs.isEmpty) emptyTypeArray else arrayMap(targs)(t => reference(t): api.Type)
val base = reference(t.getRawType)
api.Parameterized.of(base, args)
}

def reference(t: Type): api.Type =
t match {
case _: WildcardType => reference("_")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package typeparameters;

import java.util.function.Supplier;

public class Example {

static <I, O> void call() {
Supplier<BaseBlah<I, O>> blah = () ->
new BaseBlah<I, O>() {
@Override
protected O getResponseInternal(I i) {
return null;
}
};
}

public static void main(String[] args) {
Example.<String, String>call();
}
}

abstract class BaseBlah<I, O> {
protected O getResponseInternal(I i) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> compile

0 comments on commit bff7df1

Please sign in to comment.