Merge commit 'a87869cdec02b1e00cbf09d0ab93416da1c46813' into dev-release
diff --git a/build.gradle b/build.gradle
index de83e21..a3021ec 100644
--- a/build.gradle
+++ b/build.gradle
@@ -202,6 +202,7 @@
     keepanno {
         java {
             srcDirs = ['src/keepanno/java']
+            include 'com/android/tools/r8/keepanno/annotations/*.java'
         }
     }
 }
@@ -1229,6 +1230,11 @@
     from sourceSets.main.allSource
 }
 
+task keepAnnoJar(type: Jar) {
+    archiveFileName = "keepanno-annotations.jar"
+    from sourceSets.keepanno.output
+}
+
 artifacts {
     archives sourceJar
 }
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
index 7a6de42..1d33cb1 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
@@ -3,14 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.keepanno.asm;
 
-import com.android.tools.r8.keepanno.annotations.KeepConstants;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Binding;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Condition;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Edge;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Item;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Kind;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Option;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Target;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Binding;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Condition;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Item;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Kind;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Option;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Target;
 import com.android.tools.r8.keepanno.ast.KeepBindings;
 import com.android.tools.r8.keepanno.ast.KeepClassReference;
 import com.android.tools.r8.keepanno.ast.KeepCondition;
@@ -96,7 +96,7 @@
       if (descriptor.equals(Edge.DESCRIPTOR)) {
         return new KeepEdgeVisitor(parent, this::setContext);
       }
-      if (descriptor.equals(KeepConstants.UsesReflection.DESCRIPTOR)) {
+      if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
         KeepItemPattern classItem =
             KeepItemPattern.builder()
                 .setClassPattern(KeepQualifiedClassNamePattern.exact(className))
@@ -170,7 +170,7 @@
       if (descriptor.equals(Edge.DESCRIPTOR)) {
         return new KeepEdgeVisitor(parent, this::setContext);
       }
-      if (descriptor.equals(KeepConstants.UsesReflection.DESCRIPTOR)) {
+      if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
         return new UsesReflectionVisitor(parent, this::setContext, createItemContext());
       }
       return null;
@@ -224,7 +224,7 @@
       if (descriptor.equals(Edge.DESCRIPTOR)) {
         return new KeepEdgeVisitor(parent, this::setContext);
       }
-      if (descriptor.equals(KeepConstants.UsesReflection.DESCRIPTOR)) {
+      if (descriptor.equals(AnnotationConstants.UsesReflection.DESCRIPTOR)) {
         return new UsesReflectionVisitor(parent, this::setContext, createItemContext());
       }
       return null;
@@ -328,10 +328,10 @@
 
     @Override
     public AnnotationVisitor visitArray(String name) {
-      if (name.equals(KeepConstants.UsesReflection.value)) {
+      if (name.equals(AnnotationConstants.UsesReflection.value)) {
         return new KeepConsequencesVisitor(builder::setConsequences);
       }
-      if (name.equals(KeepConstants.UsesReflection.additionalPreconditions)) {
+      if (name.equals(AnnotationConstants.UsesReflection.additionalPreconditions)) {
         return new KeepPreconditionsVisitor(
             additionalPreconditions -> {
               additionalPreconditions.forEach(preconditions::addCondition);
@@ -360,7 +360,7 @@
 
     @Override
     public AnnotationVisitor visitAnnotation(String name, String descriptor) {
-      if (descriptor.equals(KeepConstants.Binding.DESCRIPTOR)) {
+      if (descriptor.equals(AnnotationConstants.Binding.DESCRIPTOR)) {
         return new KeepBindingVisitor(builder);
       }
       return super.visitAnnotation(name, descriptor);
@@ -718,7 +718,7 @@
 
     @Override
     public void visitEnum(String name, String descriptor, String value) {
-      if (!descriptor.equals(KeepConstants.Kind.DESCRIPTOR)) {
+      if (!descriptor.equals(AnnotationConstants.Kind.DESCRIPTOR)) {
         super.visitEnum(name, descriptor, value);
       }
       switch (value) {
@@ -879,11 +879,11 @@
 
     @Override
     AnnotationVisitor parseArray(String name, Consumer<KeepOptions> setValue) {
-      if (name.equals(KeepConstants.Target.disallow)) {
+      if (name.equals(AnnotationConstants.Target.disallow)) {
         return new KeepOptionsVisitor(
             options -> setValue.accept(KeepOptions.disallowBuilder().addAll(options).build()));
       }
-      if (name.equals(KeepConstants.Target.allow)) {
+      if (name.equals(AnnotationConstants.Target.allow)) {
         return new KeepOptionsVisitor(
             options -> setValue.accept(KeepOptions.allowBuilder().addAll(options).build()));
       }
@@ -934,7 +934,7 @@
 
     @Override
     public void visitEnum(String ignore, String descriptor, String value) {
-      if (!descriptor.equals(KeepConstants.Option.DESCRIPTOR)) {
+      if (!descriptor.equals(AnnotationConstants.Option.DESCRIPTOR)) {
         super.visitEnum(ignore, descriptor, value);
       }
       KeepOption option;
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java
index 515becd..dc8e7c9 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeWriter.java
@@ -3,11 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.keepanno.asm;
 
-import com.android.tools.r8.keepanno.annotations.KeepConstants;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Condition;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Edge;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Item;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Target;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Condition;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Item;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Target;
 import com.android.tools.r8.keepanno.ast.KeepClassReference;
 import com.android.tools.r8.keepanno.ast.KeepConsequences;
 import com.android.tools.r8.keepanno.ast.KeepEdge;
@@ -151,7 +151,7 @@
     KeepQualifiedClassNamePattern namePattern = classReference.asClassNamePattern();
     if (namePattern.isExact()) {
       Type typeConstant = Type.getType(namePattern.getExactDescriptor());
-      itemVisitor.visit(KeepConstants.Item.classConstant, typeConstant);
+      itemVisitor.visit(AnnotationConstants.Item.classConstant, typeConstant);
     } else {
       throw new Unimplemented();
     }
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstants.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
similarity index 89%
rename from src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstants.java
rename to src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
index f37c3fc..68cd0df 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstants.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
@@ -1,16 +1,22 @@
-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// Copyright (c) 2023, 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.keepanno.annotations;
+package com.android.tools.r8.keepanno.ast;
 
+import com.android.tools.r8.keepanno.annotations.KeepBinding;
+import com.android.tools.r8.keepanno.annotations.KeepCondition;
+import com.android.tools.r8.keepanno.annotations.KeepEdge;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepOption;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
 
 /**
  * Utility class for referencing the various keep annotations and their structure.
  *
- * <p>Use of these references avoids poluting the Java namespace with imports of the java
+ * <p>Use of these references avoids polluting the Java namespace with imports of the java
  * annotations which overlap in name with the actual semantic AST types.
  */
-public final class KeepConstants {
+public final class AnnotationConstants {
 
   public static String getDescriptor(Class<?> clazz) {
     return "L" + clazz.getTypeName().replace('.', '/') + ";";
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/processor/KeepEdgeProcessor.java b/src/keepanno/java/com/android/tools/r8/keepanno/processor/KeepEdgeProcessor.java
index 80a6ec5..72b36ed 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/processor/KeepEdgeProcessor.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/processor/KeepEdgeProcessor.java
@@ -7,11 +7,11 @@
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 import static org.objectweb.asm.Opcodes.ACC_SUPER;
 
-import com.android.tools.r8.keepanno.annotations.KeepConstants;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Edge;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Item;
 import com.android.tools.r8.keepanno.asm.KeepEdgeReader;
 import com.android.tools.r8.keepanno.asm.KeepEdgeWriter;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Item;
 import com.android.tools.r8.keepanno.ast.KeepCondition;
 import com.android.tools.r8.keepanno.ast.KeepConsequences;
 import com.android.tools.r8.keepanno.ast.KeepEdge;
@@ -89,7 +89,7 @@
   }
 
   private static byte[] writeEdges(List<KeepEdge> edges, String classTypeName) {
-    String classBinaryName = KeepConstants.getBinaryNameFromClassTypeName(classTypeName);
+    String classBinaryName = AnnotationConstants.getBinaryNameFromClassTypeName(classTypeName);
     ClassWriter classWriter = new ClassWriter(0);
     classWriter.visit(
         KeepEdgeReader.ASM_VERSION,
@@ -107,7 +107,7 @@
   }
 
   private KeepEdge processKeepEdge(Element element, RoundEnvironment roundEnv) {
-    AnnotationMirror mirror = getAnnotationMirror(element, KeepConstants.Edge.CLASS);
+    AnnotationMirror mirror = getAnnotationMirror(element, AnnotationConstants.Edge.CLASS);
     if (mirror == null) {
       return null;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 7396bf6..3826986 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -168,11 +168,19 @@
     }
     if (provider != null && appView.options().disableBackports) {
       if (appView.options().disableBackportsWithErrorDiagnostics) {
-        appView
-            .reporter()
-            .error(
-                new BackportDiagnostic(
-                    provider.method, context.getOrigin(), MethodPosition.create(context)));
+        // If the provided backport is defined on a holder that is part of the program compilation
+        // unit, assume that the compilation is the defining instance and no backport is needed.
+        DexClass clazz =
+            appView
+                .contextIndependentDefinitionForWithResolutionResult(provider.method.holder)
+                .toSingleClassWithProgramOverLibrary();
+        if (!clazz.isProgramDefinition()) {
+          appView
+              .reporter()
+              .error(
+                  new BackportDiagnostic(
+                      provider.method, context.getOrigin(), MethodPosition.create(context)));
+        }
       }
       return null;
     }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
index bd8016c..f4c77f3 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
@@ -86,6 +86,21 @@
         .compileWithExpectedDiagnostics(this::checkDiagnostics);
   }
 
+  @Test
+  public void testPlatformDefinitionD8() throws Exception {
+    testForD8(parameters.getBackend())
+        .apply(b -> b.getBuilder().setAndroidPlatformBuild(true))
+        .addOptionsModification(o -> o.disableBackportsWithErrorDiagnostics = true)
+        .addProgramClasses(CLASSES)
+        .addProgramClassFileData(
+            transformer(BooleanDefinition.class)
+                .setClassDescriptor("Ljava/lang/Boolean;")
+                .transform())
+        .setMinApi(parameters.getApiLevel())
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(EXPECTED);
+  }
+
   private void checkDiagnostics(TestDiagnosticMessages diagnostics) {
     diagnostics
         .assertAllErrorsMatch(
@@ -97,6 +112,14 @@
         .assertOnlyErrors();
   }
 
+  // Implementation of java.lang.Boolean.compare to test no error is triggered for
+  // compilation units "defining" the backport method.
+  public static class BooleanDefinition {
+    public int compare(boolean a, boolean b) {
+      return (a ? 1 : 0) - (b ? 1 : 0);
+    }
+  }
+
   static class User {
 
     private static void testBooleanCompare() {
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepEdgeAnnotationsTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepEdgeAnnotationsTest.java
index f4411a6..9f02b7c 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepEdgeAnnotationsTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepEdgeAnnotationsTest.java
@@ -14,11 +14,11 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.keepanno.annotations.KeepConstants;
-import com.android.tools.r8.keepanno.annotations.KeepConstants.Edge;
 import com.android.tools.r8.keepanno.asm.KeepEdgeReader;
 import com.android.tools.r8.keepanno.asm.KeepEdgeWriter;
 import com.android.tools.r8.keepanno.asm.KeepEdgeWriter.AnnotationVisitorInterface;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants;
+import com.android.tools.r8.keepanno.ast.AnnotationConstants.Edge;
 import com.android.tools.r8.keepanno.ast.KeepEdge;
 import com.android.tools.r8.keepanno.processor.KeepEdgeProcessor;
 import com.android.tools.r8.keepanno.testsource.KeepClassAndDefaultConstructorSource;
@@ -148,7 +148,7 @@
     List<byte[]> transformed = new ArrayList<>(classes.size());
     for (Class<?> clazz : classes) {
       transformed.add(
-          transformer(clazz).removeAnnotations(KeepConstants::isKeepAnnotation).transform());
+          transformer(clazz).removeAnnotations(AnnotationConstants::isKeepAnnotation).transform());
     }
     return transformed;
   }