Split HasBindingExpressions into GeneratedComponentModel and ComponentBindingExpressions.

Make SingleBindingExpression a subclass of BindingExpression for one binding, so that ComponentBindingExpressions can be a composite BindingExpression.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=165367432
diff --git a/java/dagger/internal/codegen/AbstractComponentWriter.java b/java/dagger/internal/codegen/AbstractComponentWriter.java
index da72571..235a226 100644
--- a/java/dagger/internal/codegen/AbstractComponentWriter.java
+++ b/java/dagger/internal/codegen/AbstractComponentWriter.java
@@ -113,7 +113,7 @@
 import javax.lang.model.util.Types;
 
 /** Creates the implementation class for a component or subcomponent. */
-abstract class AbstractComponentWriter implements HasBindingExpressions {
+abstract class AbstractComponentWriter implements GeneratedComponentModel {
   // TODO(dpb): Make all these fields private after refactoring is complete.
   protected final Elements elements;
   protected final Types types;
@@ -125,10 +125,9 @@
   protected final TypeSpec.Builder component;
   private final UniqueNameSet componentFieldNames = new UniqueNameSet();
   private final UniqueNameSet componentMethodNames = new UniqueNameSet();
-  // TODO(user): Merge these two maps if we refactor BindingKey to allow us to unify
-  // these two key spaces
-  private final Map<BindingKey, BindingExpression> bindingExpressions = new LinkedHashMap<>();
-  private final Map<BindingKey, BindingExpression> producerFromProviderBindingExpressions =
+  private final ComponentBindingExpressions bindingExpressions;
+  // TODO(user): Merge into ComponentBindingExpressions after we refactor BindingKey.
+  private final Map<BindingKey, ProducerBindingExpression> producerFromProviderBindingExpressions =
       new LinkedHashMap<>();
   private final List<CodeBlock> initializations = new ArrayList<>();
   protected final List<MethodSpec> interfaceMethods = new ArrayList<>();
@@ -169,7 +168,8 @@
       ClassName name,
       BindingGraph graph,
       ImmutableMap<ComponentDescriptor, String> subcomponentNames,
-      OptionalFactories optionalFactories) {
+      OptionalFactories optionalFactories,
+      ComponentBindingExpressions bindingExpressions) {
     this.types = types;
     this.elements = elements;
     this.keyFactory = keyFactory;
@@ -179,11 +179,13 @@
     this.graph = graph;
     this.subcomponentNames = subcomponentNames;
     this.optionalFactories = optionalFactories;
+    this.bindingExpressions = bindingExpressions;
     this.bindingExpressionFactory =
         new BindingExpression.Factory(
             compilerOptions,
             name,
             componentFieldNames,
+            bindingExpressions,
             this,
             childComponentNames(keyFactory, subcomponentNames),
             graph,
@@ -214,7 +216,8 @@
         name,
         graph,
         parent.subcomponentNames,
-        parent.optionalFactories);
+        parent.optionalFactories,
+        parent.bindingExpressions.forChildComponent());
   }
 
   protected final ClassName componentDefinitionTypeName() {
@@ -270,11 +273,6 @@
     return FieldSpec.builder(type, componentFieldNames.getUniqueName(name));
   }
 
-  @Override
-  public BindingExpression getBindingExpression(BindingKey key) {
-    return bindingExpressions.get(key);
-  }
-
   /** Adds the given code block to the initialize methods of the component. */
   @Override
   public void addInitialization(CodeBlock codeBlock) {
@@ -447,7 +445,7 @@
     Optional<BindingExpression> staticBindingExpression =
         bindingExpressionFactory.forStaticMethod(resolvedBindings);
     if (staticBindingExpression.isPresent()) {
-      bindingExpressions.put(resolvedBindings.bindingKey(), staticBindingExpression.get());
+      bindingExpressions.addBindingExpression(staticBindingExpression.get());
       return;
     }
 
@@ -457,8 +455,7 @@
     }
 
     // TODO(gak): get rid of the field for unscoped delegated bindings
-    bindingExpressions.put(
-        resolvedBindings.bindingKey(), bindingExpressionFactory.forField(resolvedBindings));
+    bindingExpressions.addBindingExpression(bindingExpressionFactory.forField(resolvedBindings));
   }
 
   private boolean useRawType(Binding binding) {
@@ -510,7 +507,8 @@
                   "return $N($N)", getMembersInjectionMethod(binding.key()), parameter);
             }
           } else {
-            interfaceMethod.addStatement("return $L", getDependencyExpression(interfaceRequest));
+            interfaceMethod.addStatement(
+                "return $L", bindingExpressions.getDependencyExpression(interfaceRequest, name));
           }
           interfaceMethods.add(interfaceMethod.build());
         }
@@ -593,12 +591,11 @@
     component.addMethods(interfaceMethods);
   }
 
-  // TODO(user): Move this method onto FieldBasedBindingExpression or subtypes of it.
   @Override
   public CodeBlock getFieldInitialization(FrameworkInstanceBindingExpression bindingExpression) {
     if (bindingExpression.isProducerFromProvider()) {
-      return getDependencyExpression(
-          FrameworkDependency.create(bindingExpression.bindingKey(), PRODUCTION));
+      return bindingExpressions.getDependencyExpression(
+          FrameworkDependency.create(bindingExpression.bindingKey(), PRODUCTION), name);
     }
 
     switch (bindingExpression.bindingKey().kind()) {
@@ -611,7 +608,8 @@
     }
   }
 
-  private CodeBlock contributionBindingInitialization(BindingExpression bindingExpression) {
+  private CodeBlock contributionBindingInitialization(
+      FrameworkInstanceBindingExpression bindingExpression) {
     ContributionBinding binding =
         graph.resolvedBindings().get(bindingExpression.bindingKey()).contributionBinding();
     switch (binding.factoryCreationStrategy()) {
@@ -620,7 +618,8 @@
             CodeBlock.of(
                 "($T) $L",
                 binding.bindingType().frameworkClass(),
-                getDependencyExpression(getOnlyElement(binding.frameworkDependencies())));
+                bindingExpressions.getDependencyExpression(
+                    getOnlyElement(binding.frameworkDependencies()), name));
         return decorateForScope(delegatingCodeBlock, binding.scope());
       case SINGLETON_INSTANCE:
         checkState(binding.scope().isPresent());
@@ -677,9 +676,7 @@
             instance,
             membersInjectedType,
             types,
-            request ->
-                getBindingExpression(request.bindingKey())
-                    .getDependencyArgumentExpression(request, name)));
+            request -> bindingExpressions.getDependencyArgumentExpression(request, name)));
     method.addStatement("return $L", instance);
 
     return method.build();
@@ -694,7 +691,8 @@
     throw new IllegalArgumentException(binding.key().toString());
   }
 
-  private CodeBlock membersInjectionBindingInitialization(BindingExpression bindingExpression) {
+  private CodeBlock membersInjectionBindingInitialization(
+      FrameworkInstanceBindingExpression bindingExpression) {
     BindingKey bindingKey = bindingExpression.bindingKey();
     MembersInjectionBinding binding =
         graph.resolvedBindings().get(bindingKey).membersInjectionBinding().get();
@@ -702,7 +700,7 @@
     return membersInjectorForBindingInitialization(binding);
   }
 
-  private BindingExpression getProducerFromProviderBindingExpression(
+  private ProducerBindingExpression getProducerFromProviderBindingExpression(
       FrameworkDependency frameworkDependency) {
     checkState(isProducerFromProvider(frameworkDependency));
     return producerFromProviderBindingExpressions.computeIfAbsent(
@@ -885,7 +883,7 @@
         return CodeBlock.of(
             "$T.create($L)",
             mapFactoryClassName(binding),
-            getDependencyExpression(frameworkDependency));
+            bindingExpressions.getDependencyExpression(frameworkDependency, name));
 
       case SYNTHETIC_MULTIBOUND_SET:
         return factoryForSetMultibindingInitialization(binding);
@@ -951,8 +949,8 @@
   private CodeBlock getDependencyArgument(FrameworkDependency frameworkDependency) {
     return isProducerFromProvider(frameworkDependency)
         ? getProducerFromProviderBindingExpression(frameworkDependency)
-            .getDependencyExpression(frameworkDependency, name)
-        : getDependencyExpression(frameworkDependency);
+            .getDependencyExpression(frameworkDependency.dependencyRequestKind(), name)
+        : bindingExpressions.getDependencyExpression(frameworkDependency, name);
   }
 
   private CodeBlock factoryForSetMultibindingInitialization(ContributionBinding binding) {
@@ -1172,14 +1170,4 @@
           binding, getOnlyElement(getDependencyArguments(binding)));
     }
   }
-
-  private CodeBlock getDependencyExpression(FrameworkDependency frameworkDependency) {
-    return getBindingExpression(frameworkDependency.bindingKey())
-        .getDependencyExpression(frameworkDependency, name);
-  }
-
-  private CodeBlock getDependencyExpression(DependencyRequest dependencyRequest) {
-    return getBindingExpression(dependencyRequest.bindingKey())
-        .getDependencyExpression(dependencyRequest, name);
-  }
 }
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index 720da39..e8df4f6 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -17,24 +17,19 @@
 package dagger.internal.codegen;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
 import static dagger.internal.codegen.MemberSelect.staticMemberSelect;
 import static dagger.internal.codegen.TypeNames.PRODUCER;
-import static dagger.internal.codegen.TypeNames.rawTypeName;
 import static javax.lang.model.element.Modifier.PRIVATE;
 
 import com.google.common.collect.ImmutableMap;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
 import java.util.Optional;
-import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
 
-/** The code expressions to declare, initialize, and/or access a binding in a component. */
+/** A factory of code expressions used to access a single binding in a component. */
 abstract class BindingExpression {
   private final BindingKey bindingKey;
 
@@ -48,51 +43,21 @@
   }
 
   /**
-   * Returns an expression that evaluates to the value of a dependency request.
-   *
-   * @param requestingClass the class that will contain the expression
-   */
-  abstract CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass);
-
-  /**
-   * Returns an expression that evaluates to the value of a framework dependency.
+   * Returns an expression that evaluates to the value of a request for a given kind of dependency
+   * on this binding.
    *
    * @param requestingClass the class that will contain the expression
    */
   abstract CodeBlock getDependencyExpression(
-      FrameworkDependency frameworkDependency, ClassName requestingClass);
-
-  /**
-   * Returns an expression that evaluates to the value of a dependency request, for passing to a
-   * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
-   *
-   * <p>If the method is a generated static {@link InjectionMethods injection method}, each
-   * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
-   * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
-   *
-   * @param requestingClass the class that will contain the expression
-   */
-  // TODO(b/64024402) Merge with getDependencyExpression(DependencyRequest, ClassName) if possible.
-  CodeBlock getDependencyArgumentExpression(
-      DependencyRequest dependencyRequest, ClassName requestingClass) {
-    CodeBlock.Builder argument = CodeBlock.builder();
-
-    TypeMirror dependencyType = dependencyRequest.key().type();
-    if (!isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
-        && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
-      argument.add("($T) ", rawTypeName(TypeName.get(dependencyType)));
-    }
-
-    argument.add(getDependencyExpression(dependencyRequest, requestingClass));
-    return argument.build();
-  }
+      DependencyRequest.Kind requestKind, ClassName requestingClass);
 
   /** Factory for building a {@link BindingExpression}. */
   static final class Factory {
     private final CompilerOptions compilerOptions;
     private final ClassName componentName;
     private final UniqueNameSet componentFieldNames;
-    private final HasBindingExpressions hasBindingExpressions;
+    private final ComponentBindingExpressions componentBindingExpressions;
+    private final GeneratedComponentModel generatedComponentModel;
     private final ImmutableMap<BindingKey, String> subcomponentNames;
     private final BindingGraph graph;
     private final Elements elements;
@@ -101,14 +66,16 @@
         CompilerOptions compilerOptions,
         ClassName componentName,
         UniqueNameSet componentFieldNames,
-        HasBindingExpressions hasBindingExpressions,
+        ComponentBindingExpressions componentBindingExpressions,
+        GeneratedComponentModel generatedComponentModel,
         ImmutableMap<BindingKey, String> subcomponentNames,
         BindingGraph graph,
         Elements elements) {
       this.compilerOptions = checkNotNull(compilerOptions);
       this.componentName = checkNotNull(componentName);
       this.componentFieldNames = checkNotNull(componentFieldNames);
-      this.hasBindingExpressions = checkNotNull(hasBindingExpressions);
+      this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+      this.generatedComponentModel = checkNotNull(generatedComponentModel);
       this.subcomponentNames = checkNotNull(subcomponentNames);
       this.graph = checkNotNull(graph);
       this.elements = checkNotNull(elements);
@@ -121,20 +88,18 @@
       return create(resolvedBindings, Optional.of(fieldSpec), memberSelect);
     }
 
-    BindingExpression forProducerFromProviderField(ResolvedBindings resolvedBindings) {
+    ProducerBindingExpression forProducerFromProviderField(ResolvedBindings resolvedBindings) {
       FieldSpec fieldSpec = generateFrameworkField(resolvedBindings, Optional.of(PRODUCER));
       MemberSelect memberSelect = MemberSelect.localField(componentName, fieldSpec.name);
       return new ProducerBindingExpression(
           resolvedBindings.bindingKey(),
           Optional.of(fieldSpec),
-          hasBindingExpressions,
+          generatedComponentModel,
           memberSelect,
           true);
     }
 
-    /**
-     * Creates a binding expression for a static method call.
-     */
+    /** Creates a binding expression for a static method call. */
     Optional<BindingExpression> forStaticMethod(ResolvedBindings resolvedBindings) {
       return staticMemberSelect(resolvedBindings)
           .map(memberSelect -> create(resolvedBindings, Optional.empty(), memberSelect));
@@ -178,17 +143,17 @@
       switch (resolvedBindings.bindingType()) {
         case MEMBERS_INJECTION:
           return new MembersInjectorBindingExpression(
-              bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+              bindingKey, fieldSpec, generatedComponentModel, memberSelect);
         case PRODUCTION:
           return new ProducerBindingExpression(
-              bindingKey, fieldSpec, hasBindingExpressions, memberSelect, false);
+              bindingKey, fieldSpec, generatedComponentModel, memberSelect, false);
         case PROVISION:
           ProvisionBinding provisionBinding =
               (ProvisionBinding) resolvedBindings.contributionBinding();
 
           ProviderBindingExpression providerBindingExpression =
               new ProviderBindingExpression(
-                  bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+                  bindingKey, fieldSpec, generatedComponentModel, memberSelect);
 
           switch (provisionBinding.bindingKind()) {
             case SUBCOMPONENT_BUILDER:
@@ -198,12 +163,12 @@
               return new SetBindingExpression(
                   provisionBinding,
                   graph,
-                  hasBindingExpressions,
+                  componentBindingExpressions,
                   providerBindingExpression,
                   elements);
             case SYNTHETIC_OPTIONAL_BINDING:
               return new OptionalBindingExpression(
-                  provisionBinding, providerBindingExpression, hasBindingExpressions);
+                  provisionBinding, providerBindingExpression, componentBindingExpressions);
             case INJECTION:
             case PROVISION:
               if (!provisionBinding.scope().isPresent()
@@ -213,7 +178,8 @@
                     compilerOptions,
                     provisionBinding,
                     providerBindingExpression,
-                    hasBindingExpressions);
+                    componentBindingExpressions,
+                    generatedComponentModel);
               }
               // fall through
             default:
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
new file mode 100644
index 0000000..32f053c
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.TypeNames.rawTypeName;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import java.util.HashMap;
+import java.util.Map;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory of code expressions used to access any binding available to a component. */
+final class ComponentBindingExpressions {
+
+  // TODO(dpb): Can this use a flattened ImmutableMap, built from its parents? Maybe make
+  // BindingExpression.Factory create it.
+
+  /**
+   * A list of binding expression maps. The first element contains the bindings owned by this
+   * component; the second contains the bindings owned by its parent; and so on.
+   */
+  private final ImmutableList<Map<BindingKey, BindingExpression>> bindingExpressionsMaps;
+
+  private ComponentBindingExpressions(
+      ImmutableList<Map<BindingKey, BindingExpression>> bindingExpressionsMaps) {
+    this.bindingExpressionsMaps = bindingExpressionsMaps;
+  }
+
+  ComponentBindingExpressions() {
+    this(ImmutableList.of(newBindingExpressionMap()));
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a dependency request for a binding owned
+   * by this component or an ancestor.
+   *
+   * @param requestingClass the class that will contain the expression
+   * @throws IllegalStateException if there is no binding expression that satisfies the dependency
+   *     request
+   */
+  CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+    return getBindingExpression(request.bindingKey())
+        .getDependencyExpression(request.kind(), requestingClass);
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a framework dependency for a binding owned
+   * in this component or an ancestor.
+   *
+   * @param requestingClass the class that will contain the expression
+   * @throws IllegalStateException if there is no binding expression that satisfies the dependency
+   *     request
+   */
+  CodeBlock getDependencyExpression(
+      FrameworkDependency frameworkDependency, ClassName requestingClass) {
+    return getBindingExpression(frameworkDependency.bindingKey())
+        .getDependencyExpression(frameworkDependency.dependencyRequestKind(), requestingClass);
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a dependency request, for passing to a
+   * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
+   *
+   * <p>If the method is a generated static {@link InjectionMethods injection method}, each
+   * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
+   * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
+   *
+   * @param requestingClass the class that will contain the expression
+   */
+  // TODO(b/64024402) Merge with getDependencyExpression(DependencyRequest, ClassName) if possible.
+  CodeBlock getDependencyArgumentExpression(
+      DependencyRequest dependencyRequest, ClassName requestingClass) {
+    CodeBlock.Builder argument = CodeBlock.builder();
+
+    TypeMirror dependencyType = dependencyRequest.key().type();
+    if (!isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
+        && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
+      argument.add("($T) ", rawTypeName(TypeName.get(dependencyType)));
+    }
+
+    argument.add(getDependencyExpression(dependencyRequest, requestingClass));
+    return argument.build();
+  }
+
+  private BindingExpression getBindingExpression(BindingKey bindingKey) {
+    for (Map<BindingKey, BindingExpression> bindingExpressionsMap : bindingExpressionsMaps) {
+      BindingExpression expression = bindingExpressionsMap.get(bindingKey);
+      if (expression != null) {
+        return expression;
+      }
+    }
+    throw new IllegalStateException("no binding expression found for " + bindingKey);
+  }
+
+  /** Adds a binding expression for a single binding owned by this component. */
+  void addBindingExpression(BindingExpression bindingExpression) {
+    bindingExpressionsMaps.get(0).put(bindingExpression.bindingKey(), bindingExpression);
+  }
+
+  /**
+   * Returns a new object representing the bindings available from a child component of this one.
+   */
+  ComponentBindingExpressions forChildComponent() {
+    return new ComponentBindingExpressions(
+        FluentIterable.of(newBindingExpressionMap()).append(bindingExpressionsMaps).toList());
+  }
+
+  private static Map<BindingKey, BindingExpression> newBindingExpressionMap() {
+    return new HashMap<>();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentWriter.java b/java/dagger/internal/codegen/ComponentWriter.java
index 06f4fb0..53b10c7 100644
--- a/java/dagger/internal/codegen/ComponentWriter.java
+++ b/java/dagger/internal/codegen/ComponentWriter.java
@@ -64,7 +64,8 @@
         name,
         graph,
         new UniqueSubcomponentNamesGenerator(graph).generate(),
-        new OptionalFactories());
+        new OptionalFactories(),
+        new ComponentBindingExpressions());
   }
 
   /**
diff --git a/java/dagger/internal/codegen/FrameworkDependency.java b/java/dagger/internal/codegen/FrameworkDependency.java
index 0cd593d..f5efe77 100644
--- a/java/dagger/internal/codegen/FrameworkDependency.java
+++ b/java/dagger/internal/codegen/FrameworkDependency.java
@@ -51,6 +51,23 @@
   /** The binding type of the framework dependency. */
   abstract BindingType bindingType();
 
+  /** The dependency request kind that is equivalent to requesting the framework dependency. */
+  DependencyRequest.Kind dependencyRequestKind() {
+    switch (bindingType()) {
+      case PROVISION:
+        return DependencyRequest.Kind.PROVIDER;
+
+      case PRODUCTION:
+        return DependencyRequest.Kind.PRODUCER;
+
+      case MEMBERS_INJECTION:
+        return DependencyRequest.Kind.MEMBERS_INJECTOR;
+
+      default:
+        throw new AssertionError(bindingType());
+    }
+  }
+
   /** The framework class to use for these requests. */
   final Class<?> frameworkClass() {
     return bindingType().frameworkClass();
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
index 2cd0b91..88bd248 100644
--- a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -26,33 +26,30 @@
 import dagger.internal.DelegateFactory;
 import java.util.Optional;
 
-/**
- * A {@link BindingExpression} that is always satisfied in components by using an instance of a
- * {@link FrameworkType}.
- */
+/** A binding expression that uses an instance of a {@link FrameworkType}. */
 // TODO(user): consider removing this class and making it a strategy that is created by
 // {Provider,Producer,MembersInjector}BindingExpression
 abstract class FrameworkInstanceBindingExpression extends BindingExpression {
   private final Optional<FieldSpec> fieldSpec;
-  private final HasBindingExpressions hasBindingExpressions;
+  private final GeneratedComponentModel generatedComponentModel;
   private final MemberSelect memberSelect;
   private InitializationState fieldInitializationState = InitializationState.UNINITIALIZED;
 
   protected FrameworkInstanceBindingExpression(
       BindingKey bindingKey,
       Optional<FieldSpec> fieldSpec,
-      HasBindingExpressions hasBindingExpressions,
+      GeneratedComponentModel generatedComponentModel,
       MemberSelect memberSelect) {
     super(bindingKey);
-    this.hasBindingExpressions = hasBindingExpressions;
+    this.generatedComponentModel = generatedComponentModel;
     this.memberSelect = memberSelect;
     this.fieldSpec = fieldSpec;
   }
 
   /**
    * The expression for the framework instance for this binding. If the instance comes from a
-   * component field, it will be {@link HasBindingExpressions#addInitialization(CodeBlock)
-   * initialized} and {@link HasBindingExpressions#addField(FieldSpec) added} to the component the
+   * component field, it will be {@link GeneratedComponentModel#addInitialization(CodeBlock)
+   * initialized} and {@link GeneratedComponentModel#addField(FieldSpec) added} to the component the
    * first time this method is invoked.
    */
   final CodeBlock getFrameworkTypeInstance(ClassName requestingClass) {
@@ -106,7 +103,7 @@
             CodeBlock.of(
                 "this.$L = $L;",
                 fieldName(),
-                checkNotNull(hasBindingExpressions.getFieldInitialization(this)));
+                checkNotNull(generatedComponentModel.getFieldInitialization(this)));
 
         if (fieldInitializationState == InitializationState.DELEGATED) {
           // If we were recursively invoked, set the delegate factory as part of our initialization
@@ -119,15 +116,15 @@
         } else {
           codeBuilder.add(initCode);
         }
-        hasBindingExpressions.addInitialization(codeBuilder.build());
-        hasBindingExpressions.addField(fieldSpec.get());
+        generatedComponentModel.addInitialization(codeBuilder.build());
+        generatedComponentModel.addField(fieldSpec.get());
 
         setFieldInitializationState(InitializationState.INITIALIZED);
         break;
 
       case INITIALIZING:
         // We were recursively invoked, so create a delegate factory instead
-        hasBindingExpressions.addInitialization(
+        generatedComponentModel.addInitialization(
             CodeBlock.of("this.$L = new $T();", fieldName(), DELEGATE_FACTORY));
         setFieldInitializationState(InitializationState.DELEGATED);
         break;
diff --git a/java/dagger/internal/codegen/HasBindingExpressions.java b/java/dagger/internal/codegen/GeneratedComponentModel.java
similarity index 68%
rename from java/dagger/internal/codegen/HasBindingExpressions.java
rename to java/dagger/internal/codegen/GeneratedComponentModel.java
index 3a0d3bb..e215332 100644
--- a/java/dagger/internal/codegen/HasBindingExpressions.java
+++ b/java/dagger/internal/codegen/GeneratedComponentModel.java
@@ -19,22 +19,12 @@
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
 import com.squareup.javapoet.MethodSpec;
-import javax.annotation.Nullable;
 
-/** An object which associates a {@link BindingExpression} instance with a {@link BindingKey}. */
-// TODO(dpb): Rename and/or split up this type.
-interface HasBindingExpressions {
-
-  /**
-   * Returns the {@link BindingExpression} associated with the given {@link BindingKey} or {@code
-   * null} if no association exists.
-   */
-  // TODO(dpb): Move the hierarchical map of binding expressions out into a separate class.
-  // This should remove the need for HasBindingExpressions
-  @Nullable
-  BindingExpression getBindingExpression(BindingKey bindingKey);
+/** The model of the component being generated. */
+interface GeneratedComponentModel {
 
   /** Returns the expression used to initialize a binding expression field. */
+  // TODO(user): Move this method onto FrameworkInstanceBindingExpression and subtypes.
   CodeBlock getFieldInitialization(FrameworkInstanceBindingExpression bindingExpression);
 
   /** Adds the given field to the component. */
diff --git a/java/dagger/internal/codegen/MembersInjectorBindingExpression.java b/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
index a620f0d..9134ed0 100644
--- a/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
+++ b/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
@@ -24,25 +24,19 @@
 import dagger.internal.codegen.DependencyRequest.Kind;
 import java.util.Optional;
 
+/** A binding expression that uses a {@link dagger.MembersInjector} instance. */
 final class MembersInjectorBindingExpression extends FrameworkInstanceBindingExpression {
   MembersInjectorBindingExpression(
       BindingKey bindingKey,
       Optional<FieldSpec> fieldSpec,
-      HasBindingExpressions hasBindingExpressions,
+      GeneratedComponentModel generatedComponentModel,
       MemberSelect memberSelect) {
-    super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+    super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
   }
 
   @Override
-  CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
-    checkArgument(request.kind().equals(Kind.MEMBERS_INJECTOR));
-    return getFrameworkTypeInstance(requestingClass);
-  }
-
-  @Override
-  CodeBlock getDependencyExpression(
-      FrameworkDependency frameworkDependency, ClassName requestingClass) {
-    checkArgument(frameworkDependency.bindingType().equals(BindingType.MEMBERS_INJECTION));
+  CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    checkArgument(requestKind.equals(Kind.MEMBERS_INJECTOR));
     return getFrameworkTypeInstance(requestingClass);
   }
 
diff --git a/java/dagger/internal/codegen/OptionalBindingExpression.java b/java/dagger/internal/codegen/OptionalBindingExpression.java
index 34cbc3d..f2d8efd 100644
--- a/java/dagger/internal/codegen/OptionalBindingExpression.java
+++ b/java/dagger/internal/codegen/OptionalBindingExpression.java
@@ -23,31 +23,29 @@
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.OptionalType.OptionalKind;
 
-/**
- * A {@link BindingExpression} for {@link
- * ContributionBinding.Kind#SYNTHETIC_OPTIONAL_BINDING}
- */
+/** A binding expression for optional bindings. */
 final class OptionalBindingExpression extends SimpleInvocationBindingExpression {
   private final ProvisionBinding binding;
-  private final HasBindingExpressions hasBindingExpressions;
+  private final ComponentBindingExpressions componentBindingExpressions;
 
   OptionalBindingExpression(
       ProvisionBinding binding,
       BindingExpression delegate,
-      HasBindingExpressions hasBindingExpressions) {
+      ComponentBindingExpressions componentBindingExpressions) {
     super(delegate);
     this.binding = binding;
-    this.hasBindingExpressions = hasBindingExpressions;
+    this.componentBindingExpressions = componentBindingExpressions;
   }
 
   @Override
-  CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
     OptionalType optionalType = OptionalType.from(binding.key());
     OptionalKind optionalKind = optionalType.kind();
     if (binding.dependencies().isEmpty()) {
       // When compiling with -source 7, javac's type inference isn't strong enough to detect
       // Futures.immediateFuture(Optional.absent()) for keys that aren't Object
-      if (request.kind().equals(DependencyRequest.Kind.FUTURE)
+      if (requestKind.equals(DependencyRequest.Kind.FUTURE)
           && isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
         return optionalKind.parameterizedAbsentValueExpression(optionalType);
       }
@@ -56,9 +54,7 @@
     DependencyRequest dependency = getOnlyElement(binding.dependencies());
 
     CodeBlock dependencyExpression =
-        hasBindingExpressions
-            .getBindingExpression(dependency.bindingKey())
-            .getDependencyExpression(dependency, requestingClass);
+        componentBindingExpressions.getDependencyExpression(dependency, requestingClass);
 
     // If the dependency type is inaccessible, then we have to use Optional.<Object>of(...), or else
     // we will get "incompatible types: inference variable has incompatible bounds.
diff --git a/java/dagger/internal/codegen/ProducerBindingExpression.java b/java/dagger/internal/codegen/ProducerBindingExpression.java
index 208a408..7fdef71 100644
--- a/java/dagger/internal/codegen/ProducerBindingExpression.java
+++ b/java/dagger/internal/codegen/ProducerBindingExpression.java
@@ -16,40 +16,28 @@
 
 package dagger.internal.codegen;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.BindingType.PRODUCTION;
-
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
 import java.util.Optional;
 
+/** A binding expression that uses a {@link dagger.producers.Producer} instance. */
 final class ProducerBindingExpression extends FrameworkInstanceBindingExpression {
   private final boolean isProducerFromProvider;
 
   ProducerBindingExpression(
       BindingKey bindingKey,
       Optional<FieldSpec> fieldSpec,
-      HasBindingExpressions hasBindingExpressions,
+      GeneratedComponentModel generatedComponentModel,
       MemberSelect memberSelect,
       boolean isProducerFromProvider) {
-    super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+    super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
     this.isProducerFromProvider = isProducerFromProvider;
   }
 
   @Override
-  CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
-    return FrameworkType.PRODUCER.to(request.kind(), getFrameworkTypeInstance(requestingClass));
-  }
-
-  @Override
-  CodeBlock getDependencyExpression(
-      FrameworkDependency frameworkDependency, ClassName requestingClass) {
-    checkArgument(
-        frameworkDependency.bindingType().equals(PRODUCTION),
-        "%s is not a production dependency",
-        frameworkDependency);
-    return getFrameworkTypeInstance(requestingClass);
+  CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    return FrameworkType.PRODUCER.to(requestKind, getFrameworkTypeInstance(requestingClass));
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/ProviderBindingExpression.java b/java/dagger/internal/codegen/ProviderBindingExpression.java
index 107b470..0d6e70c 100644
--- a/java/dagger/internal/codegen/ProviderBindingExpression.java
+++ b/java/dagger/internal/codegen/ProviderBindingExpression.java
@@ -21,34 +21,19 @@
 import com.squareup.javapoet.FieldSpec;
 import java.util.Optional;
 
+/** A binding expression that uses a {@link javax.inject.Provider} instance. */
 final class ProviderBindingExpression extends FrameworkInstanceBindingExpression {
   ProviderBindingExpression(
       BindingKey bindingKey,
       Optional<FieldSpec> fieldSpec,
-      HasBindingExpressions hasBindingExpressions,
+      GeneratedComponentModel generatedComponentModel,
       MemberSelect memberSelect) {
-    super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+    super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
   }
 
   @Override
-  CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
-    return FrameworkType.PROVIDER.to(request.kind(), getFrameworkTypeInstance(requestingClass));
-  }
-
-  @Override
-  CodeBlock getDependencyExpression(
-      FrameworkDependency frameworkDependency, ClassName requestingClass) {
-    switch (frameworkDependency.bindingType()) {
-      case PROVISION:
-        return getFrameworkTypeInstance(requestingClass);
-      case MEMBERS_INJECTION:
-        throw new IllegalArgumentException();
-      case PRODUCTION:
-        return FrameworkType.PROVIDER.to(
-            DependencyRequest.Kind.PRODUCER, getFrameworkTypeInstance(requestingClass));
-      default:
-        throw new AssertionError();
-    }
+  CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    return FrameworkType.PROVIDER.to(requestKind, getFrameworkTypeInstance(requestingClass));
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/SetBindingExpression.java b/java/dagger/internal/codegen/SetBindingExpression.java
index d94660c..71ef367 100644
--- a/java/dagger/internal/codegen/SetBindingExpression.java
+++ b/java/dagger/internal/codegen/SetBindingExpression.java
@@ -30,38 +30,36 @@
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
 
-/**
- * A {@link BindingExpression} for {@link
- * ContributionBinding.Kind#SYNTHETIC_MULTIBOUND_SET}
- */
+/** A binding expression for multibound sets. */
 final class SetBindingExpression extends SimpleInvocationBindingExpression {
   private final ProvisionBinding binding;
   private final BindingGraph graph;
-  private final HasBindingExpressions hasBindingExpressions;
+  private final ComponentBindingExpressions componentBindingExpressions;
   private final Elements elements;
 
   SetBindingExpression(
       ProvisionBinding binding,
       BindingGraph graph,
-      HasBindingExpressions hasBindingExpressions,
+      ComponentBindingExpressions componentBindingExpressions,
       BindingExpression delegate,
       Elements elements) {
     super(delegate);
     this.binding = binding;
     this.graph = graph;
-    this.hasBindingExpressions = hasBindingExpressions;
+    this.componentBindingExpressions = componentBindingExpressions;
     this.elements = elements;
   }
 
   @Override
-  CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
     // TODO(ronshapiro): We should also make an ImmutableSet version of SetFactory
     boolean isImmutableSetAvailable = isImmutableSetAvailable();
     // TODO(ronshapiro, gak): Use Sets.immutableEnumSet() if it's available?
     if (isImmutableSetAvailable && binding.dependencies().stream().allMatch(this::isSingleValue)) {
       return CodeBlock.builder()
           .add("$T.", ImmutableSet.class)
-          .add(maybeTypeParameter(request, requestingClass))
+          .add(maybeTypeParameter(requestingClass))
           .add(
               "of($L)",
               binding
@@ -73,19 +71,18 @@
     }
     switch (binding.dependencies().size()) {
       case 0:
-        return collectionsStaticFactoryInvocation(
-            request, requestingClass, CodeBlock.of("emptySet()"));
+        return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptySet()"));
       case 1:
         {
           DependencyRequest dependency = getOnlyElement(binding.dependencies());
           CodeBlock contributionExpression = getContributionExpression(dependency, requestingClass);
           if (isSingleValue(dependency)) {
             return collectionsStaticFactoryInvocation(
-                request, requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
+                requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
           } else if (isImmutableSetAvailable) {
             return CodeBlock.builder()
                 .add("$T.", ImmutableSet.class)
-                .add(maybeTypeParameter(request, requestingClass))
+                .add(maybeTypeParameter(requestingClass))
                 .add("copyOf($L)", contributionExpression)
                 .build();
           }
@@ -95,7 +92,7 @@
         CodeBlock.Builder instantiation = CodeBlock.builder();
         instantiation
             .add("$T.", isImmutableSetAvailable ? ImmutableSet.class : SetBuilder.class)
-            .add(maybeTypeParameter(request, requestingClass));
+            .add(maybeTypeParameter(requestingClass));
         if (isImmutableSetAvailable) {
           instantiation.add("builder()");
         } else {
@@ -112,23 +109,20 @@
 
   private CodeBlock getContributionExpression(
       DependencyRequest dependency, ClassName requestingClass) {
-    return hasBindingExpressions
-        .getBindingExpression(dependency.bindingKey())
-        .getDependencyExpression(dependency, requestingClass);
+    return componentBindingExpressions.getDependencyExpression(dependency, requestingClass);
   }
 
-  private static CodeBlock collectionsStaticFactoryInvocation(
-      DependencyRequest request, ClassName requestingClass, CodeBlock methodInvocation) {
+  private CodeBlock collectionsStaticFactoryInvocation(
+      ClassName requestingClass, CodeBlock methodInvocation) {
     return CodeBlock.builder()
         .add("$T.", Collections.class)
-        .add(maybeTypeParameter(request, requestingClass))
+        .add(maybeTypeParameter(requestingClass))
         .add(methodInvocation)
         .build();
   }
 
-  private static CodeBlock maybeTypeParameter(
-      DependencyRequest request, ClassName requestingClass) {
-    TypeMirror elementType = SetType.from(request.key()).elementType();
+  private CodeBlock maybeTypeParameter(ClassName requestingClass) {
+    TypeMirror elementType = SetType.from(binding.key()).elementType();
     return isTypeAccessibleFrom(elementType, requestingClass.packageName())
         ? CodeBlock.of("<$T>", elementType)
         : CodeBlock.of("");
diff --git a/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
index 62eee5f..a56bf25 100644
--- a/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
@@ -21,8 +21,8 @@
 import com.squareup.javapoet.CodeBlock;
 
 /**
- * A {@link BindingExpression} that can fulfill its request with a simple call when possible, and
- * otherwise delegates to a backing provider field.
+ * A binding expression that can use a simple expression for instance requests, and delegates to
+ * another expression for other requests.
  */
 abstract class SimpleInvocationBindingExpression extends BindingExpression {
   private final BindingExpression delegate;
@@ -38,7 +38,7 @@
    * @param requestingClass the class that will contain the expression
    */
   abstract CodeBlock getInstanceDependencyExpression(
-      DependencyRequest request, ClassName requestingClass);
+      DependencyRequest.Kind requestKind, ClassName requestingClass);
 
   /**
    * Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
@@ -52,24 +52,21 @@
   }
 
   @Override
-  final CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
-    switch (request.kind()) {
+  final CodeBlock getDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    switch (requestKind) {
       case INSTANCE:
-        return getInstanceDependencyExpression(request, requestingClass);
+        return getInstanceDependencyExpression(requestKind, requestingClass);
       case FUTURE:
         return CodeBlock.builder()
             .add("$T.", Futures.class)
             .add(explicitTypeParameter(requestingClass))
-            .add("immediateFuture($L)", getInstanceDependencyExpression(request, requestingClass))
+            .add(
+                "immediateFuture($L)",
+                getInstanceDependencyExpression(requestKind, requestingClass))
             .build();
       default:
-        return delegate.getDependencyExpression(request, requestingClass);
+        return delegate.getDependencyExpression(requestKind, requestingClass);
     }
   }
-
-  @Override
-  final CodeBlock getDependencyExpression(
-      FrameworkDependency frameworkDependency, ClassName requestingClass) {
-    return delegate.getDependencyExpression(frameworkDependency, requestingClass);
-  }
 }
diff --git a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
index bb72db0..ec9d208 100644
--- a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
@@ -36,34 +36,37 @@
 import javax.lang.model.type.DeclaredType;
 
 /**
- * A request fulfillment implementation that invokes methods or constructors directly to fulfill
- * requests whenever possible. In cases where direct invocation is not possible, this implementation
- * delegates to one that uses a {@link javax.inject.Provider}.
+ * A binding expression that invokes methods or constructors directly for a provision binding when
+ * possible.
  */
 final class SimpleMethodBindingExpression extends SimpleInvocationBindingExpression {
   private final CompilerOptions compilerOptions;
   private final ProvisionBinding provisionBinding;
-  private final HasBindingExpressions hasBindingExpressions;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final GeneratedComponentModel generatedComponentModel;
 
   SimpleMethodBindingExpression(
       CompilerOptions compilerOptions,
       ProvisionBinding provisionBinding,
       BindingExpression delegate,
-      HasBindingExpressions hasBindingExpressions) {
+      ComponentBindingExpressions componentBindingExpressions,
+      GeneratedComponentModel generatedComponentModel) {
     super(delegate);
-    this.compilerOptions = compilerOptions;
     checkArgument(
         provisionBinding.implicitDependencies().isEmpty(),
         "framework deps are not currently supported");
     checkArgument(!provisionBinding.scope().isPresent());
     checkArgument(!provisionBinding.requiresModuleInstance());
     checkArgument(provisionBinding.bindingElement().isPresent());
+    this.compilerOptions = compilerOptions;
     this.provisionBinding = provisionBinding;
-    this.hasBindingExpressions = hasBindingExpressions;
+    this.componentBindingExpressions = componentBindingExpressions;
+    this.generatedComponentModel = generatedComponentModel;
   }
 
   @Override
-  CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
     return requiresInjectionMethod(provisionBinding, requestingClass.packageName())
         ? invokeInjectionMethod(requestingClass)
         : invokeMethod(requestingClass);
@@ -115,9 +118,7 @@
   }
 
   private CodeBlock dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
-    return hasBindingExpressions
-        .getBindingExpression(dependency.bindingKey())
-        .getDependencyArgumentExpression(dependency, requestingClass);
+    return componentBindingExpressions.getDependencyArgumentExpression(dependency, requestingClass);
   }
 
   private CodeBlock maybeCheckForNulls(CodeBlock methodCall) {
@@ -141,7 +142,7 @@
 
     return CodeBlock.of(
         "$N($L)",
-        hasBindingExpressions.getMembersInjectionMethod(provisionBinding.key()),
+        generatedComponentModel.getMembersInjectionMethod(provisionBinding.key()),
         instance);
   }
 }
diff --git a/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java b/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
index 53fd28b..1e87fe7 100644
--- a/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
+++ b/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
@@ -19,6 +19,7 @@
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 
+/** A binding expression for a subcomponent builder that just invokes the constructor. */
 final class SubcomponentBuilderBindingExpression extends SimpleInvocationBindingExpression {
   private final String subcomponentBuilderName;
 
@@ -28,7 +29,8 @@
   }
 
   @Override
-  CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
     return CodeBlock.of("new $LBuilder()", subcomponentBuilderName);
   }
 }
diff --git a/java/dagger/internal/codegen/SubcomponentWriter.java b/java/dagger/internal/codegen/SubcomponentWriter.java
index bfa3a23..48e674f 100644
--- a/java/dagger/internal/codegen/SubcomponentWriter.java
+++ b/java/dagger/internal/codegen/SubcomponentWriter.java
@@ -84,12 +84,6 @@
   }
 
   @Override
-  public BindingExpression getBindingExpression(BindingKey key) {
-    BindingExpression bindingExpression = super.getBindingExpression(key);
-    return bindingExpression == null ? parent.getBindingExpression(key) : bindingExpression;
-  }
-
-  @Override
   protected CodeBlock getReferenceReleasingProviderManagerExpression(Scope scope) {
     return parent.getReferenceReleasingProviderManagerExpression(scope);
   }