Inline requests for bindings that were provided with a @BindInstance method, and enable SimpleMethodRequestFulfillment to operate on instance @Provides methods

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=166206675
diff --git a/java/dagger/internal/codegen/AbstractComponentWriter.java b/java/dagger/internal/codegen/AbstractComponentWriter.java
index 3eb0c0a..58475ec 100644
--- a/java/dagger/internal/codegen/AbstractComponentWriter.java
+++ b/java/dagger/internal/codegen/AbstractComponentWriter.java
@@ -69,7 +69,6 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
@@ -125,12 +124,14 @@
   private final UniqueNameSet componentFieldNames = new UniqueNameSet();
   private final UniqueNameSet componentMethodNames = new UniqueNameSet();
   private final ComponentBindingExpressions bindingExpressions;
+  protected final ComponentRequirementFields componentRequirementFields;
   // TODO(user): Merge into ComponentBindingExpressions after we refactor BindingKey.
   private final Map<BindingKey, FrameworkInstanceBindingExpression>
       producerFromProviderBindingExpressions = new LinkedHashMap<>();
   private final List<CodeBlock> initializations = new ArrayList<>();
   protected final List<MethodSpec> interfaceMethods = new ArrayList<>();
   private final BindingExpression.Factory bindingExpressionFactory;
+  private final ComponentRequirementField.Factory componentRequirementFieldFactory;
 
   private final Map<Key, MethodSpec> membersInjectionMethods = new LinkedHashMap<>();
   protected final MethodSpec.Builder constructor = constructorBuilder().addModifiers(PRIVATE);
@@ -142,16 +143,7 @@
    * For each component requirement, the builder field. This map is empty for subcomponents that do
    * not use a builder.
    */
-  private ImmutableMap<ComponentRequirement, FieldSpec> builderFields = ImmutableMap.of();
-
-  /**
-   * For each component requirement, the member select for the component field that holds it.
-   *
-   * <p>Fields are written for all requirements for subcomponents that do not use a builder, and for
-   * any requirement that is reused from a subcomponent of this component.
-   */
-  protected final Map<ComponentRequirement, MemberSelect> componentContributionFields =
-      Maps.newHashMap();
+  private final ImmutableMap<ComponentRequirement, FieldSpec> builderFields;
 
   /**
    * The member-selects for {@link dagger.internal.ReferenceReleasingProviderManager} fields,
@@ -168,7 +160,8 @@
       BindingGraph graph,
       ImmutableMap<ComponentDescriptor, String> subcomponentNames,
       OptionalFactories optionalFactories,
-      ComponentBindingExpressions bindingExpressions) {
+      ComponentBindingExpressions bindingExpressions,
+      ComponentRequirementFields componentRequirementFields) {
     this.types = types;
     this.elements = elements;
     this.keyFactory = keyFactory;
@@ -179,16 +172,27 @@
     this.subcomponentNames = subcomponentNames;
     this.optionalFactories = optionalFactories;
     this.bindingExpressions = bindingExpressions;
+    // TODO(dpb): Allow ComponentBuilder.create to return a no-op object
+    if (hasBuilder(graph)) {
+      builder = ComponentBuilder.create(name, graph, subcomponentNames, elements, types);
+      builderFields = builder.builderFields();
+    } else {
+      builderFields = ImmutableMap.of();
+    }
+    this.componentRequirementFields = componentRequirementFields;
     this.bindingExpressionFactory =
         new BindingExpression.Factory(
             compilerOptions,
             name,
             componentFieldNames,
             bindingExpressions,
+            componentRequirementFields,
             this,
             childComponentNames(keyFactory, subcomponentNames),
             graph,
             elements);
+    this.componentRequirementFieldFactory =
+        new ComponentRequirementField.Factory(this, componentFieldNames, name, builderFields);
   }
 
   private static ImmutableMap<BindingKey, String> childComponentNames(
@@ -216,7 +220,8 @@
         graph,
         parent.subcomponentNames,
         parent.optionalFactories,
-        parent.bindingExpressions.forChildComponent());
+        parent.bindingExpressions.forChildComponent(),
+        parent.componentRequirementFields.forChildComponent());
   }
 
   protected final ClassName componentDefinitionTypeName() {
@@ -224,48 +229,6 @@
   }
 
   /**
-   * Returns an expression that evaluates to an instance of the requirement, looking for either a
-   * builder field or a component field.
-   */
-  private CodeBlock getComponentContributionExpression(ComponentRequirement componentRequirement) {
-    if (builderFields.containsKey(componentRequirement)) {
-      return CodeBlock.of("builder.$N", builderFields.get(componentRequirement));
-    } else {
-      Optional<CodeBlock> codeBlock =
-          getOrCreateComponentRequirementFieldExpression(componentRequirement);
-      checkState(
-          codeBlock.isPresent(), "no builder or component field for %s", componentRequirement);
-      return codeBlock.get();
-    }
-  }
-
-  /**
-   * Returns an expression for a component requirement field. Adds a field the first time one is
-   * requested for a requirement if this component's builder has a field for it.
-   */
-  protected Optional<CodeBlock> getOrCreateComponentRequirementFieldExpression(
-      ComponentRequirement componentRequirement) {
-    MemberSelect fieldSelect = componentContributionFields.get(componentRequirement);
-    if (fieldSelect == null) {
-      if (!builderFields.containsKey(componentRequirement)) {
-        return Optional.empty();
-      }
-      FieldSpec componentField =
-          componentField(
-                  TypeName.get(componentRequirement.type()),
-                  simpleVariableName(componentRequirement.typeElement()))
-              .addModifiers(PRIVATE, FINAL)
-              .build();
-      component.addField(componentField);
-      constructor.addCode(
-          "this.$N = builder.$N;", componentField, builderFields.get(componentRequirement));
-      fieldSelect = localField(name, componentField.name);
-      componentContributionFields.put(componentRequirement, fieldSelect);
-    }
-    return Optional.of(fieldSelect.getExpressionFor(name));
-  }
-
-  /**
    * Creates a {@link FieldSpec.Builder} with a unique name based off of {@code name}.
    */
   protected final FieldSpec.Builder componentField(TypeName type, String name) {
@@ -300,7 +263,7 @@
   final TypeSpec.Builder write() {
     checkState(!done, "ComponentWriter has already been generated.");
     decorateComponent();
-    if (hasBuilder()) {
+    if (hasBuilder(graph)) {
       addBuilder();
     }
 
@@ -311,6 +274,7 @@
     addFactoryMethods();
     addReferenceReleasingProviderManagerFields();
     createBindingExpressions();
+    createComponentRequirementFields();
     implementInterfaceMethods();
     addSubcomponents();
     writeInitializeAndInterfaceMethods();
@@ -329,7 +293,7 @@
    */
   protected abstract void decorateComponent();
 
-  private boolean hasBuilder() {
+  private static boolean hasBuilder(BindingGraph graph) {
     ComponentDescriptor component = graph.componentDescriptor();
     return component.kind().isTopLevel() || component.builderSpec().isPresent();
   }
@@ -338,9 +302,6 @@
    * Adds a builder type.
    */
   private void addBuilder() {
-    builder = ComponentBuilder.create(name, graph, subcomponentNames, elements, types);
-    builderFields = builder.builderFields();
-
     addBuilderClass(builder.typeSpec());
 
     constructor.addParameter(builderName(), "builder");
@@ -457,6 +418,14 @@
     bindingExpressions.addBindingExpression(bindingExpressionFactory.forField(resolvedBindings));
   }
 
+  private void createComponentRequirementFields() {
+    builderFields
+        .keySet()
+        .stream()
+        .map(componentRequirementFieldFactory::forBuilderField)
+        .forEach(componentRequirementFields::add);
+  }
+
   private boolean useRawType(Binding binding) {
     return useRawType(binding.bindingPackage());
   }
@@ -578,7 +547,7 @@
                * separate fields and initilization as we do now. */
               .addAnnotation(AnnotationSpecs.suppressWarnings(UNCHECKED))
               .addCode(CodeBlocks.concat(partition));
-      if (hasBuilder()) {
+      if (hasBuilder(graph)) {
         initializeMethod.addParameter(builderName(), "builder", FINAL);
         constructor.addStatement("$L(builder)", methodName);
       } else {
@@ -720,14 +689,15 @@
     TypeName bindingKeyTypeName = TypeName.get(binding.key().type());
     switch (binding.bindingKind()) {
       case COMPONENT:
+        // This bindingKeyTypeName type parameter can be removed when we drop java 7 source support
+        return CodeBlock.of("$T.<$T>create(this)", INSTANCE_FACTORY, bindingKeyTypeName);
+
+      case COMPONENT_DEPENDENCY:
         return CodeBlock.of(
-            "$T.<$T>create($L)",
+            "$T.create($L)",
             INSTANCE_FACTORY,
-            bindingKeyTypeName,
-            bindingKeyTypeName.equals(componentDefinitionTypeName())
-                ? "this"
-                : getComponentContributionExpression(
-                    ComponentRequirement.forDependency(binding.key().type())));
+            componentRequirementFields.getExpressionDuringInitialization(
+                ComponentRequirement.forDependency(binding.key().type()), name));
 
       case COMPONENT_PROVISION:
         {
@@ -778,8 +748,8 @@
           return CodeBlock.of(
               "new $L($L)",
               factoryName,
-              getComponentContributionExpression(
-                  ComponentRequirement.forDependency(dependencyType.asType())));
+              componentRequirementFields.getExpressionDuringInitialization(
+                  ComponentRequirement.forDependency(dependencyType.asType()), name));
         }
 
       case SUBCOMPONENT_BUILDER:
@@ -807,7 +777,8 @@
             "$T.$L($L)",
             InstanceFactory.class,
             binding.nullableType().isPresent() ? "createNullable" : "create",
-            getComponentContributionExpression(ComponentRequirement.forBinding(binding)));
+            componentRequirementFields.getExpressionDuringInitialization(
+                ComponentRequirement.forBinding(binding), name));
 
       case INJECTION:
       case PROVISION:
@@ -816,8 +787,9 @@
               Lists.newArrayListWithCapacity(binding.explicitDependencies().size() + 1);
           if (binding.requiresModuleInstance()) {
             arguments.add(
-                getComponentContributionExpression(
-                    ComponentRequirement.forModule(binding.contributingModule().get().asType())));
+                componentRequirementFields.getExpressionDuringInitialization(
+                    ComponentRequirement.forModule(binding.contributingModule().get().asType()),
+                    name));
           }
           arguments.addAll(getDependencyArguments(binding));
 
@@ -853,8 +825,8 @@
               /* 1 */ PRODUCER,
               /* 2 */ binding.key().type(),
               /* 3 */ LISTENABLE_FUTURE,
-              /* 4 */ getComponentContributionExpression(
-                  ComponentRequirement.forDependency(dependencyType.asType())),
+              /* 4 */ componentRequirementFields.getExpressionDuringInitialization(
+                  ComponentRequirement.forDependency(dependencyType.asType()), name),
               /* 5 */ binding.bindingElement().get().getSimpleName(),
               /* 6 */ dependencyType,
               /* 7 */ simpleVariableName(dependencyType));
@@ -866,8 +838,9 @@
               Lists.newArrayListWithCapacity(binding.dependencies().size() + 2);
           if (binding.requiresModuleInstance()) {
             arguments.add(
-                getComponentContributionExpression(
-                    ComponentRequirement.forModule(binding.contributingModule().get().asType())));
+                componentRequirementFields.getExpressionDuringInitialization(
+                    ComponentRequirement.forModule(binding.contributingModule().get().asType()),
+                    name));
           }
           arguments.addAll(getDependencyArguments(binding));
 
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index 4d06d38..2206e66 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -59,6 +59,7 @@
     private final ClassName componentName;
     private final UniqueNameSet componentFieldNames;
     private final ComponentBindingExpressions componentBindingExpressions;
+    private final ComponentRequirementFields componentRequirementFields;
     private final GeneratedComponentModel generatedComponentModel;
     private final ImmutableMap<BindingKey, String> subcomponentNames;
     private final BindingGraph graph;
@@ -69,6 +70,7 @@
         ClassName componentName,
         UniqueNameSet componentFieldNames,
         ComponentBindingExpressions componentBindingExpressions,
+        ComponentRequirementFields componentRequirementFields,
         GeneratedComponentModel generatedComponentModel,
         ImmutableMap<BindingKey, String> subcomponentNames,
         BindingGraph graph,
@@ -77,6 +79,7 @@
       this.componentName = checkNotNull(componentName);
       this.componentFieldNames = checkNotNull(componentFieldNames);
       this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+      this.componentRequirementFields = checkNotNull(componentRequirementFields);
       this.generatedComponentModel = checkNotNull(generatedComponentModel);
       this.subcomponentNames = checkNotNull(subcomponentNames);
       this.graph = checkNotNull(graph);
@@ -151,6 +154,13 @@
 
       ProvisionBinding provisionBinding = (ProvisionBinding) resolvedBindings.contributionBinding();
       switch (provisionBinding.bindingKind()) {
+        case COMPONENT:
+          return new ComponentInstanceBindingExpression(bindingExpression, componentName);
+        case COMPONENT_DEPENDENCY:
+          return new BoundInstanceBindingExpression(
+              bindingExpression,
+              ComponentRequirement.forDependency(provisionBinding.key().type()),
+              componentRequirementFields);
         case SUBCOMPONENT_BUILDER:
           return new SubcomponentBuilderBindingExpression(
               bindingExpression, subcomponentNames.get(resolvedBindings.bindingKey()));
@@ -160,17 +170,29 @@
         case SYNTHETIC_OPTIONAL_BINDING:
           return new OptionalBindingExpression(
               provisionBinding, bindingExpression, componentBindingExpressions);
-            case INJECTION:
+        case BUILDER_BINDING:
+              return new BoundInstanceBindingExpression(
+                  bindingExpression,
+                  ComponentRequirement.forBinding(provisionBinding),
+                  componentRequirementFields);
+        case INJECTION:
         case PROVISION:
           if (!provisionBinding.scope().isPresent()
-              && !provisionBinding.requiresModuleInstance()
               && provisionBinding.bindingElement().isPresent()) {
+            Optional<ComponentRequirement> moduleRequirement =
+                provisionBinding.requiresModuleInstance()
+                    ? Optional.of(
+                        ComponentRequirement.forModule(
+                            provisionBinding.contributingModule().get().asType()))
+                    : Optional.empty();
             return new SimpleMethodBindingExpression(
                 compilerOptions,
                 provisionBinding,
                 bindingExpression,
                 componentBindingExpressions,
-                generatedComponentModel);
+                generatedComponentModel,
+                moduleRequirement,
+                componentRequirementFields);
           }
           // fall through
         default:
diff --git a/java/dagger/internal/codegen/BindingGraph.java b/java/dagger/internal/codegen/BindingGraph.java
index 25feb5b..ba01bb7 100644
--- a/java/dagger/internal/codegen/BindingGraph.java
+++ b/java/dagger/internal/codegen/BindingGraph.java
@@ -230,7 +230,8 @@
 
       // Collect Component dependencies.
       for (TypeElement componentDependency : componentDescriptor.dependencies()) {
-        explicitBindingsBuilder.add(provisionBindingFactory.forComponent(componentDependency));
+        explicitBindingsBuilder.add(
+            provisionBindingFactory.forComponentDependency(componentDependency));
         List<ExecutableElement> dependencyMethods =
             ElementFilter.methodsIn(elements.getAllMembers(componentDependency));
         for (ExecutableElement method : dependencyMethods) {
diff --git a/java/dagger/internal/codegen/BoundInstanceBindingExpression.java b/java/dagger/internal/codegen/BoundInstanceBindingExpression.java
new file mode 100644
index 0000000..2f3cd5b
--- /dev/null
+++ b/java/dagger/internal/codegen/BoundInstanceBindingExpression.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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 com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.Component;
+
+/**
+ * A binding expression for instances bound with {@link dagger.BindsInstance} and instances of
+ * {@link Component#dependencies() component dependencies}.
+ */
+final class BoundInstanceBindingExpression extends SimpleInvocationBindingExpression {
+  private final ComponentRequirement componentRequirement;
+  private final ComponentRequirementFields componentRequirementFields;
+
+  BoundInstanceBindingExpression(
+      BindingExpression delegate,
+      ComponentRequirement componentRequirement,
+      ComponentRequirementFields componentRequirementFields) {
+    super(delegate);
+    this.componentRequirement = componentRequirement;
+    this.componentRequirementFields = componentRequirementFields;
+  }
+
+  @Override
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    return componentRequirementFields.getExpression(componentRequirement, requestingClass);
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 32f053c..8e45306 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -29,11 +29,12 @@
 import java.util.Map;
 import javax.lang.model.type.TypeMirror;
 
-/** A factory of code expressions used to access any binding available to a component. */
+/** A central repository 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.
+  // TODO(dpb,ronshapiro): refactor this and ComponentRequirementFields into a
+  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
+  // parents? If so, maybe make BindingExpression.Factory create it.
 
   /**
    * A list of binding expression maps. The first element contains the bindings owned by this
diff --git a/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
new file mode 100644
index 0000000..7523cf3
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentInstanceBindingExpression.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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 com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+
+/** A binding expression for the instance of the component itself, i.e. {@code this}. */
+final class ComponentInstanceBindingExpression extends SimpleInvocationBindingExpression {
+  private final ClassName componentName;
+
+  ComponentInstanceBindingExpression(BindingExpression delegate, ClassName componentName) {
+    super(delegate);
+    this.componentName = componentName;
+  }
+
+  @Override
+  CodeBlock getInstanceDependencyExpression(
+      DependencyRequest.Kind requestKind, ClassName requestingClass) {
+    return componentName.equals(requestingClass)
+        ? CodeBlock.of("this")
+        : CodeBlock.of("$T.this", componentName);
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirementField.java b/java/dagger/internal/codegen/ComponentRequirementField.java
new file mode 100644
index 0000000..e8d721d
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementField.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2017 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 com.google.common.base.Preconditions.checkNotNull;
+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;
+
+/**
+ * A factory for expressions of {@link ComponentRequirement}s in the generated component. This is
+ * <em>not</em> a {@link BindingExpression}, since {@link ComponentRequirement}s do not have a
+ * {@link BindingKey}. See {@link BoundInstanceBindingExpression} for binding expressions that are
+ * themselves a binding.
+ */
+abstract class ComponentRequirementField {
+  private final ComponentRequirement componentRequirement;
+
+  private ComponentRequirementField(ComponentRequirement componentRequirement) {
+    this.componentRequirement = checkNotNull(componentRequirement);
+  }
+
+  final ComponentRequirement componentRequirement() {
+    return componentRequirement;
+  }
+
+  /**
+   * Returns an expression for the {@link ComponentRequirement} to be used when implementing a
+   * component method. This may add a field to the component in order to reference the component
+   * requirement outside of the {@code initialize()} methods.
+   */
+  abstract CodeBlock getExpression(ClassName requestingClass);
+
+  /**
+   * Returns an expression for the {@link ComponentRequirement} to be used only within {@code
+   * initialize()} methods, where the component builder is available.
+   *
+   * <p>When accessing this field from a subcomponent, this may cause a field to be initialized in
+   * the component that owns this {@link ComponentRequirement}.
+   */
+  abstract CodeBlock getExpressionDuringInitialization(ClassName requestingClass);
+
+  /**
+   * A {@link ComponentRequirementField} for {@link ComponentRequirement}s that have a corresponding
+   * field on the component builder.
+   */
+  private static final class BuilderField extends ComponentRequirementField {
+    private final GeneratedComponentModel generatedComponentModel;
+    private final UniqueNameSet componentFieldNames;
+    private final ClassName owningComponent;
+    private final FieldSpec builderField;
+    private MemberSelect field;
+
+    private BuilderField(
+        ComponentRequirement componentRequirement,
+        GeneratedComponentModel generatedComponentModel,
+        UniqueNameSet componentFieldNames,
+        ClassName owningComponent,
+        FieldSpec builderField) {
+      super(componentRequirement);
+      this.generatedComponentModel = checkNotNull(generatedComponentModel);
+      this.componentFieldNames = checkNotNull(componentFieldNames);
+      this.owningComponent = checkNotNull(owningComponent);
+      this.builderField = checkNotNull(builderField);
+    }
+
+    @Override
+    CodeBlock getExpression(ClassName requestingClass) {
+      return getField().getExpressionFor(requestingClass);
+    }
+
+    @Override
+    CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
+      if (owningComponent.equals(requestingClass)) {
+        return CodeBlock.of("builder.$N", builderField);
+      } else {
+        // requesting this component requirement during initialization of a child component requires
+        // the it to be access from a field and not the builder (since it is no longer available)
+        return getExpression(requestingClass);
+      }
+    }
+
+    private MemberSelect getField() {
+      if (field == null) {
+        // TODO(dpb,ronshapiro): think about whether GeneratedComponentModel.addField should make a
+        // unique name for the field.
+        String fieldName = componentFieldNames.getUniqueName(componentRequirement().variableName());
+        FieldSpec componentField =
+            FieldSpec.builder(TypeName.get(componentRequirement().type()), fieldName, PRIVATE)
+                .build();
+        generatedComponentModel.addField(componentField);
+        generatedComponentModel.addInitialization(
+            CodeBlock.of("this.$N = builder.$N;", componentField, builderField));
+        field = MemberSelect.localField(owningComponent, fieldName);
+      }
+      return field;
+    }
+  }
+
+  /**
+   * A {@link ComponentRequirementField} for {@link ComponentRequirement}s that have a corresponding
+   * field already added on the component.
+   */
+  private static final class ComponentField extends ComponentRequirementField {
+    private final MemberSelect memberSelect;
+
+    private ComponentField(
+        ComponentRequirement componentRequirement,
+        FieldSpec componentField,
+        ClassName owningComponent) {
+      super(componentRequirement);
+      this.memberSelect = MemberSelect.localField(owningComponent, componentField.name);
+    }
+
+    @Override
+    CodeBlock getExpression(ClassName requestingClass) {
+      return memberSelect.getExpressionFor(requestingClass);
+    }
+
+    @Override
+    CodeBlock getExpressionDuringInitialization(ClassName requestingClass) {
+      return getExpression(requestingClass);
+    }
+  }
+
+  static final class Factory {
+    private final GeneratedComponentModel generatedComponentModel;
+    private final UniqueNameSet componentFieldNames;
+    private final ClassName owningComponent;
+    private final ImmutableMap<ComponentRequirement, FieldSpec> builderFields;
+
+    Factory(
+        GeneratedComponentModel generatedComponentModel,
+        UniqueNameSet componentFieldNames,
+        ClassName owningComponent,
+        ImmutableMap<ComponentRequirement, FieldSpec> builderFields) {
+      this.generatedComponentModel = checkNotNull(generatedComponentModel);
+      this.componentFieldNames = checkNotNull(componentFieldNames);
+      this.owningComponent = checkNotNull(owningComponent);
+      this.builderFields = checkNotNull(builderFields);
+    }
+
+    /**
+     * Returns a {@link ComponentRequirementField} for {@link ComponentRequirement}s that have a
+     * corresponding field on the component builder.
+     */
+    ComponentRequirementField forBuilderField(ComponentRequirement componentRequirement) {
+      return new BuilderField(
+          componentRequirement,
+          generatedComponentModel,
+          componentFieldNames,
+          owningComponent,
+          builderFields.get(componentRequirement));
+    }
+  }
+
+  /**
+   * Returns a {@link ComponentRequirementField} for {@link ComponentRequirement}s that have a
+   * corresponding field already added on the component.
+   */
+  static ComponentRequirementField componentField(
+      ComponentRequirement componentRequirement,
+      FieldSpec componentField,
+      ClassName owningComponent) {
+    return new ComponentField(componentRequirement, componentField, owningComponent);
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentRequirementFields.java b/java/dagger/internal/codegen/ComponentRequirementFields.java
new file mode 100644
index 0000000..afa3382
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementFields.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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 com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A central repository of fields used to access any {@link ComponentRequirement} available to a
+ * component.
+ */
+final class ComponentRequirementFields {
+
+  // TODO(dpb,ronshapiro): refactor this and ComponentBindingExpressions into a
+  // HierarchicalComponentMap<K, V>, or perhaps this use a flattened ImmutableMap, built from its
+  // parents? If so, maybe make ComponentRequirementField.Factory create it.
+
+  /**
+   * A list of component requirement field maps. The first element contains the fields on this
+   * component; the second contains the fields owned by its parent; and so on.
+   */
+  private final ImmutableList<Map<ComponentRequirement, ComponentRequirementField>>
+      componentRequirementFieldsMaps;
+
+  private ComponentRequirementFields(
+      ImmutableList<Map<ComponentRequirement, ComponentRequirementField>>
+          componentRequirementFieldsMaps) {
+    this.componentRequirementFieldsMaps = componentRequirementFieldsMaps;
+  }
+
+  ComponentRequirementFields() {
+    this(ImmutableList.of(newComponentRequirementsMap()));
+  }
+
+  /**
+   * Returns an expression for the {@code componentRequirement} to be used when implementing a
+   * component method. This may add a field to the component in order to reference the component
+   * requirement outside of the {@code initialize()} methods.
+   */
+  CodeBlock getExpression(ComponentRequirement componentRequirement, ClassName requestingClass) {
+    return getField(componentRequirement).getExpression(requestingClass);
+  }
+
+  /**
+   * Returns an expression for the {@code componentRequirement} to be used only within {@code
+   * initialize()} methods, where the component builder is available.
+   *
+   * <p>When accessing this field from a subcomponent, this may cause a field to be initialized in
+   * the component that owns this {@link ComponentRequirement}.
+   */
+  CodeBlock getExpressionDuringInitialization(
+      ComponentRequirement componentRequirement, ClassName requestingClass) {
+    return getField(componentRequirement).getExpressionDuringInitialization(requestingClass);
+  }
+
+  private ComponentRequirementField getField(ComponentRequirement componentRequirement) {
+    for (Map<ComponentRequirement, ComponentRequirementField> componentRequirementFieldsMap :
+        componentRequirementFieldsMaps) {
+      ComponentRequirementField field = componentRequirementFieldsMap.get(componentRequirement);
+      if (field != null) {
+        return field;
+      }
+    }
+    throw new IllegalStateException(
+        "no component requirement field found for " + componentRequirement);
+  }
+
+  /**
+   * Adds a component requirement field for a single component requirement owned by this component.
+   */
+  void add(ComponentRequirementField field) {
+    componentRequirementFieldsMaps.get(0).put(field.componentRequirement(), field);
+  }
+
+  /**
+   * Returns {@code true} if the component that owns this {@link ComponentRequirementFields} has a
+   * registered {@link ComponentRequirementField} for {@code componentRequirement}.
+   */
+  boolean contains(ComponentRequirement componentRequirement) {
+    return componentRequirementFieldsMaps
+        .stream()
+        .anyMatch(map -> map.containsKey(componentRequirement));
+  }
+
+  private static Map<ComponentRequirement, ComponentRequirementField>
+      newComponentRequirementsMap() {
+    return new HashMap<>();
+  }
+
+  /**
+   * Returns a new object representing the fields available from a child component of this one.
+   */
+  ComponentRequirementFields forChildComponent() {
+    return new ComponentRequirementFields(
+        FluentIterable.of(newComponentRequirementsMap())
+            .append(componentRequirementFieldsMaps)
+            .toList());
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentWriter.java b/java/dagger/internal/codegen/ComponentWriter.java
index 53b10c7..8bb273a 100644
--- a/java/dagger/internal/codegen/ComponentWriter.java
+++ b/java/dagger/internal/codegen/ComponentWriter.java
@@ -65,7 +65,8 @@
         graph,
         new UniqueSubcomponentNamesGenerator(graph).generate(),
         new OptionalFactories(),
-        new ComponentBindingExpressions());
+        new ComponentBindingExpressions(),
+        new ComponentRequirementFields());
   }
 
   /**
diff --git a/java/dagger/internal/codegen/ContributionBinding.java b/java/dagger/internal/codegen/ContributionBinding.java
index 81eb8d9..8891e67 100644
--- a/java/dagger/internal/codegen/ContributionBinding.java
+++ b/java/dagger/internal/codegen/ContributionBinding.java
@@ -129,6 +129,9 @@
     /** A provision method on a component's {@linkplain Component#dependencies() dependency}. */
     COMPONENT_PROVISION,
 
+    /** An instance of a {@linkplain Component#dependencies() dependency}. */
+    COMPONENT_DEPENDENCY,
+
     /**
      * A subcomponent builder method on a component or subcomponent.
      */
diff --git a/java/dagger/internal/codegen/InjectionMethods.java b/java/dagger/internal/codegen/InjectionMethods.java
index d2ebf4e..6eff4dd 100644
--- a/java/dagger/internal/codegen/InjectionMethods.java
+++ b/java/dagger/internal/codegen/InjectionMethods.java
@@ -25,11 +25,11 @@
 import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
 import static dagger.internal.codegen.CodeBlocks.toConcatenatedCodeBlock;
-import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
 import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
 import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
 import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
 import static dagger.internal.codegen.TypeNames.rawTypeName;
+import static dagger.internal.codegen.Util.toImmutableList;
 import static java.util.stream.Collectors.toList;
 import static javax.lang.model.element.Modifier.PUBLIC;
 import static javax.lang.model.element.Modifier.STATIC;
@@ -136,13 +136,16 @@
     static CodeBlock invoke(
         ProvisionBinding binding,
         Function<DependencyRequest, CodeBlock> dependencyUsage,
-        ClassName requestingClass) {
+        ClassName requestingClass,
+        Optional<CodeBlock> moduleReference) {
+      ImmutableList.Builder<CodeBlock> arguments = ImmutableList.builder();
+      moduleReference.ifPresent(arguments::add);
+      arguments.addAll(
+          injectionMethodArguments(
+              binding.provisionDependencies(), dependencyUsage, requestingClass));
       return callInjectionMethod(
           create(binding).get().name,
-          // TODO(dpb): would this be simpler if injectionMethodArguments returned a List?
-          ImmutableList.of(
-              injectionMethodArguments(
-                  binding.provisionDependencies(), dependencyUsage, requestingClass)),
+          arguments.build(),
           generatedClassNameForBinding(binding),
           requestingClass);
     }
@@ -336,13 +339,13 @@
    * @param dependencyUsage function to apply on each of {@code dependencies} before casting
    * @param requestingClass the class calling the injection method
    */
-  private static CodeBlock injectionMethodArguments(
+  private static ImmutableList<CodeBlock> injectionMethodArguments(
       ImmutableSet<DependencyRequest> dependencies,
       Function<DependencyRequest, CodeBlock> dependencyUsage,
       ClassName requestingClass) {
     return dependencies.stream()
         .map(dep -> injectionMethodArgument(dep, dependencyUsage.apply(dep), requestingClass))
-        .collect(toParametersCodeBlock());
+        .collect(toImmutableList());
   }
 
   private static CodeBlock injectionMethodArgument(
diff --git a/java/dagger/internal/codegen/Key.java b/java/dagger/internal/codegen/Key.java
index 50d12bc..3c4cecc 100644
--- a/java/dagger/internal/codegen/Key.java
+++ b/java/dagger/internal/codegen/Key.java
@@ -503,7 +503,8 @@
       return builder(type).build();
     }
 
-    Key forComponent(TypeMirror type) {
+    // TODO(ronshapiro): Remove these conveniences which are simple wrappers around Key.Builder
+    Key forType(TypeMirror type) {
       return builder(type).build();
     }
 
diff --git a/java/dagger/internal/codegen/ProvisionBinding.java b/java/dagger/internal/codegen/ProvisionBinding.java
index 5eeca8d..12f43da 100644
--- a/java/dagger/internal/codegen/ProvisionBinding.java
+++ b/java/dagger/internal/codegen/ProvisionBinding.java
@@ -272,11 +272,21 @@
       return ProvisionBinding.builder()
           .contributionType(ContributionType.UNIQUE)
           .bindingElement(componentDefinitionType)
-          .key(keyFactory.forComponent(componentDefinitionType.asType()))
+          .key(keyFactory.forType(componentDefinitionType.asType()))
           .bindingKind(Kind.COMPONENT)
           .build();
     }
 
+    ProvisionBinding forComponentDependency(TypeElement dependencyType) {
+      checkNotNull(dependencyType);
+      return ProvisionBinding.builder()
+          .contributionType(ContributionType.UNIQUE)
+          .bindingElement(dependencyType)
+          .key(keyFactory.forType(dependencyType.asType()))
+          .bindingKind(Kind.COMPONENT_DEPENDENCY)
+          .build();
+    }
+
     ProvisionBinding forComponentMethod(ExecutableElement componentMethod) {
       checkNotNull(componentMethod);
       checkArgument(componentMethod.getKind().equals(METHOD));
diff --git a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
index ec9d208..de83e7b 100644
--- a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
@@ -18,20 +18,19 @@
 
 import static com.google.auto.common.MoreElements.asExecutable;
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.CodeBlocks.toParametersCodeBlock;
 import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION;
 import static dagger.internal.codegen.FactoryGenerator.checkNotNullProvidesMethod;
 import static dagger.internal.codegen.InjectionMethods.ProvisionMethod.requiresInjectionMethod;
 import static dagger.internal.codegen.TypeNames.rawTypeName;
-import static javax.lang.model.element.Modifier.STATIC;
 
 import com.google.auto.common.MoreTypes;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.TypeName;
 import dagger.internal.codegen.InjectionMethods.ProvisionMethod;
+import java.util.Optional;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.type.DeclaredType;
 
@@ -44,24 +43,29 @@
   private final ProvisionBinding provisionBinding;
   private final ComponentBindingExpressions componentBindingExpressions;
   private final GeneratedComponentModel generatedComponentModel;
+  private final Optional<ComponentRequirement> moduleRequirement;
+  private final ComponentRequirementFields componentRequirementFields;
 
   SimpleMethodBindingExpression(
       CompilerOptions compilerOptions,
       ProvisionBinding provisionBinding,
       BindingExpression delegate,
       ComponentBindingExpressions componentBindingExpressions,
-      GeneratedComponentModel generatedComponentModel) {
+      GeneratedComponentModel generatedComponentModel,
+      Optional<ComponentRequirement> moduleRequirement,
+      ComponentRequirementFields componentRequirementFields) {
     super(delegate);
     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.componentBindingExpressions = componentBindingExpressions;
     this.generatedComponentModel = generatedComponentModel;
+    this.moduleRequirement = moduleRequirement;
+    this.componentRequirementFields = componentRequirementFields;
   }
 
   @Override
@@ -85,13 +89,11 @@
       case CONSTRUCTOR:
         return CodeBlock.of("new $T($L)", constructorTypeName(requestingClass), arguments);
       case METHOD:
-        checkState(method.getModifiers().contains(STATIC));
+        CodeBlock module =
+            moduleReference(requestingClass)
+                .orElse(CodeBlock.of("$T", provisionBinding.bindingTypeElement().get()));
         return maybeCheckForNulls(
-            CodeBlock.of(
-                "$T.$L($L)",
-                provisionBinding.bindingTypeElement().get(),
-                method.getSimpleName(),
-                arguments));
+            CodeBlock.of("$L.$L($L)", module, method.getSimpleName(), arguments));
       default:
         throw new IllegalStateException();
     }
@@ -114,7 +116,8 @@
             ProvisionMethod.invoke(
                 provisionBinding,
                 request -> dependencyArgument(request, requestingClass),
-                requestingClass)));
+                requestingClass,
+                moduleReference(requestingClass))));
   }
 
   private CodeBlock dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
@@ -145,4 +148,9 @@
         generatedComponentModel.getMembersInjectionMethod(provisionBinding.key()),
         instance);
   }
+
+  private Optional<CodeBlock> moduleReference(ClassName requestingClass) {
+    return moduleRequirement.map(
+        requirement -> componentRequirementFields.getExpression(requirement, requestingClass));
+  }
 }
diff --git a/java/dagger/internal/codegen/SubcomponentWriter.java b/java/dagger/internal/codegen/SubcomponentWriter.java
index 48e674f..739e3c4 100644
--- a/java/dagger/internal/codegen/SubcomponentWriter.java
+++ b/java/dagger/internal/codegen/SubcomponentWriter.java
@@ -18,10 +18,8 @@
 
 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
 import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.Sets.difference;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.MemberSelect.localField;
 import static dagger.internal.codegen.TypeSpecs.addSupertype;
 import static javax.lang.model.element.Modifier.FINAL;
 import static javax.lang.model.element.Modifier.PRIVATE;
@@ -29,7 +27,9 @@
 
 import com.google.auto.common.MoreTypes;
 import com.google.common.base.CaseFormat;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
@@ -74,16 +74,6 @@
   }
 
   @Override
-  protected Optional<CodeBlock> getOrCreateComponentRequirementFieldExpression(
-      ComponentRequirement componentRequirement) {
-    Optional<CodeBlock> expression =
-        super.getOrCreateComponentRequirementFieldExpression(componentRequirement);
-    return expression.isPresent()
-        ? expression
-        : parent.getOrCreateComponentRequirementFieldExpression(componentRequirement);
-  }
-
-  @Override
   protected CodeBlock getReferenceReleasingProviderManagerExpression(Scope scope) {
     return parent.getReferenceReleasingProviderManagerExpression(scope);
   }
@@ -147,7 +137,7 @@
           ComponentRequirement.forModule(moduleTypeElement.asType());
       TypeName moduleType = TypeName.get(paramTypes.get(i));
       componentMethod.addParameter(moduleType, moduleVariable.getSimpleName().toString());
-      if (!componentContributionFields.containsKey(componentRequirement)) {
+      if (!componentRequirementFields.contains(componentRequirement)) {
         String preferredModuleName =
             CaseFormat.UPPER_CAMEL.to(LOWER_CAMEL, moduleTypeElement.getSimpleName().toString());
         FieldSpec contributionField =
@@ -156,23 +146,23 @@
                 .build();
         component.addField(contributionField);
 
-        String actualModuleName = contributionField.name;
         constructor
-            .addParameter(moduleType, actualModuleName)
+            .addParameter(moduleType, contributionField.name)
             .addStatement(
-                "this.$1L = $2T.checkNotNull($1L)",
-                actualModuleName,
-                Preconditions.class);
+                "this.$1N = $2T.checkNotNull($1N)", contributionField, Preconditions.class);
 
-        MemberSelect moduleSelect = localField(name, actualModuleName);
-        componentContributionFields.put(componentRequirement, moduleSelect);
+        componentRequirementFields.add(
+            ComponentRequirementField.componentField(
+                componentRequirement, contributionField, name));
         subcomponentConstructorParameters.add(
             CodeBlock.of("$L", moduleVariable.getSimpleName()));
       }
     }
 
     Set<ComponentRequirement> uninitializedModules =
-        difference(graph.componentRequirements(), componentContributionFields.keySet());
+        Sets.filter(
+            graph.componentRequirements(),
+            Predicates.not(componentRequirementFields::contains));
 
     for (ComponentRequirement componentRequirement : uninitializedModules) {
       checkState(componentRequirement.kind().equals(ComponentRequirement.Kind.MODULE));
@@ -184,11 +174,10 @@
               .addModifiers(PRIVATE, FINAL)
               .build();
       component.addField(contributionField);
-      String actualModuleName = contributionField.name;
-      constructor.addStatement(
-          "this.$L = new $T()", actualModuleName, ClassName.get(moduleType));
-      MemberSelect moduleSelect = localField(name, actualModuleName);
-      componentContributionFields.put(componentRequirement, moduleSelect);
+      constructor.addStatement("this.$N = new $T()", contributionField, ClassName.get(moduleType));
+      componentRequirementFields.add(
+          ComponentRequirementField.componentField(
+              componentRequirement, contributionField, name));
     }
 
     componentMethod.addStatement("return new $T($L)",