-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Partial handling for restrictive annotations on varargs in unannotated code #1029
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1029 +/- ##
============================================
- Coverage 87.28% 87.23% -0.05%
- Complexity 2117 2129 +12
============================================
Files 83 83
Lines 6943 6965 +22
Branches 1346 1356 +10
============================================
+ Hits 6060 6076 +16
- Misses 456 458 +2
- Partials 427 431 +4 ☔ View full report in Codecov by Sentry. |
@@ -200,7 +200,8 @@ public void testSkipJetbrainsNotNullOnVarArgsFromThirdPartyJars() { | |||
" ThirdParty.takesNullableVarargs(o1);", // Empty var args passed | |||
" ThirdParty.takesNullableVarargs(o1, o4);", | |||
" ThirdParty.takesNullableVarargs(o1, (Object) null);", | |||
" // BUG: Diagnostic contains: passing @Nullable parameter '(Object[]) null' where @NonNull", | |||
" // No error: we require a type-use annotation for nullability of the varargs array itself", | |||
// TODO should we preserve the old behavior in legacy mode? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lazaroclapp with this change, we no longer detect an error when passing a null
array in the varargs position to a third-party method with a JetBrains @NotNull
annotation on the varargs parameter. On the one hand, getting an error here is the "desired" behavior, in that the annotation is supposed to apply to the array itself (see #720). But, everywhere else, a declaration annotation on the varargs argument is treated as applying to the contents of the array, not the array itself. To me, adding the extra code complexity to detect these errors in legacy mode for this corner case is not worth it; hopefully Kotlinc will be convinced to put annotations in the "right" place soon. But I'd be interested in your opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think without a coordinated change on kotlinc
, I would prefer to keep the hack. But I don't feel super strongly about it. It's just an additional test of (a) is the annotation in bytecode, (b) is it the jetbrains annotation, (c) is it in var args... if all that is true, hacky override with a comment linking to the issue. No? Would this be hard to maintain?
Unfortunately, Java code interfacing with Kotlin code is a big portion of what we will see in Android for the foreseeable future, so kotlinc
quirks might be the kind of thing we can't ignore for the sake of uniformity. Though if you can convince them to generate the "right" bytecode, I'd be happy to see this hack disappear (hopefully we don't need then to analyze magic numbers to see which kotlinc
version produced the jar)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right; it looks like for now kotlinc
will be emitting similar bytecodes. Fixed in 7330a20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely an incomplete fix, as the description clearly states, but also a step in the right direction. See comments below. All addressable in follow ups, of course.
if ((arraySymbol.flags() & Flags.VARARGS) != 0) { | ||
return Nullness.hasNonNullDeclarationAnnotation(arraySymbol, config); | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is codecov correct here that we never test the case where this method returns false
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is correct. We should get coverage of this line when we add logic to process restrictive @NonNull
annotations on array elements in positions other than the varargs position, which we will do in a follow up.
@@ -200,7 +200,8 @@ public void testSkipJetbrainsNotNullOnVarArgsFromThirdPartyJars() { | |||
" ThirdParty.takesNullableVarargs(o1);", // Empty var args passed | |||
" ThirdParty.takesNullableVarargs(o1, o4);", | |||
" ThirdParty.takesNullableVarargs(o1, (Object) null);", | |||
" // BUG: Diagnostic contains: passing @Nullable parameter '(Object[]) null' where @NonNull", | |||
" // No error: we require a type-use annotation for nullability of the varargs array itself", | |||
// TODO should we preserve the old behavior in legacy mode? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think without a coordinated change on kotlinc
, I would prefer to keep the hack. But I don't feel super strongly about it. It's just an additional test of (a) is the annotation in bytecode, (b) is it the jetbrains annotation, (c) is it in var args... if all that is true, hacky override with a comment linking to the issue. No? Would this be hard to maintain?
Unfortunately, Java code interfacing with Kotlin code is a big portion of what we will see in Android for the foreseeable future, so kotlinc
quirks might be the kind of thing we can't ignore for the sake of uniformity. Though if you can convince them to generate the "right" bytecode, I'd be happy to see this hack disappear (hopefully we don't need then to analyze magic numbers to see which kotlinc
version produced the jar)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review!
if ((arraySymbol.flags() & Flags.VARARGS) != 0) { | ||
return Nullness.hasNonNullDeclarationAnnotation(arraySymbol, config); | ||
} | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is correct. We should get coverage of this line when we add logic to process restrictive @NonNull
annotations on array elements in positions other than the varargs position, which we will do in a follow up.
@@ -200,7 +200,8 @@ public void testSkipJetbrainsNotNullOnVarArgsFromThirdPartyJars() { | |||
" ThirdParty.takesNullableVarargs(o1);", // Empty var args passed | |||
" ThirdParty.takesNullableVarargs(o1, o4);", | |||
" ThirdParty.takesNullableVarargs(o1, (Object) null);", | |||
" // BUG: Diagnostic contains: passing @Nullable parameter '(Object[]) null' where @NonNull", | |||
" // No error: we require a type-use annotation for nullability of the varargs array itself", | |||
// TODO should we preserve the old behavior in legacy mode? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right; it looks like for now kotlinc
will be emitting similar bytecodes. Fixed in 7330a20
Partially addresses #1027. Most importantly, handles the case with unannotated methods and no restrictive annotations; we were getting warnings in some cases with the main branch, which impacts backward compatibility.
I started implementing full support for restrictive annotations on varargs parameters and then realized it would take some refactoring (since there can be a restrictive annotation on the varargs array itself or on its contents, and we have no way to express this in the current code structure). This PR contains some incomplete code towards that change, which I figured does no harm so I left it in for now. If desired I can remove it and put it in a separate PR.