phopkins' changes to BindingTargetVisitor so it accepts wildcard types. Original patch submitted with issue 290.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@745 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/extensions/commands/src/com/google/inject/commands/intercepting/InterceptingInjectorBuilder.java b/extensions/commands/src/com/google/inject/commands/intercepting/InterceptingInjectorBuilder.java
index 3411e6f..c178bcd 100644
--- a/extensions/commands/src/com/google/inject/commands/intercepting/InterceptingInjectorBuilder.java
+++ b/extensions/commands/src/com/google/inject/commands/intercepting/InterceptingInjectorBuilder.java
@@ -167,7 +167,8 @@
       }
 
       binding.acceptTargetVisitor(new DefaultBindingTargetVisitor<T, Void>() {
-        @Override public Void visitUntargetted(UntargettedBinding<T> tUntargettedBinding) {
+        @Override public Void visitUntargetted(
+            UntargettedBinding<? extends T> tUntargettedBinding) {
           throw new UnsupportedOperationException(
               String.format("Cannot intercept bare binding of %s.", key));
         }
diff --git a/src/com/google/inject/Binding.java b/src/com/google/inject/Binding.java
index 80b7cff..c25d354 100644
--- a/src/com/google/inject/Binding.java
+++ b/src/com/google/inject/Binding.java
@@ -80,7 +80,7 @@
    * @param visitor to call back on
    * @since 2.0
    */
-  <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor);
+  <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor);
 
   /**
    * Accepts a scoping visitor. Invokes the visitor method specific to this binding's scoping.
diff --git a/src/com/google/inject/BindingProcessor.java b/src/com/google/inject/BindingProcessor.java
index 2a1e77a..e51a751 100644
--- a/src/com/google/inject/BindingProcessor.java
+++ b/src/com/google/inject/BindingProcessor.java
@@ -89,7 +89,7 @@
 
     command.acceptTargetVisitor(new BindingTargetVisitor<T, Void>() {
 
-      public Void visitInstance(InstanceBinding<T> binding) {
+      public Void visitInstance(InstanceBinding<? extends T> binding) {
         Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
         T instance = binding.getInstance();
         Initializable<T> ref = initializer.requestInjection(
@@ -101,7 +101,7 @@
         return null;
       }
 
-      public Void visitProviderInstance(ProviderInstanceBinding<T> binding) {
+      public Void visitProviderInstance(ProviderInstanceBinding<? extends T> binding) {
         Provider<? extends T> provider = binding.getProviderInstance();
         Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
         Initializable<Provider<? extends T>> initializable = initializer
@@ -113,7 +113,7 @@
         return null;
       }
 
-      public Void visitProviderKey(ProviderKeyBinding<T> binding) {
+      public Void visitProviderKey(ProviderKeyBinding<? extends T> binding) {
         Key<? extends Provider<? extends T>> providerKey = binding.getProviderKey();
         BoundProviderFactory<T> boundProviderFactory
             = new BoundProviderFactory<T>(injector, providerKey, source);
@@ -125,7 +125,7 @@
         return null;
       }
 
-      public Void visitLinkedKey(LinkedKeyBinding<T> binding) {
+      public Void visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
         Key<? extends T> linkedKey = binding.getLinkedKey();
         if (key.equals(linkedKey)) {
           errors.recursiveBinding();
@@ -139,7 +139,7 @@
         return null;
       }
 
-      public Void visitUntargetted(UntargettedBinding<T> untargetted) {
+      public Void visitUntargetted(UntargettedBinding<? extends T> untargetted) {
         // Error: Missing implementation.
         // Example: bind(Date.class).annotatedWith(Red.class);
         // We can't assume abstract types aren't injectable. They may have an
@@ -175,7 +175,7 @@
         return null;
       }
 
-      public Void visitExposed(ExposedBinding<T> binding) {
+      public Void visitExposed(ExposedBinding<? extends T> binding) {
         PrivateEnvironment privateEnvironment = binding.getPrivateEnvironment();
         ExposedKeyFactory<T> exposedKeyFactory = new ExposedKeyFactory<T>(key, privateEnvironment);
         creationListeners.add(exposedKeyFactory);
@@ -184,15 +184,15 @@
         return null;
       }
 
-      public Void visitConvertedConstant(ConvertedConstantBinding<T> binding) {
+      public Void visitConvertedConstant(ConvertedConstantBinding<? extends T> binding) {
         throw new IllegalArgumentException("Cannot apply a non-module element");
       }
 
-      public Void visitConstructor(ConstructorBinding<T> binding) {
+      public Void visitConstructor(ConstructorBinding<? extends T> binding) {
         throw new IllegalArgumentException("Cannot apply a non-module element");
       }
 
-      public Void visitProviderBinding(ProviderBinding<?> binding) {
+      public Void visitProviderBinding(ProviderBinding<? extends T> binding) {
         throw new IllegalArgumentException("Cannot apply a non-module element");
       }
     });
diff --git a/src/com/google/inject/ClassBindingImpl.java b/src/com/google/inject/ClassBindingImpl.java
index 5175c3a..8805583 100644
--- a/src/com/google/inject/ClassBindingImpl.java
+++ b/src/com/google/inject/ClassBindingImpl.java
@@ -49,7 +49,7 @@
     injectionPoints = lateBoundConstructor.constructorInjector.getInjectionPoints();
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     checkState(injectionPoints != null, "not initialized");
     return visitor.visitConstructor(this);
   }
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index f020cec..52dc7d4 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -204,7 +204,7 @@
   }
 
   static class ProviderBindingImpl<T> extends BindingImpl<Provider<T>>
-      implements ProviderBinding<T> {
+      implements ProviderBinding<Provider<T>> {
     final BindingImpl<T> providedBinding;
 
     ProviderBindingImpl(InjectorImpl injector, Key<Provider<T>> key, Binding<T> providedBinding) {
@@ -226,7 +226,7 @@
       return providedBinding.getKey();
     }
 
-    public <V> V acceptTargetVisitor(BindingTargetVisitor<Provider<T>, V> visitor) {
+    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super Provider<T>, V> visitor) {
       return visitor.visitProviderBinding(this);
     }
   }
@@ -301,7 +301,7 @@
       return provider;
     }
 
-    public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
       return visitor.visitConvertedConstant(this);
     }
 
@@ -602,8 +602,7 @@
       // These casts are safe. We know T extends Provider<X> and that given Key<Provider<X>>,
       // createProviderBinding() will return BindingImpl<Provider<X>>.
       @SuppressWarnings("unchecked")
-      BindingImpl<T> binding
-          = (BindingImpl<T>) createProviderBinding((Key) key, errors);
+      BindingImpl binding = createProviderBinding((Key) key, errors);
       return binding;
     }
 
diff --git a/src/com/google/inject/internal/ExposedBindingImpl.java b/src/com/google/inject/internal/ExposedBindingImpl.java
index 0e89171..74a9198 100644
--- a/src/com/google/inject/internal/ExposedBindingImpl.java
+++ b/src/com/google/inject/internal/ExposedBindingImpl.java
@@ -41,7 +41,7 @@
     this.privateEnvironment = privateEnvironment;
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitExposed(this);
   }
 
diff --git a/src/com/google/inject/internal/InstanceBindingImpl.java b/src/com/google/inject/internal/InstanceBindingImpl.java
index f8d8f3b..23db481 100644
--- a/src/com/google/inject/internal/InstanceBindingImpl.java
+++ b/src/com/google/inject/internal/InstanceBindingImpl.java
@@ -55,7 +55,7 @@
     return this.provider;
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitInstance(this);
   }
 
diff --git a/src/com/google/inject/internal/LinkedBindingImpl.java b/src/com/google/inject/internal/LinkedBindingImpl.java
index 2b721e2..956115b 100644
--- a/src/com/google/inject/internal/LinkedBindingImpl.java
+++ b/src/com/google/inject/internal/LinkedBindingImpl.java
@@ -37,7 +37,7 @@
     this.targetKey = targetKey;
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitLinkedKey(this);
   }
 
diff --git a/src/com/google/inject/internal/LinkedProviderBindingImpl.java b/src/com/google/inject/internal/LinkedProviderBindingImpl.java
index 13f388f..855c41f 100644
--- a/src/com/google/inject/internal/LinkedProviderBindingImpl.java
+++ b/src/com/google/inject/internal/LinkedProviderBindingImpl.java
@@ -40,7 +40,7 @@
     this.providerKey = providerKey;
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitProviderKey(this);
   }
 
diff --git a/src/com/google/inject/internal/ProviderInstanceBindingImpl.java b/src/com/google/inject/internal/ProviderInstanceBindingImpl.java
index 0f07e90..cb48359 100644
--- a/src/com/google/inject/internal/ProviderInstanceBindingImpl.java
+++ b/src/com/google/inject/internal/ProviderInstanceBindingImpl.java
@@ -49,7 +49,7 @@
     this.providerInstance = providerInstance;
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitProviderInstance(this);
   }
 
diff --git a/src/com/google/inject/internal/UntargettedBindingImpl.java b/src/com/google/inject/internal/UntargettedBindingImpl.java
index f1b96ed..90d7796 100644
--- a/src/com/google/inject/internal/UntargettedBindingImpl.java
+++ b/src/com/google/inject/internal/UntargettedBindingImpl.java
@@ -36,7 +36,7 @@
     super(source, key, scoping);
   }
 
-  public <V> V acceptTargetVisitor(BindingTargetVisitor<T, V> visitor) {
+  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
     return visitor.visitUntargetted(this);
   }
 
diff --git a/src/com/google/inject/spi/BindingTargetVisitor.java b/src/com/google/inject/spi/BindingTargetVisitor.java
index e7dd31f..d69506b 100644
--- a/src/com/google/inject/spi/BindingTargetVisitor.java
+++ b/src/com/google/inject/spi/BindingTargetVisitor.java
@@ -29,55 +29,55 @@
    * Visit a instance binding. The same instance is returned for every injection. This target is
    * found in both module and injector bindings.
    */
-  V visitInstance(InstanceBinding<T> binding);
+  V visitInstance(InstanceBinding<? extends T> binding);
 
   /**
    * Visit a provider instance binding. The provider's {@code get} method is invoked to resolve
    * injections. This target is found in both module and injector bindings.
    */
-  V visitProviderInstance(ProviderInstanceBinding<T> binding);
+  V visitProviderInstance(ProviderInstanceBinding<? extends T> binding);
 
   /**
    * Visit a provider key binding. To resolve injections, the provider key is first resolved, then
    * that provider's {@code get} method is invoked. This target is found in both module and injector
    * bindings.
    */
-  V visitProviderKey(ProviderKeyBinding<T> binding);
+  V visitProviderKey(ProviderKeyBinding<? extends T> binding);
 
   /**
    * Visit a linked key binding. The other key's binding is used to resolve injections. This
    * target is found in both module and injector bindings.
    */
-  V visitLinkedKey(LinkedKeyBinding<T> binding);
+  V visitLinkedKey(LinkedKeyBinding<? extends T> binding);
 
   /**
    * Visit a binding to a key exposed from an enclosed private environment. This target is found in
    * both module and injector bindings.
    */
-  V visitExposed(ExposedBinding<T> binding);
+  V visitExposed(ExposedBinding<? extends T> binding);
 
   /**
    * Visit an untargetted binding. This target is found only on module bindings. It indicates
    * that the injector should use its implicit binding strategies to resolve injections.
    */
-  V visitUntargetted(UntargettedBinding<T> binding);
+  V visitUntargetted(UntargettedBinding<? extends T> binding);
 
   /**
    * Visit a constructor binding. To resolve injections, an instance is instantiated by invoking
    * {@code constructor}. This target is found only on injector bindings.
    */
-  V visitConstructor(ConstructorBinding<T> binding);
+  V visitConstructor(ConstructorBinding<? extends T> binding);
 
   /**
    * Visit a binding created from converting a bound instance to a new type. The source binding
    * has the same binding annotation but a different type. This target is found only on injector
    * bindings.
    */
-  V visitConvertedConstant(ConvertedConstantBinding<T> binding);
+  V visitConvertedConstant(ConvertedConstantBinding<? extends T> binding);
 
   /**
    * Visit a binding to a {@link com.google.inject.Provider} that delegates to the binding for the
    * provided type. This target is found only on injector bindings.
    */
-  V visitProviderBinding(ProviderBinding<?> binding);
+  V visitProviderBinding(ProviderBinding<? extends T> binding);
 }
diff --git a/src/com/google/inject/spi/DefaultBindingTargetVisitor.java b/src/com/google/inject/spi/DefaultBindingTargetVisitor.java
index 9ab15c2..638f1ff 100644
--- a/src/com/google/inject/spi/DefaultBindingTargetVisitor.java
+++ b/src/com/google/inject/spi/DefaultBindingTargetVisitor.java
@@ -30,44 +30,45 @@
  */
 public abstract class DefaultBindingTargetVisitor<T, V> implements BindingTargetVisitor<T, V> {
 
-  protected V visitOther(Binding<T> binding) {
+  protected V visitOther(Binding<? extends T> binding) {
     return null;
   }
 
-  public V visitInstance(InstanceBinding<T> instanceBinding) {
+  public V visitInstance(InstanceBinding<? extends T> instanceBinding) {
     return visitOther(instanceBinding);
   }
 
-  public V visitProviderInstance(ProviderInstanceBinding<T> providerInstanceBinding) {
+  public V visitProviderInstance(ProviderInstanceBinding<? extends T> providerInstanceBinding) {
     return visitOther(providerInstanceBinding);
   }
 
-  public V visitProviderKey(ProviderKeyBinding<T> providerKeyBinding) {
+  public V visitProviderKey(ProviderKeyBinding<? extends T> providerKeyBinding) {
     return visitOther(providerKeyBinding);
   }
 
-  public V visitLinkedKey(LinkedKeyBinding<T> linkedKeyBinding) {
+  public V visitLinkedKey(LinkedKeyBinding<? extends T> linkedKeyBinding) {
     return visitOther(linkedKeyBinding);
   }
 
-  public V visitExposed(ExposedBinding<T> exposedBinding) {
+  public V visitExposed(ExposedBinding<? extends T> exposedBinding) {
     return visitOther(exposedBinding);
   }
 
-  public V visitUntargetted(UntargettedBinding<T> untargettedBinding) {
+  public V visitUntargetted(UntargettedBinding<? extends T> untargettedBinding) {
     return visitOther(untargettedBinding);
   }
 
-  public V visitConstructor(ConstructorBinding<T> constructorBinding) {
+  public V visitConstructor(ConstructorBinding<? extends T> constructorBinding) {
     return visitOther(constructorBinding);
   }
 
-  public V visitConvertedConstant(ConvertedConstantBinding<T> convertedConstantBinding) {
+  public V visitConvertedConstant(ConvertedConstantBinding<? extends T> convertedConstantBinding) {
     return visitOther(convertedConstantBinding);
   }
 
-  @SuppressWarnings("unchecked") // if we visit a ProviderBinding, we know T == Provider<?>
-  public V visitProviderBinding(ProviderBinding<?> providerBinding) {
-    return visitOther((Binding<T>) providerBinding);
+   // javac says it's an error to cast ProviderBinding<? extends T> to Binding<? extends T>
+  @SuppressWarnings("unchecked")
+  public V visitProviderBinding(ProviderBinding<? extends T> providerBinding) {
+    return visitOther((Binding) providerBinding);
   }
 }
diff --git a/src/com/google/inject/spi/Elements.java b/src/com/google/inject/spi/Elements.java
index b999b7d..f1726ce 100644
--- a/src/com/google/inject/spi/Elements.java
+++ b/src/com/google/inject/spi/Elements.java
@@ -61,11 +61,11 @@
 public final class Elements {
   private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
       = new DefaultBindingTargetVisitor<Object, Object>() {
-    @Override public Object visitInstance(InstanceBinding<Object> binding) {
+    @Override public Object visitInstance(InstanceBinding<?> binding) {
       return binding.getInstance();
     }
 
-    @Override protected Object visitOther(Binding<Object> binding) {
+    @Override protected Object visitOther(Binding<?> binding) {
       throw new IllegalArgumentException();
     }
   };
diff --git a/src/com/google/inject/spi/ModuleWriter.java b/src/com/google/inject/spi/ModuleWriter.java
index f0eaf35..6731129 100644
--- a/src/com/google/inject/spi/ModuleWriter.java
+++ b/src/com/google/inject/spi/ModuleWriter.java
@@ -165,42 +165,44 @@
   protected <T> ScopedBindingBuilder bindKeyToTarget(
       final Binding<T> binding, final Binder binder, final Key<T> key) {
     return binding.acceptTargetVisitor(new BindingTargetVisitor<T, ScopedBindingBuilder>() {
-      public ScopedBindingBuilder visitInstance(InstanceBinding<T> binding) {
+      public ScopedBindingBuilder visitInstance(InstanceBinding<? extends T> binding) {
         binder.bind(key).toInstance(binding.getInstance());
         return null;
       }
 
-      public ScopedBindingBuilder visitProviderInstance(ProviderInstanceBinding<T> binding) {
+      public ScopedBindingBuilder visitProviderInstance(
+          ProviderInstanceBinding<? extends T> binding) {
         return binder.bind(key).toProvider(binding.getProviderInstance());
       }
 
-      public ScopedBindingBuilder visitProviderKey(ProviderKeyBinding<T> binding) {
+      public ScopedBindingBuilder visitProviderKey(ProviderKeyBinding<? extends T> binding) {
         return binder.bind(key).toProvider(binding.getProviderKey());
       }
 
-      public ScopedBindingBuilder visitLinkedKey(LinkedKeyBinding<T> binding) {
+      public ScopedBindingBuilder visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
         return binder.bind(key).to(binding.getLinkedKey());
       }
 
-      public ScopedBindingBuilder visitUntargetted(UntargettedBinding<T> binding) {
+      public ScopedBindingBuilder visitUntargetted(UntargettedBinding<? extends T> binding) {
         return binder.bind(key);
       }
 
-      public ScopedBindingBuilder visitExposed(ExposedBinding<T> binding) {
+      public ScopedBindingBuilder visitExposed(ExposedBinding<? extends T> binding) {
         PrivateBinder privateBinder = getPrivateBinder(binding.getPrivateEnvironment());
         privateBinder.withSource(binding.getSource()).expose(key);
         return null;
       }
 
-      public ScopedBindingBuilder visitConvertedConstant(ConvertedConstantBinding<T> binding) {
+      public ScopedBindingBuilder visitConvertedConstant(
+          ConvertedConstantBinding<? extends T> binding) {
         throw new IllegalArgumentException("Non-module element");
       }
 
-      public ScopedBindingBuilder visitConstructor(ConstructorBinding<T> binding) {
+      public ScopedBindingBuilder visitConstructor(ConstructorBinding<? extends T> binding) {
         throw new IllegalArgumentException("Non-module element");
       }
 
-      public ScopedBindingBuilder visitProviderBinding(ProviderBinding<?> binding) {
+      public ScopedBindingBuilder visitProviderBinding(ProviderBinding<? extends T> binding) {
         throw new IllegalArgumentException("Non-module element");
       }
     });
diff --git a/src/com/google/inject/spi/ProviderBinding.java b/src/com/google/inject/spi/ProviderBinding.java
index 2054f8d..caec274 100644
--- a/src/com/google/inject/spi/ProviderBinding.java
+++ b/src/com/google/inject/spi/ProviderBinding.java
@@ -27,13 +27,12 @@
  * @author jessewilson@google.com (Jesse Wilson)
  * @since 2.0
  */
-public interface ProviderBinding<T> extends Binding<Provider<T>> {
+public interface ProviderBinding<T extends Provider<?>> extends Binding<T> {
 
   /**
    * Returns the key whose binding is used to {@link Provider#get provide instances}. That binding
    * can be retrieved from an injector using {@link com.google.inject.Injector#getBinding(Key)
    * Injector.getBinding(providedKey)}
    */
-  Key<? extends T> getProvidedKey();
-
+  Key<?> getProvidedKey();
 }
\ No newline at end of file
diff --git a/test/com/google/inject/spi/BindingTargetVisitorTest.java b/test/com/google/inject/spi/BindingTargetVisitorTest.java
new file mode 100644
index 0000000..6f80495
--- /dev/null
+++ b/test/com/google/inject/spi/BindingTargetVisitorTest.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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 com.google.inject.spi;
+
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import junit.framework.TestCase;
+
+/**
+ * Simple little test that should compile. Ensures that wildcards on the
+ * generics are correct.
+ *
+ * @author phopkins@gmail.com
+ */
+public class BindingTargetVisitorTest extends TestCase {
+  public void testBindingTargetVisitorTypeTest() throws Exception {
+    Injector injector = Guice.createInjector();
+    for (Binding<?> binding : injector.getBindings().values()) {
+      binding.acceptTargetVisitor(new DefaultBindingTargetVisitor<Object, Object>() {});
+    }
+  }
+}
diff --git a/test/com/google/inject/spi/ElementsTest.java b/test/com/google/inject/spi/ElementsTest.java
index 49fb54e..f91f736 100644
--- a/test/com/google/inject/spi/ElementsTest.java
+++ b/test/com/google/inject/spi/ElementsTest.java
@@ -361,7 +361,8 @@
             assertTrue(command instanceof ProviderInstanceBinding);
             assertEquals(Key.get(String.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitProviderInstance(ProviderInstanceBinding<T> binding) {
+              @Override public Void visitProviderInstance(
+                  ProviderInstanceBinding<? extends T> binding) {
                 assertSame(aProvider, binding.getProviderInstance());
                 return null;
               }
@@ -375,7 +376,7 @@
             assertTrue(command instanceof ProviderKeyBinding);
             assertEquals(Key.get(List.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitProviderKey(ProviderKeyBinding<T> binding) {
+              @Override public Void visitProviderKey(ProviderKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(ListProvider.class), binding.getProviderKey());
                 return null;
               }
@@ -389,7 +390,7 @@
             assertTrue(command instanceof ProviderKeyBinding);
             assertEquals(Key.get(Collection.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitProviderKey(ProviderKeyBinding<T> binding) {
+              @Override public Void visitProviderKey(ProviderKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(ListProvider.class), binding.getProviderKey());
                 return null;
               }
@@ -415,7 +416,7 @@
             assertTrue(command instanceof LinkedKeyBinding);
             assertEquals(Key.get(List.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitLinkedKey(LinkedKeyBinding<T> binding) {
+              @Override public Void visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(ArrayList.class), binding.getLinkedKey());
                 return null;
               }
@@ -429,7 +430,7 @@
             assertTrue(command instanceof LinkedKeyBinding);
             assertEquals(Key.get(Map.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitLinkedKey(LinkedKeyBinding<T> binding) {
+              @Override public Void visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(new TypeLiteral<HashMap<Integer, String>>() {}),
                     binding.getLinkedKey());
                 return null;
@@ -444,7 +445,7 @@
             assertTrue(command instanceof LinkedKeyBinding);
             assertEquals(Key.get(Set.class), command.getKey());
             command.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitLinkedKey(LinkedKeyBinding<T> binding) {
+              @Override public Void visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(TreeSet.class, SampleAnnotation.class),
                     binding.getLinkedKey());
                 return null;
@@ -736,7 +737,7 @@
             assertTrue(binding instanceof ExposedBinding);
             assertEquals(arrayList, binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitExposed(ExposedBinding<T> binding) {
+              @Override public Void visitExposed(ExposedBinding<? extends T> binding) {
                 assertEquals(collections, binding.getPrivateEnvironment().getExposedKeys());
                 return null;
               }
@@ -750,7 +751,7 @@
             assertTrue(binding instanceof ExposedBinding);
             assertEquals(collection, binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitExposed(ExposedBinding<T> binding) {
+              @Override public Void visitExposed(ExposedBinding<? extends T> binding) {
                 assertEquals(collections, binding.getPrivateEnvironment().getExposedKeys());
                 return null;
               }
@@ -782,7 +783,7 @@
             assertEquals(a, binding.getKey());
             assertEquals("2 ElementsTest.java", binding.getSource());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitExposed(ExposedBinding<T> binding) {
+              @Override public Void visitExposed(ExposedBinding<? extends T> binding) {
                 assertEquals(ab, binding.getPrivateEnvironment().getExposedKeys());
                 return null;
               }
@@ -797,7 +798,7 @@
             assertEquals(b, binding.getKey());
             assertEquals("2 ElementsTest.java", binding.getSource());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitExposed(ExposedBinding<T> binding) {
+              @Override public Void visitExposed(ExposedBinding<? extends T> binding) {
                 assertEquals(ab, binding.getPrivateEnvironment().getExposedKeys());
                 return null;
               }
diff --git a/test/com/google/inject/spi/FailingTargetVisitor.java b/test/com/google/inject/spi/FailingTargetVisitor.java
index 543ffc8..9cf554a 100644
--- a/test/com/google/inject/spi/FailingTargetVisitor.java
+++ b/test/com/google/inject/spi/FailingTargetVisitor.java
@@ -20,7 +20,7 @@
 import junit.framework.AssertionFailedError;
 
 public class FailingTargetVisitor<T> extends DefaultBindingTargetVisitor<T, Void> {
-  @Override protected Void visitOther(Binding<T> binding) {
+  @Override protected Void visitOther(Binding<? extends T> binding) {
     throw new AssertionFailedError();
   }
 }
diff --git a/test/com/google/inject/spi/SpiBindingsTest.java b/test/com/google/inject/spi/SpiBindingsTest.java
index aed6480..e8cec6b 100644
--- a/test/com/google/inject/spi/SpiBindingsTest.java
+++ b/test/com/google/inject/spi/SpiBindingsTest.java
@@ -78,7 +78,7 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitInstance(InstanceBinding<T> binding) {
+              @Override public Void visitInstance(InstanceBinding<? extends T> binding) {
                 assertEquals("A", binding.getInstance());
                 return null;
               }
@@ -105,7 +105,8 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitProviderInstance(ProviderInstanceBinding<T> binding) {
+              @Override public Void visitProviderInstance(
+                  ProviderInstanceBinding<? extends T> binding) {
                 assertSame(stringProvider, binding.getProviderInstance());
                 return null;
               }
@@ -130,7 +131,7 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitProviderKey(ProviderKeyBinding<T> binding) {
+              @Override public Void visitProviderKey(ProviderKeyBinding<? extends T> binding) {
                 assertEquals(Key.get(StringProvider.class), binding.getProviderKey());
                 return null;
               }
@@ -159,7 +160,7 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(aKey, binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitLinkedKey(LinkedKeyBinding<T> binding) {
+              @Override public Void visitLinkedKey(LinkedKeyBinding<? extends T> binding) {
                 assertEquals(bKey, binding.getLinkedKey());
                 return null;
               }
@@ -191,7 +192,7 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(Key.get(D.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitConstructor(ConstructorBinding<T> binding) {
+              @Override public Void visitConstructor(ConstructorBinding<? extends T> binding) {
                 Constructor<?> expected = D.class.getDeclaredConstructors()[0];
                 assertEquals(expected, binding.getConstructor());
                 return null;
@@ -217,7 +218,7 @@
             assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
             assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
-              @Override public Void visitInstance(InstanceBinding<T> binding) {
+              @Override public Void visitInstance(InstanceBinding<? extends T> binding) {
                 assertEquals(1, binding.getInstance());
                 return null;
               }
@@ -240,7 +241,8 @@
     assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
     assertTrue(binding instanceof ConvertedConstantBinding);
     binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
-      @Override public Void visitConvertedConstant(ConvertedConstantBinding<Integer> binding) {
+      @Override public Void visitConvertedConstant(
+          ConvertedConstantBinding<? extends Integer> binding) {
         assertEquals((Integer) 1, binding.getValue());
         assertEquals(Key.get(String.class, Names.named("one")), binding.getSourceKey());
         return null;
@@ -261,7 +263,8 @@
     assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
     assertTrue(binding instanceof ProviderBinding);
     binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
-      @Override public Void visitProviderBinding(ProviderBinding<?> binding) {
+      @Override public Void visitProviderBinding(
+          ProviderBinding<? extends Provider<String>> binding) {
         assertEquals(Key.get(String.class), binding.getProvidedKey());
         return null;
       }