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;",
" }",
"",