Update MapBinder so it fails on duplicate bindings with a more descriptive error message, including all the keys that had duplicates and where the duplicate bindings were bound.  Example error message that has 'a' bound twice and 'b' bound twice:

1) Map injection failed due to duplicated key "a", from bindings at:
	com.google.inject.multibindings.MapBinderTest.configure(MapBinderTest.java:337) (via modules: com.google.inject.multibindings.MapBinderTest$1Main -> com.google.inject.multibindings.MapBinderTest$1Module1)
	com.google.inject.multibindings.MapBinderTest.configure(MapBinderTest.java:344) (via modules: com.google.inject.multibindings.MapBinderTest$1Main -> com.google.inject.multibindings.MapBinderTest$1Module2)

 and key: "b", from bindings at:
	com.google.inject.multibindings.MapBinderTest.configure(MapBinderTest.java:345) (via modules: com.google.inject.multibindings.MapBinderTest$1Main -> com.google.inject.multibindings.MapBinderTest$1Module2)
	com.google.inject.multibindings.MapBinderTest.configure(MapBinderTest.java:352) (via modules: com.google.inject.multibindings.MapBinderTest$1Main -> com.google.inject.multibindings.MapBinderTest$1Module3)

  at com.google.inject.multibindings.MapBinder.initialize(MapBinder.java:380)
  at com.google.inject.multibindings.MapBinderTest.configure(MapBinderTest.java:357) (via modules: com.google.inject.multibindings.MapBinderTest$1Main -> com.google.inject.multibindings.MapBinder$RealMapBinder)
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=62865462
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
index d423597..f5f1a24 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
@@ -25,11 +25,15 @@
 import static com.google.inject.util.Types.newParameterizedType;
 import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
 
+import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.LinkedHashMultimap;
 import com.google.inject.Binder;
 import com.google.inject.Binding;
 import com.google.inject.Inject;
@@ -38,6 +42,7 @@
 import com.google.inject.Module;
 import com.google.inject.Provider;
 import com.google.inject.TypeLiteral;
+import com.google.inject.internal.Errors;
 import com.google.inject.binder.LinkedBindingBuilder;
 import com.google.inject.multibindings.Multibinder.RealMultibinder;
 import com.google.inject.spi.BindingTargetVisitor;
@@ -302,7 +307,7 @@
    *
    * <p>We use a subclass to hide 'implements Module' from the public API.
    */
-  private static final class RealMapBinder<K, V> extends MapBinder<K, V> implements Module {
+  static final class RealMapBinder<K, V> extends MapBinder<K, V> implements Module {
     private final TypeLiteral<K> keyType;
     private final TypeLiteral<V> valueType;
     private final Key<Map<K, V>> mapKey;
@@ -377,14 +382,39 @@
 
           Map<K, Provider<V>> providerMapMutable = new LinkedHashMap<K, Provider<V>>();
           List<Map.Entry<K, Binding<V>>> bindingsMutable = Lists.newArrayList();
+          Set<K> duplicateKeys = null;
           for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
             Provider<V> previous = providerMapMutable.put(entry.getKey(), entry.getValue());
-            checkConfiguration(previous == null || permitDuplicates,
-                "Map injection failed due to duplicated key \"%s\"", entry.getKey());
+            if (previous != null && !permitDuplicates) {
+              if (duplicateKeys == null) {
+                duplicateKeys = Sets.newHashSet();
+              }
+              duplicateKeys.add(entry.getKey());
+            }
             ProviderMapEntry<K, V> providerEntry = (ProviderMapEntry<K, V>) entry;
             Key<V> valueKey = providerEntry.getValueKey();
             bindingsMutable.add(Maps.immutableEntry(entry.getKey(), injector.getBinding(valueKey)));
           }
+          if (duplicateKeys != null) {
+            Multimap<K, String> dups = LinkedHashMultimap.create();
+            for (Map.Entry<K, Binding<V>> entry : bindingsMutable) {
+              if (duplicateKeys.contains(entry.getKey())) {
+                dups.put(entry.getKey(), "\t" + Errors.convert(entry.getValue().getSource()));
+              }
+            }
+            StringBuilder sb = new StringBuilder("Map injection failed due to duplicated key ");
+            boolean first = true;
+            for (K key : dups.keySet()) {
+              if (first) {
+                first = false;
+                sb.append("\"" + key + "\", from bindings at:\n");
+              } else {
+                sb.append("\n and key: \"" + key + "\", from bindings at:\n");
+              }
+              Joiner.on('\n').appendTo(sb, dups.get(key)).append("\n");
+            }
+            checkConfiguration(false, sb.toString());
+          }
 
           providerMap = ImmutableMap.copyOf(providerMapMutable);
           mapBindings = ImmutableList.copyOf(bindingsMutable);
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
index 31aeac0..caa2e74 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
@@ -16,6 +16,7 @@
 
 package com.google.inject.multibindings;
 
+import static com.google.inject.Asserts.asModuleChain;
 import static com.google.inject.Asserts.assertContains;
 import static com.google.inject.multibindings.SpiUtils.VisitType.BOTH;
 import static com.google.inject.multibindings.SpiUtils.VisitType.MODULE;
@@ -40,6 +41,7 @@
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
+import com.google.inject.Provides;
 import com.google.inject.ProvisionException;
 import com.google.inject.Stage;
 import com.google.inject.TypeLiteral;
@@ -82,7 +84,6 @@
       
   private final TypeLiteral<String> stringType = TypeLiteral.get(String.class);
   private final TypeLiteral<Integer> intType = TypeLiteral.get(Integer.class);
-  private final TypeLiteral<Set<String>> stringSetType = new TypeLiteral<Set<String>>() {};
 
   public void testMapBinderAggregatesMultipleModules() {
     Module abc = new AbstractModule() {
@@ -327,6 +328,56 @@
         instance("a", "A"), instance("a", "B"));
   }
 
+  public void testExhaustiveDuplicateErrorMessage() throws Exception {
+    class Module1 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("a").to(String.class);
+      }
+    }
+    class Module2 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("a").to(Integer.class);
+        mapbinder.addBinding("b").to(String.class);
+      }
+    }
+    class Module3 extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder<String, Object> mapbinder =
+            MapBinder.newMapBinder(binder(), String.class, Object.class);
+        mapbinder.addBinding("b").to(Integer.class);
+      }
+    }
+    class Main extends AbstractModule {
+      @Override protected void configure() {
+        MapBinder.newMapBinder(binder(), String.class, Object.class);
+        install(new Module1());
+        install(new Module2());
+        install(new Module3());
+      }
+      @Provides String provideString() { return "foo"; }
+      @Provides Integer provideInt() { return 42; }
+    }
+    try {
+      Guice.createInjector(new Main());
+      fail();
+    } catch(CreationException ce) {
+      assertContains(ce.getMessage(),
+          "Map injection failed due to duplicated key \"a\", from bindings at:",
+          asModuleChain(Main.class, Module1.class),
+          asModuleChain(Main.class, Module2.class),
+          "and key: \"b\", from bindings at:",
+          asModuleChain(Main.class, Module2.class),
+          asModuleChain(Main.class, Module3.class),
+          "at " + Main.class.getName() + ".configure(",
+          asModuleChain(Main.class, MapBinder.RealMapBinder.class));
+      assertEquals(1, ce.getErrorMessages().size());
+    }
+  }
+
   public void testMapBinderMapPermitDuplicateElements() {
     Module ab = new AbstractModule() {
       @Override protected void configure() {