Make DependencyRequest.Kind a top-level, exposed type (RequestKind) in dagger.model

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=179205348
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index e891f22..c87bfa7 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -83,6 +83,7 @@
         "MultibindingAnnotations.java",
         "OptionalType.java",
         "Optionals.java",
+        "RequestKinds.java",
         "SetType.java",
         "SimpleAnnotationMirror.java",
         "SimpleTypeAnnotationValue.java",
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index 19406fe..45c33cd 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -22,14 +22,15 @@
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.RequestKind;
 
 /** A factory of code expressions used to access a single request for a binding in a component. */
 // TODO(user): Rename this to RequestExpression?
 abstract class BindingExpression {
   private final ResolvedBindings resolvedBindings;
-  private final DependencyRequest.Kind requestKind;
+  private final RequestKind requestKind;
 
-  BindingExpression(ResolvedBindings resolvedBindings, DependencyRequest.Kind requestKind) {
+  BindingExpression(ResolvedBindings resolvedBindings, RequestKind requestKind) {
     this.resolvedBindings = checkNotNull(resolvedBindings);
     this.requestKind = checkNotNull(requestKind);
   }
@@ -39,8 +40,8 @@
     return resolvedBindings.bindingKey();
   }
 
-  /** Returns the {#linkplain DependencyRequest.Kind request kind} handled by this expression. */
-  final DependencyRequest.Kind requestKind() {
+  /** Returns the {@linkplain RequestKind} handled by this expression. */
+  final RequestKind requestKind() {
     return requestKind;
   }
 
diff --git a/java/dagger/internal/codegen/BindingGraph.java b/java/dagger/internal/codegen/BindingGraph.java
index b347f7d..98fc901 100644
--- a/java/dagger/internal/codegen/BindingGraph.java
+++ b/java/dagger/internal/codegen/BindingGraph.java
@@ -52,6 +52,7 @@
 import dagger.internal.codegen.ContributionBinding.Kind;
 import dagger.internal.codegen.Keys.HasKey;
 import dagger.model.Key;
+import dagger.model.RequestKind;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import dagger.releasablereferences.CanReleaseReferences;
@@ -670,7 +671,7 @@
         if (optionalBindingDeclarations.isEmpty()) {
           return Optional.empty();
         }
-        DependencyRequest.Kind kind =
+        RequestKind requestKind =
             DependencyRequest.extractKindAndType(OptionalType.from(key).valueType()).kind();
         ResolvedBindings underlyingKeyBindings =
             lookUpBindings(BindingKey.contribution(keyFactory.unwrapOptional(key).get()));
@@ -678,11 +679,11 @@
           return Optional.of(provisionBindingFactory.syntheticAbsentBinding(key));
         } else if (underlyingKeyBindings.bindingTypes().contains(BindingType.PRODUCTION)
             // handles producerFromProvider cases
-            || kind.equals(DependencyRequest.Kind.PRODUCER)
-            || kind.equals(DependencyRequest.Kind.PRODUCED)) {
-          return Optional.of(productionBindingFactory.syntheticPresentBinding(key, kind));
+            || requestKind.equals(RequestKind.PRODUCER)
+            || requestKind.equals(RequestKind.PRODUCED)) {
+          return Optional.of(productionBindingFactory.syntheticPresentBinding(key, requestKind));
         } else {
-          return Optional.of(provisionBindingFactory.syntheticPresentBinding(key, kind));
+          return Optional.of(provisionBindingFactory.syntheticPresentBinding(key, requestKind));
         }
       }
 
diff --git a/java/dagger/internal/codegen/BindingGraphValidator.java b/java/dagger/internal/codegen/BindingGraphValidator.java
index 142b179..2f47bea 100644
--- a/java/dagger/internal/codegen/BindingGraphValidator.java
+++ b/java/dagger/internal/codegen/BindingGraphValidator.java
@@ -97,6 +97,7 @@
 import dagger.internal.codegen.ComponentRequirement.NullPolicy;
 import dagger.internal.codegen.ContributionType.HasContributionType;
 import dagger.model.Key;
+import dagger.model.RequestKind;
 import dagger.releasablereferences.CanReleaseReferences;
 import dagger.releasablereferences.ForReleasableReferences;
 import dagger.releasablereferences.ReleasableReferenceManager;
@@ -1127,7 +1128,7 @@
         return providers.build();
       }
 
-      private boolean breaksCycle(TypeMirror requestedType, DependencyRequest.Kind requestKind) {
+      private boolean breaksCycle(TypeMirror requestedType, RequestKind requestKind) {
         switch (requestKind) {
           case PROVIDER:
           case LAZY:
diff --git a/java/dagger/internal/codegen/BindingTypeMapper.java b/java/dagger/internal/codegen/BindingTypeMapper.java
index d40881a..326b99e 100644
--- a/java/dagger/internal/codegen/BindingTypeMapper.java
+++ b/java/dagger/internal/codegen/BindingTypeMapper.java
@@ -24,16 +24,17 @@
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
+import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import javax.inject.Provider;
 
 /**
- * A mapper for associating a {@link DependencyRequest.Kind} to a {@link BindingType}, dependent on
- * the type of code to be generated (e.g., for {@link Provider} or {@link Producer}).
+ * A mapper for associating a {@link RequestKind} to a {@link BindingType}, dependent on the type of
+ * code to be generated (e.g., for {@link Provider} or {@link Producer}).
  */
 enum BindingTypeMapper {
   FOR_PROVIDER() {
-    @Override public BindingType getBindingType(DependencyRequest.Kind requestKind) {
+    @Override public BindingType getBindingType(RequestKind requestKind) {
       switch (requestKind) {
         case INSTANCE:
         case PROVIDER:
@@ -51,7 +52,7 @@
     }
   },
   FOR_PRODUCER() {
-    @Override public BindingType getBindingType(DependencyRequest.Kind requestKind) {
+    @Override public BindingType getBindingType(RequestKind requestKind) {
       switch (requestKind) {
         case INSTANCE:
         case PRODUCED:
@@ -73,7 +74,7 @@
     return bindingType.equals(PRODUCTION) ? FOR_PRODUCER : FOR_PROVIDER;
   }
 
-  abstract BindingType getBindingType(DependencyRequest.Kind requestKind);
+  abstract BindingType getBindingType(RequestKind requestKind);
 
   /**
    * Returns the {@link BindingType} to use for a collection of requests of the same
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 6ada054..bd6db68 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -32,6 +32,7 @@
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.RequestKind;
 import java.util.EnumSet;
 import java.util.Optional;
 import javax.lang.model.type.TypeMirror;
@@ -48,7 +49,7 @@
   private final BindingGraph graph;
   private final DaggerTypes types;
   private final BindingExpressionFactory bindingExpressionFactory;
-  private final Table<BindingKey, DependencyRequest.Kind, BindingExpression> expressions =
+  private final Table<BindingKey, RequestKind, BindingExpression> expressions =
       HashBasedTable.create();
 
   ComponentBindingExpressions(
@@ -130,7 +131,7 @@
    *     request
    */
   Expression getDependencyExpression(
-      BindingKey bindingKey, DependencyRequest.Kind requestKind, ClassName requestingClass) {
+      BindingKey bindingKey, RequestKind requestKind, ClassName requestingClass) {
     return getBindingExpression(bindingKey, requestKind).getDependencyExpression(requestingClass);
   }
 
@@ -202,7 +203,7 @@
   }
 
   private BindingExpression getBindingExpression(
-      BindingKey bindingKey, DependencyRequest.Kind requestKind) {
+      BindingKey bindingKey, RequestKind requestKind) {
     if (graph.resolvedBindings().containsKey(bindingKey)
         && !graph.resolvedBindings().get(bindingKey).ownedBindings().isEmpty()) {
       if (!expressions.contains(bindingKey, requestKind)) {
@@ -265,7 +266,7 @@
     }
 
     /** Creates a binding expression. */
-    BindingExpression create(BindingKey bindingKey, DependencyRequest.Kind requestKind) {
+    BindingExpression create(BindingKey bindingKey, RequestKind requestKind) {
       ResolvedBindings resolvedBindings = graph.resolvedBindings().get(bindingKey);
       switch (resolvedBindings.bindingType()) {
         case MEMBERS_INJECTION:
@@ -284,7 +285,7 @@
 
     /** Returns a binding expression for a members injection binding. */
     private MembersInjectionBindingExpression membersInjectionBindingExpression(
-        ResolvedBindings resolvedBindings, DependencyRequest.Kind requestKind) {
+        ResolvedBindings resolvedBindings, RequestKind requestKind) {
       return new MembersInjectionBindingExpression(
           frameworkInstanceBindingExpression(resolvedBindings, requestKind),
           generatedComponentModel,
@@ -297,7 +298,7 @@
      * dagger.MembersInjector} for members injection bindings.
      */
     private FrameworkInstanceBindingExpression frameworkInstanceBindingExpression(
-        ResolvedBindings resolvedBindings, DependencyRequest.Kind requestKind) {
+        ResolvedBindings resolvedBindings, RequestKind requestKind) {
       Optional<MemberSelect> staticMethod = staticMemberSelect(resolvedBindings);
       return new FrameworkInstanceBindingExpression(
           resolvedBindings,
@@ -342,9 +343,9 @@
 
     /** Returns a binding expression for a provision binding. */
     private BindingExpression provisionBindingExpression(
-        ResolvedBindings resolvedBindings, DependencyRequest.Kind requestKind) {
+        ResolvedBindings resolvedBindings, RequestKind requestKind) {
       FrameworkInstanceBindingExpression frameworkInstanceBindingExpression =
-          requestKind.equals(DependencyRequest.Kind.PRODUCER)
+          requestKind.equals(RequestKind.PRODUCER)
               ? producerFromProviderInstanceBindingExpression(resolvedBindings, requestKind)
               : frameworkInstanceBindingExpression(resolvedBindings, requestKind);
 
@@ -370,7 +371,7 @@
      * provision binding.
      */
     private FrameworkInstanceBindingExpression producerFromProviderInstanceBindingExpression(
-        ResolvedBindings resolvedBindings, DependencyRequest.Kind requestKind) {
+        ResolvedBindings resolvedBindings, RequestKind requestKind) {
       checkArgument(resolvedBindings.bindingType().frameworkType().equals(FrameworkType.PROVIDER));
       return new FrameworkInstanceBindingExpression(
           resolvedBindings,
diff --git a/java/dagger/internal/codegen/ComponentProcessor.java b/java/dagger/internal/codegen/ComponentProcessor.java
index a078f1b..a7d680f 100644
--- a/java/dagger/internal/codegen/ComponentProcessor.java
+++ b/java/dagger/internal/codegen/ComponentProcessor.java
@@ -92,8 +92,7 @@
     MethodSignatureFormatter methodSignatureFormatter = new MethodSignatureFormatter(types);
     BindingDeclarationFormatter bindingDeclarationFormatter =
         new BindingDeclarationFormatter(methodSignatureFormatter);
-    DependencyRequestFormatter dependencyRequestFormatter =
-        new DependencyRequestFormatter(types, elements);
+    DependencyRequestFormatter dependencyRequestFormatter = new DependencyRequestFormatter(types);
 
     KeyFactory keyFactory = new KeyFactory(types, elements);
 
diff --git a/java/dagger/internal/codegen/DelegateBindingExpression.java b/java/dagger/internal/codegen/DelegateBindingExpression.java
index b3bff7b..163d5a3 100644
--- a/java/dagger/internal/codegen/DelegateBindingExpression.java
+++ b/java/dagger/internal/codegen/DelegateBindingExpression.java
@@ -19,9 +19,11 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.RequestKinds.requestType;
 import static dagger.internal.codegen.Scope.reusableScope;
 
 import com.squareup.javapoet.ClassName;
+import dagger.model.RequestKind;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
 
@@ -34,7 +36,7 @@
 
   private DelegateBindingExpression(
       ResolvedBindings resolvedBindings,
-      DependencyRequest.Kind requestKind,
+      RequestKind requestKind,
       ComponentBindingExpressions componentBindingExpressions,
       DaggerTypes types,
       Elements elements) {
@@ -61,7 +63,7 @@
     ScopeKind bindsScope = ScopeKind.get(binding, graph, elements);
     ScopeKind delegateScope = ScopeKind.get(delegateBinding, graph, elements);
     if (bindsScope.isSimilarOrWeakerScopeThan(delegateScope)) {
-      DependencyRequest.Kind requestKind = bindingExpression.requestKind();
+      RequestKind requestKind = bindingExpression.requestKind();
       return new DelegateBindingExpression(
           resolvedBindings, requestKind, componentBindingExpressions, types, elements);
     }
@@ -82,7 +84,7 @@
             : delegateExpression;
       default:
         return castToRawTypeIfNecessary(
-            delegateExpression, requestKind().type(contributedType, types));
+            delegateExpression, requestType(requestKind(), contributedType, types));
     }
   }
 
diff --git a/java/dagger/internal/codegen/DependencyRequest.java b/java/dagger/internal/codegen/DependencyRequest.java
index 8da1343..2f69eb2 100644
--- a/java/dagger/internal/codegen/DependencyRequest.java
+++ b/java/dagger/internal/codegen/DependencyRequest.java
@@ -25,12 +25,14 @@
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
 import static dagger.internal.codegen.Optionals.firstPresent;
-import static dagger.internal.codegen.TypeNames.lazyOf;
-import static dagger.internal.codegen.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.TypeNames.membersInjectorOf;
-import static dagger.internal.codegen.TypeNames.producedOf;
-import static dagger.internal.codegen.TypeNames.producerOf;
-import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.internal.codegen.RequestKinds.frameworkClass;
+import static dagger.model.RequestKind.FUTURE;
+import static dagger.model.RequestKind.INSTANCE;
+import static dagger.model.RequestKind.LAZY;
+import static dagger.model.RequestKind.MEMBERS_INJECTOR;
+import static dagger.model.RequestKind.PRODUCER;
+import static dagger.model.RequestKind.PROVIDER;
+import static dagger.model.RequestKind.PROVIDER_OF_LAZY;
 
 import com.google.auto.common.MoreTypes;
 import com.google.auto.value.AutoValue;
@@ -39,13 +41,11 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.CheckReturnValue;
-import com.squareup.javapoet.TypeName;
 import dagger.Lazy;
 import dagger.MembersInjector;
 import dagger.Provides;
 import dagger.model.Key;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
+import dagger.model.RequestKind;
 import java.util.List;
 import java.util.Optional;
 import javax.inject.Inject;
@@ -71,117 +71,7 @@
 // TODO(gak): Set bindings and the permutations thereof need to be addressed
 @AutoValue
 abstract class DependencyRequest {
-
-  enum Kind {
-    /** A default request for an instance.  E.g.: {@code Blah} */
-    INSTANCE,
-
-    /** A request for a {@link Provider}.  E.g.: {@code Provider<Blah>} */
-    PROVIDER(Provider.class),
-
-    /** A request for a {@link Lazy}.  E.g.: {@code Lazy<Blah>} */
-    LAZY(Lazy.class),
-
-    /** A request for a {@link Provider} of a {@link Lazy}. E.g.: {@code Provider<Lazy<Blah>>} */
-    PROVIDER_OF_LAZY,
-
-    /** A request for a {@link MembersInjector}.  E.g.: {@code MembersInjector<Blah>} */
-    MEMBERS_INJECTOR(MembersInjector.class),
-
-    /** A request for a {@link Producer}.  E.g.: {@code Producer<Blah>} */
-    PRODUCER(Producer.class),
-
-    /** A request for a {@link Produced}.  E.g.: {@code Produced<Blah>} */
-    PRODUCED(Produced.class),
-
-    /**
-     * A request for a {@link ListenableFuture}.  E.g.: {@code ListenableFuture<Blah>}.
-     * These can only be requested by component interfaces.
-     */
-    FUTURE,
-    ;
-
-    final Optional<Class<?>> frameworkClass;
-
-    Kind(Class<?> frameworkClass) {
-      this.frameworkClass = Optional.<Class<?>>of(frameworkClass);
-    }
-
-    Kind() {
-      this.frameworkClass = Optional.empty();
-    }
-
-    /**
-     * If {@code type}'s raw type is {@link #frameworkClass}, returns a {@link KindAndType} with
-     * this kind that represents the dependency request.
-     */
-    Optional<KindAndType> from(TypeMirror type) {
-      if (frameworkClass.isPresent() && isType(type) && isTypeOf(frameworkClass.get(), type)) {
-        List<? extends TypeMirror> typeArguments = asDeclared(type).getTypeArguments();
-        if (typeArguments.isEmpty()) {
-          return Optional.empty();
-        }
-        return Optional.of(this.ofType(getOnlyElement(typeArguments)));
-      }
-      return Optional.empty();
-    }
-
-    /** Returns a {@link KindAndType} with this kind and {@code type} type. */
-    KindAndType ofType(TypeMirror type) {
-      return new AutoValue_DependencyRequest_KindAndType(this, type);
-    }
-
-    /** Returns the type of a request of this kind for a key with a given type. */
-    TypeName typeName(TypeName keyType) {
-      switch (this) {
-        case INSTANCE:
-          return keyType;
-
-        case PROVIDER:
-          return providerOf(keyType);
-
-        case LAZY:
-          return lazyOf(keyType);
-
-        case PROVIDER_OF_LAZY:
-          return providerOf(lazyOf(keyType));
-
-        case PRODUCER:
-          return producerOf(keyType);
-
-        case PRODUCED:
-          return producedOf(keyType);
-
-        case FUTURE:
-          return listenableFutureOf(keyType);
-
-        case MEMBERS_INJECTOR:
-          return membersInjectorOf(keyType);
-
-        default:
-          throw new AssertionError(this);
-      }
-    }
-
-    /** Returns the type of a request of this kind for the given {@code type}. */
-    TypeMirror type(TypeMirror type, DaggerTypes types) {
-      switch (this) {
-        case INSTANCE:
-          return type;
-
-        case PROVIDER_OF_LAZY:
-          return types.wrapType(LAZY.type(type, types), Provider.class);
-
-        case FUTURE:
-          return types.wrapType(type, ListenableFuture.class);
-
-        default:
-          return types.wrapType(type, frameworkClass.get());
-      }
-    }
-  }
-
-  abstract Kind kind();
+  abstract RequestKind kind();
   abstract Key key();
 
   BindingKey bindingKey() {
@@ -230,8 +120,8 @@
 
   /**
    * Extracts the dependency request type and kind from the type of a dependency request element.
-   * For example, if a user requests {@code Provider<Foo>}, this will return ({@link Kind#PROVIDER},
-   * {@code Foo}).
+   * For example, if a user requests {@code Provider<Foo>}, this will return ({@link
+   * RequestKind#PROVIDER}, {@code Foo}).
    *
    * @throws TypeNotPresentException if {@code type}'s kind is {@link TypeKind#ERROR}, which may
    *     mean that the type will be generated in a later round of processing
@@ -256,21 +146,32 @@
 
           @Override
           protected KindAndType defaultAction(TypeMirror otherType, Void p) {
-            return Kind.INSTANCE.ofType(otherType);
+            return new KindAndType(INSTANCE, otherType);
           }
         },
         null);
   }
 
-  @AutoValue
-  abstract static class KindAndType {
-    abstract Kind kind();
+  static final class KindAndType {
+    private final RequestKind kind;
+    private final TypeMirror type;
 
-    abstract TypeMirror type();
+    KindAndType(RequestKind kind, TypeMirror type) {
+      this.kind = checkNotNull(kind);
+      this.type = checkNotNull(type);
+    }
+
+    RequestKind kind() {
+      return kind;
+    }
+
+    TypeMirror type() {
+      return type;
+    }
 
     static Optional<KindAndType> from(TypeMirror type) {
-      for (Kind kind : Kind.values()) {
-        Optional<KindAndType> kindAndType = kind.from(type);
+      for (RequestKind kind : RequestKind.values()) {
+        Optional<KindAndType> kindAndType = from(kind, type);
         if (kindAndType.isPresent()) {
           return firstPresent(kindAndType.get().maybeProviderOfLazy(), kindAndType);
         }
@@ -279,14 +180,32 @@
     }
 
     /**
-     * If {@code kindAndType} represents a {@link Kind#PROVIDER} of a {@code Lazy<T>} for some type
-     * {@code T}, then this method returns ({@link Kind#PROVIDER_OF_LAZY}, {@code T}).
+     * If {@code type}'s raw type is {@link RequestKinds#frameworkClass framework class}, returns a
+     * {@link KindAndType} with this kind that represents the dependency request.
+     */
+    private static Optional<KindAndType> from(RequestKind kind, TypeMirror type) {
+      Optional<Class<?>> frameworkClass = frameworkClass(kind);
+      if (frameworkClass.isPresent() && isType(type) && isTypeOf(frameworkClass.get(), type)) {
+        List<? extends TypeMirror> typeArguments = asDeclared(type).getTypeArguments();
+        if (typeArguments.isEmpty()) {
+          return Optional.empty();
+        }
+        return Optional.of(new KindAndType(kind, getOnlyElement(typeArguments)));
+      }
+      return Optional.empty();
+    }
+
+    /**
+     * If {@code kindAndType} represents a {@link RequestKind#PROVIDER} of a {@code Lazy<T>} for
+     * some type {@code T}, then this method returns ({@link RequestKind#PROVIDER_OF_LAZY}, {@code
+     * T}).
      */
     private Optional<KindAndType> maybeProviderOfLazy() {
-      if (kind().equals(Kind.PROVIDER)) {
+      if (kind().equals(PROVIDER)) {
         Optional<KindAndType> providedKindAndType = from(type());
-        if (providedKindAndType.isPresent() && providedKindAndType.get().kind().equals(Kind.LAZY)) {
-          return Optional.of(Kind.PROVIDER_OF_LAZY.ofType(providedKindAndType.get().type()));
+        if (providedKindAndType.isPresent()
+            && providedKindAndType.get().kind().equals(LAZY)) {
+          return Optional.of(new KindAndType(PROVIDER_OF_LAZY, providedKindAndType.get().type()));
         }
       }
       return Optional.empty();
@@ -296,7 +215,7 @@
   @CanIgnoreReturnValue
   @AutoValue.Builder
   abstract static class Builder {
-    abstract Builder kind(Kind kind);
+    abstract Builder kind(RequestKind kind);
 
     abstract Builder key(Key key);
 
@@ -342,23 +261,12 @@
      */
     DependencyRequest providerForImplicitMapBinding(Key mapOfFactoryKey) {
       return DependencyRequest.builder()
-          .kind(Kind.PROVIDER)
+          .kind(PROVIDER)
           .key(mapOfFactoryKey)
           .build();
     }
 
     /**
-     * Creates a implicit {@link DependencyRequest} for a {@link Producer} of {@code
-     * mapOfFactoryKey}.
-     *
-     * @param mapOfFactoryKey a key equivalent to {@code mapOfValueRequest}'s key, whose type is
-     *     {@code Map<K, Provider<V>>} or {@code Map<K, Producer<V>>}
-     */
-    DependencyRequest producerForImplicitMapBinding(Key mapOfFactoryKey) {
-      return DependencyRequest.builder().kind(Kind.PRODUCER).key(mapOfFactoryKey).build();
-    }
-
-    /**
      * Creates synthetic dependency requests for each individual multibinding contribution in {@code
      * multibindingContributions}.
      */
@@ -387,23 +295,23 @@
     }
 
     // TODO(b/28555349): support PROVIDER_OF_LAZY here too
-    private static final ImmutableSet<Kind> WRAPPING_MAP_VALUE_FRAMEWORK_TYPES =
-        ImmutableSet.of(Kind.PROVIDER, Kind.PRODUCER);
+    private static final ImmutableSet<RequestKind> WRAPPING_MAP_VALUE_FRAMEWORK_TYPES =
+        ImmutableSet.of(PROVIDER, PRODUCER);
 
-    private Kind multibindingContributionRequestKind(
+    private RequestKind multibindingContributionRequestKind(
         Key multibindingKey, ContributionBinding multibindingContribution) {
       switch (multibindingContribution.contributionType()) {
         case MAP:
           MapType mapType = MapType.from(multibindingKey);
-          for (Kind kind : WRAPPING_MAP_VALUE_FRAMEWORK_TYPES) {
-            if (mapType.valuesAreTypeOf(kind.frameworkClass.get())) {
+          for (RequestKind kind : WRAPPING_MAP_VALUE_FRAMEWORK_TYPES) {
+            if (mapType.valuesAreTypeOf(frameworkClass(kind).get())) {
               return kind;
             }
           }
           // fall through
         case SET:
         case SET_VALUES:
-          return Kind.INSTANCE;
+          return INSTANCE;
         case UNIQUE:
           throw new IllegalArgumentException(
               "multibindingContribution must be a multibinding: " + multibindingContribution);
@@ -456,7 +364,7 @@
       // special-case it here.
       if (isTypeOf(ListenableFuture.class, type)) {
         return DependencyRequest.builder()
-            .kind(Kind.FUTURE)
+            .kind(FUTURE)
             .key(keyFactory.forQualifiedType(
                 qualifier, Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())))
             .requestElement(productionMethod)
@@ -479,7 +387,7 @@
               ? getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments())
               : getOnlyElement(membersInjectionMethodType.getParameterTypes());
       return DependencyRequest.builder()
-          .kind(Kind.MEMBERS_INJECTOR)
+          .kind(MEMBERS_INJECTOR)
           .key(keyFactory.forMembersInjectedType(membersInjectedType))
           .requestElement(membersInjectionMethod)
           .build();
@@ -488,7 +396,7 @@
     DependencyRequest forProductionImplementationExecutor() {
       Key key = keyFactory.forProductionImplementationExecutor();
       return DependencyRequest.builder()
-          .kind(Kind.PROVIDER)
+          .kind(PROVIDER)
           .key(key)
           .requestElement(MoreTypes.asElement(key.type()))
           .build();
@@ -497,7 +405,7 @@
     DependencyRequest forProductionComponentMonitor() {
       Key key = keyFactory.forProductionComponentMonitor();
       return DependencyRequest.builder()
-          .kind(Kind.PROVIDER)
+          .kind(PROVIDER)
           .key(key)
           .requestElement(MoreTypes.asElement(key.type()))
           .overriddenVariableName(Optional.of("monitor"))
@@ -508,7 +416,7 @@
      * Returns a synthetic request for the present value of an optional binding generated from a
      * {@link dagger.BindsOptionalOf} declaration.
      */
-    DependencyRequest forSyntheticPresentOptionalBinding(Key requestKey, Kind kind) {
+    DependencyRequest forSyntheticPresentOptionalBinding(Key requestKey, RequestKind kind) {
       Optional<Key> key = keyFactory.unwrapOptional(requestKey);
       checkArgument(key.isPresent(), "not a request for optional: %s", requestKey);
       return builder()
@@ -527,7 +435,7 @@
         Optional<AnnotationMirror> qualifier,
         Optional<String> name) {
       KindAndType kindAndType = extractKindAndType(type);
-      if (kindAndType.kind().equals(Kind.MEMBERS_INJECTOR)) {
+      if (kindAndType.kind().equals(MEMBERS_INJECTOR)) {
         checkArgument(!qualifier.isPresent());
       }
       return DependencyRequest.builder()
@@ -540,14 +448,14 @@
     }
 
     /**
-     * Returns {@code true} if a given request element allows null values. {@link Kind#INSTANCE}
-     * requests must be annotated with {@code @Nullable} in order to allow null values. All other
-     * request kinds implicitly allow null values because they are are wrapped inside {@link
-     * Provider}, {@link Lazy}, etc.
+     * Returns {@code true} if a given request element allows null values. {@link
+     * RequestKind#INSTANCE} requests must be annotated with {@code @Nullable} in order to allow
+     * null values. All other request kinds implicitly allow null values because they are are
+     * wrapped inside {@link Provider}, {@link Lazy}, etc.
      */
     // TODO(sameb): should Produced/Producer always require non-nullable?
-    private boolean allowsNull(Kind kind, Optional<DeclaredType> nullableType) {
-      return kind.equals(Kind.INSTANCE) ? nullableType.isPresent() : true;
+    private boolean allowsNull(RequestKind kind, Optional<DeclaredType> nullableType) {
+      return kind.equals(INSTANCE) ? nullableType.isPresent() : true;
     }
   }
 }
diff --git a/java/dagger/internal/codegen/DependencyRequestFormatter.java b/java/dagger/internal/codegen/DependencyRequestFormatter.java
index 13a5a3d..f181dc8 100644
--- a/java/dagger/internal/codegen/DependencyRequestFormatter.java
+++ b/java/dagger/internal/codegen/DependencyRequestFormatter.java
@@ -20,13 +20,12 @@
 import static dagger.internal.codegen.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.ErrorMessages.DOUBLE_INDENT;
 import static dagger.internal.codegen.ErrorMessages.INDENT;
+import static dagger.internal.codegen.RequestKinds.requestType;
 
 import com.google.auto.common.MoreElements;
 import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.Lazy;
 import dagger.Provides;
 import dagger.internal.codegen.ComponentTreeTraverser.DependencyTrace;
 import dagger.model.Key;
@@ -35,17 +34,13 @@
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.inject.Inject;
-import javax.inject.Provider;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.ElementKindVisitor7;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
 
 /**
  * Formats a {@link DependencyRequest} into a {@link String} suitable for an error message listing
@@ -71,12 +66,10 @@
  */
 final class DependencyRequestFormatter extends Formatter<DependencyRequest> {
 
-  private final Types types;
-  private final Elements elements;
+  private final DaggerTypes types;
 
-  DependencyRequestFormatter(Types types, Elements elements) {
+  DependencyRequestFormatter(DaggerTypes types) {
     this.types = types;
-    this.elements = elements;
   }
 
   /** Returns a representation of the dependency trace, with the entry point at the bottom. */
@@ -184,36 +177,14 @@
   @CanIgnoreReturnValue
   private StringBuilder appendRequestedTypeIsInjectedAt(
       StringBuilder builder, DependencyRequest request) {
+    TypeMirror requestedType = requestType(request.kind(), request.key().type(), types);
     return builder
         .append(INDENT)
-        .append(formatKey(request.key().qualifier(), requestedType(request)))
+        .append(formatKey(request.key().qualifier(), requestedType))
         .append(" is injected at\n")
         .append(DOUBLE_INDENT);
   }
 
-  private TypeMirror requestedType(DependencyRequest request) {
-    TypeMirror keyType = request.key().type();
-    switch (request.kind()) {
-      case FUTURE:
-        return wrapType(ListenableFuture.class, keyType);
-
-      case PROVIDER_OF_LAZY:
-        return wrapType(Provider.class, wrapType(Lazy.class, keyType));
-
-      default:
-        if (request.kind().frameworkClass.isPresent()) {
-          return wrapType(request.kind().frameworkClass.get(), keyType);
-        } else {
-          return keyType;
-        }
-    }
-  }
-
-  private DeclaredType wrapType(Class<?> wrapperType, TypeMirror wrappedType) {
-    return types.getDeclaredType(
-        elements.getTypeElement(wrapperType.getCanonicalName()), wrappedType);
-  }
-
   private String formatKey(Key key) {
     return formatKey(key.qualifier(), key.type());
   }
diff --git a/java/dagger/internal/codegen/FrameworkDependency.java b/java/dagger/internal/codegen/FrameworkDependency.java
index f5efe77..00a9bed 100644
--- a/java/dagger/internal/codegen/FrameworkDependency.java
+++ b/java/dagger/internal/codegen/FrameworkDependency.java
@@ -17,6 +17,7 @@
 package dagger.internal.codegen;
 
 import com.google.auto.value.AutoValue;
+import dagger.model.RequestKind;
 import javax.inject.Provider;
 
 /**
@@ -52,16 +53,16 @@
   abstract BindingType bindingType();
 
   /** The dependency request kind that is equivalent to requesting the framework dependency. */
-  DependencyRequest.Kind dependencyRequestKind() {
+  RequestKind dependencyRequestKind() {
     switch (bindingType()) {
       case PROVISION:
-        return DependencyRequest.Kind.PROVIDER;
+        return RequestKind.PROVIDER;
 
       case PRODUCTION:
-        return DependencyRequest.Kind.PRODUCER;
+        return RequestKind.PRODUCER;
 
       case MEMBERS_INJECTION:
-        return DependencyRequest.Kind.MEMBERS_INJECTOR;
+        return RequestKind.MEMBERS_INJECTOR;
 
       default:
         throw new AssertionError(bindingType());
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
index 7e4ed31..c5f9fc3 100644
--- a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -23,6 +23,7 @@
 import com.squareup.javapoet.FieldSpec;
 import dagger.internal.codegen.MemberSelect.MemberSelectSupplier;
 import dagger.model.Key;
+import dagger.model.RequestKind;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
@@ -37,7 +38,7 @@
 
   FrameworkInstanceBindingExpression(
       ResolvedBindings resolvedBindings,
-      DependencyRequest.Kind requestKind,
+      RequestKind requestKind,
       ComponentBindingExpressions componentBindingExpressions,
       FrameworkType frameworkType,
       MemberSelectSupplier frameworkFieldSupplier,
@@ -69,9 +70,9 @@
       return Expression.create(expressionType, memberSelect.getExpressionFor(requestingClass));
     }
 
-    // The following expressions form a composite with the expression for the framework type.
-    // For example, the expression for a DependencyRequest.Kind.LAZY is a composite of the
-    // expression for a DependencyRequest.Kind.PROVIDER (the framework type):
+    // The following expressions form a composite with the expression for the framework type. For
+    // example, the expression for RequestKind.LAZY is a composite of the expression for a
+    // RequestKind.PROVIDER (the framework type):
     //    lazyExpression = DoubleCheck.lazy(providerExpression);
     return frameworkType.to(
         requestKind(),
@@ -81,14 +82,14 @@
   }
 
   /** Returns the request kind that matches the framework type. */
-  private DependencyRequest.Kind frameworkRequestKind() {
+  private RequestKind frameworkRequestKind() {
     switch (frameworkType) {
       case PROVIDER:
-        return DependencyRequest.Kind.PROVIDER;
+        return RequestKind.PROVIDER;
       case PRODUCER:
-        return DependencyRequest.Kind.PRODUCER;
+        return RequestKind.PRODUCER;
       case MEMBERS_INJECTOR:
-        return DependencyRequest.Kind.MEMBERS_INJECTOR;
+        return RequestKind.MEMBERS_INJECTOR;
       default:
         throw new AssertionError();
     }
diff --git a/java/dagger/internal/codegen/FrameworkType.java b/java/dagger/internal/codegen/FrameworkType.java
index 31baa12..f8b78ab 100644
--- a/java/dagger/internal/codegen/FrameworkType.java
+++ b/java/dagger/internal/codegen/FrameworkType.java
@@ -18,7 +18,8 @@
 
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
-import static dagger.internal.codegen.DependencyRequest.Kind.INSTANCE;
+import static dagger.internal.codegen.RequestKinds.frameworkClass;
+import static dagger.model.RequestKind.INSTANCE;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -27,6 +28,7 @@
 import dagger.MembersInjector;
 import dagger.internal.DoubleCheck;
 import dagger.internal.ProviderOfLazy;
+import dagger.model.RequestKind;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import dagger.producers.internal.Producers;
@@ -38,7 +40,7 @@
   /** A {@link Provider}. */
   PROVIDER {
     @Override
-    CodeBlock to(DependencyRequest.Kind requestKind, CodeBlock from) {
+    CodeBlock to(RequestKind requestKind, CodeBlock from) {
       switch (requestKind) {
         case INSTANCE:
           return CodeBlock.of("$L.get()", from);
@@ -68,7 +70,7 @@
     }
 
     @Override
-    Expression to(DependencyRequest.Kind requestKind, Expression from, DaggerTypes types) {
+    Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
       CodeBlock codeBlock = to(requestKind, from.codeBlock());
       switch (requestKind) {
         case INSTANCE:
@@ -87,7 +89,7 @@
 
         default:
           return Expression.create(
-              types.rewrapType(from.type(), requestKind.frameworkClass.get()), codeBlock);
+              types.rewrapType(from.type(), frameworkClass(requestKind).get()), codeBlock);
       }
     }
   },
@@ -95,7 +97,7 @@
   /** A {@link Producer}. */
   PRODUCER {
     @Override
-    CodeBlock to(DependencyRequest.Kind requestKind, CodeBlock from) {
+    CodeBlock to(RequestKind requestKind, CodeBlock from) {
       switch (requestKind) {
         case FUTURE:
           return CodeBlock.of("$L.get()", from);
@@ -110,7 +112,7 @@
     }
 
     @Override
-    Expression to(DependencyRequest.Kind requestKind, Expression from, DaggerTypes types) {
+    Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
       switch (requestKind) {
         case FUTURE:
           return Expression.create(
@@ -130,7 +132,7 @@
   /** A {@link MembersInjector}. */
   MEMBERS_INJECTOR {
     @Override
-    CodeBlock to(DependencyRequest.Kind requestKind, CodeBlock from) {
+    CodeBlock to(RequestKind requestKind, CodeBlock from) {
       switch (requestKind) {
         case MEMBERS_INJECTOR:
           return from;
@@ -142,7 +144,7 @@
     }
 
     @Override
-    Expression to(DependencyRequest.Kind requestKind, Expression from, DaggerTypes types) {
+    Expression to(RequestKind requestKind, Expression from, DaggerTypes types) {
       switch (requestKind) {
         case MEMBERS_INJECTOR:
           return from;
@@ -165,7 +167,7 @@
    * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
    *     requestKind}
    */
-  abstract CodeBlock to(DependencyRequest.Kind requestKind, CodeBlock from);
+  abstract CodeBlock to(RequestKind requestKind, CodeBlock from);
 
   /**
    * Returns an {@link Expression} that evaluates to a requested object given an expression that
@@ -177,7 +179,7 @@
    * @throws IllegalArgumentException if a valid expression cannot be generated for {@code
    *     requestKind}
    */
-  abstract Expression to(DependencyRequest.Kind requestKind, Expression from, DaggerTypes types);
+  abstract Expression to(RequestKind requestKind, Expression from, DaggerTypes types);
 
   @Override
   public String toString() {
diff --git a/java/dagger/internal/codegen/InjectionMethods.java b/java/dagger/internal/codegen/InjectionMethods.java
index cc0fe85..16e0a1b 100644
--- a/java/dagger/internal/codegen/InjectionMethods.java
+++ b/java/dagger/internal/codegen/InjectionMethods.java
@@ -28,6 +28,7 @@
 import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
 import static dagger.internal.codegen.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.FactoryGenerator.checkNotNullProvidesMethod;
+import static dagger.internal.codegen.RequestKinds.requestTypeName;
 import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
 import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
 import static dagger.internal.codegen.TypeNames.rawTypeName;
@@ -45,8 +46,8 @@
 import com.squareup.javapoet.ParameterSpec;
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.codegen.DependencyRequest.Kind;
 import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
+import dagger.model.RequestKind;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -364,7 +365,7 @@
     CodeBlock.Builder codeBlock = CodeBlock.builder();
     if (!isRawTypeAccessible(keyType, generatedTypeName.packageName())
         && isTypeAccessibleFrom(keyType, generatedTypeName.packageName())) {
-      if (!dependency.kind().equals(Kind.INSTANCE)) {
+      if (!dependency.kind().equals(RequestKind.INSTANCE)) {
         TypeName usageTypeName = accessibleType(dependency);
         codeBlock.add("($T) ($T)", usageTypeName, rawTypeName(usageTypeName));
       } else if (dependency.requestElement().get().asType().getKind().equals(TypeKind.TYPEVAR)) {
@@ -379,7 +380,7 @@
    * {@link Object}.
    */
   private static TypeName accessibleType(DependencyRequest dependency) {
-    TypeName typeName = dependency.kind().typeName(accessibleType(dependency.key().type()));
+    TypeName typeName = requestTypeName(dependency.kind(), accessibleType(dependency.key().type()));
     return dependency.requestsPrimitiveType() ? typeName.unbox() : typeName;
   }
 
diff --git a/java/dagger/internal/codegen/MembersInjectionBindingExpression.java b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
index adaf973..d662a71 100644
--- a/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
+++ b/java/dagger/internal/codegen/MembersInjectionBindingExpression.java
@@ -24,6 +24,7 @@
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.ParameterSpec;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.RequestKind;
 import java.util.List;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.VariableElement;
@@ -41,7 +42,7 @@
       MembersInjectionMethods membersInjectionMethods) {
     super(membersInjectorExpression.resolvedBindings(), membersInjectorExpression.requestKind());
     checkArgument(bindingKey().kind().equals(BindingKey.Kind.MEMBERS_INJECTION));
-    checkArgument(requestKind().equals(DependencyRequest.Kind.MEMBERS_INJECTOR));
+    checkArgument(requestKind().equals(RequestKind.MEMBERS_INJECTOR));
     this.membersInjectorExpression = membersInjectorExpression;
     this.generatedComponentModel = generatedComponentModel;
     this.binding = resolvedBindings().membersInjectionBinding().get();
diff --git a/java/dagger/internal/codegen/OptionalBindingExpression.java b/java/dagger/internal/codegen/OptionalBindingExpression.java
index 32b65e6..2316e65 100644
--- a/java/dagger/internal/codegen/OptionalBindingExpression.java
+++ b/java/dagger/internal/codegen/OptionalBindingExpression.java
@@ -22,6 +22,7 @@
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.model.RequestKind;
 import javax.lang.model.util.Types;
 
 /** A binding expression for optional bindings. */
@@ -48,7 +49,7 @@
     if (binding.dependencies().isEmpty()) {
       // When compiling with -source 7, javac's type inference isn't strong enough to detect
       // Futures.immediateFuture(Optional.absent()) for keys that aren't Object
-      if (requestKind().equals(DependencyRequest.Kind.FUTURE)
+      if (requestKind().equals(RequestKind.FUTURE)
           && isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
         return Expression.create(
             binding.key().type(),
diff --git a/java/dagger/internal/codegen/OptionalFactories.java b/java/dagger/internal/codegen/OptionalFactories.java
index cad53d9..1406677 100644
--- a/java/dagger/internal/codegen/OptionalFactories.java
+++ b/java/dagger/internal/codegen/OptionalFactories.java
@@ -28,6 +28,7 @@
 import static dagger.internal.codegen.GeneratedComponentModel.FieldSpecKind.ABSENT_OPTIONAL_FIELD;
 import static dagger.internal.codegen.GeneratedComponentModel.MethodSpecKind.ABSENT_OPTIONAL_METHOD;
 import static dagger.internal.codegen.GeneratedComponentModel.TypeSpecKind.PRESENT_FACTORY;
+import static dagger.internal.codegen.RequestKinds.requestTypeName;
 import static dagger.internal.codegen.TypeNames.PROVIDER;
 import static dagger.internal.codegen.TypeNames.listenableFutureOf;
 import static dagger.internal.codegen.TypeNames.providerOf;
@@ -53,6 +54,7 @@
 import dagger.internal.InstanceFactory;
 import dagger.internal.Preconditions;
 import dagger.internal.codegen.OptionalType.OptionalKind;
+import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import dagger.producers.internal.Producers;
 import java.util.Comparator;
@@ -157,7 +159,7 @@
     abstract OptionalKind optionalKind();
 
     /** The kind of request satisfied by the value of the {@code Optional}. */
-    abstract DependencyRequest.Kind valueKind();
+    abstract RequestKind valueKind();
 
     /** The type variable for the factory class. */
     TypeVariableName typeVariable() {
@@ -166,7 +168,7 @@
 
     /** The type contained by the {@code Optional}. */
     TypeName valueType() {
-      return valueKind().typeName(typeVariable());
+      return requestTypeName(valueKind(), typeVariable());
     }
 
     /** The type provided or produced by the factory. */
@@ -200,25 +202,25 @@
           getOnlyElement(binding.dependencies()).kind());
     }
   }
-  
+
   /**
    * Returns an expression for an instance of a nested class that implements {@code
    * Provider<Optional<T>>} or {@code Producer<Optional<T>>} for a present optional binding, where
    * {@code T} represents dependency requests of that kind.
    *
    * <ul>
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#INSTANCE}, the class
-   *     implements {@code ProviderOrProducer<Optional<T>>}.
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#PROVIDER}, the class
-   *     implements {@code Provider<Optional<Provider<T>>>}.
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#LAZY}, the class implements
-   *     {@code Provider<Optional<Lazy<T>>>}.
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#PROVIDER_OF_LAZY}, the
-   *     class implements {@code Provider<Optional<Provider<Lazy<T>>>>}.
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#PRODUCER}, the class
-   *     implements {@code Producer<Optional<Producer<T>>>}.
-   * <li>If {@code optionalRequestKind} is {@link DependencyRequest.Kind#PRODUCED}, the class
-   *     implements {@code Producer<Optional<Produced<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#INSTANCE}, the class implements
+   *       {@code ProviderOrProducer<Optional<T>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER}, the class implements
+   *       {@code Provider<Optional<Provider<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#LAZY}, the class implements {@code
+   *       Provider<Optional<Lazy<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PROVIDER_OF_LAZY}, the class
+   *       implements {@code Provider<Optional<Provider<Lazy<T>>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCER}, the class implements
+   *       {@code Producer<Optional<Producer<T>>>}.
+   *   <li>If {@code optionalRequestKind} is {@link RequestKind#PRODUCED}, the class implements
+   *       {@code Producer<Optional<Produced<T>>>}.
    * </ul>
    *
    * @param delegateFactory an expression for a {@link Provider} or {@link Producer} of the
diff --git a/java/dagger/internal/codegen/PrivateMethodBindingExpression.java b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
index fa479c7..02535c4 100644
--- a/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/PrivateMethodBindingExpression.java
@@ -24,6 +24,7 @@
 import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
 import static dagger.internal.codegen.GeneratedComponentModel.FieldSpecKind.PRIVATE_METHOD_SCOPED_FIELD;
 import static dagger.internal.codegen.GeneratedComponentModel.MethodSpecKind.PRIVATE_METHOD;
+import static dagger.internal.codegen.RequestKinds.requestType;
 import static dagger.internal.codegen.Scope.reusableScope;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
@@ -37,6 +38,7 @@
 import com.squareup.javapoet.TypeSpec;
 import dagger.internal.MemoizedSentinel;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
+import dagger.model.RequestKind;
 import java.util.EnumMap;
 import java.util.Map;
 import java.util.Optional;
@@ -54,10 +56,8 @@
   private final ComponentBindingExpressions componentBindingExpressions;
   private final BindingExpression delegate;
   // TODO(user): No need for a map. Each PMBE instance only handles 1 request kind now.
-  private final Map<DependencyRequest.Kind, String> methodNames =
-      new EnumMap<>(DependencyRequest.Kind.class);
-  private final Map<DependencyRequest.Kind, String> fieldNames =
-      new EnumMap<>(DependencyRequest.Kind.class);
+  private final Map<RequestKind, String> methodNames = new EnumMap<>(RequestKind.class);
+  private final Map<RequestKind, String> fieldNames = new EnumMap<>(RequestKind.class);
   private final ContributionBinding binding;
   private final CompilerOptions compilerOptions;
   private final ReferenceReleasingManagerFields referenceReleasingManagerFields;
@@ -143,8 +143,7 @@
   }
 
   private boolean isNullaryProvisionMethod() {
-    return (requestKind().equals(DependencyRequest.Kind.INSTANCE)
-            || requestKind().equals(DependencyRequest.Kind.FUTURE))
+    return (requestKind().equals(RequestKind.INSTANCE) || requestKind().equals(RequestKind.FUTURE))
         && binding.dependencies().isEmpty()
         && !findComponentMethod().isPresent();
   }
@@ -193,11 +192,11 @@
 
   /** Returns the return type for the dependency request. */
   private TypeMirror returnType() {
-    if (requestKind().equals(DependencyRequest.Kind.INSTANCE)
+    if (requestKind().equals(RequestKind.INSTANCE)
         && binding.contributedPrimitiveType().isPresent()) {
       return binding.contributedPrimitiveType().get();
     }
-    return accessibleType(requestKind().type(binding.contributedType(), types));
+    return accessibleType(requestType(requestKind(), binding.contributedType(), types));
   }
 
   /** Returns the method body for the dependency request. */
@@ -276,7 +275,7 @@
                     "return $L",
                     componentBindingExpressions
                         .getDependencyExpression(
-                            bindingKey(), DependencyRequest.Kind.INSTANCE, componentName())
+                            bindingKey(), RequestKind.INSTANCE, componentName())
                         .codeBlock())
                 .build())
         .build();
@@ -286,7 +285,7 @@
   private String methodName() {
     // TODO(user): Use a better name for @MapKey binding instances.
     // TODO(user): Include the binding method as part of the method name.
-    if (requestKind().equals(DependencyRequest.Kind.INSTANCE)) {
+    if (requestKind().equals(RequestKind.INSTANCE)) {
       return "get" + bindingName();
     }
     return "get" + bindingName() + dependencyKindName(requestKind());
@@ -297,8 +296,8 @@
     return LOWER_CAMEL.to(UPPER_CAMEL, BindingVariableNamer.name(binding));
   }
 
-  /** Returns a canonical name for the {@link DependencyRequest.Kind}. */
-  private static String dependencyKindName(DependencyRequest.Kind kind) {
+  /** Returns a canonical name for the {@link RequestKind}. */
+  private static String dependencyKindName(RequestKind kind) {
     return UPPER_UNDERSCORE.to(UPPER_CAMEL, kind.name());
   }
 
diff --git a/java/dagger/internal/codegen/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
index fc38de5..d702e9d 100644
--- a/java/dagger/internal/codegen/ProducerFactoryGenerator.java
+++ b/java/dagger/internal/codegen/ProducerFactoryGenerator.java
@@ -57,6 +57,7 @@
 import com.squareup.javapoet.ParameterizedTypeName;
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeSpec;
+import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import java.util.Map;
 import java.util.Optional;
@@ -161,7 +162,7 @@
           "$T $L = $L",
           futureType,
           dependencyFutureName(dependency),
-          dependency.kind().equals(DependencyRequest.Kind.PRODUCED)
+          dependency.kind().equals(RequestKind.PRODUCED)
               ? CodeBlock.of("$T.createFutureProduced($L)", PRODUCERS, futureAccess)
               : futureAccess);
     }
diff --git a/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java b/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java
index fae83ac..0b3c9e6 100644
--- a/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java
+++ b/java/dagger/internal/codegen/ProducerFromProviderFieldInitializer.java
@@ -21,6 +21,7 @@
 
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
+import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import java.util.Optional;
 
@@ -43,7 +44,7 @@
   @Override
   protected CodeBlock getFieldInitialization() {
     return FrameworkType.PROVIDER.to(
-        DependencyRequest.Kind.PRODUCER,
+        RequestKind.PRODUCER,
         componentBindingExpressions
             .getDependencyExpression(
                 FrameworkDependency.create(resolvedBindings.bindingKey(), PROVISION),
diff --git a/java/dagger/internal/codegen/ProductionBinding.java b/java/dagger/internal/codegen/ProductionBinding.java
index 93a8ee4..f873211 100644
--- a/java/dagger/internal/codegen/ProductionBinding.java
+++ b/java/dagger/internal/codegen/ProductionBinding.java
@@ -31,6 +31,7 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.CheckReturnValue;
 import dagger.model.Key;
+import dagger.model.RequestKind;
 import dagger.producers.Producer;
 import java.util.Optional;
 import java.util.stream.Stream;
@@ -228,7 +229,7 @@
      * Returns a synthetic binding for an {@linkplain dagger.BindsOptionalOf optional binding} in a
      * component with a binding for the underlying key.
      */
-    ProductionBinding syntheticPresentBinding(Key key, DependencyRequest.Kind kind) {
+    ProductionBinding syntheticPresentBinding(Key key, RequestKind kind) {
       return ProductionBinding.builder()
           .contributionType(ContributionType.UNIQUE)
           .key(key)
diff --git a/java/dagger/internal/codegen/ProvisionBinding.java b/java/dagger/internal/codegen/ProvisionBinding.java
index f70755e..000d8de 100644
--- a/java/dagger/internal/codegen/ProvisionBinding.java
+++ b/java/dagger/internal/codegen/ProvisionBinding.java
@@ -40,6 +40,7 @@
 import dagger.internal.codegen.ComponentDescriptor.BuilderRequirementMethod;
 import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
 import dagger.model.Key;
+import dagger.model.RequestKind;
 import java.util.Optional;
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -410,7 +411,7 @@
      * Returns a synthetic binding for an {@linkplain dagger.BindsOptionalOf optional binding} in a
      * component with a binding for the underlying key.
      */
-    ProvisionBinding syntheticPresentBinding(Key key, DependencyRequest.Kind kind) {
+    ProvisionBinding syntheticPresentBinding(Key key, RequestKind kind) {
       return syntheticAbsentBinding(key)
           .toBuilder()
           .provisionDependencies(
diff --git a/java/dagger/internal/codegen/RequestKinds.java b/java/dagger/internal/codegen/RequestKinds.java
new file mode 100644
index 0000000..f676ea2
--- /dev/null
+++ b/java/dagger/internal/codegen/RequestKinds.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 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.TypeNames.lazyOf;
+import static dagger.internal.codegen.TypeNames.listenableFutureOf;
+import static dagger.internal.codegen.TypeNames.membersInjectorOf;
+import static dagger.internal.codegen.TypeNames.producedOf;
+import static dagger.internal.codegen.TypeNames.producerOf;
+import static dagger.internal.codegen.TypeNames.providerOf;
+import static dagger.model.RequestKind.LAZY;
+import static dagger.model.RequestKind.MEMBERS_INJECTOR;
+import static dagger.model.RequestKind.PRODUCED;
+import static dagger.model.RequestKind.PRODUCER;
+import static dagger.model.RequestKind.PROVIDER;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.squareup.javapoet.TypeName;
+import dagger.Lazy;
+import dagger.MembersInjector;
+import dagger.model.RequestKind;
+import dagger.producers.Produced;
+import dagger.producers.Producer;
+import java.util.Optional;
+import javax.inject.Provider;
+import javax.lang.model.type.TypeMirror;
+
+/** Utility methods for {@link RequestKind}s. */
+final class RequestKinds {
+  /** Returns the type of a request of this kind for a key with a given type. */
+  static TypeMirror requestType(RequestKind requestKind, TypeMirror type, DaggerTypes types) {
+    switch (requestKind) {
+      case INSTANCE:
+        return type;
+
+      case PROVIDER_OF_LAZY:
+        return types.wrapType(requestType(RequestKind.LAZY, type, types), Provider.class);
+
+      case FUTURE:
+        return types.wrapType(type, ListenableFuture.class);
+
+      default:
+        return types.wrapType(type, frameworkClass(requestKind).get());
+    }
+  }
+
+  /** Returns the type of a request of this kind for a key with a given type. */
+  static TypeName requestTypeName(RequestKind requestKind, TypeName keyType) {
+    switch (requestKind) {
+      case INSTANCE:
+        return keyType;
+
+      case PROVIDER:
+        return providerOf(keyType);
+
+      case LAZY:
+        return lazyOf(keyType);
+
+      case PROVIDER_OF_LAZY:
+        return providerOf(lazyOf(keyType));
+
+      case PRODUCER:
+        return producerOf(keyType);
+
+      case PRODUCED:
+        return producedOf(keyType);
+
+      case FUTURE:
+        return listenableFutureOf(keyType);
+
+      case MEMBERS_INJECTOR:
+        return membersInjectorOf(keyType);
+
+      default:
+        throw new AssertionError(requestKind);
+    }
+  }
+
+  private static final ImmutableMap<RequestKind, Class<?>> FRAMEWORK_CLASSES =
+      ImmutableMap.of(
+          PROVIDER, Provider.class,
+          LAZY, Lazy.class,
+          MEMBERS_INJECTOR, MembersInjector.class,
+          PRODUCER, Producer.class,
+          PRODUCED, Produced.class);
+
+  /**
+   * A dagger- or {@code javax.inject}-defined class for {@code requestKind} that that can wrap
+   * another type but share the same {@link dagger.model.Key}.
+   *
+   * <p>For example, {@code Provider<String>} and {@code Lazy<String>} can both be requested if a
+   * key exists for {@code String}; they all share the same key.
+   *
+   * <p>This concept is not well defined and should probably be removed and inlined into the cases
+   * that need it. For example, {@link RequestKind#PROVIDER_OF_LAZY} has <em>2</em> wrapping
+   * classes, and {@link RequestKind#FUTURE} is wrapped with a {@link ListenableFuture}, but for
+   * historical/implementation reasons has not had an associated framework class.
+   */
+  static Optional<Class<?>> frameworkClass(RequestKind requestKind) {
+    return Optional.ofNullable(FRAMEWORK_CLASSES.get(requestKind));
+  }
+
+  private RequestKinds() {}
+}
diff --git a/java/dagger/internal/codegen/SourceFiles.java b/java/dagger/internal/codegen/SourceFiles.java
index e0f75e3..a9390c6 100644
--- a/java/dagger/internal/codegen/SourceFiles.java
+++ b/java/dagger/internal/codegen/SourceFiles.java
@@ -54,6 +54,7 @@
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeVariableName;
 import dagger.internal.SetFactory;
+import dagger.model.RequestKind;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import dagger.producers.internal.SetOfProducedProducer;
@@ -147,7 +148,7 @@
   }
 
   static CodeBlock frameworkTypeUsageStatement(
-      CodeBlock frameworkTypeMemberSelect, DependencyRequest.Kind dependencyKind) {
+      CodeBlock frameworkTypeMemberSelect, RequestKind dependencyKind) {
     switch (dependencyKind) {
       case LAZY:
         return CodeBlock.of("$T.lazy($L)", DOUBLE_CHECK, frameworkTypeMemberSelect);
@@ -167,7 +168,7 @@
 
   /**
    * Returns a mapping of {@link DependencyRequest}s to {@link CodeBlock}s that {@linkplain
-   * #frameworkTypeUsageStatement(CodeBlock, DependencyRequest.Kind) use them}.
+   * #frameworkTypeUsageStatement(CodeBlock, RequestKind) use them}.
    */
   static ImmutableMap<DependencyRequest, CodeBlock> frameworkFieldUsages(
       ImmutableSet<DependencyRequest> dependencies, ImmutableMap<BindingKey, FieldSpec> fields) {
diff --git a/java/dagger/internal/codegen/TypeNames.java b/java/dagger/internal/codegen/TypeNames.java
index 7716526..d6b01c7 100644
--- a/java/dagger/internal/codegen/TypeNames.java
+++ b/java/dagger/internal/codegen/TypeNames.java
@@ -24,7 +24,6 @@
 import com.squareup.javapoet.TypeName;
 import dagger.Lazy;
 import dagger.MembersInjector;
-import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
 import dagger.internal.Factory;
 import dagger.internal.InstanceFactory;
@@ -48,8 +47,6 @@
 import dagger.producers.internal.SetProducer;
 import dagger.producers.monitoring.ProducerToken;
 import dagger.producers.monitoring.ProductionComponentMonitor;
-import dagger.releasablereferences.ReleasableReferenceManager;
-import dagger.releasablereferences.TypedReleasableReferenceManager;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -63,12 +60,10 @@
 
   static final ClassName ABSTRACT_PRODUCER = ClassName.get(AbstractProducer.class);
   static final ClassName ASYNC_FUNCTION = ClassName.get(AsyncFunction.class);
-  static final ClassName DELEGATE_FACTORY = ClassName.get(DelegateFactory.class);
   static final ClassName DOUBLE_CHECK = ClassName.get(DoubleCheck.class);
   static final ClassName EXECUTOR = ClassName.get(Executor.class);
   static final ClassName FACTORY = ClassName.get(Factory.class);
   static final ClassName FUTURES = ClassName.get(Futures.class);
-  static final ClassName ILLEGAL_STATE_EXCEPTION = ClassName.get(IllegalStateException.class);
   static final ClassName INSTANCE_FACTORY = ClassName.get(InstanceFactory.class);
   static final ClassName LAZY = ClassName.get(Lazy.class);
   static final ClassName LIST = ClassName.get(List.class);
@@ -94,22 +89,14 @@
       ClassName.get(ReferenceReleasingProvider.class);
   static final ClassName REFERENCE_RELEASING_PROVIDER_MANAGER =
       ClassName.get(ReferenceReleasingProviderManager.class);
-  static final ClassName RELEASABLE_REFERENCE_MANAGER =
-      ClassName.get(ReleasableReferenceManager.class);
   static final ClassName SET = ClassName.get(Set.class);
   static final ClassName SET_FACTORY = ClassName.get(SetFactory.class);
   static final ClassName SET_OF_PRODUCED_PRODUCER = ClassName.get(SetOfProducedProducer.class);
   static final ClassName SET_PRODUCER = ClassName.get(SetProducer.class);
   static final ClassName SINGLE_CHECK = ClassName.get(SingleCheck.class);
-  static final ClassName STRING = ClassName.get(String.class);
-  static final ClassName TYPED_RELEASABLE_REFERENCE_MANAGER =
-      ClassName.get(TypedReleasableReferenceManager.class);
   static final ClassName TYPED_RELEASABLE_REFERENCE_MANAGER_DECORATOR =
       ClassName.get(TypedReleasableReferenceManagerDecorator.class);
 
-  static final ClassName UNSUPPORTED_OPERATION_EXCEPTION =
-      ClassName.get(UnsupportedOperationException.class);
-
   /**
    * {@link TypeName#VOID} is lowercase-v {@code void} whereas this represents the class, {@link
    * Void}.