I haven't fixed the bind out-of-order problem, but I have constrainted it to a much more limited set.

The only problem remaining is when: 
 - a type is bound with a scope: bind(x).asEagerSingleton()
 - that type is needed in creation of another untargetted binding

git-svn-id: https://google-guice.googlecode.com/svn/trunk@425 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/BindCommandProcessor.java b/src/com/google/inject/BindCommandProcessor.java
index ddf9c06..b6f11da 100644
--- a/src/com/google/inject/BindCommandProcessor.java
+++ b/src/com/google/inject/BindCommandProcessor.java
@@ -46,6 +46,7 @@
   private final Stage stage;
   private final Map<Key<?>, BindingImpl<?>> bindings;
   private final Map<Object, Void> outstandingInjections;
+  private final List<Runnable> untargettedBindings = new ArrayList<Runnable>();
 
   BindCommandProcessor(InjectorImpl injector,
       Map<Class<? extends Annotation>, Scope> scopes,
@@ -153,7 +154,7 @@
       }
 
       public Void visitUntargetted() {
-        Type type = key.getTypeLiteral().getType();
+        final Type type = key.getTypeLiteral().getType();
 
         // Error: Missing implementation.
         // Example: bind(Date.class).annotatedWith(Red.class);
@@ -165,20 +166,26 @@
           return null;
         }
 
-        // This cast is safe after the preceeding check.
-        @SuppressWarnings("unchecked")
-        Class<T> clazz = (Class<T>) type;
+        untargettedBindings.add(new Runnable() {
+          public void run() {
+            // This cast is safe after the preceeding check.
+            @SuppressWarnings("unchecked")
+            Class<T> clazz = (Class<T>) type;
 
-        BindingImpl<T> binding = injector.createBindingFromType(clazz, scope, source);
-        // TODO: Should we clean up the binding left behind in jitBindings?
+            BindingImpl<T> binding = injector.createBindingFromType(clazz, scope, source);
+            // TODO: Should we clean up the binding left behind in jitBindings?
 
-        if (binding == null) {
-          addError(source, ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, clazz);
-          createBinding(source, shouldPreload, invalidBinding(injector, key, source));
-          return null;
-        }
+            if (binding == null) {
+              injector.errorHandler.handle(
+                  source, ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, clazz);
+              createBinding(source, shouldPreload, invalidBinding(injector, key, source));
+              return;
+            }
 
-        createBinding(source, shouldPreload, binding);
+            createBinding(source, shouldPreload, binding);
+          }
+        });
+
         return null;
       }
     });
@@ -214,7 +221,7 @@
 
     validateKey(command.getSource(), command.getKey());
     ConstantFactory<Object> factory = new ConstantFactory<Object>(value);
-    putBinding(new ContantBindingImpl<Object>(
+    putBinding(new ConstantBindingImpl<Object>(
         injector, command.getKey(), command.getSource(), factory, value));
 
     return true;
@@ -236,6 +243,12 @@
     }
   }
 
+  public void createUntargettedBindings() {
+    for (Runnable untargettedBinding : untargettedBindings) {
+      untargettedBinding.run();
+    }
+  }
+
   public void createEagerSingletons(InjectorImpl injector) {
     for (ContextualCallable<Void> preloader : eagerSingletonCreators) {
       injector.callInContext(preloader);