Refactor LateBoundDefault to be abstract, in preparation for being subclassed by a skylark-specific implementation

RELNOTES: None.
PiperOrigin-RevId: 174486116
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index bc35b3a..54f6255 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -1549,6 +1549,25 @@
     }
   }
 
+  private static final class SimpleLateBoundDefault<FragmentT, ValueT>
+      extends LateBoundDefault<FragmentT, ValueT> {
+
+    private final Resolver<FragmentT, ValueT> resolver;
+
+    private SimpleLateBoundDefault(boolean useHostConfiguration,
+        Class<FragmentT> fragmentClass,
+        ValueT defaultValue, Resolver<FragmentT, ValueT> resolver) {
+      super(useHostConfiguration, fragmentClass, defaultValue);
+
+      this.resolver = resolver;
+    }
+
+    @Override
+    public ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input) {
+      return resolver.resolve(rule, attributes, input);
+    }
+  }
+
   // TODO(b/65746853): Remove documentation about accepting BuildConfiguration when uses are cleaned
   // up.
   /**
@@ -1564,7 +1583,7 @@
    * @param <ValueT> The type of value returned by this class.
    */
   @Immutable
-  public static final class LateBoundDefault<FragmentT, ValueT> {
+  public abstract static class LateBoundDefault<FragmentT, ValueT> {
     /**
      * Functional interface for computing the value of a late-bound attribute.
      *
@@ -1578,7 +1597,6 @@
     private final boolean useHostConfiguration;
     private final ValueT defaultValue;
     private final Class<FragmentT> fragmentClass;
-    private final Resolver<FragmentT, ValueT> resolver;
 
     /**
      * Creates a new LateBoundDefault which uses the rule, its configured attributes, and a fragment
@@ -1618,7 +1636,7 @@
           !fragmentClass.equals(Void.class),
           "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use "
               + "configuration.");
-      return new LateBoundDefault<>(false, fragmentClass, defaultValue, resolver);
+      return new SimpleLateBoundDefault<>(false, fragmentClass, defaultValue, resolver);
     }
 
     /**
@@ -1648,7 +1666,7 @@
           !fragmentClass.equals(Void.class),
           "Use fromRuleAndAttributesOnly to specify a LateBoundDefault which does not use "
               + "configuration.");
-      return new LateBoundDefault<>(true, fragmentClass, defaultValue, resolver);
+      return new SimpleLateBoundDefault<>(true, fragmentClass, defaultValue, resolver);
     }
 
     /**
@@ -1666,7 +1684,7 @@
      */
     public static <ValueT> LateBoundDefault<Void, ValueT> fromRuleAndAttributesOnly(
         ValueT defaultValue, Resolver<Void, ValueT> resolver) {
-      return new LateBoundDefault<>(false, Void.class, defaultValue, resolver);
+      return new SimpleLateBoundDefault<>(false, Void.class, defaultValue, resolver);
     }
 
     /**
@@ -1679,7 +1697,7 @@
       if (defaultValue == null) {
         return alwaysNull();
       }
-      return new LateBoundDefault<>(
+      return new SimpleLateBoundDefault<>(
           false, Void.class, defaultValue, (rule, attributes, unused) -> defaultValue);
     }
 
@@ -1695,24 +1713,22 @@
     }
 
     private static final LateBoundDefault<Void, Void> ALWAYS_NULL =
-        new LateBoundDefault<>(false, Void.class, null, (rule, attributes, unused) -> null);
+        new SimpleLateBoundDefault<>(false, Void.class, null, (rule, attributes, unused) -> null);
 
     private LateBoundDefault(
         boolean useHostConfiguration,
         Class<FragmentT> fragmentClass,
-        ValueT defaultValue,
-        Resolver<FragmentT, ValueT> resolver) {
+        ValueT defaultValue) {
       this.useHostConfiguration = useHostConfiguration;
       this.defaultValue = defaultValue;
       this.fragmentClass = fragmentClass;
-      this.resolver = resolver;
     }
 
     /**
      * Whether to look up the label in the host configuration. This is only here for host
      * compilation tools - we usually need to look up labels in the target configuration.
      */
-    public boolean useHostConfiguration() {
+    public final boolean useHostConfiguration() {
       return useHostConfiguration;
     }
 
@@ -1726,12 +1742,12 @@
      * <p>It may also be BuildConfiguration to receive the entire configuration. This is deprecated,
      * and only necessary when the default is computed from methods of BuildConfiguration itself.
      */
-    public Class<FragmentT> getFragmentClass() {
+    public final Class<FragmentT> getFragmentClass() {
       return fragmentClass;
     }
 
     /** The default value for the attribute that is set during the loading phase. */
-    public ValueT getDefault() {
+    public final ValueT getDefault() {
       return defaultValue;
     }
 
@@ -1744,9 +1760,7 @@
      * @param attributes interface for retrieving the values of the rule's other attributes
      * @param input the configuration fragment to evaluate with
      */
-    public ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input) {
-      return resolver.resolve(rule, attributes, input);
-    }
+    public abstract ValueT resolve(Rule rule, AttributeMap attributes, FragmentT input);
   }
 
   private final String name;