Check the accessibility of types in BindingMethodImplementation as well

This was an oversight from 1ae4c00921ff3c0be64c3c4f71c5c957ef42dcd8

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=222997803
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index bf84f06..d043d85 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -20,6 +20,7 @@
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
 import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import javax.lang.model.type.TypeMirror;
 
 /** A factory of code expressions used to access a single request for a binding in a component. */
 // TODO(user): Rename this to RequestExpression?
@@ -66,7 +67,41 @@
    * component.
    */
   CodeBlock getModifiableBindingMethodImplementation(
-      ModifiableBindingMethod modifiableBindingMethod, ComponentImplementation component) {
-    return CodeBlock.of("return $L;", getDependencyExpression(component.name()).codeBlock());
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
+    Expression dependencyExpression = getDependencyExpression(component.name());
+    BindingRequest request = modifiableBindingMethod.request();
+    TypeMirror requestedType = request.requestedType(request.key().type(), types);
+
+    // It's possible to have a case where a modifiable component method delegates to another
+    // binding method from an enclosing class that is not itself a component method. In that case,
+    // the enclosing class's method may return a publicly accessible type, but the nested class will
+    // have a return type that is defined by the component method. In that case, a downcast is
+    // necessary so that the return statement is valid.
+    //
+    // E.g.:
+    //
+    // public class DaggerAncestor implements Ancestor {
+    //   protected Object packagePrivateModifiable() { ... }
+    //
+    //   protected class LeafImpl extends DaggerLeaf {
+    //     @Override
+    //     public final PackagePrivateModifiable componentMethod() {
+    //       return (PackagePrivateModifiable) DaggerAncestor.this.packagePrivateModifiable();
+    //     }
+    //   }
+    // }
+    //
+    // DaggerAncestor.packagePrivateModifiable returns Object even though the actual instance's type
+    // is PackagePrivateModifiable. So a cast is necessary.
+    //
+    // This isn't necessary for getComponentMethodImplementation() because that's only used for
+    // non-modifiable bindings
+    if (!types.isAssignable(dependencyExpression.type(), requestedType)) {
+      dependencyExpression = dependencyExpression.castTo(requestedType);
+    }
+
+    return CodeBlock.of("return $L;", dependencyExpression.codeBlock());
   }
 }
diff --git a/java/dagger/internal/codegen/BindingMethodImplementation.java b/java/dagger/internal/codegen/BindingMethodImplementation.java
index 814bf3a..387aa66 100644
--- a/java/dagger/internal/codegen/BindingMethodImplementation.java
+++ b/java/dagger/internal/codegen/BindingMethodImplementation.java
@@ -19,44 +19,43 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.base.Supplier;
-import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
 import dagger.model.RequestKind;
+import java.util.Optional;
 import javax.lang.model.type.TypeMirror;
 
 /** Defines a method body and return type for a given {@link BindingExpression}. */
 class BindingMethodImplementation {
+  private final ComponentImplementation component;
   private final ContributionBinding binding;
   private final BindingRequest request;
   private final BindingExpression bindingExpression;
-  private final ClassName componentName;
   private final DaggerTypes types;
 
   BindingMethodImplementation(
-      ResolvedBindings resolvedBindings,
+      ComponentImplementation component,
+      ContributionBinding binding,
       BindingRequest request,
       BindingExpression bindingExpression,
-      ClassName componentName,
       DaggerTypes types) {
-    this.binding = resolvedBindings.contributionBinding();
-    this.request = checkNotNull(request);
+    this.component = component;
+    this.binding = binding;
+    this.request = request;
     this.bindingExpression = checkNotNull(bindingExpression);
-    this.componentName = checkNotNull(componentName);
-    this.types = checkNotNull(types);
+    this.types = types;
   }
 
   /** The method's body. */
   final CodeBlock body() {
-    return implementation(bindingExpression.getDependencyExpression(componentName)::codeBlock);
+    return implementation(bindingExpression.getDependencyExpression(component.name())::codeBlock);
   }
 
   /** The method's body if this method is a component method. */
-  final CodeBlock bodyForComponentMethod(
-      ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+  final CodeBlock bodyForComponentMethod(ComponentMethodDescriptor componentMethod) {
     return implementation(
-        bindingExpression
-            .getDependencyExpressionForComponentMethod(componentMethod, component)::codeBlock);
+        bindingExpression.getDependencyExpressionForComponentMethod(componentMethod, component)
+            ::codeBlock);
   }
 
   /**
@@ -78,6 +77,33 @@
         && binding.contributedPrimitiveType().isPresent()) {
       return binding.contributedPrimitiveType().get();
     }
-    return request.accessibleType(binding, componentName, types);
+
+    TypeMirror requestedType = request.requestedType(binding.contributedType(), types);
+
+    if (matchingComponentMethod().isPresent()) {
+      // Component methods are part of the user-defined API, and thus we must use the user-defined
+      // type. If the return type of the method is a primitive, use that since the key type is 
+      // always boxed. We still use the requestedType if the return type is not a primitive, as
+      // opposed to componentMethodReturnType, since that will have all type variables from
+      // component supertypes resolved.
+      TypeMirror componentMethodReturnType =
+          matchingComponentMethod().get().methodElement().getReturnType();
+      return componentMethodReturnType.getKind().isPrimitive()
+          ? componentMethodReturnType
+          : requestedType;
+    }
+
+    // If the component is abstract, this method may be overridden by another implementation in a
+    // different package for which requestedType is inaccessible. In order to make that method
+    // overridable, we use the publicly accessible type. If the type is final, we don't need to 
+    // worry about this, and instead just need to check accessibility of the file we're about to
+    // write
+    return component.isAbstract()
+        ? types.publiclyAccessibleType(requestedType)
+        : types.accessibleType(requestedType, component.name());
+  }
+
+  private Optional<ComponentMethodDescriptor> matchingComponentMethod() {
+    return component.componentDescriptor().firstMatchingComponentMethod(request);
   }
 }
diff --git a/java/dagger/internal/codegen/BindingRequest.java b/java/dagger/internal/codegen/BindingRequest.java
index 9bbb0b0..76f342a 100644
--- a/java/dagger/internal/codegen/BindingRequest.java
+++ b/java/dagger/internal/codegen/BindingRequest.java
@@ -16,11 +16,9 @@
 
 package dagger.internal.codegen;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static dagger.internal.codegen.RequestKinds.requestType;
 
 import com.google.auto.value.AutoValue;
-import com.squareup.javapoet.ClassName;
 import dagger.model.DependencyRequest;
 import dagger.model.Key;
 import dagger.model.RequestKind;
@@ -92,17 +90,6 @@
     return types.publiclyAccessibleType(requestedType(key().type(), types));
   }
 
-  /**
-   * Returns the {@link DaggerTypes#accessibleType(TypeMirror, ClassName) accessible type} of
-   * instances created by a {@code binding} for this request. This may differ from the accessible
-   * type of the key for multibindings.
-   */
-  final TypeMirror accessibleType(
-      ContributionBinding binding, ClassName requestingClass, DaggerTypes types) {
-    checkArgument(binding.key().equals(key()));
-    return types.accessibleType(requestedType(binding.contributedType(), types), requestingClass);
-  }
-
   final TypeMirror requestedType(TypeMirror contributedType, DaggerTypes types) {
     if (requestKind().isPresent()) {
       return requestType(requestKind().get(), contributedType, types);
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 7028151..835c7f5 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -660,27 +660,27 @@
   }
 
   // TODO(ronshapiro): pass ContributionBinding directly instead of ResolvedBindings. The
-  // ResolvedBindings type is only needed in one case, and it seems like it could be removed. The
-  // rest seem could all use a ContributionBinding directly
+  // ResolvedBindings type is only needed in one case, and it seems like it could be removed.
   private BindingMethodImplementation methodImplementation(
       ResolvedBindings resolvedBindings,
       BindingRequest request,
       BindingExpression bindingExpression) {
+    ContributionBinding binding = resolvedBindings.contributionBinding();
     if (compilerOptions.fastInit()) {
       if (request.isRequestKind(RequestKind.PROVIDER)) {
         return new SingleCheckedMethodImplementation(
-            resolvedBindings, request, bindingExpression, types, componentImplementation);
+            componentImplementation, resolvedBindings, request, bindingExpression, types);
       } else if (request.isRequestKind(RequestKind.INSTANCE) && needsCaching(resolvedBindings)) {
         return resolvedBindings.scope().get().isReusable()
             ? new SingleCheckedMethodImplementation(
-                resolvedBindings, request, bindingExpression, types, componentImplementation)
+                componentImplementation, resolvedBindings, request, bindingExpression, types)
             : new DoubleCheckedMethodImplementation(
-                resolvedBindings, request, bindingExpression, types, componentImplementation);
+                componentImplementation, binding, request, bindingExpression, types);
       }
     }
 
     return new BindingMethodImplementation(
-        resolvedBindings, request, bindingExpression, componentImplementation.name(), types);
+        componentImplementation, binding, request, bindingExpression, types);
   }
 
   /**
diff --git a/java/dagger/internal/codegen/ComponentImplementation.java b/java/dagger/internal/codegen/ComponentImplementation.java
index 5bd94c7..4a34946 100644
--- a/java/dagger/internal/codegen/ComponentImplementation.java
+++ b/java/dagger/internal/codegen/ComponentImplementation.java
@@ -498,6 +498,15 @@
     return method;
   }
 
+  /**
+   * Returns the {@link ModifiableBindingMethod} of a supertype for this method's {@code request},
+   * if one exists.
+   */
+  Optional<ModifiableBindingMethod> supertypeModifiableBindingMethod(BindingRequest request) {
+    return superclassImplementation()
+        .flatMap(superImplementation -> superImplementation.getModifiableBindingMethod(request));
+  }
+
   /** Generates the component and returns the resulting {@link TypeSpec.Builder}. */
   TypeSpec.Builder generate() {
     fieldSpecsMap.asMap().values().forEach(component::addFields);
diff --git a/java/dagger/internal/codegen/ComponentMethodBindingExpression.java b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
index 21a2441..e5e5c27 100644
--- a/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ComponentMethodBindingExpression.java
@@ -58,7 +58,7 @@
     // the child's can delegate to the parent. So use methodImplementation.body() only if
     // componentName equals the component for this instance.
     return componentMethod.equals(this.componentMethod) && component.equals(componentImplementation)
-        ? methodImplementation.bodyForComponentMethod(componentMethod, component)
+        ? methodImplementation.bodyForComponentMethod(componentMethod)
         : super.getComponentMethodImplementation(componentMethod, component);
   }
 
diff --git a/java/dagger/internal/codegen/DoubleCheckedMethodImplementation.java b/java/dagger/internal/codegen/DoubleCheckedMethodImplementation.java
index f5b8927..e14d449 100644
--- a/java/dagger/internal/codegen/DoubleCheckedMethodImplementation.java
+++ b/java/dagger/internal/codegen/DoubleCheckedMethodImplementation.java
@@ -16,6 +16,7 @@
 
 package dagger.internal.codegen;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.PRIVATE_METHOD_SCOPED_FIELD;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.VOLATILE;
@@ -39,14 +40,14 @@
   private final Supplier<String> fieldName = Suppliers.memoize(this::createField);
 
   DoubleCheckedMethodImplementation(
-      ResolvedBindings resolvedBindings,
+      ComponentImplementation component,
+      ContributionBinding binding,
       BindingRequest request,
       BindingExpression bindingExpression,
-      DaggerTypes types,
-      ComponentImplementation componentImplementation) {
-    super(resolvedBindings, request, bindingExpression, componentImplementation.name(), types);
-    this.componentImplementation = componentImplementation;
-    this.binding = resolvedBindings.contributionBinding();
+      DaggerTypes types) {
+    super(component, binding, request, bindingExpression, types);
+    this.componentImplementation = checkNotNull(component);
+    this.binding = checkNotNull(binding);
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/MethodBindingExpression.java b/java/dagger/internal/codegen/MethodBindingExpression.java
index fce9fb5..86b8787 100644
--- a/java/dagger/internal/codegen/MethodBindingExpression.java
+++ b/java/dagger/internal/codegen/MethodBindingExpression.java
@@ -55,7 +55,9 @@
 
   @Override
   final CodeBlock getModifiableBindingMethodImplementation(
-      ModifiableBindingMethod modifiableBindingMethod, ComponentImplementation component) {
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
     // A matching modifiable binding method means that we have previously created the binding method
     // and we are now implementing it. If there is no matching method we need to first create the
     // method. We create the method by deferring to getDependencyExpression (defined above) via a
@@ -65,17 +67,12 @@
           supertypeModifiableBindingMethod().get().fulfillsSameRequestAs(modifiableBindingMethod));
       return methodImplementation.body();
     }
-    return super.getModifiableBindingMethodImplementation(modifiableBindingMethod, component);
+    return super.getModifiableBindingMethodImplementation(
+        modifiableBindingMethod, component, types);
   }
 
-  /**
-   * Returns the {@link ModifiableBindingMethod} of a supertype for this method's {@link #request},
-   * if one exists.
-   */
   protected final Optional<ModifiableBindingMethod> supertypeModifiableBindingMethod() {
-    return componentImplementation
-        .superclassImplementation()
-        .flatMap(superImplementation -> superImplementation.getModifiableBindingMethod(request));
+    return componentImplementation.supertypeModifiableBindingMethod(request);
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
index 075ae9f..e9e2787 100644
--- a/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ModifiableAbstractMethodBindingExpression.java
@@ -115,15 +115,14 @@
       BindingRequest bindingRequest,
       Optional<ComponentMethodDescriptor> matchingComponentMethod,
       DaggerTypes types) {
+    TypeMirror requestedType = bindingRequest.requestedType(bindingRequest.key().type(), types);
     if (matchingComponentMethod.isPresent()) {
       TypeMirror returnType =
           matchingComponentMethod.get().dependencyRequest().get().requestElement().get().asType();
-      return returnType.getKind().isPrimitive()
-          ? returnType
-          : bindingRequest.requestedType(bindingRequest.key().type(), types);
-    } else {
-      return bindingRequest.publiclyAccessibleRequestType(types);
+      return returnType.getKind().isPrimitive() ? returnType : requestedType;
     }
+
+    return types.publiclyAccessibleType(requestedType);
   }
 
   /** Returns a unique 'getter' method name for the current component. */
diff --git a/java/dagger/internal/codegen/ModifiableBindingExpressions.java b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
index a47ed95..6755825 100644
--- a/java/dagger/internal/codegen/ModifiableBindingExpressions.java
+++ b/java/dagger/internal/codegen/ModifiableBindingExpressions.java
@@ -105,7 +105,7 @@
                       bindingExpressions
                           .getBindingExpression(modifiableBindingMethod.request())
                           .getModifiableBindingMethodImplementation(
-                              modifiableBindingMethod, componentImplementation))
+                              modifiableBindingMethod, componentImplementation, types))
                   .build(),
               markMethodFinal));
     }
diff --git a/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
index 1471497..c577ea9 100644
--- a/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/PrunedConcreteMethodBindingExpression.java
@@ -43,7 +43,9 @@
 
   @Override
   CodeBlock getModifiableBindingMethodImplementation(
-      ModifiableBindingMethod modifiableBindingMethod, ComponentImplementation component) {
+      ModifiableBindingMethod modifiableBindingMethod,
+      ComponentImplementation component,
+      DaggerTypes types) {
     return METHOD_IMPLEMENTATION;
   }
 
diff --git a/java/dagger/internal/codegen/SingleCheckedMethodImplementation.java b/java/dagger/internal/codegen/SingleCheckedMethodImplementation.java
index 289aa2c..18dc04d 100644
--- a/java/dagger/internal/codegen/SingleCheckedMethodImplementation.java
+++ b/java/dagger/internal/codegen/SingleCheckedMethodImplementation.java
@@ -16,6 +16,7 @@
 
 package dagger.internal.codegen;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static dagger.internal.codegen.ComponentImplementation.FieldSpecKind.PRIVATE_METHOD_SCOPED_FIELD;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.VOLATILE;
@@ -42,16 +43,16 @@
   private final Supplier<FieldSpec> field = Suppliers.memoize(this::createField);
 
   SingleCheckedMethodImplementation(
+      ComponentImplementation component,
       ResolvedBindings resolvedBindings,
       BindingRequest request,
       BindingExpression bindingExpression,
-      DaggerTypes types,
-      ComponentImplementation componentImplementation) {
-    super(resolvedBindings, request, bindingExpression, componentImplementation.name(), types);
-    this.componentImplementation = componentImplementation;
+      DaggerTypes types) {
+    super(component, resolvedBindings.contributionBinding(), request, bindingExpression, types);
+    this.componentImplementation = checkNotNull(component);
     this.resolvedBindings = resolvedBindings;
     this.binding = resolvedBindings.contributionBinding();
-    this.request = request;
+    this.request = checkNotNull(request);
   }
 
   @Override
diff --git a/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java b/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java
new file mode 100644
index 0000000..06cebb9
--- /dev/null
+++ b/javatests/dagger/functional/aot/SubcomponentWithModifiedInaccessibleDependency.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 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.functional.aot;
+
+import dagger.Subcomponent;
+import dagger.functional.aot.sub.BindsPackagePrivateModule;
+import dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod;
+
+/**
+ * See {@link dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod}. This
+ * subcomponent will induce a modified binding method for its single child for the key {@code
+ * Optional<dagger.functional.aot.sub.PackagePrivate>}. When it tries to reimplement it, it must use
+ * the publicly accessible type.
+ */
+@Subcomponent(modules = BindsPackagePrivateModule.class)
+interface SubcomponentWithModifiedInaccessibleDependency {
+  SubcomponentWithInaccessibleOptionalBindingMethod child();
+}
diff --git a/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java b/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java
new file mode 100644
index 0000000..2eee3c9
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/BindsPackagePrivateModule.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.functional.aot.sub;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public final class BindsPackagePrivateModule {
+  @Provides
+  static PackagePrivate packagePrivate() {
+    return new PackagePrivate();
+  }
+}
diff --git a/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java
new file mode 100644
index 0000000..1d69723
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/PublicTypeWithPackagePrivateOptionalDep.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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.functional.aot.sub;
+
+import java.util.Optional;
+import javax.inject.Inject;
+
+public class PublicTypeWithPackagePrivateOptionalDep {
+  @Inject
+  PublicTypeWithPackagePrivateOptionalDep(Optional<PackagePrivate> packagePrivateOptional) {}
+}
diff --git a/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java b/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java
new file mode 100644
index 0000000..d908b1c
--- /dev/null
+++ b/javatests/dagger/functional/aot/sub/SubcomponentWithInaccessibleOptionalBindingMethod.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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.functional.aot.sub;
+
+import dagger.BindsOptionalOf;
+import dagger.Module;
+import dagger.Subcomponent;
+import dagger.functional.aot.sub.SubcomponentWithInaccessibleOptionalBindingMethod.ExposesModifiablePackagePrivateBindingModule;
+import javax.inject.Provider;
+
+/**
+ * This component will generate a modifiable binding method for the key {@code
+ * Optional<PackagePrivate>} as a dependency of {@link PublicTypeWithPackagePrivateOptionalDep}.
+ * Even though this subcomponent implementation can refer to the parameterized type, a subclass
+ * implementation in another package will not be able to, and thus the return type must be reduced
+ * to the publicly accessible type. This is exhibited in {@link
+ * dagger.functional.aot.SubcomponentWithModifiedInaccessibleDependency}.
+ */
+@Subcomponent(modules = ExposesModifiablePackagePrivateBindingModule.class)
+public interface SubcomponentWithInaccessibleOptionalBindingMethod {
+  PublicTypeWithPackagePrivateOptionalDep instance();
+  Provider<PublicTypeWithPackagePrivateOptionalDep> frameworkInstance();
+
+  @Module
+  interface ExposesModifiablePackagePrivateBindingModule {
+    @BindsOptionalOf
+    PackagePrivate optional();
+  }
+}
diff --git a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
index 606873a..331535f 100644
--- a/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
+++ b/javatests/dagger/internal/codegen/AheadOfTimeSubcomponentsTest.java
@@ -1195,7 +1195,7 @@
             "            getOptionalOfSatisfiedInAncestor());",
             "  }",
             "",
-            "  protected Optional<SatisfiedInAncestor> getOptionalOfSatisfiedInAncestor() {",
+            "  protected Optional getOptionalOfSatisfiedInAncestor() {",
             "    return Optional.<SatisfiedInAncestor>empty();",
             "  }",
             "}");
@@ -1246,8 +1246,7 @@
             "    protected LeafImpl() {}",
             "",
             "    @Override",
-            "    protected final Optional<SatisfiedInAncestor>",
-            "        getOptionalOfSatisfiedInAncestor() {",
+            "    protected final Optional getOptionalOfSatisfiedInAncestor() {",
             "      return Optional.of(",
             "          AncestorModule_SatisfiedInAncestorFactory.proxySatisfiedInAncestor());",
             "    }",
@@ -1901,7 +1900,7 @@
             "        .proxyProvidesRequresInAllSubcomponentsSet(getSetOfInAllSubcomponents());",
             "  }",
             "",
-            "  protected Set<InAllSubcomponents> getSetOfInAllSubcomponents() {",
+            "  protected Set getSetOfInAllSubcomponents() {",
             "    return ImmutableSet.<InAllSubcomponents>of(",
             "        LeafModule_ProvideInAllSubcomponentsFactory",
             "            .proxyProvideInAllSubcomponents());",
@@ -1958,7 +1957,7 @@
             "    protected LeafImpl() {}",
             "",
             "    @Override",
-            "    protected Set<InAllSubcomponents> getSetOfInAllSubcomponents() {",
+            "    protected Set getSetOfInAllSubcomponents() {",
             "      return ImmutableSet.<InAllSubcomponents>builderWithExpectedSize(2)",
             "          .add(AncestorModule_ProvideInAllSubcomponentsFactory",
             "              .proxyProvideInAllSubcomponents())",
@@ -2054,12 +2053,15 @@
             "public abstract class DaggerAncestor implements Ancestor {",
             "  protected DaggerAncestor() {}",
             "",
-            "  private RequiresInAncestorSet getRequiresInAncestorSet() {",
+            // TODO(b/117833324): because this is a private method, the return type shouldn't need
+            // to be the publicly accessible type. This may be easier to detect if we fold
+            // BindingMethodImplementation into MethodBindingExpression
+            "  private Object getRequiresInAncestorSet() {",
             "    return AncestorModule_ProvideRequiresInAncestorSetFactory",
             "        .proxyProvideRequiresInAncestorSet(getSetOfInAncestor());",
             "  }",
             "",
-            "  protected Set<InAncestor> getSetOfInAncestor() {",
+            "  protected Set getSetOfInAncestor() {",
             "    return ImmutableSet.<InAncestor>of(",
             "        AncestorModule_ProvideInAncestorFactory.proxyProvideInAncestor());",
             "  }",
@@ -2069,7 +2071,7 @@
             "",
             "    @Override",
             "    public final RequiresInAncestorSet missingWithSetDependency() {",
-            "      return DaggerAncestor.this.getRequiresInAncestorSet();",
+            "      return (RequiresInAncestorSet) DaggerAncestor.this.getRequiresInAncestorSet();",
             "    }",
             "  }",
             "}");
@@ -2203,7 +2205,7 @@
             "              .build();",
             "    }",
             "",
-            "    protected Provider<Set<Multibound>> getSetOfMultiboundProvider() {",
+            "    protected Provider getSetOfMultiboundProvider() {",
             "      return setOfMultiboundProvider;",
             "    }",
             "",
@@ -3233,8 +3235,7 @@
             "              .build();",
             "    }",
             "",
-            "    protected Provider<Map<Integer, Multibound>> ",
-            "        getMapOfIntegerAndMultiboundProvider() {",
+            "    protected Provider getMapOfIntegerAndMultiboundProvider() {",
             "      return mapOfIntegerAndMultiboundProvider;",
             "    }",
             "",
@@ -4022,12 +4023,12 @@
             "",
             "  @Override",
             "  public InjectedInLeaf injectedInLeaf() {",
-            "    return new InjectedInLeaf(getProvidedInAncestor());",
+            "    return InjectedInLeaf_Factory.newInjectedInLeaf(getProvidedInAncestor());",
             "  }",
             "",
             "  protected abstract String getString();",
             "",
-            "  protected ProvidedInAncestor getProvidedInAncestor() {",
+            "  protected Object getProvidedInAncestor() {",
             "    return new ProvidedInAncestor(getString());",
             "  }",
             "}");
@@ -4077,7 +4078,7 @@
             "    protected LeafImpl() {}",
             "",
             "    @Override",
-            "    protected final ProvidedInAncestor getProvidedInAncestor() {",
+            "    protected final Object getProvidedInAncestor() {",
             "      return AncestorModule_ProvideProvidedInAncestorFactory",
             "          .proxyProvideProvidedInAncestor();",
             "    }",
@@ -4327,11 +4328,11 @@
             "",
             "  protected abstract Producer getResponseDependencyProducer();",
             "",
-            "  protected Producer<Response> getResponseProducer() {",
+            "  protected Producer getResponseProducer() {",
             "    return responseProducer;",
             "  }",
             "",
-            "  protected Producer<Set<Response>> getSetOfResponseProducer() {",
+            "  protected Producer getSetOfResponseProducer() {",
             "    return setOfResponseProducer;",
             "  }",
             "",
@@ -4544,7 +4545,7 @@
             "    }",
             "",
             "    @Override",
-            "    protected Producer<Set<Response>> getSetOfResponseProducer() {",
+            "    protected Producer getSetOfResponseProducer() {",
             "      return setOfResponseProducer;",
             "    }",
             "",