Updates the internals of an Element's source to keep track of the Modules that installed it, as well as the complete stack trace leading to the binding. The data is not yet exposed in Element.getSource(), but will be exposed in a future CL.

Technical details:
1) The call stack data is only available for elements created by the binder (excepting Message objects). So, elements that are created at injection time (e.g, JIT bindings, Stage, Injector, Logger, etc.) will not contain these data.
For elements affected, ElementSource.getDeclaringSource() should return what is returned by getSource() currently.
2) In the case of binding builder, similar to the current implementation, ElementSource provides the call stack of builder creation not 'element addition to the binder's elements.'

-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=50247441
diff --git a/core/src/com/google/inject/internal/BindingImpl.java b/core/src/com/google/inject/internal/BindingImpl.java
index 9bcb7e1..76b5b07 100644
--- a/core/src/com/google/inject/internal/BindingImpl.java
+++ b/core/src/com/google/inject/internal/BindingImpl.java
@@ -21,6 +21,7 @@
 import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.spi.BindingScopingVisitor;
+import com.google.inject.spi.ElementSource;
 import com.google.inject.spi.ElementVisitor;
 import com.google.inject.spi.InstanceBinding;
 
@@ -57,6 +58,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/internal/Errors.java b/core/src/com/google/inject/internal/Errors.java
index 13c5cee..f185543 100644
--- a/core/src/com/google/inject/internal/Errors.java
+++ b/core/src/com/google/inject/internal/Errors.java
@@ -31,6 +31,7 @@
 import com.google.inject.internal.util.SourceProvider;
 import com.google.inject.internal.util.StackTraceElements;
 import com.google.inject.spi.Dependency;
+import com.google.inject.spi.ElementSource;
 import com.google.inject.spi.InjectionListener;
 import com.google.inject.spi.InjectionPoint;
 import com.google.inject.spi.Message;
@@ -675,6 +676,9 @@
       });
 
   public static Object convert(Object o) {
+    if (o instanceof ElementSource) {
+      o = ((ElementSource) o).getDeclaringSource();
+    }
     for (Converter<?> converter : converters) {
       if (converter.appliesTo(o)) {
         return converter.convert(o);
@@ -684,6 +688,10 @@
   }
 
   public static void formatSource(Formatter formatter, Object source) {
+    if (source instanceof ElementSource) {
+      source = ((ElementSource) source).getDeclaringSource();
+    }
+
     if (source instanceof Dependency) {
       Dependency<?> dependency = (Dependency<?>) source;
       InjectionPoint injectionPoint = dependency.getInjectionPoint();
diff --git a/core/src/com/google/inject/internal/PrivateElementsImpl.java b/core/src/com/google/inject/internal/PrivateElementsImpl.java
index 6a3d915..bb7eeab 100644
--- a/core/src/com/google/inject/internal/PrivateElementsImpl.java
+++ b/core/src/com/google/inject/internal/PrivateElementsImpl.java
@@ -30,6 +30,7 @@
 import com.google.inject.Key;
 import com.google.inject.PrivateBinder;
 import com.google.inject.spi.Element;
+import com.google.inject.spi.ElementSource;
 import com.google.inject.spi.ElementVisitor;
 import com.google.inject.spi.PrivateElements;
 
@@ -65,6 +66,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/internal/util/SourceProvider.java b/core/src/com/google/inject/internal/util/SourceProvider.java
index b47493a..d627554 100644
--- a/core/src/com/google/inject/internal/util/SourceProvider.java
+++ b/core/src/com/google/inject/internal/util/SourceProvider.java
@@ -16,6 +16,7 @@
 
 package com.google.inject.internal.util;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 
@@ -80,8 +81,9 @@
    * Returns the calling line of code. The selected line is the nearest to the top of the stack that
    * is not skipped.
    */
-  public StackTraceElement get() {
-    for (final StackTraceElement element : new Throwable().getStackTrace()) {
+  public StackTraceElement get(StackTraceElement[] stackTraceElements) {
+    Preconditions.checkNotNull(stackTraceElements, "The stack trace elements cannot be null.");
+    for (final StackTraceElement element : stackTraceElements) {
       String className = element.getClassName();
       
       if (!shouldBeSkipped(className)) {
diff --git a/core/src/com/google/inject/internal/util/StackTraceElements.java b/core/src/com/google/inject/internal/util/StackTraceElements.java
index 4f5b167..80580b5 100644
--- a/core/src/com/google/inject/internal/util/StackTraceElements.java
+++ b/core/src/com/google/inject/internal/util/StackTraceElements.java
@@ -44,7 +44,10 @@
         }
       });
   /*end[AOP]*/
-
+  
+  private static Map<Object, Object> cache = new MapMaker().makeMap();
+  private static final String UNKNOWN_SOURCE = "Unknown Source";
+  
   public static Object forMember(Member member) {
     if (member == null) {
       return SourceProvider.UNKNOWN_SOURCE;
@@ -81,4 +84,122 @@
 
     return new StackTraceElement(implementation.getName(), "class", fileName, lineNumber);
   }
+  
+  /**
+   * Clears the internal cache for {@link StackTraceElement StackTraceElements}.
+   */
+  public static void clearCache() {
+    cache.clear();
+  }
+  
+  /**
+   * Returns encoded in-memory version of {@link StackTraceElement StackTraceElements}.
+   */
+  public static InMemoryStackTraceElement[] convertToInMemoryStackTraceElement(
+      StackTraceElement[] stackTraceElements) {
+    InMemoryStackTraceElement[] inMemoryStackTraceElements = 
+        new InMemoryStackTraceElement[stackTraceElements.length];
+    for (int i = 0; i < stackTraceElements.length; i++) {
+      inMemoryStackTraceElements[i] = 
+          weakIntern(new InMemoryStackTraceElement(stackTraceElements[i]));
+    }
+    return inMemoryStackTraceElements;
+  }
+  
+  /**
+   * Decodes in-memory stack trace elements to regular {@link StackTraceElement StackTraceElements}.
+   */
+  public static StackTraceElement[] convertToStackTraceElement(
+      InMemoryStackTraceElement[] inMemoryStackTraceElements) {
+    StackTraceElement[] stackTraceElements = 
+        new StackTraceElement[inMemoryStackTraceElements.length];
+    for (int i = 0; i < inMemoryStackTraceElements.length; i++) {
+      String declaringClass = inMemoryStackTraceElements[i].getClassName();
+      String methodName = inMemoryStackTraceElements[i].getMethodName();
+      int lineNumber = inMemoryStackTraceElements[i].getLineNumber();
+      stackTraceElements[i] = 
+          new StackTraceElement(declaringClass, methodName, UNKNOWN_SOURCE, lineNumber);
+    }
+    return stackTraceElements;
+  }
+  
+  private static InMemoryStackTraceElement weakIntern(
+      InMemoryStackTraceElement inMemoryStackTraceElement) {
+    InMemoryStackTraceElement cached = 
+        (InMemoryStackTraceElement) cache.get(inMemoryStackTraceElement);
+    if (cached != null) {
+      return cached;
+    }
+    inMemoryStackTraceElement = new InMemoryStackTraceElement(
+        weakIntern(inMemoryStackTraceElement.getClassName()), 
+        weakIntern(inMemoryStackTraceElement.getMethodName()), 
+        inMemoryStackTraceElement.getLineNumber());
+    cache.put(inMemoryStackTraceElement, inMemoryStackTraceElement);
+    return inMemoryStackTraceElement;
+  }
+  
+  private static String weakIntern(String s) {
+    String cached = (String) cache.get(s);
+    if (cached != null) {
+      return cached;
+    }
+    cache.put(s, s);
+    return s;  
+  }
+  
+  /**
+   * In-Memory version of {@link StackTraceElement} that does not store the file name. 
+   */
+  public static class InMemoryStackTraceElement {
+    private String declaringClass;
+    private String methodName;
+    private int lineNumber;
+
+    InMemoryStackTraceElement(StackTraceElement ste) {
+      this(ste.getClassName(), ste.getMethodName(), ste.getLineNumber());
+    }
+
+    InMemoryStackTraceElement(String declaringClass, String methodName, int lineNumber) {
+      this.declaringClass = declaringClass;
+      this.methodName = methodName;
+      this.lineNumber = lineNumber;
+    }
+
+    String getClassName() {
+      return declaringClass;
+    }
+    
+    String getMethodName() {
+      return methodName;
+    }
+    
+    int getLineNumber() {
+      return lineNumber;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof InMemoryStackTraceElement)) {
+        return false;
+      }
+      InMemoryStackTraceElement e = (InMemoryStackTraceElement) obj;
+      return e.declaringClass.equals(declaringClass) && e.lineNumber == lineNumber && 
+          methodName.equals(e.methodName);
+    }
+
+    @Override
+    public int hashCode() {
+      int result = 31 * declaringClass.hashCode() + methodName.hashCode();
+      result = 31 * result + lineNumber;
+      return result;
+    }
+    
+    @Override
+    public String toString() {
+      return declaringClass + "." + methodName + "(" + lineNumber + ")";
+    }
+  }
 }
diff --git a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
index 4193e0a..633d204 100644
--- a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
+++ b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
@@ -34,6 +34,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ElementSource.java b/core/src/com/google/inject/spi/ElementSource.java
new file mode 100644
index 0000000..fff4400
--- /dev/null
+++ b/core/src/com/google/inject/spi/ElementSource.java
@@ -0,0 +1,171 @@
+package com.google.inject.spi;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;
+
+import java.util.List;
+
+/**
+ * Contains information about where and how an {@link Element element} was bound.
+ * <p> 
+ * The {@link #getDeclaringSource() declaring source} refers to a location in source code that 
+ * defines the Guice {@link Element element}. For example, if the element is created from a method
+ * annotated by {@literal @Provides}, the declaring source of element would be the method itself. 
+ * <p>
+ * The creation call stack is the sequence of calls ends at one of {@link Binder} {@code bindXXX()} 
+ * methods and eventually defines the element. Note that {@link #getStackTrace()} lists {@link 
+ * StackTraceElement StackTraceElements} in reverse chronological order. The first element (index 
+ * zero) is the last method call and the last element is the first method invocation.
+ * <p>
+ * The sequence of class names of {@link Module modules} involved in the element creation can be 
+ * retrieved by {@link #getModuleClassNames()}. Similar to the call stack, the order is reverse 
+ * chronological. The first module (index 0) is the module that installs the {@link Element 
+ * element}. The last module is the root module.
+ * <p>
+ * In order to support the cases where a Guice {@link Element element} is created from another
+ * Guice {@link Element element} (original) (e.g., by {@link Element#applyTo()}), it also
+ * provides a reference to the original element source ({@link #getOriginalElementSource()}).
+ */
+public final class ElementSource {
+
+  /** 
+   * The {@link ElementSource source} of element that this element created from (if there is any), 
+   * otherwise {@code null}.
+   */
+  final ElementSource originalElementSource;
+  
+  /** The {@link ModuleSource source} of module creates the element. */
+  final ModuleSource moduleSource;
+  
+  /** 
+   * The partial call stack that starts at the last module {@link Module#Configure(Binder) 
+   * configure(Binder)} call. 
+   */
+  final InMemoryStackTraceElement[] partialCallStack;
+  
+  /** 
+   * Refers to a single location in source code that causes the element creation. It can be any 
+   * object such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, 
+   * etc. For example, if the element is created from a method annotated by {@literal @Provides}, 
+   * the declaring source of element would be the method itself.
+   */
+  final Object declaringSource;
+
+  /**
+   * Creates a new {@ElementSource} from the given parameters. 
+   * @param originalElementSource The source of element that this element created from (if there is 
+   * any), otherwise {@code null}.
+   * @param declaringSource the source (in)directly declared the element.
+   * @param moduleSource the moduleSource when the element is bound
+   * @param partialCallStack the partial call stack from the top module to where the element is 
+   * bound
+   */
+  ElementSource(/* @Nullable */ ElementSource originalSource, Object declaringSource, 
+      ModuleSource moduleSource, StackTraceElement[] partialCallStack) {
+    Preconditions.checkNotNull(moduleSource, "moduleSource cannot be null.");
+    Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null.");
+    Preconditions.checkNotNull(declaringSource, "declaringSource cannot be null.");
+    this.originalElementSource = originalSource;
+    this.moduleSource = moduleSource;
+    this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack);
+    this.declaringSource = declaringSource;
+  }
+  
+  /**
+   * Returns the {@link ElementSource} of the element this was created or copied from.  If this was 
+   * not created or copied from another element, returns {@code null}.
+   */
+  public ElementSource getOriginalElementSource() {
+    return originalElementSource;
+  }
+  
+  /**
+   * Returns a single location in source code that defines the element. It can be any object
+   * such as {@link Constructor}, {@link Method}, {@link Field}, {@link StackTraceElement}, etc. For
+   * example, if the element is created from a method annotated by {@literal @Provides}, the 
+   * declaring source of element would be the method itself.
+   */
+  public Object getDeclaringSource() {
+    return declaringSource;
+  }
+  
+  /**
+   * Returns the class names of modules involved in creating this {@link Element}.  The first
+   * element (index 0) is the class name of module that defined the element, and the last element
+   * is the class name of root module. In the cases where the class name is null an empty string
+   * is returned.
+   */
+  public List<String> getModuleClassNames() {
+    String[] classNames = new String[moduleSource.size()];
+    ModuleSource current = moduleSource;
+    int cursor = 0;
+    while (current != null) {
+      classNames[cursor] = current.getModuleClassName();
+      if (classNames[cursor] == null) {
+          classNames[cursor] = "";
+      }
+      current = current.getParent();
+      cursor++;
+    }
+    return ImmutableList.<String>copyOf(classNames);
+  }
+  
+  /**
+   * Returns the position of {@link Module#configure(Binder) configure(Binder)} method call in the 
+   * {@link #getStackTrace() stack trace} for modules that their classes returned by 
+   * {@link #getModuleClassNames()}. For example, if the stack trace looks like the following:
+   * <p>
+   * {@code
+   *  0 - Binder.bind(),
+   *  1 - ModuleTwo.configure(),
+   *  2 - Binder.install(),
+   *  3 - ModuleOne.configure(),
+   *  4 - theRest(). 
+   * }
+   * <p>
+   * 1 and 3 are returned.   
+   */
+  public List<Integer> getModuleConfigurePositionsInStackTrace() {
+    int size = moduleSource.size();
+    Integer[] positions = new Integer[size];
+    int position = partialCallStack.length;
+    positions[0] = position;
+    ModuleSource current = moduleSource;
+    int cursor = 1;
+    while (cursor < size) {
+      position += current.getPartialCallStack().length;
+      positions[cursor] = position;
+      current = current.getParent();
+      cursor++;
+    }
+    return ImmutableList.<Integer>copyOf(positions);
+  }
+  
+  /**
+   * Returns the sequence of method calls that ends at one of {@link Binder} {@code bindXXX()} 
+   * methods and eventually defines the element. Note that {@link #getStackTrace()} lists {@link 
+   * StackTraceElement StackTraceElements} in reverse chronological order. The first element (index 
+   * zero) is the last method call and the last element is the first method invocation.
+   */
+  public StackTraceElement[] getStackTrace() {
+    int modulesCallStackSize = moduleSource.getStackTraceSize();
+    int chunkSize = partialCallStack.length;
+    int size = moduleSource.getStackTraceSize() + partialCallStack.length;
+    StackTraceElement[] callStack = new StackTraceElement[size];
+    System.arraycopy(
+        StackTraceElements.convertToStackTraceElement(partialCallStack), 0, callStack, 0, 
+        chunkSize);
+    System.arraycopy(moduleSource.getStackTrace(), 0, callStack, chunkSize, modulesCallStackSize);
+    return callStack;
+  }
+  
+  /**
+   * Returns {@code getDeclaringSource().toString()} value.
+   */
+  @Override
+  public String toString() {
+    return getDeclaringSource().toString();
+  }
+}
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
index b11afef..73999b3 100644
--- a/core/src/com/google/inject/spi/Elements.java
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -44,6 +44,7 @@
 import com.google.inject.internal.PrivateElementsImpl;
 import com.google.inject.internal.ProviderMethodsModule;
 import com.google.inject.internal.util.SourceProvider;
+import com.google.inject.internal.util.StackTraceElements;
 import com.google.inject.matcher.Matcher;
 
 import java.lang.annotation.Annotation;
@@ -62,6 +63,19 @@
  * @since 2.0
  */
 public final class Elements {
+
+  private enum IncludeStackTraceFlagValues {
+    // Minimum stack trace collection
+    DEFAULT,
+    // Full stack trace for everything
+    COMPLETE
+  }
+
+  // Use "-Dguice_include_stack_traces={DEFAULT,COMPLETE}" to specify
+  // how guice should collect stack trace data.
+  private static final String guice_include_stack_traces_property =
+       System.getProperty("guice_include_stack_traces", "DEFAULT");
+
   private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
       = new DefaultBindingTargetVisitor<Object, Object>() {
     @Override public Object visit(InstanceBinding<?> binding) {
@@ -102,6 +116,10 @@
     for (Module module : modules) {
       binder.install(module);
     }
+    if (collectCompleteStackTrace()) {
+      // Free the memory consumed by the stack trace elements cache
+      StackTraceElements.clearCache();
+    }
     return Collections.unmodifiableList(binder.elements);
   }
 
@@ -123,11 +141,19 @@
     return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
   }
 
+
+  private static boolean collectCompleteStackTrace() {
+    return IncludeStackTraceFlagValues.COMPLETE.name().equals(
+        guice_include_stack_traces_property);
+  }
+
   private static class RecordingBinder implements Binder, PrivateBinder {
     private final Stage stage;
     private final Set<Module> modules;
     private final List<Element> elements;
     private final Object source;
+    /** The current modules stack */
+    private ModuleSource moduleSource = null;
     private final SourceProvider sourceProvider;
 
     /** The binder where exposed bindings will be created */
@@ -155,6 +181,7 @@
       this.modules = prototype.modules;
       this.elements = prototype.elements;
       this.source = source;
+      this.moduleSource = prototype.moduleSource;
       this.sourceProvider = sourceProvider;
       this.parent = prototype.parent;
       this.privateElements = prototype.privateElements;
@@ -166,6 +193,7 @@
       this.modules = Sets.newHashSet();
       this.elements = privateElements.getElementsMutable();
       this.source = parent.source;
+      this.moduleSource = parent.moduleSource;
       this.sourceProvider = parent.sourceProvider;
       this.parent = parent;
       this.privateElements = privateElements;
@@ -176,12 +204,13 @@
         Matcher<? super Class<?>> classMatcher,
         Matcher<? super Method> methodMatcher,
         org.aopalliance.intercept.MethodInterceptor... interceptors) {
-      elements.add(new InterceptorBinding(getSource(), classMatcher, methodMatcher, interceptors));
+      elements.add(new InterceptorBinding(
+          getElementSource(), classMatcher, methodMatcher, interceptors));
     }
     /*end[AOP]*/
 
     public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
-      elements.add(new ScopeBinding(getSource(), annotationType, scope));
+      elements.add(new ScopeBinding(getElementSource(), annotationType, scope));
     }
 
     @SuppressWarnings("unchecked") // it is safe to use the type literal for the raw type
@@ -190,12 +219,12 @@
     }
 
     public <T> void requestInjection(TypeLiteral<T> type, T instance) {
-      elements.add(new InjectionRequest<T>(getSource(), type, instance));
+      elements.add(new InjectionRequest<T>(getElementSource(), type, instance));
     }
 
     public <T> MembersInjector<T> getMembersInjector(final TypeLiteral<T> typeLiteral) {
       final MembersInjectorLookup<T> element
-          = new MembersInjectorLookup<T>(getSource(), typeLiteral);
+          = new MembersInjectorLookup<T>(getElementSource(), typeLiteral);
       elements.add(element);
       return element.getMembersInjector();
     }
@@ -205,27 +234,30 @@
     }
 
     public void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) {
-      elements.add(new TypeListenerBinding(getSource(), listener, typeMatcher));
+      elements.add(new TypeListenerBinding(getElementSource(), listener, typeMatcher));
     }
-    
+
     public void bindListener(Matcher<? super Binding<?>> bindingMatcher,
         ProvisionListener... listeners) {
-      elements.add(new ProvisionListenerBinding(getSource(), bindingMatcher, listeners));
+      elements.add(new ProvisionListenerBinding(getElementSource(), bindingMatcher, listeners));
     }
 
     public void requestStaticInjection(Class<?>... types) {
       for (Class<?> type : types) {
-        elements.add(new StaticInjectionRequest(getSource(), type));
+        elements.add(new StaticInjectionRequest(getElementSource(), type));
       }
     }
 
     public void install(Module module) {
       if (modules.add(module)) {
         Binder binder = this;
+        // Update the module source for the new module
+        if (!(module instanceof ProviderMethodsModule)) {
+          moduleSource = getModuleSource(module);
+        }
         if (module instanceof PrivateModule) {
           binder = binder.newPrivateBinder();
         }
-
         try {
           module.configure(binder);
         } catch (RuntimeException e) {
@@ -237,6 +269,10 @@
           }
         }
         binder.install(ProviderMethodsModule.forModule(module));
+        // We are done with this module, so undo module source change
+        if (!(module instanceof ProviderMethodsModule)) {
+          moduleSource = moduleSource.getParent();
+        }
       }
     }
 
@@ -245,12 +281,12 @@
     }
 
     public void addError(String message, Object... arguments) {
-      elements.add(new Message(getSource(), Errors.format(message, arguments)));
+      elements.add(new Message(getElementSource(), Errors.format(message, arguments)));
     }
 
     public void addError(Throwable t) {
       String message = "An exception was caught and reported. Message: " + t.getMessage();
-      elements.add(new Message(ImmutableList.of(getSource()), message, t));
+      elements.add(new Message(ImmutableList.of((Object) getElementSource()), message, t));
     }
 
     public void addError(Message message) {
@@ -258,7 +294,7 @@
     }
 
     public <T> AnnotatedBindingBuilder<T> bind(Key<T> key) {
-      return new BindingBuilder<T>(this, elements, getSource(), key);
+      return new BindingBuilder<T>(this, elements, getElementSource(), key);
     }
 
     public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
@@ -270,11 +306,11 @@
     }
 
     public AnnotatedConstantBindingBuilder bindConstant() {
-      return new ConstantBindingBuilderImpl<Void>(this, elements, getSource());
+      return new ConstantBindingBuilderImpl<Void>(this, elements, getElementSource());
     }
 
     public <T> Provider<T> getProvider(final Key<T> key) {
-      final ProviderLookup<T> element = new ProviderLookup<T>(getSource(), key);
+      final ProviderLookup<T> element = new ProviderLookup<T>(getElementSource(), key);
       elements.add(element);
       return element.getProvider();
     }
@@ -285,7 +321,7 @@
 
     public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
         TypeConverter converter) {
-      elements.add(new TypeConverterBinding(getSource(), typeMatcher, converter));
+      elements.add(new TypeConverterBinding(getElementSource(), typeMatcher, converter));
     }
 
     public RecordingBinder withSource(final Object source) {
@@ -303,25 +339,25 @@
     }
 
     public PrivateBinder newPrivateBinder() {
-      PrivateElementsImpl privateElements = new PrivateElementsImpl(getSource());
+      PrivateElementsImpl privateElements = new PrivateElementsImpl(getElementSource());
       elements.add(privateElements);
       return new RecordingBinder(this, privateElements);
     }
-    
+
     public void disableCircularProxies() {
-      elements.add(new DisableCircularProxiesOption(getSource()));
+      elements.add(new DisableCircularProxiesOption(getElementSource()));
     }
-    
+
     public void requireExplicitBindings() {
-      elements.add(new RequireExplicitBindingsOption(getSource()));     
+      elements.add(new RequireExplicitBindingsOption(getElementSource()));
     }
-    
+
     public void requireAtInjectOnConstructors() {
-      elements.add(new RequireAtInjectOnConstructorsOption(getSource()));
+      elements.add(new RequireAtInjectOnConstructorsOption(getElementSource()));
     }
 
     public void requireExactBindingAnnotations() {
-      elements.add(new RequireExactBindingAnnotationsOption(getSource()));
+      elements.add(new RequireExactBindingAnnotationsOption(getElementSource()));
     }
 
     public void expose(Key<?> key) {
@@ -346,15 +382,70 @@
         };
       }
 
-      ExposureBuilder<T> builder = new ExposureBuilder<T>(this, getSource(), key);
+      ExposureBuilder<T> builder = new ExposureBuilder<T>(this, getElementSource(), key);
       privateElements.addExposureBuilder(builder);
       return builder;
     }
 
-    protected Object getSource() {
-      return sourceProvider != null
-          ? sourceProvider.get()
-          : source;
+    private ModuleSource getModuleSource(Module module) {
+      StackTraceElement[] partialCallStack;
+      if (!collectCompleteStackTrace()) {
+        partialCallStack = new StackTraceElement[0];
+      } else {
+        partialCallStack = getPartialCallStack(new Throwable().getStackTrace());
+      }
+      if (moduleSource == null) {
+        return new ModuleSource(module, partialCallStack);
+      }
+      return moduleSource.createChild(module, partialCallStack);
+    }
+
+    private ElementSource getElementSource() {
+      Object declaringSource = source;
+      // Full call stack
+      StackTraceElement[] callStack;
+      // The call stack starts from current top module configure and ends at this method caller
+      StackTraceElement[] partialCallStack;
+      if (!collectCompleteStackTrace()) {
+        callStack = null;
+        partialCallStack = new StackTraceElement[0];
+      } else {
+        callStack = new Throwable().getStackTrace();
+        partialCallStack = getPartialCallStack(callStack);
+      }
+      if (declaringSource == null) {
+        // TODO(salmanmir): can we avoid getting the full stack trace by using modules stack?
+        if (callStack == null) {
+          callStack = new Throwable().getStackTrace();
+        }
+        declaringSource = sourceProvider.get(callStack);
+      }
+      ElementSource originalSource = null;
+      if (declaringSource instanceof ElementSource) {
+        originalSource = (ElementSource) declaringSource;
+        declaringSource = originalSource.getDeclaringSource();
+      }
+      // Build the binding call stack
+      return new ElementSource(
+          originalSource, declaringSource, moduleSource, partialCallStack);
+    }
+
+    /**
+     * Removes the {@link #moduleSource} call stack from the beginning of current call stack. It
+     * also removes the last two elements in order to make {@link #install(Module)} the last call
+     * in the call stack.
+     */
+    private StackTraceElement[] getPartialCallStack(StackTraceElement[] callStack) {
+      int toSkip = 0;
+      if (moduleSource != null) {
+        toSkip = moduleSource.getStackTraceSize();
+      }
+      // -1 for skipping 'getModuleSource' and 'getElementSource' calls
+      int chunkSize = callStack.length - toSkip - 1;
+
+      StackTraceElement[] partialCallStack = new StackTraceElement[chunkSize];
+      System.arraycopy(callStack, 1, partialCallStack, 0, chunkSize);
+      return partialCallStack;
     }
 
     @Override public String toString() {
diff --git a/core/src/com/google/inject/spi/InjectionRequest.java b/core/src/com/google/inject/spi/InjectionRequest.java
index f80e37a..21bd575 100644
--- a/core/src/com/google/inject/spi/InjectionRequest.java
+++ b/core/src/com/google/inject/spi/InjectionRequest.java
@@ -47,6 +47,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/InterceptorBinding.java b/core/src/com/google/inject/spi/InterceptorBinding.java
index a16e701..410eeb1 100644
--- a/core/src/com/google/inject/spi/InterceptorBinding.java
+++ b/core/src/com/google/inject/spi/InterceptorBinding.java
@@ -60,6 +60,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/MembersInjectorLookup.java b/core/src/com/google/inject/spi/MembersInjectorLookup.java
index d4da8bd..5a152fb 100644
--- a/core/src/com/google/inject/spi/MembersInjectorLookup.java
+++ b/core/src/com/google/inject/spi/MembersInjectorLookup.java
@@ -45,6 +45,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ModuleSource.java b/core/src/com/google/inject/spi/ModuleSource.java
new file mode 100644
index 0000000..f5074ba
--- /dev/null
+++ b/core/src/com/google/inject/spi/ModuleSource.java
@@ -0,0 +1,141 @@
+package com.google.inject.spi;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Module;
+import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.internal.util.StackTraceElements.InMemoryStackTraceElement;
+
+/**
+ * Associated to a {@link Module module}, provides the module class name, the parent module {@link
+ * ModuleSource source}, and the call stack that ends just before the module {@link
+ * Module#configure(Binder) configure(Binder)} method invocation.  
+ */
+final class ModuleSource {
+   
+  /**
+   * The class name of module that this {@link ModuleSource} associated to. This value is null when
+   * the module class {@link Class#getName() getName()} returns null.
+   */
+  private final String moduleClassName;
+  
+  /**
+   * The parent {@link ModuleSource module source}.
+   */
+  private final ModuleSource parent;
+  
+  /** 
+   * The chunk of call stack that starts from the parent module {@link Module#configure(Binder) 
+   * configure(Binder)} call and ends just before the module {@link Module#configure(Binder) 
+   * configure(Binder)} method invocation. For a module without a parent module the chunk starts 
+   * from the bottom of call stack.
+   */
+  private final InMemoryStackTraceElement[] partialCallStack;  
+
+  /**
+   * Creates a new {@link ModuleSource} with a {@literal null} parent.
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link 
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link 
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  ModuleSource(Module module, StackTraceElement[] partialCallStack) {
+    this(null, module, partialCallStack);
+  } 
+  
+ /**
+   * Creates a new {@link ModuleSource} Object.
+   * @param parent the parent module {@link ModuleSource source} 
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link 
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link 
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  private ModuleSource(
+      /* @Nullable */ ModuleSource parent, Module module, StackTraceElement[] partialCallStack) {
+    Preconditions.checkNotNull(module, "module cannot be null.");
+    Preconditions.checkNotNull(partialCallStack, "partialCallStack cannot be null.");
+    this.parent = parent;
+    this.moduleClassName = module.getClass().getName();
+    this.partialCallStack = StackTraceElements.convertToInMemoryStackTraceElement(partialCallStack);
+  }
+  
+  /** 
+   * Returns the corresponding module class name. The value can be null.
+   *
+   * @see Class#getName()
+   */
+  String getModuleClassName() {
+    return moduleClassName;
+  }
+
+  /**
+   * Returns the chunk of call stack that starts from the parent module {@link 
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link 
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  StackTraceElement[] getPartialCallStack() {
+    int chunkSize = partialCallStack.length;
+    StackTraceElement[] callStack = new StackTraceElement[chunkSize];
+    System.arraycopy(partialCallStack, 0, callStack, 0, chunkSize);
+    return callStack;
+  }
+  
+  /** 
+   * Creates and returns a child {@link ModuleSource} corresponding to the {@link Module module}.
+   * @param module the corresponding module
+   * @param partialCallStack the chunk of call stack that starts from the parent module {@link 
+   * Module#configure(Binder) configure(Binder)} call and ends just before the module {@link 
+   * Module#configure(Binder) configure(Binder)} method invocation
+   */
+  ModuleSource createChild(Module module, StackTraceElement[] partialCallStack) {
+    return new ModuleSource(this, module, partialCallStack);
+  }
+
+  /** 
+   * Returns the parent module {@link ModuleSource source}. 
+   */
+  ModuleSource getParent() {
+    return parent;
+  }
+  
+  /**
+   * Returns the size of {@link ModuleSource ModuleSources} chain (all parents) that ends at this 
+   * object.
+   */
+  int size() {
+    if (parent == null) {
+      return 1;
+    }
+    return parent.size() + 1;
+  }
+  
+  /**
+   * Returns the size of call stack that ends just before the module {@link Module#configure(Binder)
+   * configure(Binder)} method invocation (see {@link #getStackTrace()}). 
+   */
+  int getStackTraceSize() {
+    if (parent == null) {
+      return partialCallStack.length;
+    }
+    return parent.getStackTraceSize() + partialCallStack.length;  
+  }  
+  
+  /**
+   * Returns the full call stack that ends just before the module {@link Module#configure(Binder) 
+   * configure(Binder)} method invocation. 
+   */
+  StackTraceElement[] getStackTrace() {
+    StackTraceElement[] callStack = new StackTraceElement[getStackTraceSize()];
+    int cursor = 0; // Index 0 stores the top Module.configure() 
+    ModuleSource current = this;
+    while (current != null) {
+      StackTraceElement[] chunk = 
+          StackTraceElements.convertToStackTraceElement(current.partialCallStack);
+      int chunkSize = chunk.length;
+      System.arraycopy(chunk, 0, callStack, cursor, chunkSize);
+      current = current.parent;
+      cursor = cursor + chunkSize;
+    }
+    return callStack;
+  }
+}
diff --git a/core/src/com/google/inject/spi/ProviderLookup.java b/core/src/com/google/inject/spi/ProviderLookup.java
index b9ff7a1..cb58591 100644
--- a/core/src/com/google/inject/spi/ProviderLookup.java
+++ b/core/src/com/google/inject/spi/ProviderLookup.java
@@ -44,6 +44,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ProvisionListenerBinding.java b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
index 4f349d4..33229d8 100644
--- a/core/src/com/google/inject/spi/ProvisionListenerBinding.java
+++ b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
@@ -57,6 +57,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
index 03d8c34..4992a5c 100644
--- a/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
+++ b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
@@ -35,6 +35,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
index ee52cfc..afab64b 100644
--- a/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
+++ b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
@@ -34,6 +34,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
index 5962eb7..812ee43 100644
--- a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
+++ b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
@@ -34,6 +34,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ScopeBinding.java b/core/src/com/google/inject/spi/ScopeBinding.java
index 86ed685..ad062f1 100644
--- a/core/src/com/google/inject/spi/ScopeBinding.java
+++ b/core/src/com/google/inject/spi/ScopeBinding.java
@@ -46,6 +46,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/StaticInjectionRequest.java b/core/src/com/google/inject/spi/StaticInjectionRequest.java
index 87e5376..97c4e42 100644
--- a/core/src/com/google/inject/spi/StaticInjectionRequest.java
+++ b/core/src/com/google/inject/spi/StaticInjectionRequest.java
@@ -43,6 +43,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/TypeConverterBinding.java b/core/src/com/google/inject/spi/TypeConverterBinding.java
index f4925a5..e8c8b17 100644
--- a/core/src/com/google/inject/spi/TypeConverterBinding.java
+++ b/core/src/com/google/inject/spi/TypeConverterBinding.java
@@ -46,6 +46,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/TypeListenerBinding.java b/core/src/com/google/inject/spi/TypeListenerBinding.java
index 8ad4672..752d495 100644
--- a/core/src/com/google/inject/spi/TypeListenerBinding.java
+++ b/core/src/com/google/inject/spi/TypeListenerBinding.java
@@ -54,6 +54,9 @@
   }
 
   public Object getSource() {
+    if (source instanceof ElementSource) {
+      return ((ElementSource) source).getDeclaringSource();
+    }
     return source;
   }
 
diff --git a/core/test/com/google/inject/AllTests.java b/core/test/com/google/inject/AllTests.java
index d6b59f3..2030726 100644
--- a/core/test/com/google/inject/AllTests.java
+++ b/core/test/com/google/inject/AllTests.java
@@ -25,11 +25,13 @@
 import com.google.inject.name.NamesTest;
 import com.google.inject.spi.BindingTargetVisitorTest;
 import com.google.inject.spi.ElementApplyToTest;
+import com.google.inject.spi.ElementSourceTest;
 import com.google.inject.spi.ElementsTest;
 import com.google.inject.spi.HasDependenciesTest;
 import com.google.inject.spi.InjectionPointTest;
 import com.google.inject.spi.InjectorSpiTest;
 import com.google.inject.spi.ModuleRewriterTest;
+import com.google.inject.spi.ModuleSourceTest;
 import com.google.inject.spi.ProviderMethodsTest;
 import com.google.inject.spi.SpiBindingsTest;
 import com.google.inject.spi.ToolStageInjectorTest;
@@ -125,6 +127,8 @@
     suite.addTestSuite(ProviderMethodsTest.class);
     suite.addTestSuite(SpiBindingsTest.class);
     suite.addTestSuite(ToolStageInjectorTest.class);
+    suite.addTestSuite(ModuleSourceTest.class);
+    suite.addTestSuite(ElementSourceTest.class);
 
     // tools
     // suite.addTestSuite(JmxTest.class); not a testcase
diff --git a/core/test/com/google/inject/spi/ElementSourceTest.java b/core/test/com/google/inject/spi/ElementSourceTest.java
new file mode 100644
index 0000000..6406b2a
--- /dev/null
+++ b/core/test/com/google/inject/spi/ElementSourceTest.java
@@ -0,0 +1,159 @@
+package com.google.inject.spi;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Module;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+
+/**
+ * Tests for {@link ElementSource}.
+ */
+public class ElementSourceTest extends TestCase {
+
+  private static final StackTraceElement BINDER_INSTALL = 
+      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", 
+          "Unknown Source", 234 /* line number*/);
+  
+  public void testCallStackSize() {
+    ModuleSource moduleSource = createModuleSource();
+    StackTraceElement[] bindingCallStack = new StackTraceElement[3];
+    bindingCallStack[0] = new StackTraceElement(
+        "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 200);
+    bindingCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 100);
+    bindingCallStack[2] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$C", "configure", "Unknown Source", 100);
+    ElementSource elementSource = new ElementSource(
+        null /* No original element source */, "" /* Don't care */, moduleSource, bindingCallStack);
+    assertEquals(10 /* call stack size */, elementSource.getStackTrace().length);
+  }  
+
+  public void testSourceIsNotElementSource() {
+    List<Element> elements = Elements.getElements(new A());
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
+        if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
+          assertFalse("Source can not be an ElementSource.", 
+              binding.getSource() instanceof ElementSource);
+        }
+      }
+    }
+  }  
+  
+  // TODO(salmanmir): uncomment this test when the above test is removed.
+//  public void testGetCallStack_integrationTest() {
+//    List<Element> elements = Elements.getElements(new A());
+//    for (Element element : elements) {
+//      if (element instanceof Binding) {
+//        Binding<?> binding = (Binding<?>) element;
+//        Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
+//        if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
+//          ElementSource elementSource = (ElementSource) binding.getSource();
+//          StackTraceElement[] callStack = elementSource.getStackTrace();
+//          // check call stack size
+//          int skippedCallStackSize = new Throwable().getStackTrace().length - 1;
+//          assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length);
+//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+//              callStack[0].getClassName());
+//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+//              callStack[1].getClassName());
+//          assertEquals("com.google.inject.AbstractModule",
+//              callStack[2].getClassName());
+//          // Module C
+//          assertEquals("com.google.inject.spi.ElementSourceTest$C",
+//              callStack[3].getClassName());
+//          assertEquals("configure",
+//              callStack[3].getMethodName());
+//          assertEquals("Unknown Source",
+//              callStack[3].getFileName());
+//          assertEquals("com.google.inject.AbstractModule",
+//              callStack[4].getClassName());
+//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+//              callStack[5].getClassName());
+//          // Module B
+//          assertEquals("com.google.inject.spi.ElementSourceTest$B",
+//              callStack[6].getClassName());
+//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+//              callStack[7].getClassName());
+//          // Module A
+//          assertEquals("com.google.inject.AbstractModule",
+//              callStack[8].getClassName());
+//          assertEquals("com.google.inject.spi.ElementSourceTest$A",
+//              callStack[9].getClassName());
+//          assertEquals("com.google.inject.AbstractModule",
+//              callStack[10].getClassName());
+//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+//              callStack[11].getClassName());
+//          assertEquals("com.google.inject.spi.Elements",
+//              callStack[12].getClassName());
+//          assertEquals("com.google.inject.spi.Elements",
+//              callStack[13].getClassName());
+//          assertEquals("com.google.inject.spi.ElementSourceTest",
+//              callStack[14].getClassName());
+//          return;
+//        }
+//      }
+//    }
+//  fail("The test should not reach this line.");
+//  }  
+
+  private ModuleSource createModuleSource() {
+    // First module
+    StackTraceElement[] partialCallStack = new StackTraceElement[1];
+    partialCallStack[0] = BINDER_INSTALL;    
+    ModuleSource moduleSource = new ModuleSource(new A(), partialCallStack);
+    // Second module 
+    partialCallStack = new StackTraceElement[2];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100);
+    moduleSource = moduleSource.createChild(new B(), partialCallStack);    
+    // Third module
+    partialCallStack = new StackTraceElement[4];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1);
+    partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2);
+    partialCallStack[3] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200);
+    return moduleSource.createChild(new C(), partialCallStack);
+  }
+
+  private static class A extends AbstractModule {
+    @Override
+    public void configure() {
+      install(new B());
+    }
+  }
+  
+  private static class B implements Module {
+    @Override
+    public void configure(Binder binder) {
+      binder.install(new C());
+    }
+  }
+  
+  @Retention(RUNTIME)
+  @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
+  @BindingAnnotation
+  @interface SampleAnnotation { }
+
+  private static class C extends AbstractModule {
+    @Override
+    public void configure() {
+      bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("the value");
+    }
+  }  
+}
diff --git a/core/test/com/google/inject/spi/ElementsTest.java b/core/test/com/google/inject/spi/ElementsTest.java
index 57b844c..53eeb82 100644
--- a/core/test/com/google/inject/spi/ElementsTest.java
+++ b/core/test/com/google/inject/spi/ElementsTest.java
@@ -939,11 +939,11 @@
         new FailingElementVisitor() {
           @Override public Void visit(PrivateElements two) {
             assertEquals(ab, two.getExposedKeys());
-            assertEquals("1 ElementsTest.java", two.getSource());
+            assertEquals("1 ElementsTest.java", two.getSource().toString());
             checkElements(two.getElements(),
                 new FailingElementVisitor() {
                   @Override public <T> Void visit(Binding<T> binding) {
-                    assertEquals("2 ElementsTest.java", binding.getSource());
+                    assertEquals("2 ElementsTest.java", binding.getSource().toString());
                     assertEquals(Key.get(List.class), binding.getKey());
                     return null;
                   }
diff --git a/core/test/com/google/inject/spi/ModuleSourceTest.java b/core/test/com/google/inject/spi/ModuleSourceTest.java
new file mode 100644
index 0000000..b72d976
--- /dev/null
+++ b/core/test/com/google/inject/spi/ModuleSourceTest.java
@@ -0,0 +1,125 @@
+package com.google.inject.spi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binder;
+import com.google.inject.Module;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link ModuleSource}.
+ */
+public class ModuleSourceTest extends TestCase {
+
+  private static final StackTraceElement BINDER_INSTALL = 
+      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", 
+          "Unknown Source", 235 /* line number*/);
+  
+  public void testOneModule() {
+    ModuleSource moduleSource = createWithSizeOne();
+    checkSizeOne(moduleSource);    
+  }
+  
+  public void testTwoModules() {
+    ModuleSource moduleSource = createWithSizeTwo();
+    checkSizeTwo(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeOne(moduleSource);
+  }
+  
+  public void testThreeModules() {
+    ModuleSource moduleSource = createWithSizeThree();
+    checkSizeThree(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeTwo(moduleSource);
+    moduleSource = moduleSource.getParent();
+    checkSizeOne(moduleSource);
+  }
+
+  private void checkSizeOne(ModuleSource moduleSource) {
+    assertEquals(1, moduleSource.size());
+    assertEquals(1, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+  }
+  
+  private void checkSizeTwo(ModuleSource moduleSource) {
+    assertEquals(2, moduleSource.size());
+    assertEquals(3, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100),
+        callStack[1]);
+    assertEquals(BINDER_INSTALL, callStack[2]);    
+  }
+  
+  private void checkSizeThree(ModuleSource moduleSource) {
+    assertEquals(3, moduleSource.size());
+    assertEquals(7, moduleSource.getStackTraceSize());
+    // Check call stack
+    StackTraceElement[] callStack = moduleSource.getStackTrace();
+    assertEquals(BINDER_INSTALL, callStack[0]);    
+    assertEquals(new StackTraceElement("class1", "method1", "Unknown Source", 1), callStack[1]);
+    assertEquals(new StackTraceElement("class2", "method2", "Unknown Source", 2), callStack[2]);   
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200),
+            callStack[3]); 
+    assertEquals(BINDER_INSTALL, callStack[4]);    
+
+    assertEquals(
+        new StackTraceElement(
+            "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100),
+        callStack[5]);
+    assertEquals(BINDER_INSTALL, callStack[6]);    
+  }
+  
+  private ModuleSource createWithSizeOne() {
+    StackTraceElement[] partialCallStack = new StackTraceElement[1];
+    partialCallStack[0] = BINDER_INSTALL;    
+    return new ModuleSource(new A(), partialCallStack);
+  }
+  
+  private ModuleSource createWithSizeTwo() {
+    ModuleSource moduleSource = createWithSizeOne();
+    StackTraceElement[] partialCallStack = new StackTraceElement[2];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$A", "configure", "moduleSourceTest.java", 100);
+    return moduleSource.createChild(new B(), partialCallStack);
+  }
+    
+  private ModuleSource createWithSizeThree() {
+    ModuleSource moduleSource = createWithSizeTwo();
+    StackTraceElement[] partialCallStack = new StackTraceElement[4];
+    partialCallStack[0] = BINDER_INSTALL;
+    partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1);
+    partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2);
+    partialCallStack[3] = new StackTraceElement(
+        "com.google.inject.spi.moduleSourceTest$B", "configure", "moduleSourceTest.java", 200);
+    return moduleSource.createChild(new C(), partialCallStack);
+  }
+
+  private static class A extends AbstractModule {
+    @Override
+    public void configure() {
+      install(new B());
+    }
+  }
+  
+  private static class B implements Module {
+    @Override
+    public void configure(Binder binder) {
+      binder.install(new C());
+    }
+  }
+  
+  private static class C extends AbstractModule {
+    @Override
+    public void configure() {}
+  }
+}