Reland "Do not rewrite generic signatures in target of merged classes" This reverts commit ceac696c81a3a23a960ebd0acb4992019c29e053. Bug: 147386014 Change-Id: I55e5b7a6ffcc23188e7c631d577f0ca824cd093e
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java index d0240e9..d13cc3b 100644 --- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java +++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -13,6 +13,7 @@ import com.android.tools.r8.graph.DexClass; import com.android.tools.r8.graph.DexEncodedField; import com.android.tools.r8.graph.DexEncodedMethod; +import com.android.tools.r8.graph.DexProgramClass; import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; @@ -24,12 +25,14 @@ import com.android.tools.r8.utils.DescriptorUtils; import com.android.tools.r8.utils.InternalOptions; import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode; +import com.android.tools.r8.utils.IteratorUtils; import com.android.tools.r8.utils.Timing; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -132,7 +135,15 @@ timing.end(); timing.begin("rename-generic"); - new GenericSignatureRewriter(appView, renaming).run(classes); + new GenericSignatureRewriter(appView, renaming) + .run( + new Iterable<DexProgramClass>() { + @Override + public Iterator<DexProgramClass> iterator() { + return IteratorUtils.<DexClass, DexProgramClass>filter( + classes.iterator(), DexClass::isProgramClass); + } + }); timing.end(); timing.begin("rename-arrays");
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureAction.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureAction.java index 6753e06..7cb3506 100644 --- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureAction.java +++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureAction.java
@@ -9,11 +9,17 @@ */ public interface GenericSignatureAction<T> { + enum ParserPosition { + CLASS_SUPER_OR_INTERFACE_ANNOTATION, + ENCLOSING_INNER_OR_TYPE_ANNOTATION, + MEMBER_ANNOTATION + } + public void parsedSymbol(char symbol); public void parsedIdentifier(String identifier); - public T parsedTypeName(String name); + public T parsedTypeName(String name, ParserPosition isTopLevel); public T parsedInnerTypeName(T enclosingType, String name);
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureParser.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureParser.java index c1f6a7d..dc0aa8c 100644 --- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureParser.java +++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureParser.java
@@ -4,6 +4,7 @@ package com.android.tools.r8.naming.signature; +import com.android.tools.r8.naming.signature.GenericSignatureAction.ParserPosition; import java.lang.reflect.GenericSignatureFormatError; import java.nio.CharBuffer; @@ -50,7 +51,7 @@ */ public class GenericSignatureParser<T> { - private final GenericSignatureAction<T> actions; + private GenericSignatureAction<T> actions; /* * Parser: @@ -110,7 +111,7 @@ try { actions.start(); setInput(signature); - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION); actions.stop(); } catch (GenericSignatureFormatError e) { throw e; @@ -141,11 +142,11 @@ parseOptFormalTypeParameters(); // SuperclassSignature ::= ClassTypeSignature. - parseClassTypeSignature(); + parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION); while (symbol > 0) { // SuperinterfaceSignature ::= ClassTypeSignature. - parseClassTypeSignature(); + parseClassTypeSignature(ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION); } } @@ -178,28 +179,28 @@ expect(':'); if (symbol == 'L' || symbol == '[' || symbol == 'T') { - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION); } while (symbol == ':') { // InterfaceBound ::= ":" FieldTypeSignature. actions.parsedSymbol(symbol); scanSymbol(); - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.MEMBER_ANNOTATION); } } - private void parseFieldTypeSignature() { + private void parseFieldTypeSignature(ParserPosition parserPosition) { // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature. switch (symbol) { case 'L': - parseClassTypeSignature(); + parseClassTypeSignature(parserPosition); break; case '[': - // ArrayTypeSignature ::= "[" TypSignature. + // ArrayTypeSignature ::= "[" TypeSignature. actions.parsedSymbol(symbol); scanSymbol(); - updateTypeSignature(); + updateTypeSignature(parserPosition); break; case 'T': updateTypeVariableSignature(); @@ -209,7 +210,7 @@ } } - private void parseClassTypeSignature() { + private void parseClassTypeSignature(ParserPosition parserPosition) { // ClassTypeSignature ::= "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments} // ";". actions.parsedSymbol(symbol); @@ -226,18 +227,22 @@ } qualIdent.append(this.identifier); - T parsedEnclosingType = actions.parsedTypeName(qualIdent.toString()); + T parsedEnclosingType = actions.parsedTypeName(qualIdent.toString(), parserPosition); - updateOptTypeArguments(); - - while (symbol == '.') { - // Deal with Member Classes: - actions.parsedSymbol(symbol); - scanSymbol(); - scanIdentifier(); - assert identifier != null; - parsedEnclosingType = actions.parsedInnerTypeName(parsedEnclosingType, identifier); + if (parsedEnclosingType != null) { + // We should only parse any optional type arguments and member classes if we have not merged + // the class into the current subtype. updateOptTypeArguments(); + + while (symbol == '.') { + // Deal with Member Classes. + actions.parsedSymbol(symbol); + scanSymbol(); + scanIdentifier(); + assert identifier != null; + parsedEnclosingType = actions.parsedInnerTypeName(parsedEnclosingType, identifier); + updateOptTypeArguments(); + } } actions.parsedSymbol(symbol); @@ -268,13 +273,13 @@ } else if (symbol == '+') { actions.parsedSymbol(symbol); scanSymbol(); - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION); } else if (symbol == '-') { actions.parsedSymbol(symbol); scanSymbol(); - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION); } else { - parseFieldTypeSignature(); + parseFieldTypeSignature(ParserPosition.ENCLOSING_INNER_OR_TYPE_ANNOTATION); } } @@ -291,7 +296,7 @@ expect(';'); } - private void updateTypeSignature() { + private void updateTypeSignature(ParserPosition parserPosition) { switch (symbol) { case 'B': case 'C': @@ -306,7 +311,7 @@ break; default: // Not an elementary type, but a FieldTypeSignature. - parseFieldTypeSignature(); + parseFieldTypeSignature(parserPosition); } } @@ -319,7 +324,7 @@ expect('('); while (symbol != ')' && (symbol > 0)) { - updateTypeSignature(); + updateTypeSignature(ParserPosition.MEMBER_ANNOTATION); } actions.parsedSymbol(symbol); @@ -336,7 +341,7 @@ if (symbol == 'T') { updateTypeVariableSignature(); } else { - parseClassTypeSignature(); + parseClassTypeSignature(ParserPosition.MEMBER_ANNOTATION); } } while (symbol == '^'); } @@ -345,7 +350,7 @@ private void updateReturnType() { // ReturnType ::= TypeSignature | "V". if (symbol != 'V') { - updateTypeSignature(); + updateTypeSignature(ParserPosition.MEMBER_ANNOTATION); } else { actions.parsedSymbol(symbol); scanSymbol();
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java index c3b7188..13c2c43 100644 --- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java +++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -10,8 +10,8 @@ import com.android.tools.r8.graph.AppView; import com.android.tools.r8.graph.DexAnnotation; import com.android.tools.r8.graph.DexAnnotationSet; -import com.android.tools.r8.graph.DexClass; import com.android.tools.r8.graph.DexDefinition; +import com.android.tools.r8.graph.DexProgramClass; import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.origin.Origin; @@ -43,15 +43,16 @@ this.reporter = appView.options().reporter; } - public void run(Iterable<? extends DexClass> classes) { + public void run(Iterable<? extends DexProgramClass> classes) { final GenericSignatureCollector genericSignatureCollector = new GenericSignatureCollector(); final GenericSignatureParser<DexType> genericSignatureParser = new GenericSignatureParser<>(genericSignatureCollector); - // classes may not be the same as appInfo().classes() if applymapping is used on classpath + // Classes may not be the same as appInfo().classes() if applymapping is used on classpath // arguments. If that is the case, the ProguardMapMinifier will pass in all classes that is // either ProgramClass or has a mapping. This is then transitively called inside the // ClassNameMinifier. - for (DexClass clazz : classes) { + for (DexProgramClass clazz : classes) { + genericSignatureCollector.setCurrentClassContext(clazz); clazz.annotations = rewriteGenericSignatures( clazz.annotations, @@ -152,13 +153,22 @@ private class GenericSignatureCollector implements GenericSignatureAction<DexType> { private StringBuilder renamedSignature; + private DexProgramClass currentClassContext; - public String getRenamedSignature() { + String getRenamedSignature() { return renamedSignature.toString(); } + void setCurrentClassContext(DexProgramClass clazz) { + currentClassContext = clazz; + } + @Override public void parsedSymbol(char symbol) { + if (symbol == ';' && renamedSignature.charAt(renamedSignature.length() - 1) == ';') { + // The type was never written (maybe because it was merged with it's subtype) + return; + } renamedSignature.append(symbol); } @@ -168,13 +178,24 @@ } @Override - public DexType parsedTypeName(String name) { - DexType type = appView.dexItemFactory().createType(getDescriptorFromClassBinaryName(name)); - type = appView.graphLense().lookupType(type); + public DexType parsedTypeName(String name, ParserPosition parserPosition) { + String originalDescriptor = getDescriptorFromClassBinaryName(name); + DexType type = + appView.graphLense().lookupType(appView.dexItemFactory().createType(originalDescriptor)); if (appView.appInfo().wasPruned(type)) { type = appView.dexItemFactory().objectType; } DexString renamedDescriptor = renaming.getOrDefault(type, type.descriptor); + if (parserPosition == ParserPosition.CLASS_SUPER_OR_INTERFACE_ANNOTATION + && currentClassContext != null) { + // We may have merged the type down to the current class type. + DexString classDescriptor = currentClassContext.type.descriptor; + if (!originalDescriptor.equals(classDescriptor.toString()) + && renamedDescriptor.equals(classDescriptor)) { + renamedSignature.deleteCharAt(renamedSignature.length() - 1); + return null; + } + } renamedSignature.append(getClassBinaryNameFromDescriptor(renamedDescriptor.toString())); return type; } @@ -197,6 +218,7 @@ type = appView.graphLense().lookupType(type); DexString renamedDescriptor = renaming.get(type); if (renamedDescriptor != null) { + // TODO(b/147504070): If this is a merged class equal to the class context, do not add. // Pick the renamed inner class from the fully renamed binary name. String fullRenamedBinaryName = getClassBinaryNameFromDescriptor(renamedDescriptor.toString());
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java index 69b77cd..62241d5 100644 --- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java +++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -383,7 +383,7 @@ } } if (clazz.getEnclosingMethod() != null || !clazz.getInnerClasses().isEmpty()) { - // TODO(herhut): Consider supporting merging of enclosing-method and inner-class attributes. + // TODO(b/147504070): Consider merging of enclosing-method and inner-class attributes. if (Log.ENABLED) { AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(clazz); } @@ -440,7 +440,7 @@ return false; } if (targetClass.getEnclosingMethod() != null || !targetClass.getInnerClasses().isEmpty()) { - // TODO(herhut): Consider supporting merging of enclosing-method and inner-class attributes. + // TODO(b/147504070): Consider merging of enclosing-method and inner-class attributes. if (Log.ENABLED) { AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(clazz); }
diff --git a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java index 7ffce35..f38c02a 100644 --- a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java +++ b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
@@ -16,7 +16,8 @@ public class IteratorUtils { - public static <T, S extends T> Iterator<S> filter(Iterator<T> iterator, Predicate<T> predicate) { + public static <T, S extends T> Iterator<S> filter( + Iterator<? extends T> iterator, Predicate<T> predicate) { return new Iterator<S>() { private S next = advance();
diff --git a/src/test/java/com/android/tools/r8/naming/GenericSignatureParserTest.java b/src/test/java/com/android/tools/r8/naming/GenericSignatureParserTest.java index b264ef5..4489b75 100644 --- a/src/test/java/com/android/tools/r8/naming/GenericSignatureParserTest.java +++ b/src/test/java/com/android/tools/r8/naming/GenericSignatureParserTest.java
@@ -22,6 +22,7 @@ import org.junit.Test; public class GenericSignatureParserTest extends TestBase { + private static class ReGenerateGenericSignatureRewriter implements GenericSignatureAction<String> { @@ -42,7 +43,7 @@ } @Override - public String parsedTypeName(String name) { + public String parsedTypeName(String name, ParserPosition parserPosition) { renamedSignature.append(name); return name; } @@ -389,7 +390,7 @@ } @Override - public String parsedTypeName(String name) { + public String parsedTypeName(String name, ParserPosition parserPosition) { throw exceptionSupplier.get(); } }
diff --git a/src/test/java/com/android/tools/r8/naming/signature/SignatureOfMergedClassesTest.java b/src/test/java/com/android/tools/r8/naming/signature/SignatureOfMergedClassesTest.java new file mode 100644 index 0000000..a9fc20f --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/SignatureOfMergedClassesTest.java
@@ -0,0 +1,122 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature; + +import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.android.tools.r8.CompilationFailedException; +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestParametersCollection; +import com.android.tools.r8.naming.signature.merging.I; +import com.android.tools.r8.naming.signature.merging.ImplI; +import com.android.tools.r8.naming.signature.merging.ImplK; +import com.android.tools.r8.naming.signature.merging.InterfaceToKeep; +import com.android.tools.r8.naming.signature.merging.J; +import com.android.tools.r8.naming.signature.merging.K; +import java.io.IOException; +import java.lang.invoke.LambdaConversionException; +import java.lang.reflect.Type; +import java.util.concurrent.ExecutionException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class SignatureOfMergedClassesTest extends TestBase { + + private final TestParameters parameters; + + @Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withAllRuntimesAndApiLevels().build(); + } + + public SignatureOfMergedClassesTest(TestParameters parameters) { + this.parameters = parameters; + } + + @Test + public void testRemovalOfMergedInterfaceOnSameClass() + throws IOException, CompilationFailedException, ExecutionException, + LambdaConversionException { + testForR8(parameters.getBackend()) + .addProgramClasses( + ImplI.class, ImplK.class, I.class, J.class, InterfaceToKeep.class, K.class, Main.class) + .addKeepMainRule(Main.class) + .addKeepClassRules(InterfaceToKeep.class) + .addKeepAttributes("Signature, InnerClasses, EnclosingMethod, *Annotation*") + .setMinApi(parameters.getApiLevel()) + .noMinification() + .addOptionsModification( + internalOptions -> { + internalOptions.enableUnusedInterfaceRemoval = false; + }) + .run(parameters.getRuntime(), Main.class) + .assertSuccessWithOutputLines( + "ImplI.foo", + "ImplI: com.android.tools.r8.naming.signature.merging.InterfaceToKeep<java.lang.Void>", + "K: com.android.tools.r8.naming.signature.merging.InterfaceToKeep<java.lang.Void>", + "ImplK.foo", + "ImplK.bar", + "ImplK: interface com.android.tools.r8.naming.signature.merging.K") + .inspect( + codeInspector -> { + assertThat(codeInspector.clazz(I.class), not(isPresent())); + assertThat(codeInspector.clazz(J.class), not(isPresent())); + }); + } + + @Test + public void testKeepingOneSelfOnInterface() + throws ExecutionException, CompilationFailedException, IOException { + testForR8(parameters.getBackend()) + .addProgramClasses(Foo.class, InterfaceToKeep.class) + .addKeepMainRule(Foo.class) + .addKeepClassRules(InterfaceToKeep.class) + .addKeepAttributes("Signature, InnerClasses, EnclosingMethod, *Annotation*") + .setMinApi(parameters.getApiLevel()) + .noMinification() + .addOptionsModification( + internalOptions -> { + internalOptions.enableUnusedInterfaceRemoval = false; + }) + .run(parameters.getRuntime(), Foo.class) + .assertSuccessWithOutputLines( + "com.android.tools.r8.naming.signature.merging.InterfaceToKeep" + + "<com.android.tools.r8.naming.signature.SignatureOfMergedClassesTest$Foo>"); + } + + public static class Foo implements InterfaceToKeep<Foo> { + + public static void main(String[] args) { + for (Type genericInterface : Foo.class.getGenericInterfaces()) { + System.out.println(genericInterface); + } + } + } + + public static class Main { + + public static void main(String[] args) { + new ImplI().foo(); + for (Type genericInterface : ImplI.class.getGenericInterfaces()) { + System.out.println("ImplI: " + genericInterface); + } + for (Type genericInterface : K.class.getGenericInterfaces()) { + System.out.println("K: " + genericInterface); + } + K k = new ImplK(); + k.foo(); + k.bar(); + for (Type genericInterface : ImplK.class.getGenericInterfaces()) { + System.out.println("ImplK: " + genericInterface); + } + } + } +}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/I.java b/src/test/java/com/android/tools/r8/naming/signature/merging/I.java new file mode 100644 index 0000000..237786c --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/I.java
@@ -0,0 +1,9 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public interface I { + void foo(); +}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/ImplI.java b/src/test/java/com/android/tools/r8/naming/signature/merging/ImplI.java new file mode 100644 index 0000000..b842386 --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/ImplI.java
@@ -0,0 +1,13 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public class ImplI implements InterfaceToKeep<Void>, I { + + @Override + public void foo() { + System.out.println("ImplI.foo"); + } +}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/ImplK.java b/src/test/java/com/android/tools/r8/naming/signature/merging/ImplK.java new file mode 100644 index 0000000..3c23d56 --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/ImplK.java
@@ -0,0 +1,18 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public class ImplK implements K { + + @Override + public void foo() { + System.out.println("ImplK.foo"); + } + + @Override + public void bar() { + System.out.println("ImplK.bar"); + } +}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/InterfaceToKeep.java b/src/test/java/com/android/tools/r8/naming/signature/merging/InterfaceToKeep.java new file mode 100644 index 0000000..6bebcd0 --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/InterfaceToKeep.java
@@ -0,0 +1,7 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public interface InterfaceToKeep<T> {}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/J.java b/src/test/java/com/android/tools/r8/naming/signature/merging/J.java new file mode 100644 index 0000000..444a5e8 --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/J.java
@@ -0,0 +1,9 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public interface J { + void foo(); +}
diff --git a/src/test/java/com/android/tools/r8/naming/signature/merging/K.java b/src/test/java/com/android/tools/r8/naming/signature/merging/K.java new file mode 100644 index 0000000..4b8ed50 --- /dev/null +++ b/src/test/java/com/android/tools/r8/naming/signature/merging/K.java
@@ -0,0 +1,9 @@ +// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.android.tools.r8.naming.signature.merging; + +public interface K extends InterfaceToKeep<Void>, J { + void bar(); +}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java index 4aec544..1a4dcc16 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -423,7 +423,7 @@ } @Override - public String parsedTypeName(String name) { + public String parsedTypeName(String name, ParserPosition parserPosition) { String type = name; if (obfuscatedToOriginalMapping != null) { String original = mapType(obfuscatedToOriginalMapping, name);