@@ -68,14 +68,15 @@ object ImplicitNullInterop:
6868 if isEnumValueDef || sym.name == nme.TYPE_ || sym.is(Flags .ModuleVal ) then
6969 return tp
7070
71- // Skip result type for `toString`, constructors, and @NotNull methods
71+ // Don't nullify result type for `toString`, constructors, and @NotNull methods
7272 val skipResultType = sym.name == nme.toString_ || sym.isConstructor || hasNotNullAnnot(sym)
73- // Don't nullify parameter types for Scala-defined methods since those are already nullified
74- val skipParamTypes = sym.is(Method ) && ! sym.is(Flags .JavaDefined )
75- // Skip Given/implicit parameters
73+ // Don't nullify Given/implicit parameters
7674 val skipCurrentLevel = sym.isOneOf(GivenOrImplicitVal )
7775
78- val map = new ImplicitNullMap (skipResultType = skipResultType, skipParamTypes = skipParamTypes, skipCurrentLevel = skipCurrentLevel)
76+ val map = new ImplicitNullMap (
77+ javaDefined = sym.is(JavaDefined ),
78+ skipResultType = skipResultType,
79+ skipCurrentLevel = skipCurrentLevel)
7980 map(tp)
8081
8182 private def hasNotNullAnnot (sym : Symbol )(using Context ): Boolean =
@@ -85,15 +86,14 @@ object ImplicitNullInterop:
8586 * coming from Scala code compiled without explicit nulls, this adds `| Null` or `FlexibleType` in the
8687 * right places to make nullability explicit in a conservative way (without forcing incomplete symbols).
8788 *
89+ * @param javaDefined whether the type is from Java source, we always nullify type param refs from Java
8890 * @param skipResultType do not nullify the method result type at the outermost level (e.g. for `toString`,
8991 * constructors, or methods annotated as not-null)
90- * @param skipParamTypes do not nullify parameter types for the current method (used for Scala-defined methods
91- * or specific parameter sections)
9292 * @param skipCurrentLevel do not nullify at the current level (used for implicit/Given parameters, varargs, etc.)
9393 */
9494 private class ImplicitNullMap (
95+ val javaDefined : Boolean ,
9596 var skipResultType : Boolean = false ,
96- var skipParamTypes : Boolean = false ,
9797 var skipCurrentLevel : Boolean = false
9898 )(using Context ) extends TypeMap :
9999
@@ -109,6 +109,7 @@ object ImplicitNullInterop:
109109 if skipCurrentLevel || ! tp.hasSimpleKind then false
110110 else tp.dealias match
111111 case tp : TypeRef =>
112+ // We don't modify value types because they're non-nullable even in Java.
112113 val isValueOrSpecialClass =
113114 tp.symbol.isValueClass
114115 || tp.isRef(defn.NullClass )
@@ -117,8 +118,9 @@ object ImplicitNullInterop:
117118 || tp.isRef(defn.SingletonClass )
118119 || tp.isRef(defn.AnyKindClass )
119120 || tp.isRef(defn.AnyClass )
120- // We don't modify value types because they're non-nullable even in Java.
121- tp.symbol.isNullableClassAfterErasure && ! isValueOrSpecialClass
121+ ! isValueOrSpecialClass && (javaDefined || tp.symbol.isNullableClassAfterErasure)
122+ case tp : TypeParamRef =>
123+ javaDefined
122124 case _ => false
123125
124126 // We don't nullify varargs (repeated parameters) at the top level.
@@ -136,6 +138,8 @@ object ImplicitNullInterop:
136138 override def apply (tp : Type ): Type = tp match
137139 case tp : TypeRef if needsNull(tp) =>
138140 nullify(tp)
141+ case tp : TypeParamRef if needsNull(tp) =>
142+ nullify(tp)
139143 case appTp @ AppliedType (tycon, targs) =>
140144 val savedSkipCurrentLevel = skipCurrentLevel
141145
@@ -151,9 +155,8 @@ object ImplicitNullInterop:
151155 case mtp : MethodType =>
152156 val savedSkipCurrentLevel = skipCurrentLevel
153157
154- // Skip param types for implicit/using sections
155- val skipThisParamList = skipParamTypes || mtp.isImplicitMethod
156- skipCurrentLevel = skipThisParamList
158+ // Don't nullify param types for implicit/using sections
159+ skipCurrentLevel = mtp.isImplicitMethod
157160 val paramInfos2 = mtp.paramInfos.map(this )
158161
159162 skipCurrentLevel = skipResultType
0 commit comments