Fixing a old bug wherein calling "Provider.get()" inside of an existing scope would kill the internal context and leave the injector in an inconsistent state.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@1032 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/internal/InjectorBuilder.java b/src/com/google/inject/internal/InjectorBuilder.java
index cea61dc..0f80f41 100644
--- a/src/com/google/inject/internal/InjectorBuilder.java
+++ b/src/com/google/inject/internal/InjectorBuilder.java
@@ -195,14 +195,14 @@
           injector.callInContext(new ContextualCallable<Void>() {
             Dependency<?> dependency = Dependency.get(binding.getKey());
             public Void call(InternalContext context) {
-              context.setDependency(dependency);
+              Dependency previous = context.setDependency(dependency);
               Errors errorsForBinding = errors.withSource(dependency);
               try {
                 binding.getInternalFactory().get(errorsForBinding, context, dependency);
               } catch (ErrorsException e) {
                 errorsForBinding.merge(e.getErrors());
               } finally {
-                context.setDependency(null);
+                context.setDependency(previous);
               }
 
               return null;
diff --git a/src/com/google/inject/internal/InjectorImpl.java b/src/com/google/inject/internal/InjectorImpl.java
index d986e48..b55014e 100644
--- a/src/com/google/inject/internal/InjectorImpl.java
+++ b/src/com/google/inject/internal/InjectorImpl.java
@@ -727,11 +727,11 @@
         try {
           T t = callInContext(new ContextualCallable<T>() {
             public T call(InternalContext context) throws ErrorsException {
-              context.setDependency(dependency);
+              Dependency previous = context.setDependency(dependency);
               try {
                 return factory.get(errors, context, dependency);
               } finally {
-                context.setDependency(null);
+                context.setDependency(previous);
               }
             }
           });
diff --git a/src/com/google/inject/internal/InternalContext.java b/src/com/google/inject/internal/InternalContext.java
index 40b6132..c772910 100644
--- a/src/com/google/inject/internal/InternalContext.java
+++ b/src/com/google/inject/internal/InternalContext.java
@@ -45,7 +45,9 @@
     return dependency;
   }
 
-  public void setDependency(Dependency dependency) {
+  public Dependency setDependency(Dependency dependency) {
+    Dependency previous = dependency;
     this.dependency = dependency;
+    return previous;
   }
 }
diff --git a/src/com/google/inject/internal/SingleFieldInjector.java b/src/com/google/inject/internal/SingleFieldInjector.java
index 3614105..aa8b73f 100644
--- a/src/com/google/inject/internal/SingleFieldInjector.java
+++ b/src/com/google/inject/internal/SingleFieldInjector.java
@@ -47,7 +47,7 @@
   public void inject(Errors errors, InternalContext context, Object o) {
     errors = errors.withSource(dependency);
 
-    context.setDependency(dependency);
+    Dependency previous = context.setDependency(dependency);
     try {
       Object value = factory.get(errors, context, dependency);
       field.set(o, value);
@@ -56,7 +56,7 @@
     } catch (IllegalAccessException e) {
       throw new AssertionError(e); // a security manager is blocking us, we're hosed
     } finally {
-      context.setDependency(null);
+      context.setDependency(previous);
     }
   }
 }
diff --git a/src/com/google/inject/internal/SingleParameterInjector.java b/src/com/google/inject/internal/SingleParameterInjector.java
index 1f2de9d..9b4cb00 100644
--- a/src/com/google/inject/internal/SingleParameterInjector.java
+++ b/src/com/google/inject/internal/SingleParameterInjector.java
@@ -33,11 +33,11 @@
   }
 
   private T inject(Errors errors, InternalContext context) throws ErrorsException {
-    context.setDependency(dependency);
+    Dependency previous = context.setDependency(dependency);
     try {
       return factory.get(errors.withSource(dependency), context, dependency);
     } finally {
-      context.setDependency(null);
+      context.setDependency(previous);
     }
   }
 
diff --git a/src/com/google/inject/spi/Dependency.java b/src/com/google/inject/spi/Dependency.java
index 8908518..e9d5650 100644
--- a/src/com/google/inject/spi/Dependency.java
+++ b/src/com/google/inject/spi/Dependency.java
@@ -20,6 +20,7 @@
 import com.google.inject.internal.ImmutableSet;
 import com.google.inject.internal.Lists;
 import com.google.inject.internal.Objects;
+import static com.google.inject.internal.Preconditions.checkNotNull;
 import java.util.List;
 import java.util.Set;
 
@@ -39,10 +40,9 @@
   private final boolean nullable;
   private final int parameterIndex;
 
-  Dependency(InjectionPoint injectionPoint, Key<T> key,
-      boolean nullable, int parameterIndex) {
+  Dependency(InjectionPoint injectionPoint, Key<T> key, boolean nullable, int parameterIndex) {
     this.injectionPoint = injectionPoint;
-    this.key = key;
+    this.key = checkNotNull(key, "key");
     this.nullable = nullable;
     this.parameterIndex = parameterIndex;
   }
diff --git a/test/com/google/inject/ScopesTest.java b/test/com/google/inject/ScopesTest.java
index 980a77f..ca354fc 100644
--- a/test/com/google/inject/ScopesTest.java
+++ b/test/com/google/inject/ScopesTest.java
@@ -415,4 +415,31 @@
       return new ProvidedBySingleton();
     }
   }
+
+  public void testScopeThatGetsAnUnrelatedObject() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(B.class);
+        bind(C.class);
+        ProviderGetScope providerGetScope = new ProviderGetScope();
+        requestInjection(providerGetScope);
+        bindScope(CustomScoped.class, providerGetScope);
+      }
+    });
+
+    injector.getInstance(C.class);
+  }
+
+  class ProviderGetScope implements Scope {
+    @Inject Provider<B> bProvider;
+
+    public <T> Provider<T> scope(Key<T> key, final Provider<T> unscoped) {
+      return new Provider<T>() {
+        public T get() {
+          bProvider.get();
+          return unscoped.get();
+        }
+      };
+    }
+  }
 }