TypeMirror#toString should include type annotations for primitive types

A few of the `toString` overrides in `TurbineTypeMirror` were unnecessary, and the one for primitives was incorrect because it dropped the type annotations.

PiperOrigin-RevId: 715858768
diff --git a/java/com/google/turbine/processing/TurbineTypeMirror.java b/java/com/google/turbine/processing/TurbineTypeMirror.java
index a0ee3ff..60ca690 100644
--- a/java/com/google/turbine/processing/TurbineTypeMirror.java
+++ b/java/com/google/turbine/processing/TurbineTypeMirror.java
@@ -19,7 +19,6 @@
 import static com.google.common.collect.Iterables.getLast;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Ascii;
 import com.google.common.base.Joiner;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
@@ -101,11 +100,6 @@
   static class TurbinePrimitiveType extends TurbineTypeMirror implements PrimitiveType {
 
     @Override
-    public String toString() {
-      return Ascii.toLowerCase(type.primkind().toString());
-    }
-
-    @Override
     public Type asTurbineType() {
       return type;
     }
@@ -182,11 +176,6 @@
       this.type = type;
     }
 
-    @Override
-    public String toString() {
-      return type.toString();
-    }
-
     final Supplier<Element> element =
         factory.memoize(
             new Supplier<Element>() {
@@ -340,11 +329,6 @@
     public List<? extends TypeMirror> getTypeArguments() {
       return factory.asTypeMirrors(type.targs());
     }
-
-    @Override
-    public String toString() {
-      return type.toString();
-    }
   }
 
   /** A 'package type' implementation backed by a {@link PackageSymbol}. */
@@ -417,11 +401,6 @@
     }
 
     @Override
-    public String toString() {
-      return "none";
-    }
-
-    @Override
     public boolean equals(@Nullable Object other) {
       return other instanceof TurbineNoType;
     }
@@ -531,11 +510,6 @@
     }
 
     @Override
-    public String toString() {
-      return type.toString();
-    }
-
-    @Override
     protected ImmutableList<AnnoInfo> annos() {
       return type.annos();
     }
@@ -695,11 +669,6 @@
   public static class TurbineExecutableType extends TurbineTypeMirror implements ExecutableType {
 
     @Override
-    public String toString() {
-      return type.toString();
-    }
-
-    @Override
     public MethodTy asTurbineType() {
       return type;
     }
diff --git a/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java b/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java
index 822283b..504001b 100644
--- a/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java
+++ b/javatests/com/google/turbine/processing/AbstractTurbineTypesTest.java
@@ -238,6 +238,7 @@
     // type annotations
     List<String> annotatedTypes = new ArrayList<>();
     annotatedTypes.add("@A int @B []");
+    annotatedTypes.add("@A int");
     // The string representation of these types changed in JDK 19, see JDK-8281238
     if (Runtime.version().feature() >= 19) {
       annotatedTypes.add("@A List<@B Integer>");
diff --git a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java b/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java
index 097e59a..8be0cc3 100644
--- a/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java
+++ b/javatests/com/google/turbine/processing/ProcessingIntegrationTest.java
@@ -71,6 +71,7 @@
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.RecordComponentElement;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.ErrorType;
 import javax.lang.model.type.ExecutableType;
@@ -1098,6 +1099,70 @@
             "c supertype: B.E<F>, arguments: [F], enclosing: none");
   }
 
+  @SupportedAnnotationTypes("*")
+  public static class TypeAnnotationFieldType extends AbstractProcessor {
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+      return SourceVersion.latestSupported();
+    }
+
+    private boolean first = true;
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+      if (!first) {
+        return false;
+      }
+      first = false;
+      for (Element root : roundEnv.getRootElements()) {
+        for (VariableElement field : ElementFilter.fieldsIn(root.getEnclosedElements())) {
+          TypeMirror type = field.asType();
+          processingEnv
+              .getMessager()
+              .printMessage(
+                  Diagnostic.Kind.ERROR,
+                  String.format(
+                      "field %s with annotations %s, type '%s' with annotations %s",
+                      field, field.getAnnotationMirrors(), type, type.getAnnotationMirrors()));
+        }
+      }
+      return false;
+    }
+  }
+
+  // Ensure that type annotations are included in the string representation of primtive types
+  @Test
+  public void fieldTypeToString() {
+    ImmutableList<Tree.CompUnit> units =
+        parseUnit(
+            """
+            === T.java ===
+            class T {
+              private final @A int f;
+              private final @A Object g;
+              private final @A int[] h;
+            }
+            === A.java ===
+            import java.lang.annotation.ElementType;
+            import java.lang.annotation.Retention;
+            import java.lang.annotation.RetentionPolicy;
+            import java.lang.annotation.Target;
+            @Retention(RetentionPolicy.SOURCE)
+            @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+            public @interface A {
+            }
+            """);
+    TurbineError e = runProcessors(units, new TypeAnnotationFieldType());
+    assertThat(
+            e.diagnostics().stream()
+                .filter(d -> d.severity().equals(Diagnostic.Kind.ERROR))
+                .map(d -> d.message()))
+        .containsExactly(
+            "field f with annotations [], type '@A int' with annotations [@A]",
+            "field g with annotations [], type 'java.lang.@A Object' with annotations [@A]",
+            "field h with annotations [], type '@A int[]' with annotations []");
+  }
+
   private TurbineError runProcessors(ImmutableList<Tree.CompUnit> units, Processor... processors) {
     return assertThrows(
         TurbineError.class,
diff --git a/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java b/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java
index 2fd5d4c..eaa7887 100644
--- a/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java
+++ b/javatests/com/google/turbine/processing/TurbineTypesUnaryTest.java
@@ -105,6 +105,9 @@
       case "@p.Test0.A int @p.Test0.B []":
         expected = "int[]";
         break;
+      case "@p.Test0.A int":
+        expected = "int";
+        break;
       default: // fall out
     }
     assertWithMessage("erasure(`%s`) = erasure(`%s`)", javacA, turbineA)