Skip to content

Commit 3aa4b0d

Browse files
committed
Always nullify type param refs from Java
1 parent 75dd9d4 commit 3aa4b0d

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

compiler/src/dotty/tools/dotc/core/ImplicitNullInterop.scala

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)