Automated g4 rollback of changelist 70738452.

*** Reason for rollback ***

Fix projects that were doing dependency analysis by returning a dependency on the Injector when run on raw Elements (instead of a dependency on @Actual+@Default, even though we didn't know which would really exist).

*** Original change description ***

Automated g4 rollback of changelist 70734332.

*** Reason for rollback ***

Broke a project.

*** Original change description ***

Simplify OptionalBinder implementation to not delegate to a MapBinder.
Instead, bind directly to annotated @Actual/@Default keys.  This is in
preparation for future improvements.

This contains two logical changes:
1) The error message for duplicate actual/default bindings is now the default Guice message, instead of a custom thing in MapBinder.
2) getDependencies now...

***
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=70742247
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java
index 5d4447d..4d4dfac 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/OptionalBinder.java
@@ -17,14 +17,12 @@
 package com.google.inject.multibindings;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.inject.internal.RehashableKeys.Keys.needsRehashing;
-import static com.google.inject.internal.RehashableKeys.Keys.rehash;
 import static com.google.inject.multibindings.Multibinder.checkConfiguration;
 import static com.google.inject.util.Types.newParameterizedType;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
 import com.google.inject.Binder;
 import com.google.inject.Binding;
 import com.google.inject.Inject;
@@ -34,12 +32,9 @@
 import com.google.inject.Provider;
 import com.google.inject.TypeLiteral;
 import com.google.inject.binder.LinkedBindingBuilder;
-import com.google.inject.internal.Errors;
-import com.google.inject.multibindings.Element.Type;
-import com.google.inject.multibindings.MapBinder.RealMapBinder;
 import com.google.inject.spi.BindingTargetVisitor;
 import com.google.inject.spi.Dependency;
-import com.google.inject.spi.HasDependencies;
+import com.google.inject.spi.Element;
 import com.google.inject.spi.ProviderInstanceBinding;
 import com.google.inject.spi.ProviderLookup;
 import com.google.inject.spi.ProviderWithDependencies;
@@ -47,9 +42,14 @@
 import com.google.inject.spi.Toolable;
 import com.google.inject.util.Types;
 
-import java.util.Map;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.reflect.Type;
 import java.util.Set;
 
+import javax.inject.Qualifier;
+
 
 /**
  * An API to bind optional values, optionally with a default value.
@@ -168,6 +168,12 @@
     return (TypeLiteral<Optional<Provider<T>>>) TypeLiteral.get(Types.newParameterizedType(
         Optional.class, newParameterizedType(Provider.class, type.getType())));
   }
+  
+  @SuppressWarnings("unchecked")
+  static <T> Key<Provider<T>> providerOf(Key<T> key) {
+    Type providerT = Types.providerOf(key.getTypeLiteral().getType());
+    return (Key<Provider<T>>) key.ofType(providerT);
+  }
 
   /**
    * Returns a binding builder used to set the default value that will be injected.
@@ -189,6 +195,18 @@
   public abstract LinkedBindingBuilder<T> setBinding();
   
   enum Source { DEFAULT, ACTUAL }
+  
+  @Retention(RUNTIME)
+  @Qualifier
+  @interface Default {
+    String value();
+  }
+
+  @Retention(RUNTIME)
+  @Qualifier
+  @interface Actual {
+    String value();
+  }
 
   /**
    * The actual OptionalBinder plays several roles.  It implements Module to hide that
@@ -199,18 +217,21 @@
     private final Key<Optional<T>> optionalKey;
     private final Key<Optional<javax.inject.Provider<T>>> optionalJavaxProviderKey;
     private final Key<Optional<Provider<T>>> optionalProviderKey;
-    private final Key<Map<Source, Provider<T>>> mapKey;
-    private final RealMapBinder<Source, T> mapBinder;
-    private final Set<Dependency<?>> dependencies;
     private final Provider<Optional<Provider<T>>> optionalProviderT;
-    
+    private final Key<T> defaultKey;
+    private final Key<T> actualKey;
 
     /** the target injector's binder. non-null until initialization, null afterwards */
     private Binder binder;
     /** the default binding, for the SPI. */
-    private Binding<?> defaultBinding;
+    private Binding<T> defaultBinding;
     /** the actual binding, for the SPI */
-    private Binding<?> actualBinding;
+    private Binding<T> actualBinding;
+    
+    /** the dependencies -- initialized with defaults & overridden when tooled. */
+    private Set<Dependency<?>> dependencies;
+    /** the dependencies -- initialized with defaults & overridden when tooled. */
+    private Set<Dependency<?>> providerDependencies;
 
     private RealOptionalBinder(Binder binder, Key<T> typeKey) {
       this.binder = binder;
@@ -219,26 +240,15 @@
       this.optionalKey = typeKey.ofType(optionalOf(literal));
       this.optionalJavaxProviderKey = typeKey.ofType(optionalOfJavaxProvider(literal));
       this.optionalProviderKey = typeKey.ofType(optionalOfProvider(literal));
-      this.mapKey =
-          typeKey.ofType(MapBinder.mapOfProviderOf(TypeLiteral.get(Source.class), literal));
-      this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(mapKey));
       this.optionalProviderT = binder.getProvider(optionalProviderKey);
-      if (typeKey.getAnnotation() != null) {
-        this.mapBinder = (RealMapBinder<Source, T>) MapBinder.newMapBinder(binder,
-            TypeLiteral.get(Source.class), typeKey.getTypeLiteral(), typeKey.getAnnotation());
-      } else if (typeKey.getAnnotationType() != null) {
-        this.mapBinder = (RealMapBinder<Source, T>) MapBinder.newMapBinder(binder,
-            TypeLiteral.get(Source.class), typeKey.getTypeLiteral(), typeKey.getAnnotationType());
-      } else {
-        this.mapBinder = (RealMapBinder<Source, T>) MapBinder.newMapBinder(binder,
-            TypeLiteral.get(Source.class), typeKey.getTypeLiteral());
-      }
-      mapBinder.updateDuplicateKeyMessage(Source.DEFAULT, "OptionalBinder for "
-          + Errors.convert(typeKey)
-          + " called with different setDefault values, from bindings:\n");
-      mapBinder.updateDuplicateKeyMessage(Source.ACTUAL, "OptionalBinder for "
-          + Errors.convert(typeKey)
-          + " called with different setBinding values, from bindings:\n");
+      String name = RealElement.nameOf(typeKey);
+      this.defaultKey = Key.get(typeKey.getTypeLiteral(), new DefaultImpl(name));
+      this.actualKey = Key.get(typeKey.getTypeLiteral(), new ActualImpl(name));
+      // Until the injector initializes us, we don't know what our dependencies are,
+      // so initialize to the whole Injector (like Multibinder, and MapBinder indirectly).
+      this.dependencies = ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
+      this.providerDependencies =
+          ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
     }
     
     /**
@@ -265,82 +275,49 @@
     }
 
     @Override public LinkedBindingBuilder<T> setDefault() {
-      checkConfiguration(!isInitialized(), "already initialized");
-      
+      checkConfiguration(!isInitialized(), "already initialized");      
       addDirectTypeBinding(binder);
-
-      RealElement.BindingBuilder<T> valueBinding = RealElement.addBinding(binder,
-          Element.Type.OPTIONALBINDER, typeKey.getTypeLiteral(), RealElement.nameOf(typeKey));
-      Key<T> valueKey = Key.get(typeKey.getTypeLiteral(), valueBinding.getAnnotation());
-      mapBinder.addBinding(Source.DEFAULT).toProvider(
-          new ValueProvider<T>(valueKey, binder.getProvider(valueKey)));
-      return valueBinding;
+      return binder.bind(defaultKey);
     }
 
     @Override public LinkedBindingBuilder<T> setBinding() {
-      checkConfiguration(!isInitialized(), "already initialized");
-      
+      checkConfiguration(!isInitialized(), "already initialized");      
       addDirectTypeBinding(binder);
-
-      RealElement.BindingBuilder<T> valueBinding = RealElement.addBinding(binder,
-          Element.Type.OPTIONALBINDER, typeKey.getTypeLiteral(), RealElement.nameOf(typeKey));
-      Key<T> valueKey = Key.get(typeKey.getTypeLiteral(), valueBinding.getAnnotation());
-      mapBinder.addBinding(Source.ACTUAL).toProvider(
-          new ValueProvider<T>(valueKey, binder.getProvider(valueKey)));
-      return valueBinding;
-    }
-    
-    /**
-     * Traverses through the dependencies of the providers in order to get to the user's binding.
-     */
-    private Binding<?> getBindingFromMapProvider(Injector injector, Provider<T> mapProvider) {
-      HasDependencies deps = (HasDependencies) mapProvider;
-      Key<?> depKey = Iterables.getOnlyElement(deps.getDependencies()).getKey();
-      // The dep flow is (and will stay this way, until we change the internals) --
-      //    Key[type=Provider<java.lang.String>, annotation=@Element(type=MAPBINDER)]
-      // -> Key[type=String, annotation=@Element(type=MAPBINDER)]
-      // -> Key[type=Provider<String>, annotation=@Element(type=OPTIONALBINDER)]
-      // -> Key[type=String, annotation=@Element(type=OPTIONALBINDER)]
-      // The last one points to the user's binding.
-      for (int i = 0; i < 3; i++) {
-        deps = (HasDependencies) injector.getBinding(depKey);
-        depKey = Iterables.getOnlyElement(deps.getDependencies()).getKey();
-      }
-      return injector.getBinding(depKey);
+      return binder.bind(actualKey);
     }
 
     public void configure(Binder binder) {
       checkConfiguration(!isInitialized(), "OptionalBinder was already initialized");
 
-      final Provider<Map<Source, Provider<T>>> mapProvider = binder.getProvider(mapKey);
       binder.bind(optionalProviderKey).toProvider(
           new RealOptionalBinderProviderWithDependencies<Optional<Provider<T>>>(typeKey) {
         private Optional<Provider<T>> optional;
 
         @Toolable @Inject void initialize(Injector injector) {
           RealOptionalBinder.this.binder = null;
-          Map<Source, Provider<T>> map = mapProvider.get();
-          // Map might be null if duplicates prevented MapBinder from initializing
-          if (map != null) {
-            if (map.containsKey(Source.ACTUAL)) {
-              // TODO(sameb): Consider exposing an option that will allow
-              // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null.
-              // Right now, an ACTUAL binding can convert from present -> absent
-              // if it's bound to a provider that returns null.
-              optional = Optional.fromNullable(map.get(Source.ACTUAL)); 
-            } else if (map.containsKey(Source.DEFAULT)) {
-              optional = Optional.fromNullable(map.get(Source.DEFAULT));
-            } else {
-              optional = Optional.absent();
-            }
-            
-            // Also set up the bindings for the SPI.
-            if (map.containsKey(Source.ACTUAL)) {
-              actualBinding = getBindingFromMapProvider(injector, map.get(Source.ACTUAL));
-            }
-            if (map.containsKey(Source.DEFAULT)) {
-              defaultBinding = getBindingFromMapProvider(injector, map.get(Source.DEFAULT));
-            }
+          actualBinding = injector.getExistingBinding(actualKey);
+          defaultBinding = injector.getExistingBinding(defaultKey);
+          Binding<T> binding = null;
+          if (actualBinding != null) {
+            // TODO(sameb): Consider exposing an option that will allow
+            // ACTUAL to fallback to DEFAULT if ACTUAL's provider returns null.
+            // Right now, an ACTUAL binding can convert from present -> absent
+            // if it's bound to a provider that returns null.
+            binding = actualBinding;
+          } else if (defaultBinding != null) {
+            binding = defaultBinding;
+          }
+          
+          if (binding != null) {
+            optional = Optional.of(binding.getProvider());
+            RealOptionalBinder.this.dependencies =
+                ImmutableSet.<Dependency<?>>of(Dependency.get(binding.getKey()));
+            RealOptionalBinder.this.providerDependencies = 
+                ImmutableSet.<Dependency<?>>of(Dependency.get(providerOf(binding.getKey())));
+          } else {            
+            optional = Optional.absent();
+            RealOptionalBinder.this.dependencies = ImmutableSet.of();
+            RealOptionalBinder.this.providerDependencies = ImmutableSet.of();
           }
         }
         
@@ -349,7 +326,7 @@
         }
 
         public Set<Dependency<?>> getDependencies() {
-          return dependencies;
+          return providerDependencies;
         }
       });
       
@@ -368,7 +345,7 @@
             OptionalBinderBinding<Optional<T>>,
             Provider<Optional<T>> {
       RealOptionalKeyProvider() {
-        super(mapKey);
+        super(typeKey);
       }
       
       public Optional<T> get() {
@@ -416,30 +393,27 @@
         }
       }
 
-      public boolean containsElement(com.google.inject.spi.Element element) {
-        if (mapBinder.containsElement(element)) {
-          return true;
+      public boolean containsElement(Element element) {
+        Key<?> elementKey;
+        if (element instanceof Binding) {
+          elementKey = ((Binding<?>) element).getKey();
+        } else if (element instanceof ProviderLookup) {
+          elementKey = ((ProviderLookup<?>) element).getKey();
         } else {
-          Key<?> elementKey;
-          if (element instanceof Binding) {
-            elementKey = ((Binding<?>) element).getKey();
-          } else if (element instanceof ProviderLookup) {
-            elementKey = ((ProviderLookup<?>) element).getKey();
-          } else {
-            return false; // cannot match;
-          }
-
-          return elementKey.equals(optionalKey)
-              || elementKey.equals(optionalProviderKey)
-              || elementKey.equals(optionalJavaxProviderKey)
-              || matchesTypeKey(element, elementKey)
-              || matchesUserBinding(elementKey);
+          return false; // cannot match;
         }
+
+        return elementKey.equals(optionalKey)
+            || elementKey.equals(optionalProviderKey)
+            || elementKey.equals(optionalJavaxProviderKey)
+            || elementKey.equals(defaultKey)
+            || elementKey.equals(actualKey)
+            || matchesTypeKey(element, elementKey);
       }
     }
     
     /** Returns true if the key & element indicate they were bound by this OptionalBinder. */
-    private boolean matchesTypeKey(com.google.inject.spi.Element element, Key<?> elementKey) {
+    private boolean matchesTypeKey(Element element, Key<?> elementKey) {
       // Just doing .equals(typeKey) isn't enough, because the user can bind that themselves.
       return elementKey.equals(typeKey)
           && element instanceof ProviderInstanceBinding
@@ -447,73 +421,17 @@
               .getUserSuppliedProvider() instanceof RealOptionalBinderProviderWithDependencies);
     }
 
-    /** Returns true if the key indicates this is a user bound value for the optional binder. */
-    private boolean matchesUserBinding(Key<?> elementKey) {
-      return elementKey.getAnnotation() instanceof Element
-          && ((Element) elementKey.getAnnotation()).setName().equals(RealElement.nameOf(typeKey))
-          && ((Element) elementKey.getAnnotation()).type() == Type.OPTIONALBINDER
-          && elementKey.getTypeLiteral().equals(typeKey.getTypeLiteral());
-    }
-
     private boolean isInitialized() {
       return binder == null;
     }
 
     @Override public boolean equals(Object o) {
       return o instanceof RealOptionalBinder
-          && ((RealOptionalBinder<?>) o).mapKey.equals(mapKey);
+          && ((RealOptionalBinder<?>) o).typeKey.equals(typeKey);
     }
 
     @Override public int hashCode() {
-      return mapKey.hashCode();
-    }
-
-    /** A Provider that bases equality & hashcodes off another key. */
-    private static final class ValueProvider<T> implements ProviderWithDependencies<T> {
-      private final Provider<T> provider;
-      private volatile Key<T> key;
-
-      private ValueProvider(Key<T> key, Provider<T> provider) {
-        this.key = key;
-        this.provider = provider;
-      }
-      
-      public T get() {
-        return provider.get();
-      }
-      
-      public Set<Dependency<?>> getDependencies() {
-        return ((HasDependencies) provider).getDependencies();
-      }
-
-      private Key<T> getCurrentKey() {
-        // Every time, check if the key needs rehashing.
-        // If so, update the field as an optimization for next time.
-        Key<T> currentKey = key;
-        if (needsRehashing(currentKey)) {
-          currentKey = rehash(currentKey);
-          key = currentKey;
-        }
-        return currentKey;
-      }
-
-      /**
-       * Equality is based on the key (which includes the target information, because of how
-       * RealElement works). This lets duplicate bindings collapse.
-       */
-      @Override public boolean equals(Object obj) {
-        return obj instanceof ValueProvider
-            && getCurrentKey().equals(((ValueProvider) obj).getCurrentKey());
-      }
-
-      /** We only use the hashcode of the typeliteral, which can't change. */
-      @Override public int hashCode() {
-        return key.getTypeLiteral().hashCode();
-      }
-
-      @Override public String toString() {
-        return provider.toString();
-      }
+      return typeKey.hashCode();
     }
 
     /**
@@ -539,4 +457,55 @@
       }
     }
   }
+  
+  static class DefaultImpl extends BaseAnnotation implements Default {
+    public DefaultImpl(String value) {
+      super(Default.class, value);
+    }
+  }
+  
+  static class ActualImpl extends BaseAnnotation implements Actual {
+    public ActualImpl(String value) {
+      super(Actual.class, value);
+    }
+  }
+  
+  abstract static class BaseAnnotation implements Serializable, Annotation {
+
+    private final String value;
+    private final Class<? extends Annotation> clazz;
+
+    BaseAnnotation(Class<? extends Annotation> clazz, String value) {
+      this.clazz = checkNotNull(clazz, "clazz");
+      this.value = checkNotNull(value, "value");
+    }
+
+    public String value() {
+      return this.value;
+    }
+
+    @Override public int hashCode() {
+      // This is specified in java.lang.Annotation.
+      return (127 * "value".hashCode()) ^ value.hashCode();
+    }
+
+    @Override public boolean equals(Object o) {
+      if (!(clazz.isInstance(o))) {
+        return false;
+      }
+
+      BaseAnnotation other = (BaseAnnotation) o;
+      return value.equals(other.value());
+    }
+
+    @Override public String toString() {
+      return "@" + clazz.getName() + (value.isEmpty() ? "" : "(value=" + value + ")");
+    }
+
+    @Override public Class<? extends Annotation> annotationType() {
+      return clazz;
+    }
+
+    private static final long serialVersionUID = 0;
+  }
 }
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java
index 246c7a3..2529c18 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/OptionalBinderTest.java
@@ -43,6 +43,8 @@
 import com.google.inject.Scopes;
 import com.google.inject.TypeLiteral;
 import com.google.inject.internal.RehashableKeys;
+import com.google.inject.multibindings.OptionalBinder.Actual;
+import com.google.inject.multibindings.OptionalBinder.Default;
 import com.google.inject.multibindings.SpiUtils.VisitType;
 import com.google.inject.name.Named;
 import com.google.inject.name.Names;
@@ -345,11 +347,10 @@
     } catch (CreationException ce) {
       assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
       assertContains(ce.getMessage(),
-          "1) OptionalBinder for java.lang.String called with different setDefault values, " 
-              + "from bindings:",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + MapBinder.RealMapBinder.class.getName());
+          "1) A binding to java.lang.String annotated with @" 
+              + Default.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
     }
   }  
   
@@ -366,11 +367,10 @@
     } catch (CreationException ce) {
       assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
       assertContains(ce.getMessage(),
-          "1) OptionalBinder for java.lang.String called with different setBinding values, " 
-              + "from bindings:",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + MapBinder.RealMapBinder.class.getName());
+          "1) A binding to java.lang.String annotated with @" 
+              + Actual.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
     }
   }  
   
@@ -387,17 +387,16 @@
       Guice.createInjector(module);
       fail();
     } catch (CreationException ce) {
-      assertEquals(ce.getMessage(), 1, ce.getErrorMessages().size());
+      assertEquals(ce.getMessage(), 2, ce.getErrorMessages().size());      
       assertContains(ce.getMessage(),
-          "1) OptionalBinder for java.lang.String called with different setDefault values, " 
-              + "from bindings:",
+          "1) A binding to java.lang.String annotated with @"
+              + Default.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
           "at " + module.getClass().getName() + ".configure(",
-          "at " + module.getClass().getName() + ".configure(",
-          "and OptionalBinder for java.lang.String called with different setBinding values, " 
-              + "from bindings:",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + module.getClass().getName() + ".configure(",
-          "at " + MapBinder.RealMapBinder.class.getName());
+          "2) A binding to java.lang.String annotated with @"
+              + Actual.class.getName() + " was already configured at "
+              + module.getClass().getName() + ".configure(",
+          "at " + module.getClass().getName() + ".configure(");
     }
   }
   
@@ -449,17 +448,27 @@
   }
   
   public void testMultipleDifferentOptionals() {
+    final Key<String> bKey = Key.get(String.class, named("b"));
+    final Key<String> cKey = Key.get(String.class, named("c"));
     Module module = new AbstractModule() {
       @Override protected void configure() {
         OptionalBinder.newOptionalBinder(binder(), String.class).setDefault().toInstance("a");
         OptionalBinder.newOptionalBinder(binder(), Integer.class).setDefault().toInstance(1);
+        
+        OptionalBinder.newOptionalBinder(binder(), bKey).setDefault().toInstance("b");
+        OptionalBinder.newOptionalBinder(binder(), cKey).setDefault().toInstance("c");
       }
     };
     Injector injector = Guice.createInjector(module);
     assertEquals("a", injector.getInstance(String.class));
     assertEquals(1, injector.getInstance(Integer.class).intValue());
+    assertEquals("b", injector.getInstance(bKey));
+    assertEquals("c", injector.getInstance(cKey));
     
-    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 1, instance("a"), null);
+    assertOptionalVisitor(stringKey, setOf(module), VisitType.BOTH, 3, instance("a"), null);
+    assertOptionalVisitor(intKey, setOf(module), VisitType.BOTH, 3, instance(1), null);
+    assertOptionalVisitor(bKey, setOf(module), VisitType.BOTH, 3, instance("b"), null);
+    assertOptionalVisitor(cKey, setOf(module), VisitType.BOTH, 3, instance("c"), null);
   }
   
   public void testOptionalIsAppropriatelyLazy() {
@@ -604,7 +613,7 @@
     }
   }
 
-  public void testDependencies() {
+  public void testDependencies_both() {
     Injector injector = Guice.createInjector(new AbstractModule() {
       @Override protected void configure() {
         OptionalBinder<String> optionalbinder =
@@ -619,7 +628,40 @@
     HasDependencies withDependencies = (HasDependencies) binding;
     Set<String> elements = Sets.newHashSet();
     elements.addAll(recurseForDependencies(injector, withDependencies));
-    assertEquals(ImmutableSet.of("A", "B"), elements);
+    assertEquals(ImmutableSet.of("B"), elements);
+  }
+
+  public void testDependencies_actual() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalbinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalbinder.setBinding().to(Key.get(String.class, Names.named("b")));
+        bindConstant().annotatedWith(Names.named("b")).to("B");
+      }
+    });
+
+    Binding<String> binding = injector.getBinding(Key.get(String.class));
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("B"), elements);
+  }
+
+  public void testDependencies_default() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        OptionalBinder<String> optionalbinder =
+            OptionalBinder.newOptionalBinder(binder(), String.class);
+        optionalbinder.setDefault().toInstance("A");
+      }
+    });
+
+    Binding<String> binding = injector.getBinding(Key.get(String.class));
+    HasDependencies withDependencies = (HasDependencies) binding;
+    Set<String> elements = Sets.newHashSet();
+    elements.addAll(recurseForDependencies(injector, withDependencies));
+    assertEquals(ImmutableSet.of("A"), elements);
   }
   
   private Set<String> recurseForDependencies(Injector injector, HasDependencies hasDependencies) {
@@ -878,7 +920,6 @@
     list.add("C");
     Key<?> keyAfter = binding.getKey();
     assertSame(keyBefore, keyAfter);
-    assertTrue(RehashableKeys.Keys.needsRehashing(keyAfter));
   }
 
   @BindingAnnotation
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
index d121944..9517425 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/SpiUtils.java
@@ -16,7 +16,6 @@
 
 package com.google.inject.multibindings;
 
-import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.inject.multibindings.MapBinder.entryOfProviderOf;
 import static com.google.inject.multibindings.MapBinder.mapOf;
 import static com.google.inject.multibindings.MapBinder.mapOfJavaxProviderOf;
@@ -54,14 +53,12 @@
 import com.google.inject.spi.DefaultBindingTargetVisitor;
 import com.google.inject.spi.Element;
 import com.google.inject.spi.Elements;
-import com.google.inject.spi.HasDependencies;
 import com.google.inject.spi.InstanceBinding;
 import com.google.inject.spi.LinkedKeyBinding;
 import com.google.inject.spi.ProviderInstanceBinding;
 import com.google.inject.spi.ProviderKeyBinding;
 import com.google.inject.spi.ProviderLookup;
 
-import java.lang.reflect.ParameterizedType;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -526,16 +523,11 @@
         keyType.ofType(optionalOfJavaxProvider(keyType.getTypeLiteral()));
     Key<Optional<Provider<T>>> optionalProviderKey =
         keyType.ofType(optionalOfProvider(keyType.getTypeLiteral()));
-    Binding<Map<Source, T>> mapBinding = injector.getBinding(
-        keyType.ofType(mapOf(TypeLiteral.get(Source.class), keyType.getTypeLiteral())));
-    MapBinderBinding<Map<Source, T>> mapbinderBinding = (MapBinderBinding<
-        Map<Source, T>>) mapBinding.acceptTargetVisitor(new Visitor<Map<Source, T>>());
 
     boolean keyMatch = false;
     boolean optionalKeyMatch = false;
     boolean optionalJavaxProviderKeyMatch = false;
     boolean optionalProviderKeyMatch = false;
-    boolean mapBindingMatch = false;
     boolean defaultMatch = false;
     boolean actualMatch = false;
     List<Object> otherOptionalBindings = Lists.newArrayList();
@@ -566,19 +558,12 @@
       } else if (b.getKey().equals(optionalProviderKey)) {
         assertTrue(contains);
         optionalProviderKeyMatch = true;
-      } else if (b.getKey().equals(mapBinding.getKey())) {
-        assertTrue(contains);
-        mapBindingMatch = true;
-        // Validate that this binding is also a MapBinding.
-        assertEquals(mapbinderBinding, b.acceptTargetVisitor(visitor));
       } else if (expectedDefault != null && matches(b, expectedDefault)) {
         assertTrue(contains);
         defaultMatch = true;
       } else if (expectedActual != null && matches(b, expectedActual)) {
         assertTrue(contains);
         actualMatch = true;
-      } else if (mapbinderBinding.containsElement(b)) {
-        assertTrue(contains);
       } else if (contains) {
         otherMatches.add(b);
       }
@@ -590,7 +575,6 @@
     assertTrue(optionalKeyMatch);
     assertTrue(optionalJavaxProviderKeyMatch);
     assertTrue(optionalProviderKeyMatch);
-    assertTrue(mapBindingMatch);
     assertEquals(expectedDefault != null, defaultMatch);
     assertEquals(expectedActual != null, actualMatch);
     assertEquals("other OptionalBindings found: " + otherOptionalBindings,
@@ -605,27 +589,22 @@
     Map<Key<?>, Binding<?>> indexed = index(elements);
     Key<Optional<T>> optionalKey =
         keyType.ofType(OptionalBinder.optionalOf(keyType.getTypeLiteral()));
-    Key<Map<Source, T>> sourceMapKey =
-        keyType.ofType(mapOf(TypeLiteral.get(Source.class), keyType.getTypeLiteral()));
     Visitor<Optional<T>> visitor = new Visitor<Optional<T>>();
     OptionalBinderBinding<T> optionalBinder = null;
-    MapBinderBinding<Map<Source, T>> mapbinderBinding = null;
     Key<?> defaultKey = null;
     Key<?> actualKey = null;
 
     Binding optionalBinding = indexed.get(optionalKey);
     optionalBinder = (OptionalBinderBinding<T>) optionalBinding.acceptTargetVisitor(visitor);
-    Binding mapBinding = indexed.get(sourceMapKey);
-    mapbinderBinding = (MapBinderBinding<Map<Source, T>>) mapBinding.acceptTargetVisitor(visitor);
 
     // Locate the defaultKey & actualKey
     for (Element element : elements) {
       if (optionalBinder.containsElement(element) && element instanceof Binding) {
         Binding binding = (Binding) element;
         if (isSourceEntry(binding, Source.DEFAULT)) {
-          defaultKey = keyFromOptionalSourceBinding(binding, indexed);
+          defaultKey = binding.getKey();
         } else if (isSourceEntry(binding, Source.ACTUAL)) {
-          actualKey = keyFromOptionalSourceBinding(binding, indexed);
+          actualKey = binding.getKey();
         }
       }
     }
@@ -641,7 +620,6 @@
     boolean optionalKeyMatch = false;
     boolean optionalJavaxProviderKeyMatch = false;
     boolean optionalProviderKeyMatch = false;
-    boolean mapBindingMatch = false;
     boolean defaultMatch = false;
     boolean actualMatch = false;
     List<Object> otherOptionalElements = Lists.newArrayList();
@@ -685,11 +663,6 @@
       } else if (key != null && key.equals(optionalProviderKey)) {
         assertTrue(contains);
         optionalProviderKeyMatch = true;
-      } else if (key != null && key.equals(sourceMapKey)) {
-        assertTrue(contains);
-        mapBindingMatch = true;
-        // Validate that this binding is also a MapBinding.
-        assertEquals(mapbinderBinding, b.acceptTargetVisitor(visitor));
       } else if (key != null && key.equals(defaultKey)) {
         assertTrue(contains);
         if (b != null) { // otherwise it might just be a ProviderLookup into it
@@ -703,8 +676,6 @@
           assertTrue("expected: " + expectedActual + ", but was: " + b, matches(b, expectedActual));
           actualMatch = true;
         }
-      } else if (mapbinderBinding.containsElement(element)) {
-        assertTrue(contains);
       } else if (contains) {
         otherContains.add(element);
       }
@@ -715,7 +686,6 @@
     assertTrue(optionalKeyMatch);
     assertTrue(optionalJavaxProviderKeyMatch);
     assertTrue(optionalProviderKeyMatch);
-    assertTrue(mapBindingMatch);
     assertEquals(expectedDefault != null, defaultMatch);
     assertEquals(expectedActual != null, actualMatch);
     assertEquals(otherContains.toString(), 0, otherContains.size());
@@ -725,40 +695,16 @@
      // Validate that we can construct an injector out of the remaining bindings.
     Guice.createInjector(Elements.getModule(nonContainedElements));
   }
-  
-  private static Key<?> keyFromOptionalSourceBinding(Binding<?> binding,
-      Map<Key<?>, Binding<?>> elements) {
-    // Flow is:
-    //  binding == ProviderInstanceBinding<Map.Entry<Source, Provider<String>>
-    //   dependency on: Provider<String> that maps to ProviderInstanceBinding<String> in MapBinder
-    //      dependency on: Provider<String> of user set value.
-    Key<?> mapKey =
-        genericOf(getOnlyElement(((HasDependencies) binding).getDependencies()).getKey());
-    Binding<?> mapBinding = elements.get(mapKey);
-    Key<?> userKey =
-        genericOf(getOnlyElement(((HasDependencies) mapBinding).getDependencies()).getKey());
-    return userKey;
-  }
-
-  /** Returns {@code Key<T>} for something like {@code Key<Provider<T>>} */
-  private static Key<?> genericOf(Key<?> key) {
-    ParameterizedType type = (ParameterizedType) key.getTypeLiteral().getType();
-    assertEquals(1, type.getActualTypeArguments().length);
-    Key<?> result = key.ofType(type.getActualTypeArguments()[0]);
-    return result;
-  }
 
   private static boolean isSourceEntry(Binding b, Source type) {
-    if (b instanceof ProviderInstanceBinding && b.getKey().getAnnotation() instanceof RealElement) {
-      javax.inject.Provider provider = ((ProviderInstanceBinding) b).getUserSuppliedProvider();
-      if (provider instanceof Map.Entry) {
-        Map.Entry entry = (Map.Entry) provider;
-        if (entry.getKey() == type) {
-          return true;
-        }
-      }
+    switch(type) {
+      case ACTUAL:
+        return b.getKey().getAnnotation() instanceof OptionalBinder.Actual;
+      case DEFAULT:
+        return b.getKey().getAnnotation() instanceof OptionalBinder.Default;
+      default:
+        throw new IllegalStateException("invalid type: " + type);
     }
-    return false;
   }
 
   /** Returns the subset of elements that have keys, indexed by them. */