incremental compilation: handle property mutability changes (KT-76927)

(cherry picked from commit 43c22d037a7d895066f2e0d9aa32cf13cc0d7543)

GitOrigin-RevId: 472c56cf5750b3ccf1950b58d9981dfda7554ab3
This commit is contained in:
Eugene Zhuravlev
2025-10-31 17:06:26 +01:00
committed by intellij-monorepo-bot
parent 4c7e2a21dc
commit 279ee7af86
7 changed files with 57 additions and 3 deletions

View File

@@ -477,7 +477,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
@Override
public boolean unchanged() {
return !typeChanged() && !visibilityChanged() && !customAccessorAdded();
return !typeChanged() && !visibilityChanged() && !customAccessorAdded() && !mutabilityChanged();
}
public boolean typeChanged() {
@@ -492,6 +492,10 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
return Attributes.isNullable(past.getReturnType()) && !Attributes.isNullable(now.getReturnType());
}
public boolean mutabilityChanged() {
return Attributes.isVar(past) != Attributes.isVar(now);
}
public boolean visibilityChanged() {
return Attributes.getVisibility(past) != Attributes.getVisibility(now) || getGetterVisibility(past) != getGetterVisibility(now) || getSetterVisibility(past) != getSetterVisibility(now);
}

View File

@@ -420,8 +420,19 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
for (Difference.Change<KmProperty, KotlinMeta.KmPropertiesDiff> propChange : metaDiff.properties().changed()) {
KmProperty changedProp = propChange.getPast();
KotlinMeta.KmPropertiesDiff propDiff = propChange.getDiff();
if (propDiff.accessRestricted() || propDiff.customAccessorAdded()) {
debug(context, "A property has become less accessible or got custom accessors; affecting its lookup usages ", changedProp.getName());
String affectLookupUsagesReason = null;
if (propDiff.accessRestricted()) {
affectLookupUsagesReason = "Property has become less accessible; affecting its lookup usages ";
}
else if (propDiff.customAccessorAdded()) {
affectLookupUsagesReason = "Custom accessors were added to a property; affecting its lookup usages ";
}
else if (propDiff.mutabilityChanged()) {
affectLookupUsagesReason = "Property mutability has changed (val <=> var); affecting its lookup usages ";
}
if (affectLookupUsagesReason != null) {
debug(context, affectLookupUsagesReason, changedProp.getName());
affectMemberLookupUsages(context, changedClass, changedProp.getName(), future, cache);
}

View File

@@ -0,0 +1,6 @@
internal fun doSmth(bar: Int) {}
fun main() {
val foo = Foo()
if (foo.bar != null) doSmth(foo.bar)
}

View File

@@ -0,0 +1,22 @@
================ Step #1 =================
Cleaning output files:
out/production/module/Foo.class
out/production/module/META-INF/module.kotlin_module
End of files
Compiling files:
src/foo.kt
End of files
Exit code: OK
------------------------------------------
Cleaning output files:
out/production/module/AppKt.class
out/production/module/META-INF/module.kotlin_module
End of files
Compiling files:
src/app.kt
End of files
Exit code: ABORT
------------------------------------------
COMPILATION FAILED
Smart cast to 'Int' is impossible, because 'bar' is a mutable property that could be mutated concurrently.

View File

@@ -0,0 +1,3 @@
class Foo(
val bar: Int? = null
)

View File

@@ -0,0 +1,3 @@
class Foo(
var bar: Int? = null
)

View File

@@ -601,6 +601,11 @@ public class IncrementalK2JvmJpsTestGenerated extends AbstractIncrementalK2JvmJp
runTest("pureKotlin/propertyRedeclaration/");
}
@TestMetadata("valPropertyBecameWritable")
public void testValPropertyBecameWritable() throws Exception {
runTest("pureKotlin/valPropertyBecameWritable/");
}
@TestMetadata("publicPropertyWithPrivateSetter")
public void testPublicPropertyWithPrivateSetter() throws Exception {
runTest("pureKotlin/publicPropertyWithPrivateSetter/");