Hygienic nest desugaring of private constructor access.
Bug: 158159959
Change-Id: I5c9e63bc1e4fecd21fcecbbeee011e45abf6d0d7
Fixes: 176900254
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 30ac84b..9675f9c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -25,7 +25,6 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.desugar.nest.NestBasedAccessDesugaring;
import com.android.tools.r8.kotlin.Kotlin;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -454,10 +453,6 @@
createStaticallyKnownType("Landroid/util/Property;");
public final DexType androidViewViewType = createStaticallyKnownType("Landroid/view/View;");
- public final DexString nestConstructorDescriptor =
- createString("L" + NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME + ";");
- public final DexType nestConstructorType = createStaticallyKnownType(nestConstructorDescriptor);
-
public final StringBuildingMethods stringBuilderMethods =
new StringBuildingMethods(stringBuilderType);
public final StringBuildingMethods stringBufferMethods =
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 76d2ea4..902e3b7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.desugar.nest.NestBasedAccessDesugaring;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.structural.CompareToVisitor;
@@ -36,6 +35,7 @@
"$-DC",
"$$ServiceLoaderMethods",
"com.android.tools.r8.GeneratedOutlineSupport",
+ "-$$Nest$Constructor",
"-$$Lambda$");
public final DexString descriptor;
@@ -308,8 +308,7 @@
private static boolean isSynthesizedTypeThatCouldBeDuplicated(String name) {
// Any entry that is removed from here must be added to OLD_SYNTHESIZED_NAMES to ensure that
// newer releases can be used to merge previous builds.
- return name.contains(LAMBDA_GROUP_CLASS_NAME_PREFIX) // Could collide.
- || name.contains(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME); // Global singleton.
+ return name.contains(LAMBDA_GROUP_CLASS_NAME_PREFIX);
}
private boolean oldSynthesizedName(String name) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 4131111..6960b96 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -398,12 +398,8 @@
}
}
- private void finalizeNestBasedAccessDesugaring(Builder<?> builder) {
+ private void reportNestDesugarDependencies() {
if (d8NestBasedAccessDesugaring != null) {
- DexProgramClass nestConstructor = d8NestBasedAccessDesugaring.synthesizeNestConstructor();
- if (nestConstructor != null) {
- builder.addProgramClass(nestConstructor);
- }
d8NestBasedAccessDesugaring.reportDesugarDependencies();
}
}
@@ -489,10 +485,7 @@
convertClasses(application, executor);
- // Build a new application with jumbo string info,
- Builder<?> builder = application.builder().setHighestSortingString(highestSortingString);
-
- finalizeNestBasedAccessDesugaring(builder);
+ reportNestDesugarDependencies();
// Synthesize lambda classes and commit to the app in full.
synthesizeLambdaClasses(executor);
@@ -500,13 +493,14 @@
if (appView.getSyntheticItems().hasPendingSyntheticClasses()) {
appView.setAppInfo(
new AppInfo(
- appView.appInfo().getSyntheticItems().commit(builder.build()),
+ appView.appInfo().getSyntheticItems().commit(application),
appView.appInfo().getMainDexClasses()));
application = appView.appInfo().app();
- builder = application.builder();
- builder.setHighestSortingString(highestSortingString);
}
+ // Build a new application with jumbo string info,
+ Builder<?> builder = application.builder().setHighestSortingString(highestSortingString);
+
desugarInterfaceMethods(builder, ExcludeDexResources, executor);
processSynthesizedJava8UtilityClasses(executor);
synthesizeRetargetClass(builder, executor);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index cbaa05a..c516ce8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -10,18 +10,14 @@
import com.android.tools.r8.cf.code.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
-import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.Code;
-import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMember;
@@ -30,21 +26,20 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexTypeList;
-import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.LibraryMember;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.origin.SynthesizedOrigin;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import org.objectweb.asm.Opcodes;
@@ -63,14 +58,10 @@
private static final String NEST_ACCESS_FIELD_PUT_NAME_PREFIX = NEST_ACCESS_NAME_PREFIX + "fput";
private static final String NEST_ACCESS_STATIC_PUT_FIELD_NAME_PREFIX =
NEST_ACCESS_NAME_PREFIX + "sfput";
- public static final String NEST_CONSTRUCTOR_NAME = NEST_ACCESS_NAME_PREFIX + "Constructor";
protected final AppView<?> appView;
private final DexItemFactory dexItemFactory;
-
- // Common single empty class for nest based private constructors
- private DexProgramClass nestConstructor;
- private boolean nestConstructorUsed;
+ private final Map<DexType, DexType> syntheticNestConstructorTypes = new ConcurrentHashMap<>();
public NestBasedAccessDesugaring(AppView<?> appView) {
this.appView = appView;
@@ -234,40 +225,6 @@
throw appView.options().errorMissingNestMember(nest);
}
- private DexProgramClass createNestAccessConstructor() {
- // TODO(b/176900254): ensure hygienic synthetic class.
- return new DexProgramClass(
- dexItemFactory.nestConstructorType,
- null,
- new SynthesizedOrigin("Nest based access desugaring", getClass()),
- // Make the synthesized class public since shared in the whole program.
- ClassAccessFlags.fromDexAccessFlags(
- Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
- dexItemFactory.objectType,
- DexTypeList.empty(),
- dexItemFactory.createString("nest"),
- null,
- Collections.emptyList(),
- null,
- Collections.emptyList(),
- ClassSignature.noSignature(),
- DexAnnotationSet.empty(),
- DexEncodedField.EMPTY_ARRAY,
- DexEncodedField.EMPTY_ARRAY,
- DexEncodedMethod.EMPTY_ARRAY,
- DexEncodedMethod.EMPTY_ARRAY,
- dexItemFactory.getSkipNameValidationForTesting(),
- DexProgramClass::checksumFromType);
- }
-
- public DexProgramClass synthesizeNestConstructor() {
- if (nestConstructorUsed && nestConstructor == null) {
- nestConstructor = createNestAccessConstructor();
- return nestConstructor;
- }
- return null;
- }
-
DexMethod ensureFieldAccessBridge(
DexClassAndField field, boolean isGet, NestBridgeConsumer bridgeConsumer) {
if (field.isProgramField()) {
@@ -360,9 +317,31 @@
private DexMethod getMethodBridgeReference(DexClassAndMethod method) {
if (method.getDefinition().isInstanceInitializer()) {
- DexProto newProto =
- dexItemFactory.appendTypeToProto(method.getProto(), dexItemFactory.nestConstructorType);
- nestConstructorUsed = true;
+ DexType nestConstructorType =
+ syntheticNestConstructorTypes.computeIfAbsent(
+ method.getHolderType(),
+ holder -> {
+ if (method.isProgramMethod()) {
+ return appView
+ .getSyntheticItems()
+ .createFixedClass(
+ SyntheticKind.INIT_TYPE_ARGUMENT,
+ method.asProgramMethod().getHolder(),
+ dexItemFactory,
+ builder -> {})
+ .getType();
+ } else {
+ assert method.isClasspathMethod();
+ return appView
+ .getSyntheticItems()
+ .createFixedClasspathClass(
+ SyntheticKind.INIT_TYPE_ARGUMENT,
+ method.asClasspathMethod().getHolder(),
+ dexItemFactory)
+ .getType();
+ }
+ });
+ DexProto newProto = dexItemFactory.appendTypeToProto(method.getProto(), nestConstructorType);
return method.getReference().withProto(newProto, dexItemFactory);
}
DexProto proto =
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index ce1dadb..8d661f9 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3155,8 +3155,6 @@
Map<DexMethod, ProgramMethod> liveMethods = new IdentityHashMap<>();
- Map<DexType, DexProgramClass> syntheticProgramClasses = new IdentityHashMap<>();
-
Map<DexType, DexClasspathClass> syntheticClasspathClasses = new IdentityHashMap<>();
// Subset of live methods that need have keep requirements.
@@ -3171,7 +3169,6 @@
desugaredMethods.isEmpty()
&& syntheticInstantiations.isEmpty()
&& liveMethods.isEmpty()
- && syntheticProgramClasses.isEmpty()
&& syntheticClasspathClasses.isEmpty();
assert !empty || (liveMethodsWithKeepActions.isEmpty() && mainDexTypes.isEmpty());
return empty;
@@ -3187,11 +3184,6 @@
assert old == null;
}
- void addProgramClass(DexProgramClass clazz) {
- DexProgramClass old = syntheticProgramClasses.put(clazz.type, clazz);
- assert old == null;
- }
-
void addLiveMethod(ProgramMethod method) {
DexMethod signature = method.getDefinition().method;
assert !liveMethods.containsKey(signature);
@@ -3206,7 +3198,6 @@
void amendApplication(Builder appBuilder) {
assert !isEmpty();
- appBuilder.addProgramClasses(syntheticProgramClasses.values());
appBuilder.addClasspathClasses(syntheticClasspathClasses.values());
}
@@ -3283,7 +3274,6 @@
synthesizeLambdas(additions);
synthesizeLibraryConversionWrappers(additions);
synthesizeBackports(additions);
- synthesizeNestConstructor(additions);
synthesizeTwrCloseResource(additions);
if (additions.isEmpty()) {
return;
@@ -3372,16 +3362,6 @@
}
}
- private void synthesizeNestConstructor(SyntheticAdditions additions) {
- if (nestBasedAccessRewriter != null) {
- DexProgramClass nestConstructor = nestBasedAccessRewriter.synthesizeNestConstructor();
- if (nestConstructor != null) {
- // TODO(b/177638147): use getSyntheticItems().createClass().
- additions.addProgramClass(nestConstructor);
- }
- }
- }
-
private void synthesizeTwrCloseResource(SyntheticAdditions additions) {
for (ProgramMethod method : methodsWithTwrCloseResource.values()) {
twrCloseResourceRewriter.rewriteCf(method, additions::addLiveMethod);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 932359d..f6da35b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.MainDexClasses;
import com.android.tools.r8.synthesis.SyntheticNaming.Phase;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import java.util.Comparator;
import java.util.Set;
@@ -63,14 +64,27 @@
}
static SynthesizingContext fromSyntheticContextChange(
- DexType syntheticType, SynthesizingContext oldContext, DexItemFactory factory) {
+ SyntheticKind kind,
+ DexType syntheticType,
+ SynthesizingContext oldContext,
+ DexItemFactory factory) {
String descriptor = syntheticType.toDescriptorString();
- int i = descriptor.indexOf(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
- if (i <= 0) {
- assert false : "Unexpected synthetic without internal separator: " + syntheticType;
- return null;
+ DexType newContext;
+ if (kind.isFixedSuffixSynthetic) {
+ int i = descriptor.lastIndexOf(kind.descriptor);
+ if (i < 0 || descriptor.length() != i + kind.descriptor.length() + 1) {
+ assert false : "Unexpected fixed synthetic with invalid suffix: " + syntheticType;
+ return null;
+ }
+ newContext = factory.createType(descriptor.substring(0, i) + ";");
+ } else {
+ int i = descriptor.indexOf(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
+ if (i <= 0) {
+ assert false : "Unexpected synthetic without internal separator: " + syntheticType;
+ return null;
+ }
+ newContext = factory.createType(descriptor.substring(0, i) + ";");
}
- DexType newContext = factory.createType(descriptor.substring(0, i) + ";");
return newContext == oldContext.getSynthesizingContextType()
? oldContext
: new SynthesizingContext(newContext, newContext, oldContext.inputContextOrigin);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index eefe1b9..239e7d0 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -64,7 +64,7 @@
final HashCode computeHash(
RepresentativeMap map, boolean intermediate, ClassToFeatureSplitMap classToFeatureSplitMap) {
Hasher hasher = Hashing.murmur3_128().newHasher();
- if (intermediate) {
+ if (intermediate || getKind().isFixedSuffixSynthetic) {
// If in intermediate mode, include the context type as sharing is restricted to within a
// single context.
getContext().getSynthesizingContextType().hashWithTypeEquivalence(hasher, map);
@@ -95,7 +95,7 @@
boolean includeContext,
GraphLens graphLens,
ClassToFeatureSplitMap classToFeatureSplitMap) {
- if (includeContext) {
+ if (includeContext || getKind().isFixedSuffixSynthetic) {
int order = getContext().compareTo(other.getContext());
if (order != 0) {
return order;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index e2e0b55..2d5ec60 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -765,16 +765,17 @@
DexType representativeContext,
Map<DexType, NumberGenerator> generators,
AppView<?> appView) {
+ DexItemFactory factory = appView.dexItemFactory();
+ if (kind.isFixedSuffixSynthetic) {
+ return SyntheticNaming.createExternalType(kind, representativeContext, "", factory);
+ }
NumberGenerator generator =
generators.computeIfAbsent(representativeContext, k -> new NumberGenerator());
DexType externalType;
do {
externalType =
SyntheticNaming.createExternalType(
- kind,
- representativeContext,
- Integer.toString(generator.next()),
- appView.dexItemFactory());
+ kind, representativeContext, Integer.toString(generator.next()), factory);
DexClass clazz = appView.appInfo().definitionForWithoutExistenceAssert(externalType);
if (clazz != null && isNotSyntheticType(clazz.type)) {
assert options.testing.allowConflictingSyntheticTypes
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index c198197..c40dbee 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -305,6 +305,36 @@
return clazz;
}
+ public DexProgramClass createFixedClass(
+ SyntheticKind kind,
+ DexProgramClass context,
+ DexItemFactory factory,
+ Consumer<SyntheticProgramClassBuilder> fn) {
+ // Obtain the outer synthesizing context in the case the context itself is synthetic.
+ // This is to ensure a flat input-type -> synthetic-item mapping.
+ SynthesizingContext outerContext = getSynthesizingContext(context);
+ DexType type = SyntheticNaming.createFixedType(kind, outerContext, factory);
+ SyntheticProgramClassBuilder classBuilder =
+ new SyntheticProgramClassBuilder(type, outerContext, factory);
+ fn.accept(classBuilder);
+ DexProgramClass clazz = classBuilder.build();
+ addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
+ return clazz;
+ }
+
+ public DexClasspathClass createFixedClasspathClass(
+ SyntheticKind kind, DexClasspathClass context, DexItemFactory factory) {
+ // Obtain the outer synthesizing context in the case the context itself is synthetic.
+ // This is to ensure a flat input-type -> synthetic-item mapping.
+ SynthesizingContext outerContext = SynthesizingContext.fromNonSyntheticInputContext(context);
+ DexType type = SyntheticNaming.createFixedType(kind, outerContext, factory);
+ SyntheticClasspathClassBuilder classBuilder =
+ new SyntheticClasspathClassBuilder(type, outerContext, factory);
+ DexClasspathClass clazz = classBuilder.build();
+ addPendingDefinition(new SyntheticClasspathClassDefinition(kind, outerContext, clazz));
+ return clazz;
+ }
+
/** Create a single synthetic method item. */
public ProgramMethod createMethod(
SyntheticKind kind,
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
index 09a0f1a..0b53962 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
@@ -66,7 +66,7 @@
if (method != rewritten) {
context =
SynthesizingContext.fromSyntheticContextChange(
- rewritten.holder, context, lens.dexItemFactory());
+ getKind(), rewritten.holder, context, lens.dexItemFactory());
if (context == null) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index fc5b278..c433ec0 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -24,6 +24,7 @@
// Class synthetics.
COMPANION_CLASS("CompanionClass", false),
LAMBDA("Lambda", false),
+ INIT_TYPE_ARGUMENT("-IA", false, true),
// Method synthetics.
BACKPORT("Backport", true),
STATIC_INTERFACE_CALL("StaticInterfaceCall", true),
@@ -37,10 +38,17 @@
public final String descriptor;
public final boolean isSingleSyntheticMethod;
+ public final boolean isFixedSuffixSynthetic;
SyntheticKind(String descriptor, boolean isSingleSyntheticMethod) {
+ this(descriptor, isSingleSyntheticMethod, false);
+ }
+
+ SyntheticKind(
+ String descriptor, boolean isSingleSyntheticMethod, boolean isFixedSuffixSynthetic) {
this.descriptor = descriptor;
this.isSingleSyntheticMethod = isSingleSyntheticMethod;
+ this.isFixedSuffixSynthetic = isFixedSuffixSynthetic;
}
public static SyntheticKind fromDescriptor(String descriptor) {
@@ -73,8 +81,15 @@
|| typeName.contains(EXTERNAL_SYNTHETIC_CLASS_SEPARATOR);
}
+ public static DexType createFixedType(
+ SyntheticKind kind, SynthesizingContext context, DexItemFactory factory) {
+ assert kind.isFixedSuffixSynthetic;
+ return createType("", kind, context.getSynthesizingContextType(), "", factory);
+ }
+
static DexType createInternalType(
SyntheticKind kind, SynthesizingContext context, String id, DexItemFactory factory) {
+ assert !kind.isFixedSuffixSynthetic;
return createType(
INTERNAL_SYNTHETIC_CLASS_SEPARATOR,
kind,
@@ -85,7 +100,13 @@
static DexType createExternalType(
SyntheticKind kind, DexType context, String id, DexItemFactory factory) {
- return createType(EXTERNAL_SYNTHETIC_CLASS_SEPARATOR, kind, context, id, factory);
+ assert kind.isFixedSuffixSynthetic == id.isEmpty();
+ return createType(
+ kind.isFixedSuffixSynthetic ? "" : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR,
+ kind,
+ context,
+ id,
+ factory);
}
private static DexType createType(
@@ -134,6 +155,10 @@
static boolean isSynthetic(ClassReference clazz, Phase phase, SyntheticKind kind) {
String typeName = clazz.getTypeName();
+ if (kind.isFixedSuffixSynthetic) {
+ assert phase == null;
+ return clazz.getBinaryName().endsWith(kind.descriptor);
+ }
String separator = getPhaseSeparator(phase);
int i = typeName.indexOf(separator);
return i >= 0 && checkMatchFrom(kind, typeName, i, separator, phase == Phase.EXTERNAL);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java
index 8b42eb6..3506dab 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java
@@ -48,7 +48,9 @@
@Override
public boolean isValid() {
- return clazz.isPublic() && clazz.isFinal() && clazz.accessFlags.isSynthetic();
+ return clazz.isPublic()
+ && clazz.accessFlags.isSynthetic()
+ && (clazz.isFinal() || clazz.isAbstract());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
index 3472268..7e798e0 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
@@ -53,7 +53,8 @@
// Ensure that if a synthetic moves its context moves consistently.
if (type != rewritten) {
context =
- SynthesizingContext.fromSyntheticContextChange(rewritten, context, lens.dexItemFactory());
+ SynthesizingContext.fromSyntheticContextChange(
+ getKind(), rewritten, context, lens.dexItemFactory());
if (context == null) {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index 8a9fc12..4de3828 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -24,7 +24,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
-import com.android.tools.r8.ir.desugar.nest.NestBasedAccessDesugaring;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.tracereferences.TraceReferences;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -154,15 +153,8 @@
.startsWith(
"Invalid parameter counts in MethodParameter attributes.")));
}
- // TODO(b/176900254): The nest check should not be necessary.
new CodeInspector(desugaredLib, mapping)
- .forAllClasses(
- clazz ->
- assertTrue(
- clazz.getFinalName().startsWith("j$.")
- || clazz
- .getOriginalName()
- .startsWith(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME)));
+ .forAllClasses(clazz -> assertTrue(clazz.getFinalName().startsWith("j$.")));
return desugaredLib;
} catch (Exception e) {
// Don't wrap assumption violation so junit can catch it.
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
index c55df8c..6557f52 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MinimumNumberOfBridgesGenerated.java
@@ -13,7 +13,10 @@
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.nest.NestBasedAccessDesugaring;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
@@ -79,9 +82,14 @@
private boolean isNestBridge(FoundMethodSubject methodSubject) {
DexEncodedMethod method = methodSubject.getMethod();
if (method.isInstanceInitializer()) {
- return method.method.proto.parameters.size() > 0 && method.method.proto.parameters.values[
- method.method.proto.parameters.size() - 1].toSourceString()
- .contains(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME);
+ if (method.method.proto.parameters.isEmpty()) {
+ return false;
+ }
+ DexType[] formals = method.method.proto.parameters.values;
+ DexType lastFormal = formals[formals.length - 1];
+ return lastFormal.isClassType()
+ && SyntheticItemsTestUtils.isInitializerTypeArgument(
+ Reference.classFromDescriptor(lastFormal.toDescriptorString()));
}
return method.method.name.toString()
.startsWith(NestBasedAccessDesugaring.NEST_ACCESS_NAME_PREFIX);
diff --git a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
index 3f9c6af..6f3a6cc 100644
--- a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -86,6 +86,10 @@
return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.OUTLINE);
}
+ public static boolean isInitializerTypeArgument(ClassReference reference) {
+ return SyntheticNaming.isSynthetic(reference, null, SyntheticKind.INIT_TYPE_ARGUMENT);
+ }
+
public static Matcher<String> containsInternalSyntheticReference() {
return containsString(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
}