Extract FrameworkInstanceCreationExpression from FrameworkFieldSupplier, and split ProviderOrProducerFieldInitializer up into implementations of that by binding kind.

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=180805825
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index efeb75c..f10ee5e 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -199,34 +199,45 @@
         "ComponentRequirementBindingExpression.java",
         "ComponentRequirementField.java",
         "ComponentRequirementFields.java",
+        "ComponentRequirementProviderCreationExpression.java",
         "ComponentWriter.java",
         "DelegateBindingExpression.java",
+        "DelegatingFrameworkInstanceCreationExpression.java",
+        "DependencyMethodProducerCreationExpression.java",
+        "DependencyMethodProviderCreationExpression.java",
         "FactoryGenerator.java",
         "FrameworkFieldInitializer.java",
-        "FrameworkFieldSupplier.java",
         "FrameworkInstanceBindingExpression.java",
+        "FrameworkInstanceSupplier.java",
         "GeneratedComponentModel.java",
         "GwtCompatibility.java",
         "InjectionMethods.java",
+        "InjectionOrProvisionProviderCreationExpression.java",
         "MapBindingExpression.java",
+        "MapFactoryCreationExpression.java",
         "MemberSelect.java",
         "MembersInjectionBindingExpression.java",
         "MembersInjectionMethods.java",
         "MembersInjectorGenerator.java",
+        "MembersInjectorProviderCreationExpression.java",
         "MonitoringModuleGenerator.java",
         "MonitoringModuleProcessingStep.java",
         "OptionalBindingExpression.java",
         "OptionalFactories.java",
         "PrivateMethodBindingExpression.java",
+        "ProducerCreationExpression.java",
         "ProducerFactoryGenerator.java",
-        "ProducerFromProviderFieldInitializer.java",
+        "ProducerFromProviderCreationExpression.java",
         "ProductionExecutorModuleGenerator.java",
-        "ProviderOrProducerFieldInitializer.java",
         "ReferenceReleasingManagerFields.java",
+        "ReleasableReferenceManagerProviderCreationExpression.java",
+        "ReleasableReferenceManagerSetProviderCreationExpression.java",
         "SetBindingExpression.java",
+        "SetFactoryCreationExpression.java",
         "SimpleInvocationBindingExpression.java",
         "SimpleMethodBindingExpression.java",
         "SubcomponentBuilderBindingExpression.java",
+        "SubcomponentBuilderProviderCreationExpression.java",
         "SubcomponentNames.java",
         "SubcomponentWriter.java",
         "UnwrappedMapKeyGenerator.java",
diff --git a/java/dagger/internal/codegen/CodeBlocks.java b/java/dagger/internal/codegen/CodeBlocks.java
index ea3058e..ab4d90f 100644
--- a/java/dagger/internal/codegen/CodeBlocks.java
+++ b/java/dagger/internal/codegen/CodeBlocks.java
@@ -106,6 +106,11 @@
             .build());
   }
 
+  /** Returns {@code expression} cast to a type. */
+  static CodeBlock cast(CodeBlock expression, Class<?> castTo) {
+    return CodeBlock.of("($T) $L", castTo, expression);
+  }
+
   private static final class CodeBlockJoiner {
     private final String delimiter;
     private final CodeBlock.Builder builder;
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 861e2e4..7aa8541 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -18,23 +18,37 @@
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
 import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.BindingType.MEMBERS_INJECTION;
+import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
 import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION;
 import static dagger.internal.codegen.ContributionBinding.Kind.PROVISION;
 import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_MULTIBOUND_MAP;
 import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_MULTIBOUND_SET;
+import static dagger.internal.codegen.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.MemberSelect.staticMemberSelect;
+import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
+import static dagger.internal.codegen.TypeNames.DOUBLE_CHECK;
+import static dagger.internal.codegen.TypeNames.REFERENCE_RELEASING_PROVIDER;
+import static dagger.internal.codegen.TypeNames.SINGLE_CHECK;
 
+import com.google.auto.common.MoreTypes;
 import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Table;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
+import dagger.internal.InstanceFactory;
+import dagger.internal.MembersInjectors;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
 import dagger.model.DependencyRequest;
 import dagger.model.Key;
 import dagger.model.RequestKind;
+import dagger.model.Scope;
 import java.util.EnumSet;
 import java.util.Optional;
 import javax.lang.model.type.TypeMirror;
@@ -162,6 +176,18 @@
   }
 
   /**
+   * Returns the expressions for each of the given {@linkplain FrameworkDependency framework
+   * dependencies}.
+   */
+  ImmutableList<CodeBlock> getDependencyExpressions(
+      ImmutableList<FrameworkDependency> frameworkDependencies, ClassName requestingClass) {
+    return frameworkDependencies
+        .stream()
+        .map(dependency -> getDependencyExpression(dependency, requestingClass).codeBlock())
+        .collect(toImmutableList());
+  }
+
+  /**
    * 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.
    *
@@ -286,13 +312,18 @@
     }
 
     /**
-     * Returns a binding expression that uses a {@link javax.inject.Provider} for provision
-     * bindings, a {@link dagger.producers.Producer} for production bindings, or a {@link
-     * dagger.MembersInjector} for members injection bindings.
+     * Returns a binding expression that uses a {@link javax.inject.Provider} for provision bindings
+     * or a {@link dagger.producers.Producer} for production bindings.
      */
     private FrameworkInstanceBindingExpression frameworkInstanceBindingExpression(
         ResolvedBindings resolvedBindings, RequestKind requestKind) {
       Optional<MemberSelect> staticMethod = staticMemberSelect(resolvedBindings);
+      FrameworkInstanceCreationExpression frameworkInstanceCreationExpression =
+          resolvedBindings.scope().isPresent()
+              ? scope(
+                  resolvedBindings.scope().get(),
+                  frameworkInstanceCreationExpression(resolvedBindings))
+              : frameworkInstanceCreationExpression(resolvedBindings);
       return new FrameworkInstanceBindingExpression(
           resolvedBindings,
           requestKind,
@@ -300,32 +331,136 @@
           resolvedBindings.bindingType().frameworkType(),
           staticMethod.isPresent()
               ? staticMethod::get
-              : frameworkFieldInitializer(resolvedBindings),
+              : new FrameworkFieldInitializer(
+                  generatedComponentModel, resolvedBindings, frameworkInstanceCreationExpression),
           types,
           elements);
     }
 
+    private FrameworkInstanceCreationExpression scope(
+        Scope scope, FrameworkInstanceCreationExpression unscoped) {
+      if (referenceReleasingManagerFields.requiresReleasableReferences(scope)) {
+        return () ->
+            CodeBlock.of(
+                "$T.create($L, $L)",
+                REFERENCE_RELEASING_PROVIDER,
+                unscoped.creationExpression(),
+                referenceReleasingManagerFields.getExpression(
+                    scope, generatedComponentModel.name()));
+      } else {
+        return () ->
+            CodeBlock.of(
+                "$T.provider($L)",
+                scope.isReusable() ? SINGLE_CHECK : DOUBLE_CHECK,
+                unscoped.creationExpression());
+      }
+    }
+
     /**
-     * Returns an initializer for a {@link javax.inject.Provider} field for provision bindings, a
-     * {@link dagger.producers.Producer} field for production bindings, or a {@link
-     * dagger.MembersInjector} field for members injection bindings.
+     * Returns a creation expression for a {@link javax.inject.Provider} for provision bindings or a
+     * {@link dagger.producers.Producer} for production bindings.
      */
-    private FrameworkFieldInitializer frameworkFieldInitializer(ResolvedBindings resolvedBindings) {
-      switch (resolvedBindings.bindingType()) {
-        case PRODUCTION:
+    private FrameworkInstanceCreationExpression frameworkInstanceCreationExpression(
+        ResolvedBindings resolvedBindings) {
+      checkArgument(!resolvedBindings.bindingType().equals(MEMBERS_INJECTION));
+      ContributionBinding binding = resolvedBindings.contributionBinding();
+      switch (binding.bindingKind()) {
+        case COMPONENT:
+          // The type parameter can be removed when we drop java 7 source support
+          return () ->
+              CodeBlock.of("$T.<$T>create(this)", InstanceFactory.class, binding.key().type());
+
+        case BOUND_INSTANCE:
+        case COMPONENT_DEPENDENCY:
+          return new ComponentRequirementProviderCreationExpression(
+              binding, generatedComponentModel, componentRequirementFields);
+
+        case COMPONENT_PROVISION:
+          return new DependencyMethodProviderCreationExpression(
+              binding, generatedComponentModel, componentRequirementFields, compilerOptions, graph);
+
+        case SUBCOMPONENT_BUILDER:
+          return new SubcomponentBuilderProviderCreationExpression(
+              binding.key().type(), subcomponentNames.get(binding.key()));
+
+        case INJECTION:
         case PROVISION:
-          return new ProviderOrProducerFieldInitializer(
-              resolvedBindings,
-              subcomponentNames,
+          return new InjectionOrProvisionProviderCreationExpression(
+              binding,
               generatedComponentModel,
               componentBindingExpressions,
-              componentRequirementFields,
-              referenceReleasingManagerFields,
-              compilerOptions,
-              graph,
-              optionalFactories);
+              componentRequirementFields);
+
+        case COMPONENT_PRODUCTION:
+          return new DependencyMethodProducerCreationExpression(
+              binding, generatedComponentModel, componentRequirementFields, graph);
+
+        case PRODUCTION:
+          return new ProducerCreationExpression(
+              binding,
+              generatedComponentModel,
+              componentBindingExpressions,
+              componentRequirementFields);
+
+        case SYNTHETIC_MULTIBOUND_SET:
+          return new SetFactoryCreationExpression(
+              binding, generatedComponentModel, componentBindingExpressions, graph);
+
+        case SYNTHETIC_MULTIBOUND_MAP:
+          return new MapFactoryCreationExpression(
+              binding, generatedComponentModel, componentBindingExpressions, graph);
+
+        case SYNTHETIC_RELEASABLE_REFERENCE_MANAGER:
+          return new ReleasableReferenceManagerProviderCreationExpression(
+              binding, generatedComponentModel, referenceReleasingManagerFields);
+
+        case SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS:
+          return new ReleasableReferenceManagerSetProviderCreationExpression(
+              binding, generatedComponentModel, referenceReleasingManagerFields, graph);
+
+        case SYNTHETIC_DELEGATE_BINDING:
+          return new DelegatingFrameworkInstanceCreationExpression(
+              binding, generatedComponentModel, componentBindingExpressions);
+
+        case SYNTHETIC_OPTIONAL_BINDING:
+          if (binding.explicitDependencies().isEmpty()) {
+            return () -> optionalFactories.absentOptionalProvider(binding);
+          } else {
+            return () ->
+                optionalFactories.presentOptionalFactory(
+                    binding,
+                    componentBindingExpressions
+                        .getDependencyExpression(
+                            getOnlyElement(binding.frameworkDependencies()),
+                            generatedComponentModel.name())
+                        .codeBlock());
+          }
+
+        case MEMBERS_INJECTOR:
+          TypeMirror membersInjectedType =
+              getOnlyElement(MoreTypes.asDeclared(binding.key().type()).getTypeArguments());
+
+          if (((ProvisionBinding) binding).injectionSites().isEmpty()) {
+            return () ->
+                // The type parameter can be removed when we drop Java 7 source support.
+                CodeBlock.of(
+                    "$T.create($T.<$T>noOp())",
+                    InstanceFactory.class,
+                    MembersInjectors.class,
+                    membersInjectedType);
+          } else {
+            return () ->
+                CodeBlock.of(
+                    "$T.create($T.create($L))",
+                    InstanceFactory.class,
+                    membersInjectorNameForType(MoreTypes.asTypeElement(membersInjectedType)),
+                    makeParametersCodeBlock(
+                        componentBindingExpressions.getDependencyExpressions(
+                            binding.frameworkDependencies(), generatedComponentModel.name())));
+          }
+
         default:
-          throw new AssertionError(resolvedBindings);
+          throw new AssertionError(binding);
       }
     }
 
@@ -366,8 +501,13 @@
           requestKind,
           componentBindingExpressions,
           FrameworkType.PRODUCER,
-          new ProducerFromProviderFieldInitializer(
-              resolvedBindings, generatedComponentModel, componentBindingExpressions),
+          new FrameworkFieldInitializer(
+              generatedComponentModel,
+              resolvedBindings,
+              new ProducerFromProviderCreationExpression(
+                  resolvedBindings.contributionBinding(),
+                  generatedComponentModel,
+                  componentBindingExpressions)),
           types,
           elements);
     }
diff --git a/java/dagger/internal/codegen/ComponentRequirementProviderCreationExpression.java b/java/dagger/internal/codegen/ComponentRequirementProviderCreationExpression.java
new file mode 100644
index 0000000..bc2bf17
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentRequirementProviderCreationExpression.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 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 com.squareup.javapoet.CodeBlock;
+import dagger.internal.InstanceFactory;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/**
+ * A {@link javax.inject.Provider} creation expression for a {@linkplain
+ * dagger.Component#dependencies() component dependency} or an instance passed to a {@link
+ * dagger.BindsInstance @BindsInstance} builder method.
+ */
+final class ComponentRequirementProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentRequirementFields componentRequirementFields;
+
+  ComponentRequirementProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentRequirementFields componentRequirementFields) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentRequirementFields = checkNotNull(componentRequirementFields);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return CodeBlock.of(
+        "$T.$L($L)",
+        InstanceFactory.class,
+        binding.nullableType().isPresent() ? "createNullable" : "create",
+        componentRequirementFields.getExpressionDuringInitialization(
+            componentRequirement(), generatedComponentModel.name()));
+  }
+
+  private ComponentRequirement componentRequirement() {
+    switch (binding.bindingKind()) {
+      case COMPONENT_DEPENDENCY:
+        return ComponentRequirement.forDependency(binding.key().type());
+
+      case BOUND_INSTANCE:
+        return ComponentRequirement.forBoundInstance(binding);
+
+      default:
+        throw new IllegalArgumentException(
+            "binding must be for a bound instance or a dependency: " + binding);
+    }
+  }
+}
diff --git a/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
new file mode 100644
index 0000000..09fd1f9
--- /dev/null
+++ b/java/dagger/internal/codegen/DelegatingFrameworkInstanceCreationExpression.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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 com.google.common.collect.Iterables.getOnlyElement;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/** A framework instance creation expression for a {@link dagger.Binds @Binds} binding. */
+final class DelegatingFrameworkInstanceCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+
+  DelegatingFrameworkInstanceCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    FrameworkDependency frameworkDependency = getOnlyElement(binding.frameworkDependencies());
+    return CodeBlocks.cast(
+        componentBindingExpressions
+            .getDependencyExpression(frameworkDependency, generatedComponentModel.name())
+            .codeBlock(),
+        binding.bindingType().frameworkClass());
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
new file mode 100644
index 0000000..6efe4c7
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyMethodProducerCreationExpression.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 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 com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
+import static dagger.internal.codegen.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.TypeNames.producerOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+
+/**
+ * A {@link dagger.producers.Producer} creation expression for a production method on a production
+ * component's {@linkplain dagger.producers.ProductionComponent#dependencies()} dependency} that
+ * returns a {@link com.google.common.util.concurrent.ListenableFuture}.
+ */
+// TODO(dpb): Resolve with DependencyMethodProviderCreationExpression.
+final class DependencyMethodProducerCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentRequirementFields componentRequirementFields;
+  private final BindingGraph graph;
+
+  DependencyMethodProducerCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentRequirementFields componentRequirementFields,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentRequirementFields = checkNotNull(componentRequirementFields);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    ComponentRequirement dependency =
+        graph
+            .componentDescriptor()
+            .dependenciesByDependencyMethod()
+            .get(binding.bindingElement().get());
+    FieldSpec dependencyField =
+        FieldSpec.builder(
+                ClassName.get(dependency.typeElement()), dependency.variableName(), PRIVATE, FINAL)
+            .initializer(
+                componentRequirementFields.getExpressionDuringInitialization(
+                    dependency, generatedComponentModel.name()))
+            .build();
+    // TODO(b/70395982): Explore using a private static type instead of an anonymous class.
+    TypeName keyType = TypeName.get(binding.key().type());
+    return CodeBlock.of(
+        "$L",
+        anonymousClassBuilder("")
+            .superclass(producerOf(keyType))
+            .addField(dependencyField)
+            .addMethod(
+                methodBuilder("get")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(listenableFutureOf(keyType))
+                    .addStatement(
+                        "return $N.$L()",
+                        dependencyField,
+                        binding.bindingElement().get().getSimpleName())
+                    .build())
+            .build());
+  }
+}
diff --git a/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
new file mode 100644
index 0000000..e76400a
--- /dev/null
+++ b/java/dagger/internal/codegen/DependencyMethodProviderCreationExpression.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 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 com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.GeneratedComponentModel.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
+import static dagger.internal.codegen.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+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.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import java.util.Optional;
+import javax.lang.model.element.Element;
+
+/**
+ * A {@link javax.inject.Provider} creation expression for a provision method on a component's
+ * {@linkplain dagger.Component#dependencies()} dependency}.
+ */
+// TODO(dpb): Resolve with DependencyMethodProducerCreationExpression.
+final class DependencyMethodProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentRequirementFields componentRequirementFields;
+  private final CompilerOptions compilerOptions;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+
+  DependencyMethodProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentRequirementFields componentRequirementFields,
+      CompilerOptions compilerOptions,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentRequirementFields = checkNotNull(componentRequirementFields);
+    this.compilerOptions = checkNotNull(compilerOptions);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    // TODO(sameb): The Provider.get() throws a very vague NPE.  The stack trace doesn't
+    // help to figure out what the method or return type is.  If we include a string
+    // of the return type or method name in the error message, that can defeat obfuscation.
+    // We can easily include the raw type (no generics) + annotation type (no values),
+    // using .class & String.format -- but that wouldn't be the whole story.
+    // What should we do?
+    CodeBlock invocation =
+        ComponentProvisionBindingExpression.maybeCheckForNull(
+            (ProvisionBinding) binding,
+            compilerOptions,
+            CodeBlock.of(
+                "$N.$N()", dependency().variableName(), provisionMethod().getSimpleName()));
+    ClassName dependencyClassName = ClassName.get(dependency().typeElement());
+    TypeName keyType = TypeName.get(binding.key().type());
+    MethodSpec.Builder getMethod =
+        methodBuilder("get")
+            .addAnnotation(Override.class)
+            .addModifiers(PUBLIC)
+            .returns(keyType)
+            .addStatement("return $L", invocation);
+    if (binding.nullableType().isPresent()) {
+      getMethod.addAnnotation(ClassName.get(MoreTypes.asTypeElement(binding.nullableType().get())));
+    }
+    generatedComponentModel.addType(
+        COMPONENT_PROVISION_FACTORY,
+        classBuilder(factoryClassName())
+            .addSuperinterface(providerOf(keyType))
+            .addModifiers(PRIVATE, STATIC)
+            .addField(dependencyClassName, dependency().variableName(), PRIVATE, FINAL)
+            .addMethod(
+                constructorBuilder()
+                    .addParameter(dependencyClassName, dependency().variableName())
+                    .addStatement("this.$1L = $1L", dependency().variableName())
+                    .build())
+            .addMethod(getMethod.build())
+            .build());
+    return CodeBlock.of(
+        "new $T($L)",
+        factoryClassName(),
+        componentRequirementFields.getExpressionDuringInitialization(
+            dependency(), generatedComponentModel.name()));
+  }
+
+  private ClassName factoryClassName() {
+    String factoryName =
+        ClassName.get(dependency().typeElement()).toString().replace('.', '_')
+            + "_"
+            + binding.bindingElement().get().getSimpleName();
+    return generatedComponentModel.name().nestedClass(factoryName);
+  }
+
+  private ComponentRequirement dependency() {
+    return graph.componentDescriptor().dependenciesByDependencyMethod().get(provisionMethod());
+  }
+
+  private Element provisionMethod() {
+    return binding.bindingElement().get();
+  }
+
+  @Override
+  public Optional<TypeName> specificType() {
+    return Optional.of(factoryClassName());
+  }
+}
diff --git a/java/dagger/internal/codegen/FrameworkFieldInitializer.java b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
index 1f5752d..ca444ea 100644
--- a/java/dagger/internal/codegen/FrameworkFieldInitializer.java
+++ b/java/dagger/internal/codegen/FrameworkFieldInitializer.java
@@ -17,13 +17,10 @@
 package dagger.internal.codegen;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
-import static dagger.internal.codegen.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.GeneratedComponentModel.FieldSpecKind.FRAMEWORK_FIELD;
 import static javax.lang.model.element.Modifier.PRIVATE;
 
-import com.google.common.collect.ImmutableList;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
@@ -35,28 +32,46 @@
  * An object that can initialize a framework-type component field for a binding. An instance should
  * be created for each field.
  */
-abstract class FrameworkFieldInitializer implements FrameworkFieldSupplier {
+class FrameworkFieldInitializer implements FrameworkInstanceSupplier {
 
-  protected final GeneratedComponentModel generatedComponentModel;
-  private final ComponentBindingExpressions componentBindingExpressions;
+  /**
+   * An object that can determine the expression to use to assign to the component field for a
+   * binding.
+   */
+  interface FrameworkInstanceCreationExpression {
+    /** Returns the expression to use to assign to the component field for the binding. */
+    CodeBlock creationExpression();
+
+    /**
+     * Returns the type of the creation expression when it is a specific factory type. This
+     * implementation returns {@link Optional#empty()}.
+     */
+    default Optional<TypeName> specificType() {
+      return Optional.empty();
+    }
+
+    /**
+     * Returns the framework class to use for the field, if different from the one implied by the
+     * binding. This implementation returns {@link Optional#empty()}.
+     */
+    default Optional<ClassName> alternativeFrameworkClass() {
+      return Optional.empty();
+    }
+  }
+
+  private final GeneratedComponentModel generatedComponentModel;
   private final ResolvedBindings resolvedBindings;
+  private final FrameworkInstanceCreationExpression frameworkInstanceCreationExpression;
   private FieldSpec fieldSpec;
   private InitializationState fieldInitializationState = InitializationState.UNINITIALIZED;
 
-  /**
-   * Indicates the type of the initializer when has been replaced with a more-specific factory type.
-   * This is used by {@code FrameworkInstanceBindingExpression} to create fields with the
-   * most-specific type available.  This allows javac to complete much faster for large components.
-   */
-  private Optional<TypeName> fieldTypeReplacement = Optional.empty();
-
-  protected FrameworkFieldInitializer(
+  FrameworkFieldInitializer(
       GeneratedComponentModel generatedComponentModel,
-      ComponentBindingExpressions componentBindingExpressions,
-      ResolvedBindings resolvedBindings) {
+      ResolvedBindings resolvedBindings,
+      FrameworkInstanceCreationExpression frameworkInstanceCreationExpression) {
     this.generatedComponentModel = checkNotNull(generatedComponentModel);
-    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
     this.resolvedBindings = checkNotNull(resolvedBindings);
+    this.frameworkInstanceCreationExpression = checkNotNull(frameworkInstanceCreationExpression);
   }
 
   /**
@@ -76,7 +91,7 @@
         // Change our state in case we are recursively invoked via initializeBindingExpression
         fieldInitializationState = InitializationState.INITIALIZING;
         CodeBlock.Builder codeBuilder = CodeBlock.builder();
-        CodeBlock fieldInitialization = getFieldInitialization();
+        CodeBlock fieldInitialization = frameworkInstanceCreationExpression.creationExpression();
         CodeBlock initCode = CodeBlock.of("this.$N = $L;", getOrCreateField(), fieldInitialization);
 
         if (fieldInitializationState == InitializationState.DELEGATED) {
@@ -97,9 +112,9 @@
 
       case INITIALIZING:
         // We were recursively invoked, so create a delegate factory instead
+        fieldInitializationState = InitializationState.DELEGATED;
         generatedComponentModel.addInitialization(
             CodeBlock.of("this.$N = new $T<>();", getOrCreateField(), DelegateFactory.class));
-        fieldInitializationState = InitializationState.DELEGATED;
         break;
 
       case DELEGATED:
@@ -119,17 +134,17 @@
     if (fieldSpec != null) {
       return fieldSpec;
     }
-    boolean useRawType =
-        !isTypeAccessibleFrom(
-            resolvedBindings.key().type(), generatedComponentModel.name().packageName());
+    boolean useRawType = !generatedComponentModel.isTypeAccessible(resolvedBindings.key().type());
     FrameworkField contributionBindingField =
-        FrameworkField.forResolvedBindings(resolvedBindings, alternativeFrameworkClass());
+        FrameworkField.forResolvedBindings(
+            resolvedBindings, frameworkInstanceCreationExpression.alternativeFrameworkClass());
 
     TypeName fieldType;
-    if (fieldTypeReplacement.isPresent()) {
+    if (!fieldInitializationState.equals(InitializationState.DELEGATED)
+        && specificType().isPresent()) {
       // For some larger components, this causes javac to compile much faster by getting the
       // field type to exactly match the type of the expression being assigned to it.
-      fieldType = fieldTypeReplacement.get();
+      fieldType = specificType().get();
     } else if (useRawType) {
       fieldType = contributionBindingField.type().rawType;
     } else {
@@ -141,7 +156,7 @@
             fieldType,
             generatedComponentModel.getUniqueFieldName(contributionBindingField.name()));
     contributionField.addModifiers(PRIVATE);
-    if (useRawType && !fieldTypeReplacement.isPresent()) {
+    if (useRawType && !specificType().isPresent()) {
       contributionField.addAnnotation(AnnotationSpecs.suppressWarnings(RAWTYPES));
     }
     fieldSpec = contributionField.build();
@@ -150,37 +165,10 @@
     return fieldSpec;
   }
 
+  /** Returns the type of the instance when it is a specific factory type. */
   @Override
-  public boolean fieldTypeReplaced() {
-    return fieldTypeReplacement.isPresent();
-  }
-
-  /**
-   * Returns the framework class to use for the field, if different from the one implied by the
-   * binding. This implementation returns {@link Optional#empty()}.
-   */
-  protected Optional<ClassName> alternativeFrameworkClass() {
-    return Optional.empty();
-  }
-
-  /** Returns the expression to use to initialize the field. */
-  protected abstract CodeBlock getFieldInitialization();
-
-  /** Returns a list of code blocks for referencing all of the given binding's dependencies. */
-  protected final ImmutableList<CodeBlock> getBindingDependencyExpressions(Binding binding) {
-    ImmutableList<FrameworkDependency> dependencies = binding.frameworkDependencies();
-    return dependencies.stream().map(this::getDependencyExpression).collect(toImmutableList());
-  }
-
-  /** Returns a code block referencing the given dependency. */
-  protected final CodeBlock getDependencyExpression(FrameworkDependency frameworkDependency) {
-    return componentBindingExpressions
-        .getDependencyExpression(frameworkDependency, generatedComponentModel.name())
-        .codeBlock();
-  }
-
-  protected final void setFieldTypeReplacement(TypeName typeName) {
-    this.fieldTypeReplacement = Optional.of(typeName);
+  public Optional<TypeName> specificType() {
+    return frameworkInstanceCreationExpression.specificType();
   }
 
   /** Initialization state for a factory field. */
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
index 20a5f47..b9ddb1d 100644
--- a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -30,7 +30,7 @@
 /** A binding expression that uses an instance of a {@link FrameworkType}. */
 final class FrameworkInstanceBindingExpression extends BindingExpression {
   private final ComponentBindingExpressions componentBindingExpressions;
-  private final FrameworkFieldSupplier frameworkFieldSupplier;
+  private final FrameworkInstanceSupplier frameworkInstanceSupplier;
   private final FrameworkType frameworkType;
   private final DaggerTypes types;
   private final Elements elements;
@@ -40,13 +40,13 @@
       RequestKind requestKind,
       ComponentBindingExpressions componentBindingExpressions,
       FrameworkType frameworkType,
-      FrameworkFieldSupplier frameworkFieldSupplier,
+      FrameworkInstanceSupplier frameworkInstanceSupplier,
       DaggerTypes types,
       Elements elements) {
     super(resolvedBindings, requestKind);
     this.componentBindingExpressions = componentBindingExpressions;
     this.frameworkType = frameworkType;
-    this.frameworkFieldSupplier = frameworkFieldSupplier;
+    this.frameworkInstanceSupplier = frameworkInstanceSupplier;
     this.types = types;
     this.elements = elements;
   }
@@ -60,11 +60,11 @@
   @Override
   Expression getDependencyExpression(ClassName requestingClass) {
     if (requestKind().equals(frameworkRequestKind())) {
-      MemberSelect memberSelect = frameworkFieldSupplier.memberSelect();
+      MemberSelect memberSelect = frameworkInstanceSupplier.memberSelect();
       TypeMirror expressionType =
-          isTypeAccessibleFrom(instanceType(), requestingClass.packageName())
+          frameworkInstanceSupplier.specificType().isPresent()
+                  || isTypeAccessibleFrom(instanceType(), requestingClass.packageName())
                   || isInlinedFactoryCreation(memberSelect)
-                  || frameworkFieldSupplier.fieldTypeReplaced()
               ? types.wrapType(instanceType(), resolvedBindings().frameworkClass())
               : rawFrameworkType();
       return Expression.create(expressionType, memberSelect.getExpressionFor(requestingClass));
diff --git a/java/dagger/internal/codegen/FrameworkFieldSupplier.java b/java/dagger/internal/codegen/FrameworkInstanceSupplier.java
similarity index 76%
rename from java/dagger/internal/codegen/FrameworkFieldSupplier.java
rename to java/dagger/internal/codegen/FrameworkInstanceSupplier.java
index 80dcf0f..d7392a6 100644
--- a/java/dagger/internal/codegen/FrameworkFieldSupplier.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceSupplier.java
@@ -16,16 +16,16 @@
 
 package dagger.internal.codegen;
 
-/** An object that supplies a {@link MemberSelect} for a framework field. */
-interface FrameworkFieldSupplier {
+import com.squareup.javapoet.TypeName;
+import java.util.Optional;
+
+/** An object that supplies a {@link MemberSelect} for a framework instance. */
+interface FrameworkInstanceSupplier {
   /** Returns a {@link MemberSelect}, with possible side effects on the first call. */
   MemberSelect memberSelect();
 
-  /**
-   * If true, signals that a publicly-visible concrete type was used to replace the original type
-   * of the field being initialized.
-   */
-  default boolean fieldTypeReplaced() {
-    return false;
+  /** The framework instance is of this specific subtype. */
+  default Optional<TypeName> specificType() {
+    return Optional.empty();
   }
 }
diff --git a/java/dagger/internal/codegen/GeneratedComponentModel.java b/java/dagger/internal/codegen/GeneratedComponentModel.java
index b0c27c0..32ad46e 100644
--- a/java/dagger/internal/codegen/GeneratedComponentModel.java
+++ b/java/dagger/internal/codegen/GeneratedComponentModel.java
@@ -17,6 +17,7 @@
 package dagger.internal.codegen;
 
 import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
 import static javax.lang.model.element.Modifier.FINAL;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
@@ -35,6 +36,7 @@
 import javax.lang.model.element.Modifier;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
 
 /** The model of the component being generated. */
 final class GeneratedComponentModel {
@@ -133,6 +135,11 @@
     return name;
   }
 
+  /** Returns {@code true} if {@code type} is accessible from the generated component. */
+  boolean isTypeAccessible(TypeMirror type) {
+    return isTypeAccessibleFrom(type, name.packageName());
+  }
+
   /** Adds the given super type to the component. */
   void addSupertype(TypeElement supertype) {
     TypeSpecs.addSupertype(component, supertype);
diff --git a/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
new file mode 100644
index 0000000..eb8cf7c
--- /dev/null
+++ b/java/dagger/internal/codegen/InjectionOrProvisionProviderCreationExpression.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 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 dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+
+import com.google.common.collect.Lists;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * A {@link javax.inject.Provider} creation expression for an {@link
+ * javax.inject.Inject @Inject}-constructed class or a {@link dagger.Provides @Provides}-annotated
+ * module method.
+ */
+// TODO(dpb): Resolve with ProducerCreationExpression.
+final class InjectionOrProvisionProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ComponentRequirementFields componentRequirementFields;
+
+  InjectionOrProvisionProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions,
+      ComponentRequirementFields componentRequirementFields) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.componentRequirementFields = checkNotNull(componentRequirementFields);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    List<CodeBlock> arguments =
+        Lists.newArrayListWithCapacity(binding.explicitDependencies().size() + 1);
+    if (binding.requiresModuleInstance()) {
+      arguments.add(
+          componentRequirementFields.getExpressionDuringInitialization(
+              ComponentRequirement.forModule(binding.contributingModule().get().asType()),
+              generatedComponentModel.name()));
+    }
+    arguments.addAll(
+        componentBindingExpressions.getDependencyExpressions(
+            binding.frameworkDependencies(), generatedComponentModel.name()));
+
+    CodeBlock createFactory =
+        CodeBlock.of(
+            "$T.create($L)",
+            generatedClassNameForBinding(binding),
+            makeParametersCodeBlock(arguments));
+
+    // When scoping a parameterized factory for an @Inject class, Java 7 cannot always infer the
+    // type properly, so cast to a raw framework type before scoping.
+    if (binding.bindingKind().equals(INJECTION)
+        && binding.unresolved().isPresent()
+        && binding.scope().isPresent()) {
+      return CodeBlocks.cast(createFactory, binding.bindingType().frameworkClass());
+    } else {
+      return createFactory;
+    }
+  }
+
+  @Override
+  public Optional<TypeName> specificType() {
+    return Optional.of(generatedClassNameForBinding(binding));
+  }
+}
diff --git a/java/dagger/internal/codegen/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
new file mode 100644
index 0000000..4bc3921
--- /dev/null
+++ b/java/dagger/internal/codegen/MapFactoryCreationExpression.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 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 dagger.internal.codegen.MapKeys.getMapKeyExpression;
+import static dagger.internal.codegen.SourceFiles.mapFactoryClassName;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory creation expression for a multibound map. */
+// TODO(dpb): Resolve with SetFactoryCreationExpression.
+final class MapFactoryCreationExpression implements FrameworkInstanceCreationExpression {
+
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+
+  MapFactoryCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName(binding));
+    boolean useRawType = !generatedComponentModel.isTypeAccessible(binding.key().type());
+    if (!useRawType) {
+      MapType mapType = MapType.from(binding.key().type());
+      // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
+      // mapType.unwrappedValueType() method that doesn't require a framework type
+      TypeMirror valueType = mapType.valueType();
+      for (Class<?> frameworkClass :
+          ImmutableSet.of(Provider.class, Producer.class, Produced.class)) {
+        if (mapType.valuesAreTypeOf(frameworkClass)) {
+          valueType = mapType.unwrappedValueType(frameworkClass);
+          break;
+        }
+      }
+      builder.add("<$T, $T>", mapType.keyType(), valueType);
+    }
+
+    ImmutableList<FrameworkDependency> frameworkDependencies = binding.frameworkDependencies();
+    if (binding.bindingType().equals(BindingType.PROVISION)) {
+      builder.add("builder($L)", frameworkDependencies.size());
+    } else {
+      builder.add("builder()");
+    }
+
+    for (FrameworkDependency frameworkDependency : frameworkDependencies) {
+      ContributionBinding contributionBinding =
+          graph.contributionBindings().get(frameworkDependency.key()).contributionBinding();
+      CodeBlock value =
+          componentBindingExpressions
+              .getDependencyExpression(frameworkDependency, generatedComponentModel.name())
+              .codeBlock();
+      builder.add(
+          ".put($L, $L)",
+          getMapKeyExpression(contributionBinding, generatedComponentModel.name()),
+          useRawType ? CodeBlocks.cast(value, frameworkDependency.frameworkClass()) : value);
+    }
+    builder.add(".build()");
+
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
new file mode 100644
index 0000000..5939052
--- /dev/null
+++ b/java/dagger/internal/codegen/MembersInjectorProviderCreationExpression.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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 com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
+import static dagger.internal.codegen.TypeNames.INSTANCE_FACTORY;
+import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTORS;
+
+import com.google.auto.common.MoreTypes;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import javax.lang.model.type.TypeMirror;
+
+/** A {@code Provider<MembersInjector<Foo>>} creation expression. */
+final class MembersInjectorProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ContributionBinding binding;
+
+  MembersInjectorProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    TypeMirror membersInjectedType =
+        getOnlyElement(MoreTypes.asDeclared(binding.key().type()).getTypeArguments());
+
+    CodeBlock membersInjector =
+        ((ProvisionBinding) binding).injectionSites().isEmpty()
+            ? CodeBlock.of("$T.<$T>noOp()", MEMBERS_INJECTORS, membersInjectedType)
+            : CodeBlock.of(
+                "$T.create($L)",
+                membersInjectorNameForType(MoreTypes.asTypeElement(membersInjectedType)),
+                makeParametersCodeBlock(
+                    componentBindingExpressions.getDependencyExpressions(
+                        binding.frameworkDependencies(), generatedComponentModel.name())));
+
+    // TODO(ronshapiro): consider adding a MembersInjectorBindingExpression to return this directly
+    // (as it's rarely requested as a Provider).
+    return CodeBlock.of("$T.create($L)", INSTANCE_FACTORY, membersInjector);
+  }
+}
diff --git a/java/dagger/internal/codegen/OptionalFactories.java b/java/dagger/internal/codegen/OptionalFactories.java
index 1406677..498ec35 100644
--- a/java/dagger/internal/codegen/OptionalFactories.java
+++ b/java/dagger/internal/codegen/OptionalFactories.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Verify.verify;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.squareup.javapoet.MethodSpec.constructorBuilder;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
@@ -96,6 +97,10 @@
    * for absent optional bindings.
    */
   CodeBlock absentOptionalProvider(ContributionBinding binding) {
+    verify(
+        binding.bindingType().equals(BindingType.PROVISION),
+        "Absent optional bindings should be provisions: %s",
+        binding);
     OptionalKind optionalKind = OptionalType.from(binding.key()).kind();
     return CodeBlock.of(
         "$N()",
diff --git a/java/dagger/internal/codegen/ProducerCreationExpression.java b/java/dagger/internal/codegen/ProducerCreationExpression.java
new file mode 100644
index 0000000..696f6d6
--- /dev/null
+++ b/java/dagger/internal/codegen/ProducerCreationExpression.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 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 dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
+
+import com.google.common.collect.Lists;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * A {@link dagger.producers.Producer} creation expression for a {@link
+ * dagger.producers.Produces @Produces}-annotated module method.
+ */
+// TODO(dpb): Resolve with InjectionOrProvisionProviderCreationExpression.
+final class ProducerCreationExpression implements FrameworkInstanceCreationExpression {
+
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final ComponentRequirementFields componentRequirementFields;
+  private final ContributionBinding binding;
+
+  ProducerCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions,
+      ComponentRequirementFields componentRequirementFields) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.componentRequirementFields = checkNotNull(componentRequirementFields);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    List<CodeBlock> arguments = Lists.newArrayListWithCapacity(binding.dependencies().size() + 2);
+    if (binding.requiresModuleInstance()) {
+      arguments.add(
+          componentRequirementFields.getExpressionDuringInitialization(
+              ComponentRequirement.forModule(binding.contributingModule().get().asType()),
+              generatedComponentModel.name()));
+    }
+    arguments.addAll(
+        componentBindingExpressions.getDependencyExpressions(
+            binding.frameworkDependencies(), generatedComponentModel.name()));
+
+    return CodeBlock.of(
+        "new $T($L)", generatedClassNameForBinding(binding), makeParametersCodeBlock(arguments));
+  }
+
+  @Override
+  public Optional<TypeName> specificType() {
+    return Optional.of(generatedClassNameForBinding(binding));
+  }
+}
diff --git a/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
similarity index 65%
rename from java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java
rename to java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
index 61e122d..05a0e41 100644
--- a/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java
+++ b/java/dagger/internal/codegen/ProducerFromProviderCreationExpression.java
@@ -21,38 +21,39 @@
 
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
-import dagger.model.Key;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
 import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import java.util.Optional;
 
-/** An initializer for {@link Producer} fields that are adaptations of provision bindings. */
-final class ProducerFromProviderFieldInitializer extends FrameworkFieldInitializer {
-
+/** An {@link Producer} creation expression for provision bindings. */
+final class ProducerFromProviderCreationExpression implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
   private final ComponentBindingExpressions componentBindingExpressions;
-  private final Key key;
 
-  ProducerFromProviderFieldInitializer(
-      ResolvedBindings resolvedBindings,
+  ProducerFromProviderCreationExpression(
+      ContributionBinding binding,
       GeneratedComponentModel generatedComponentModel,
       ComponentBindingExpressions componentBindingExpressions) {
-    super(generatedComponentModel, componentBindingExpressions, resolvedBindings);
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
     this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
-    this.key = resolvedBindings.key();
   }
 
   @Override
-  protected CodeBlock getFieldInitialization() {
+  public CodeBlock creationExpression() {
     return FrameworkType.PROVIDER.to(
         RequestKind.PRODUCER,
         componentBindingExpressions
             .getDependencyExpression(
-                FrameworkDependency.create(key, PROVISION), generatedComponentModel.name())
+                FrameworkDependency.create(binding.key(), PROVISION),
+                generatedComponentModel.name())
             .codeBlock());
   }
 
   @Override
-  protected Optional<ClassName> alternativeFrameworkClass() {
+  public Optional<ClassName> alternativeFrameworkClass() {
     return Optional.of(ClassName.get(Producer.class));
   }
 }
diff --git a/java/dagger/internal/codegen/ProviderOrProducerFieldInitializer.java b/java/dagger/internal/codegen/ProviderOrProducerFieldInitializer.java
deleted file mode 100644
index 0c048fa..0000000
--- a/java/dagger/internal/codegen/ProviderOrProducerFieldInitializer.java
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 2015 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.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Verify.verify;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.CodeBlocks.anonymousProvider;
-import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
-import static dagger.internal.codegen.ContributionBinding.Kind.INJECTION;
-import static dagger.internal.codegen.GeneratedComponentModel.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
-import static dagger.internal.codegen.MapKeys.getMapKeyExpression;
-import static dagger.internal.codegen.MoreAnnotationMirrors.getTypeValue;
-import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
-import static dagger.internal.codegen.SourceFiles.mapFactoryClassName;
-import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.SourceFiles.setFactoryClassName;
-import static dagger.internal.codegen.TypeNames.DOUBLE_CHECK;
-import static dagger.internal.codegen.TypeNames.INSTANCE_FACTORY;
-import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTORS;
-import static dagger.internal.codegen.TypeNames.REFERENCE_RELEASING_PROVIDER;
-import static dagger.internal.codegen.TypeNames.SINGLE_CHECK;
-import static dagger.internal.codegen.TypeNames.TYPED_RELEASABLE_REFERENCE_MANAGER_DECORATOR;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.TypeNames.producerOf;
-import static dagger.internal.codegen.TypeNames.providerOf;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.InstanceFactory;
-import dagger.internal.TypedReleasableReferenceManagerDecorator;
-import dagger.model.Key;
-import dagger.model.Scope;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import dagger.releasablereferences.ForReleasableReferences;
-import dagger.releasablereferences.ReleasableReferenceManager;
-import dagger.releasablereferences.TypedReleasableReferenceManager;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import javax.inject.Provider;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.type.TypeMirror;
-
-/**
- * An initializer for {@link Provider} or {@link Producer} fields other than {@link Producer} fields
- * that {@linkplain ProducerFromProviderFieldInitializer adapt provision bindings}.
- */
-// TODO(dpb): Split this up by binding kind.
-final class ProviderOrProducerFieldInitializer extends FrameworkFieldInitializer {
-  private final SubcomponentNames subcomponentNames;
-  private final ComponentRequirementFields componentRequirementFields;
-  private final ResolvedBindings resolvedBindings;
-  private final CompilerOptions compilerOptions;
-  private final BindingGraph graph;
-  private final OptionalFactories optionalFactories;
-  private final ReferenceReleasingManagerFields referenceReleasingManagerFields;
-
-  ProviderOrProducerFieldInitializer(
-      ResolvedBindings resolvedBindings,
-      SubcomponentNames subcomponentNames,
-      GeneratedComponentModel generatedComponentModel,
-      ComponentBindingExpressions componentBindingExpressions,
-      ComponentRequirementFields componentRequirementFields,
-      ReferenceReleasingManagerFields referenceReleasingManagerFields,
-      CompilerOptions compilerOptions,
-      BindingGraph graph,
-      OptionalFactories optionalFactories) {
-    super(generatedComponentModel, componentBindingExpressions, resolvedBindings);
-    checkArgument(resolvedBindings.contributionBindings().size() == 1);
-    this.subcomponentNames = checkNotNull(subcomponentNames);
-    this.componentRequirementFields = checkNotNull(componentRequirementFields);
-    this.referenceReleasingManagerFields = checkNotNull(referenceReleasingManagerFields);
-    this.resolvedBindings = checkNotNull(resolvedBindings);
-    this.compilerOptions = checkNotNull(compilerOptions);
-    this.graph = checkNotNull(graph);
-    this.optionalFactories = checkNotNull(optionalFactories);
-  }
-
-  @Override
-  protected CodeBlock getFieldInitialization() {
-    ContributionBinding contributionBinding = resolvedBindings.contributionBinding();
-    switch (contributionBinding.factoryCreationStrategy()) {
-      case DELEGATE:
-        CodeBlock delegatingCodeBlock =
-            CodeBlock.of(
-                "($T) $L",
-                contributionBinding.bindingType().frameworkClass(),
-                getDependencyExpression(
-                    getOnlyElement(contributionBinding.frameworkDependencies())));
-        return decorateForScope(delegatingCodeBlock, contributionBinding.scope());
-      case SINGLETON_INSTANCE:
-        checkState(contributionBinding.scope().isPresent());
-        // fall through
-      case CLASS_CONSTRUCTOR:
-        return factoryForContributionBindingInitialization(contributionBinding);
-
-      default:
-        throw new AssertionError();
-    }
-  }
-
-  private CodeBlock factoryForContributionBindingInitialization(ContributionBinding binding) {
-    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.create($L)",
-            INSTANCE_FACTORY,
-            componentRequirementFields.getExpressionDuringInitialization(
-                ComponentRequirement.forDependency(binding.key().type()),
-                generatedComponentModel.name()));
-
-      case COMPONENT_PROVISION:
-        {
-          ComponentRequirement dependency = dependencyForBinding(binding);
-          String componentMethod = binding.bindingElement().get().getSimpleName().toString();
-          // TODO(sameb): The Provider.get() throws a very vague NPE.  The stack trace doesn't
-          // help to figure out what the method or return type is.  If we include a string
-          // of the return type or method name in the error message, that can defeat obfuscation.
-          // We can easily include the raw type (no generics) + annotation type (no values),
-          // using .class & String.format -- but that wouldn't be the whole story.
-          // What should we do?
-          CodeBlock invocation =
-              ComponentProvisionBindingExpression.maybeCheckForNull(
-                  (ProvisionBinding) binding,
-                  compilerOptions,
-                  CodeBlock.of("$L.$L()", dependency.variableName(), componentMethod));
-          ClassName dependencyClassName = ClassName.get(dependency.typeElement());
-          String factoryName =
-              dependencyClassName.toString().replace('.', '_') + "_" + componentMethod;
-          MethodSpec.Builder getMethod =
-              methodBuilder("get")
-                  .addAnnotation(Override.class)
-                  .addModifiers(PUBLIC)
-                  .returns(bindingKeyTypeName)
-                  .addStatement("return $L", invocation);
-          if (binding.nullableType().isPresent()) {
-            getMethod.addAnnotation(
-                ClassName.get(MoreTypes.asTypeElement(binding.nullableType().get())));
-          }
-          generatedComponentModel.addType(
-              COMPONENT_PROVISION_FACTORY,
-              TypeSpec.classBuilder(factoryName)
-                  .addSuperinterface(providerOf(bindingKeyTypeName))
-                  .addModifiers(PRIVATE, STATIC)
-                  .addField(dependencyClassName, dependency.variableName(), PRIVATE, FINAL)
-                  .addMethod(
-                      constructorBuilder()
-                          .addParameter(dependencyClassName, dependency.variableName())
-                          .addStatement("this.$1L = $1L", dependency.variableName())
-                          .build())
-                  .addMethod(getMethod.build())
-                  .build());
-          setFieldTypeReplacement(generatedComponentModel.name().nestedClass(factoryName));
-          return CodeBlock.of(
-              "new $L($L)",
-              factoryName,
-              componentRequirementFields.getExpressionDuringInitialization(
-                  dependency, generatedComponentModel.name()));
-        }
-
-      case SUBCOMPONENT_BUILDER:
-        String subcomponentName =
-            subcomponentNames.get(
-                graph
-                    .componentDescriptor()
-                    .subcomponentsByBuilderType()
-                    .get(MoreTypes.asTypeElement(binding.key().type())));
-        return anonymousProvider(
-            bindingKeyTypeName, CodeBlock.of("return new $NBuilder();", subcomponentName));
-
-      case BOUND_INSTANCE:
-        return CodeBlock.of(
-            "$T.$L($L)",
-            InstanceFactory.class,
-            binding.nullableType().isPresent() ? "createNullable" : "create",
-            componentRequirementFields.getExpressionDuringInitialization(
-                ComponentRequirement.forBoundInstance(binding), generatedComponentModel.name()));
-
-      case INJECTION:
-      case PROVISION:
-        {
-          List<CodeBlock> arguments =
-              Lists.newArrayListWithCapacity(binding.explicitDependencies().size() + 1);
-          if (binding.requiresModuleInstance()) {
-            arguments.add(
-                componentRequirementFields.getExpressionDuringInitialization(
-                    ComponentRequirement.forModule(binding.contributingModule().get().asType()),
-                    generatedComponentModel.name()));
-          }
-          arguments.addAll(getBindingDependencyExpressions(binding));
-
-          CodeBlock factoryCreate =
-              CodeBlock.of(
-                  "$T.create($L)",
-                  generatedClassNameForBinding(binding),
-                  makeParametersCodeBlock(arguments));
-
-          // If scoping a parameterized factory for an @Inject class, Java 7 cannot always infer the
-          // type properly, so cast to a raw framework type before scoping.
-          if (binding.bindingKind().equals(INJECTION)
-              && binding.unresolved().isPresent()
-              && binding.scope().isPresent()) {
-            factoryCreate =
-                CodeBlock.of("($T) $L", binding.bindingType().frameworkClass(), factoryCreate);
-          } else if (!binding.scope().isPresent()) {
-            setFieldTypeReplacement(generatedClassNameForBinding(binding));
-          }
-          return decorateForScope(factoryCreate, binding.scope());
-        }
-
-      case COMPONENT_PRODUCTION:
-        {
-          ComponentRequirement dependency = dependencyForBinding(binding);
-          FieldSpec dependencyField =
-              FieldSpec.builder(
-                      ClassName.get(dependency.typeElement()),
-                      dependency.variableName(),
-                      PRIVATE,
-                      FINAL)
-                  .initializer(
-                      componentRequirementFields.getExpressionDuringInitialization(
-                          dependency, generatedComponentModel.name()))
-                  .build();
-          // TODO(b/70395982): Explore using a private static type instead of an anonymous class.
-          return CodeBlock.of(
-              "$L",
-              anonymousClassBuilder("")
-                  .superclass(producerOf(bindingKeyTypeName))
-                  .addField(dependencyField)
-                  .addMethod(
-                      methodBuilder("get")
-                          .addAnnotation(Override.class)
-                          .addModifiers(PUBLIC)
-                          .returns(listenableFutureOf(bindingKeyTypeName))
-                          .addStatement(
-                              "return $N.$L()",
-                              dependencyField,
-                              binding.bindingElement().get().getSimpleName())
-                          .build())
-                  .build());
-        }
-
-      case PRODUCTION:
-        {
-          List<CodeBlock> arguments =
-              Lists.newArrayListWithCapacity(binding.dependencies().size() + 2);
-          if (binding.requiresModuleInstance()) {
-            arguments.add(
-                componentRequirementFields.getExpressionDuringInitialization(
-                    ComponentRequirement.forModule(binding.contributingModule().get().asType()),
-                    generatedComponentModel.name()));
-          }
-          arguments.addAll(getBindingDependencyExpressions(binding));
-
-          setFieldTypeReplacement(generatedClassNameForBinding(binding));
-          return CodeBlock.of(
-              "new $T($L)",
-              generatedClassNameForBinding(binding),
-              makeParametersCodeBlock(arguments));
-        }
-
-      case SYNTHETIC_MULTIBOUND_SET:
-        return factoryForSetMultibindingInitialization(binding);
-
-      case SYNTHETIC_MULTIBOUND_MAP:
-        return factoryForMapMultibindingInitialization(binding);
-
-      case SYNTHETIC_RELEASABLE_REFERENCE_MANAGER:
-        return factoryForSyntheticReleasableReferenceManagerBindingInitialization(binding);
-
-      case SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS:
-        return factoryForSyntheticSetOfReleasableReferenceManagersInitialization(binding);
-
-      case SYNTHETIC_OPTIONAL_BINDING:
-        return factoryForSyntheticOptionalBindingInitialization(binding);
-
-      case MEMBERS_INJECTOR:
-        return factoryForSyntheticMembersInjectorBinding(binding);
-
-      default:
-        throw new AssertionError(binding);
-    }
-  }
-
-  /**
-   * Maybe wraps the given creation code block in single/double check or reference releasing
-   * providers.
-   */
-  private CodeBlock decorateForScope(CodeBlock factoryCreate, Optional<Scope> maybeScope) {
-    if (!maybeScope.isPresent()) {
-      return factoryCreate;
-    }
-    Scope scope = maybeScope.get();
-    if (referenceReleasingManagerFields.requiresReleasableReferences(scope)) {
-      return CodeBlock.of(
-          "$T.create($L, $L)",
-          REFERENCE_RELEASING_PROVIDER,
-          factoryCreate,
-          referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name()));
-    } else {
-      return CodeBlock.of(
-          "$T.provider($L)", scope.isReusable() ? SINGLE_CHECK : DOUBLE_CHECK, factoryCreate);
-    }
-  }
-
-  private ComponentRequirement dependencyForBinding(ContributionBinding binding) {
-    return graph
-        .componentDescriptor()
-        .dependenciesByDependencyMethod()
-        .get(binding.bindingElement().get());
-  }
-
-  private CodeBlock factoryForSetMultibindingInitialization(ContributionBinding binding) {
-    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", setFactoryClassName(binding));
-    boolean useRawTypes = useRawType();
-    if (!useRawTypes) {
-      SetType setType = SetType.from(binding.key());
-      builder.add(
-          "<$T>",
-          setType.elementsAreTypeOf(Produced.class)
-              ? setType.unwrappedElementType(Produced.class)
-              : setType.elementType());
-    }
-    int individualProviders = 0;
-    int setProviders = 0;
-    CodeBlock.Builder builderMethodCalls = CodeBlock.builder();
-    for (FrameworkDependency frameworkDependency : binding.frameworkDependencies()) {
-      ContributionType contributionType =
-          graph.contributionBindings().get(frameworkDependency.key()).contributionType();
-      String methodName;
-      String methodNameSuffix = frameworkDependency.frameworkClass().getSimpleName();
-      switch (contributionType) {
-        case SET:
-          individualProviders++;
-          methodName = "add" + methodNameSuffix;
-          break;
-        case SET_VALUES:
-          setProviders++;
-          methodName = "addCollection" + methodNameSuffix;
-          break;
-        default:
-          throw new AssertionError(frameworkDependency + " is not a set multibinding");
-      }
-
-      builderMethodCalls.add(
-          ".$L($L)",
-          methodName,
-          potentiallyCast(
-              useRawTypes,
-              frameworkDependency.frameworkClass(),
-              getDependencyExpression(frameworkDependency)));
-    }
-    builder.add("builder($L, $L)", individualProviders, setProviders);
-    builder.add(builderMethodCalls.build());
-    return builder.add(".build()").build();
-  }
-
-  private CodeBlock factoryForMapMultibindingInitialization(ContributionBinding binding) {
-    ImmutableList<FrameworkDependency> frameworkDependencies = binding.frameworkDependencies();
-
-    ImmutableList.Builder<CodeBlock> codeBlocks = ImmutableList.builder();
-    MapType mapType = MapType.from(binding.key().type());
-    CodeBlock.Builder builderCall = CodeBlock.builder().add("$T.", mapFactoryClassName(binding));
-    boolean useRawTypes = useRawType();
-    if (!useRawTypes) {
-      // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
-      // mapType.unwrappedValueType() method that doesn't require a framework type
-      TypeMirror valueType = mapType.valueType();
-      for (Class<?> frameworkClass :
-          ImmutableSet.of(Provider.class, Producer.class, Produced.class)) {
-        if (mapType.valuesAreTypeOf(frameworkClass)) {
-          valueType = mapType.unwrappedValueType(frameworkClass);
-          break;
-        }
-      }
-      builderCall.add("<$T, $T>", mapType.keyType(), valueType);
-    }
-
-    if (binding.bindingType().equals(BindingType.PROVISION)) {
-      builderCall.add("builder($L)", frameworkDependencies.size());
-    } else {
-      builderCall.add("builder()");
-    }
-    codeBlocks.add(builderCall.build());
-
-    for (FrameworkDependency frameworkDependency : frameworkDependencies) {
-      ContributionBinding contributionBinding =
-          graph.contributionBindings().get(frameworkDependency.key()).contributionBinding();
-      CodeBlock value =
-          potentiallyCast(
-              useRawTypes,
-              frameworkDependency.frameworkClass(),
-              getDependencyExpression(frameworkDependency));
-      codeBlocks.add(
-          CodeBlock.of(
-              ".put($L, $L)",
-              getMapKeyExpression(contributionBinding, generatedComponentModel.name()),
-              value));
-    }
-    codeBlocks.add(CodeBlock.of(".build()"));
-
-    return CodeBlocks.concat(codeBlocks.build());
-  }
-
-  // TODO(ronshapiro): Use functionality from Expression
-  private CodeBlock potentiallyCast(boolean shouldCast, Class<?> classToCast, CodeBlock notCasted) {
-    if (!shouldCast) {
-      return notCasted;
-    }
-    return CodeBlock.of("($T) $L", classToCast, notCasted);
-  }
-
-  private boolean useRawType() {
-
-    return !isTypeAccessibleFrom(
-        resolvedBindings.key().type(), generatedComponentModel.name().packageName());
-  }
-
-  /**
-   * Initializes the factory for a {@link
-   * ContributionBinding.Kind#SYNTHETIC_RELEASABLE_REFERENCE_MANAGER} binding.
-   *
-   * <p>The {@code get()} method just returns the component field with the {@link
-   * dagger.internal.ReferenceReleasingProviderManager} object.
-   */
-  private CodeBlock factoryForSyntheticReleasableReferenceManagerBindingInitialization(
-      ContributionBinding binding) {
-    // The scope is the value of the @ForReleasableReferences annotation.
-    Scope scope = forReleasableReferencesAnnotationValue(binding.key().qualifier().get());
-
-    CodeBlock managerExpression;
-    if (MoreTypes.isTypeOf(TypedReleasableReferenceManager.class, binding.key().type())) {
-      /* The key's type is TypedReleasableReferenceManager<M>, so return
-       * new TypedReleasableReferenceManager(field, metadata). */
-      TypeMirror metadataType =
-          MoreTypes.asDeclared(binding.key().type()).getTypeArguments().get(0);
-      managerExpression =
-          typedReleasableReferenceManagerDecoratorExpression(
-              referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name()),
-              scope.releasableReferencesMetadata(metadataType).get());
-    } else {
-      // The key's type is ReleasableReferenceManager, so return the field as is.
-      managerExpression =
-          referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name());
-    }
-
-    return anonymousProvider(
-        TypeName.get(binding.key().type()), CodeBlock.of("return $L;", managerExpression));
-  }
-
-  /**
-   * Initializes the factory for a {@link
-   * ContributionBinding.Kind#SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS} binding.
-   *
-   * <p>A binding for {@code Set<ReleasableReferenceManager>} will include managers for all
-   * reference-releasing scopes. A binding for {@code Set<TypedReleasableReferenceManager<M>>} will
-   * include managers for all reference-releasing scopes whose metadata type is {@code M}.
-   */
-  private CodeBlock factoryForSyntheticSetOfReleasableReferenceManagersInitialization(
-      ContributionBinding binding) {
-    Key key = binding.key();
-    SetType keyType = SetType.from(key);
-    ImmutableList.Builder<CodeBlock> managerExpressions = ImmutableList.builder();
-    for (Scope scope : graph.scopesRequiringReleasableReferenceManagers()) {
-      CodeBlock releasableReferenceManagerExpression =
-          referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name());
-
-      if (keyType.elementsAreTypeOf(ReleasableReferenceManager.class)) {
-        managerExpressions.add(releasableReferenceManagerExpression);
-      } else if (keyType.elementsAreTypeOf(TypedReleasableReferenceManager.class)) {
-        TypeMirror metadataType =
-            keyType.unwrappedElementType(TypedReleasableReferenceManager.class);
-        Optional<AnnotationMirror> metadata = scope.releasableReferencesMetadata(metadataType);
-        if (metadata.isPresent()) {
-          managerExpressions.add(
-              typedReleasableReferenceManagerDecoratorExpression(
-                  releasableReferenceManagerExpression, metadata.get()));
-        }
-      } else {
-        throw new IllegalArgumentException("inappropriate key: " + binding);
-      }
-    }
-    TypeName keyTypeName = TypeName.get(key.type());
-    CodeBlock body =
-        CodeBlock.of(
-            "return new $T($T.asList($L));",
-            HashSet.class,
-            Arrays.class,
-            makeParametersCodeBlock(managerExpressions.build()));
-    return anonymousProvider(keyTypeName, body);
-  }
-
-  /**
-   * Returns an expression that evaluates to a {@link TypedReleasableReferenceManagerDecorator} that
-   * decorates the {@code managerExpression} to supply {@code metadata}.
-   */
-  private CodeBlock typedReleasableReferenceManagerDecoratorExpression(
-      CodeBlock managerExpression, AnnotationMirror metadata) {
-    return CodeBlock.of(
-        "new $T<$T>($L, $L)",
-        TYPED_RELEASABLE_REFERENCE_MANAGER_DECORATOR,
-        metadata.getAnnotationType(),
-        managerExpression,
-        new AnnotationExpression(metadata).getAnnotationInstanceExpression());
-  }
-
-  private Scope forReleasableReferencesAnnotationValue(AnnotationMirror annotation) {
-    checkArgument(
-        MoreTypes.isTypeOf(ForReleasableReferences.class, annotation.getAnnotationType()));
-    return Scopes.scope(
-        MoreElements.asType(MoreTypes.asDeclared(getTypeValue(annotation, "value")).asElement()));
-  }
-
-  /**
-   * Returns an expression that initializes a {@link Provider} or {@link Producer} for an optional
-   * binding.
-   */
-  private CodeBlock factoryForSyntheticOptionalBindingInitialization(ContributionBinding binding) {
-    if (binding.explicitDependencies().isEmpty()) {
-      verify(
-          binding.bindingType().equals(BindingType.PROVISION),
-          "Absent optional bindings should be provisions: %s",
-          binding);
-      return optionalFactories.absentOptionalProvider(binding);
-    } else {
-      return optionalFactories.presentOptionalFactory(
-          binding, getDependencyExpression(getOnlyElement(binding.frameworkDependencies())));
-    }
-  }
-
-  /**
-   * Returns an expression that initializes a {@code Provider<MembersInjector<T>>} for a {@link
-   * ContributionBinding.Kind#MEMBERS_INJECTOR} binding.
-   */
-  private CodeBlock factoryForSyntheticMembersInjectorBinding(ContributionBinding binding) {
-    TypeMirror membersInjectedType =
-        getOnlyElement(MoreTypes.asDeclared(binding.key().type()).getTypeArguments());
-
-    CodeBlock membersInjector =
-        ((ProvisionBinding) binding).injectionSites().isEmpty()
-            ? CodeBlock.of("$T.<$T>noOp()", MEMBERS_INJECTORS, membersInjectedType)
-            : CodeBlock.of(
-                "$T.create($L)",
-                membersInjectorNameForType(MoreTypes.asTypeElement(membersInjectedType)),
-                makeParametersCodeBlock(getBindingDependencyExpressions(binding)));
-
-    // TODO(ronshapiro): consider adding a MembersInjectorBindingExpression to return this directly
-    // (as it's rarely requested as a Provider).
-    return CodeBlock.of("$T.create($L)", INSTANCE_FACTORY, membersInjector);
-  }
-}
diff --git a/java/dagger/internal/codegen/ReferenceReleasingManagerFields.java b/java/dagger/internal/codegen/ReferenceReleasingManagerFields.java
index d915a70..fe69621 100644
--- a/java/dagger/internal/codegen/ReferenceReleasingManagerFields.java
+++ b/java/dagger/internal/codegen/ReferenceReleasingManagerFields.java
@@ -23,6 +23,7 @@
 import static dagger.internal.codegen.GeneratedComponentModel.FieldSpecKind.REFERENCE_RELEASING_MANAGER_FIELD;
 import static dagger.internal.codegen.MemberSelect.localField;
 import static dagger.internal.codegen.TypeNames.REFERENCE_RELEASING_PROVIDER_MANAGER;
+import static dagger.internal.codegen.TypeNames.TYPED_RELEASABLE_REFERENCE_MANAGER_DECORATOR;
 import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
 import static javax.lang.model.element.Modifier.FINAL;
 import static javax.lang.model.element.Modifier.PRIVATE;
@@ -30,9 +31,11 @@
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
+import dagger.internal.TypedReleasableReferenceManagerDecorator;
 import dagger.model.Scope;
 import java.util.HashMap;
 import java.util.Map;
+import javax.lang.model.element.AnnotationMirror;
 
 /**
  * Manages the {@link dagger.internal.ReferenceReleasingProviderManager} fields and the logic for
@@ -60,6 +63,20 @@
   }
 
   /**
+   * Returns an expression that evaluates to a {@link TypedReleasableReferenceManagerDecorator} that
+   * decorates the {@code managerExpression} to supply {@code metadata}.
+   */
+  static CodeBlock typedReleasableReferenceManagerDecoratorExpression(
+      CodeBlock managerExpression, AnnotationMirror metadata) {
+    return CodeBlock.of(
+        "new $T<$T>($L, $L)",
+        TYPED_RELEASABLE_REFERENCE_MANAGER_DECORATOR,
+        metadata.getAnnotationType(),
+        managerExpression,
+        new AnnotationExpression(metadata).getAnnotationInstanceExpression());
+  }
+
+  /**
    * Returns {@code true} if {@code scope} is in {@link
    * BindingGraph#scopesRequiringReleasableReferenceManagers()} for the root graph.
    */
diff --git a/java/dagger/internal/codegen/ReleasableReferenceManagerProviderCreationExpression.java b/java/dagger/internal/codegen/ReleasableReferenceManagerProviderCreationExpression.java
new file mode 100644
index 0000000..083244c
--- /dev/null
+++ b/java/dagger/internal/codegen/ReleasableReferenceManagerProviderCreationExpression.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 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.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
+import static dagger.internal.codegen.MoreAnnotationMirrors.getTypeValue;
+import static dagger.internal.codegen.ReferenceReleasingManagerFields.typedReleasableReferenceManagerDecoratorExpression;
+import static dagger.internal.codegen.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.google.auto.common.MoreElements;
+import com.google.auto.common.MoreTypes;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.model.Scope;
+import dagger.releasablereferences.ForReleasableReferences;
+import dagger.releasablereferences.TypedReleasableReferenceManager;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@link dagger.releasablereferences.ReleasableReferenceManager
+ * Provider<ReleasableReferenceManager>} creation expression.
+ *
+ * <p>The {@code get()} method just returns the component's {@link
+ * dagger.internal.ReferenceReleasingProviderManager} field.
+ */
+final class ReleasableReferenceManagerProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+
+  private final ContributionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ReferenceReleasingManagerFields referenceReleasingManagerFields;
+
+  ReleasableReferenceManagerProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ReferenceReleasingManagerFields referenceReleasingManagerFields) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.referenceReleasingManagerFields = checkNotNull(referenceReleasingManagerFields);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    TypeName keyType = TypeName.get(binding.key().type());
+    return CodeBlock.of(
+        "$L",
+        anonymousClassBuilder("")
+            .addSuperinterface(providerOf(keyType))
+            .addMethod(
+                methodBuilder("get")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(keyType)
+                    .addCode("return $L;", releasableReferenceManagerExpression())
+                    .build())
+            .build());
+  }
+
+  private CodeBlock releasableReferenceManagerExpression() {
+    // The scope is the value of the @ForReleasableReferences annotation.
+    Scope scope = forReleasableReferencesAnnotationValue(binding.key().qualifier().get());
+
+    if (MoreTypes.isTypeOf(TypedReleasableReferenceManager.class, binding.key().type())) {
+      /* The key's type is TypedReleasableReferenceManager<M>, so return
+       * new TypedReleasableReferenceManager(field, metadata). */
+      TypeMirror metadataType =
+          MoreTypes.asDeclared(binding.key().type()).getTypeArguments().get(0);
+      return typedReleasableReferenceManagerDecoratorExpression(
+          referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name()),
+          scope.releasableReferencesMetadata(metadataType).get());
+    } else {
+      // The key's type is ReleasableReferenceManager, so return the field as is.
+      return referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name());
+    }
+  }
+
+  private Scope forReleasableReferencesAnnotationValue(AnnotationMirror annotation) {
+    checkArgument(
+        MoreTypes.isTypeOf(ForReleasableReferences.class, annotation.getAnnotationType()));
+    return Scopes.scope(
+        MoreElements.asType(MoreTypes.asDeclared(getTypeValue(annotation, "value")).asElement()));
+  }
+}
diff --git a/java/dagger/internal/codegen/ReleasableReferenceManagerSetProviderCreationExpression.java b/java/dagger/internal/codegen/ReleasableReferenceManagerSetProviderCreationExpression.java
new file mode 100644
index 0000000..078fd6b
--- /dev/null
+++ b/java/dagger/internal/codegen/ReleasableReferenceManagerSetProviderCreationExpression.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 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 com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
+import static dagger.internal.codegen.CodeBlocks.makeParametersCodeBlock;
+import static dagger.internal.codegen.ReferenceReleasingManagerFields.typedReleasableReferenceManagerDecoratorExpression;
+import static dagger.internal.codegen.TypeNames.providerOf;
+import static javax.lang.model.element.Modifier.PUBLIC;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.model.Scope;
+import dagger.releasablereferences.ReleasableReferenceManager;
+import dagger.releasablereferences.TypedReleasableReferenceManager;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Optional;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A {@link ReleasableReferenceManager Provider<Set<ReleasableReferenceManager>>} creation
+ * expression.
+ *
+ * <p>A binding for {@code Set<ReleasableReferenceManager>} will include managers for all
+ * reference-releasing scopes. A binding for {@code Set<TypedReleasableReferenceManager<M>>} will
+ * include managers for all reference-releasing scopes whose metadata type is {@code M}.
+ */
+final class ReleasableReferenceManagerSetProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final ContributionBinding binding;
+  private final BindingGraph graph;
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ReferenceReleasingManagerFields referenceReleasingManagerFields;
+
+  ReleasableReferenceManagerSetProviderCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ReferenceReleasingManagerFields referenceReleasingManagerFields,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.referenceReleasingManagerFields = checkNotNull(referenceReleasingManagerFields);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    TypeName keyType = TypeName.get(binding.key().type());
+    return CodeBlock.of(
+        "$L",
+        anonymousClassBuilder("")
+            .addSuperinterface(providerOf(keyType))
+            .addMethod(
+                methodBuilder("get")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(keyType)
+                    .addCode(
+                        "return new $T($T.asList($L));",
+                        HashSet.class,
+                        Arrays.class,
+                        makeParametersCodeBlock(releasableReferenceManagerExpressions()))
+                    .build())
+            .build());
+  }
+
+  private ImmutableList<CodeBlock> releasableReferenceManagerExpressions() {
+    SetType keyType = SetType.from(binding.key());
+    ImmutableList.Builder<CodeBlock> managerExpressions = ImmutableList.builder();
+    for (Scope scope : graph.scopesRequiringReleasableReferenceManagers()) {
+      CodeBlock releasableReferenceManagerExpression =
+          referenceReleasingManagerFields.getExpression(scope, generatedComponentModel.name());
+
+      if (keyType.elementsAreTypeOf(ReleasableReferenceManager.class)) {
+        managerExpressions.add(releasableReferenceManagerExpression);
+      } else if (keyType.elementsAreTypeOf(TypedReleasableReferenceManager.class)) {
+        TypeMirror metadataType =
+            keyType.unwrappedElementType(TypedReleasableReferenceManager.class);
+        Optional<AnnotationMirror> metadata = scope.releasableReferencesMetadata(metadataType);
+        if (metadata.isPresent()) {
+          managerExpressions.add(
+              typedReleasableReferenceManagerDecoratorExpression(
+                  releasableReferenceManagerExpression, metadata.get()));
+        }
+      } else {
+        throw new IllegalArgumentException("inappropriate key: " + binding);
+      }
+    }
+    return managerExpressions.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/SetFactoryCreationExpression.java b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
new file mode 100644
index 0000000..e1a1618
--- /dev/null
+++ b/java/dagger/internal/codegen/SetFactoryCreationExpression.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 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 dagger.internal.codegen.SourceFiles.setFactoryClassName;
+
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.producers.Produced;
+
+/** A factory creation expression for a multibound set. */
+// TODO(dpb): Resolve with MapFactoryCreationExpression.
+final class SetFactoryCreationExpression implements FrameworkInstanceCreationExpression {
+
+  private final GeneratedComponentModel generatedComponentModel;
+  private final ComponentBindingExpressions componentBindingExpressions;
+  private final BindingGraph graph;
+  private final ContributionBinding binding;
+
+  SetFactoryCreationExpression(
+      ContributionBinding binding,
+      GeneratedComponentModel generatedComponentModel,
+      ComponentBindingExpressions componentBindingExpressions,
+      BindingGraph graph) {
+    this.binding = checkNotNull(binding);
+    this.generatedComponentModel = checkNotNull(generatedComponentModel);
+    this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+    this.graph = checkNotNull(graph);
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", setFactoryClassName(binding));
+    boolean useRawType = !generatedComponentModel.isTypeAccessible(binding.key().type());
+    if (!useRawType) {
+      SetType setType = SetType.from(binding.key());
+      builder.add(
+          "<$T>",
+          setType.elementsAreTypeOf(Produced.class)
+              ? setType.unwrappedElementType(Produced.class)
+              : setType.elementType());
+    }
+    int individualProviders = 0;
+    int setProviders = 0;
+    CodeBlock.Builder builderMethodCalls = CodeBlock.builder();
+    for (FrameworkDependency frameworkDependency : binding.frameworkDependencies()) {
+      ContributionType contributionType =
+          graph.contributionBindings().get(frameworkDependency.key()).contributionType();
+      String methodName;
+      String methodNameSuffix = frameworkDependency.frameworkClass().getSimpleName();
+      switch (contributionType) {
+        case SET:
+          individualProviders++;
+          methodName = "add" + methodNameSuffix;
+          break;
+        case SET_VALUES:
+          setProviders++;
+          methodName = "addCollection" + methodNameSuffix;
+          break;
+        default:
+          throw new AssertionError(frameworkDependency + " is not a set multibinding");
+      }
+
+      CodeBlock argument =
+          componentBindingExpressions
+              .getDependencyExpression(frameworkDependency, generatedComponentModel.name())
+              .codeBlock();
+      builderMethodCalls.add(
+          ".$L($L)",
+          methodName,
+          useRawType ? CodeBlocks.cast(argument, frameworkDependency.frameworkClass()) : argument);
+    }
+    builder.add("builder($L, $L)", individualProviders, setProviders);
+    builder.add(builderMethodCalls.build());
+    return builder.add(".build()").build();
+  }
+}
diff --git a/java/dagger/internal/codegen/SubcomponentBuilderProviderCreationExpression.java b/java/dagger/internal/codegen/SubcomponentBuilderProviderCreationExpression.java
new file mode 100644
index 0000000..90b9cdf
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentBuilderProviderCreationExpression.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.CodeBlocks.anonymousProvider;
+
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import javax.lang.model.type.TypeMirror;
+
+/** A {@link javax.inject.Provider} creation expression for a subcomponent builder.. */
+final class SubcomponentBuilderProviderCreationExpression
+    implements FrameworkInstanceCreationExpression {
+  private final String subcomponentName;
+  private final TypeMirror subcomponentBuilderType;
+
+  SubcomponentBuilderProviderCreationExpression(
+      TypeMirror subcomponentBuilderType, String subcomponentName) {
+    this.subcomponentName = subcomponentName;
+    this.subcomponentBuilderType = subcomponentBuilderType;
+  }
+
+  @Override
+  public CodeBlock creationExpression() {
+    return anonymousProvider(
+        TypeName.get(subcomponentBuilderType),
+        CodeBlock.of("return new $LBuilder();", subcomponentName));
+  }
+}