Aspects can get information from their base rule.

--
MOS_MIGRATED_REVID=102126786
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
new file mode 100644
index 0000000..0cffc4c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
@@ -0,0 +1,79 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.analysis;
+
+import com.google.devtools.build.lib.packages.AspectParameters;
+
+import java.util.Objects;
+
+/**
+ * Wrapper around {@link ConfiguredAspectFactory} class and {@link AspectParameters}. Aspects are
+ * created with help of aspect factory instances and parameters are used to configure them, so we
+ * have to keep them together. 
+ */
+public final class AspectWithParameters {
+  // TODO(bazel-team): class objects are not really hashable or comparable for equality other than
+  // by reference. We should identify the aspect here in a way that does not rely on comparison
+  // by reference so that keys can be serialized and deserialized properly.
+  private final Class<? extends ConfiguredAspectFactory> aspectFactory;
+  private final AspectParameters parameters;
+
+  public AspectWithParameters(
+      Class<? extends ConfiguredAspectFactory> aspect, AspectParameters parameters) {
+    this.aspectFactory = aspect;
+    this.parameters = parameters;
+  }
+
+  public AspectWithParameters(Class<? extends ConfiguredAspectFactory> aspect) {
+    this.aspectFactory = aspect;
+    this.parameters = AspectParameters.EMPTY;
+  }
+
+  /**
+   * Returns the aspectFactory required for building the aspect.
+   */
+  public Class<? extends ConfiguredAspectFactory> getAspectFactory() {
+    return aspectFactory;
+  }
+
+  /**
+   * Returns parameters for evaluation of the aspect.
+   */
+  public AspectParameters getParameters() {
+    return parameters;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    if (!(other instanceof AspectWithParameters)) {
+      return false;
+    }
+    AspectWithParameters that = (AspectWithParameters) other;
+    return Objects.equals(this.aspectFactory, that.aspectFactory) 
+        && Objects.equals(this.parameters, that.parameters);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(aspectFactory, parameters);
+  }
+
+  @Override
+  public String toString() {
+    return String.format("AspectWithParameters %s(%s)", aspectFactory, parameters);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index b27c2f3..a7fff98 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -877,8 +877,8 @@
     TargetAndConfiguration ctNode = new TargetAndConfiguration(target);
     ListMultimap<Attribute, Dependency> depNodeNames;
     try {
-      depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(), null,
-          getConfigurableAttributeKeys(ctNode));
+      depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(),
+          /*aspect=*/null, /*aspectParameters=*/null, getConfigurableAttributeKeys(ctNode));
     } catch (EvalException e) {
       throw new IllegalStateException(e);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index f193298..9cce2f3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
 import com.google.devtools.build.lib.packages.InputFile;
@@ -280,8 +281,10 @@
   public Aspect createAspect(
       AnalysisEnvironment env, RuleConfiguredTarget associatedTarget,
       ConfiguredAspectFactory aspectFactory,
+      AspectParameters aspectParameters,
       ListMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
-      Set<ConfigMatchingProvider> configConditions, BuildConfiguration hostConfiguration) {
+      Set<ConfigMatchingProvider> configConditions,
+      BuildConfiguration hostConfiguration) {
     RuleContext.Builder builder = new RuleContext.Builder(env,
         associatedTarget.getTarget(),
         associatedTarget.getConfiguration(),
@@ -297,7 +300,7 @@
       return null;
     }
 
-    return aspectFactory.create(associatedTarget, ruleContext);
+    return aspectFactory.create(associatedTarget, ruleContext, aspectParameters);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index 9b6ea93..f8ec20a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -26,6 +26,7 @@
 import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
 import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
@@ -100,7 +101,7 @@
     private final Attribute.Transition transition;
 
     private final boolean hasStaticConfiguration;
-    private final ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects;
+    private final ImmutableSet<AspectWithParameters> aspects;
 
     /**
      * Constructs a Dependency with a given configuration (suitable for static configuration
@@ -108,7 +109,7 @@
      */
     public Dependency(Label label,
         @Nullable BuildConfiguration configuration,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       this.label = Preconditions.checkNotNull(label);
       this.configuration = configuration;
       this.transition = null;
@@ -121,14 +122,14 @@
      * builds).
      */
     public Dependency(Label label, @Nullable BuildConfiguration configuration) {
-      this(label, configuration, ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of());
+      this(label, configuration, ImmutableSet.<AspectWithParameters>of());
     }
 
     /**
      * Constructs a Dependency with a given transition (suitable for dynamic configuration builds).
      */
     public Dependency(Label label, Attribute.Transition transition,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       this.label = Preconditions.checkNotNull(label);
       this.configuration = null;
       this.transition = Preconditions.checkNotNull(transition);
@@ -165,7 +166,7 @@
       return transition;
     }
 
-    public ImmutableSet<Class<? extends ConfiguredAspectFactory>> getAspects() {
+    public ImmutableSet<AspectWithParameters> getAspects() {
       return aspects;
     }
 
@@ -217,7 +218,7 @@
    */
   public final ListMultimap<Attribute, Dependency> dependentNodeMap(
       TargetAndConfiguration node, BuildConfiguration hostConfig, AspectDefinition aspect,
-      Set<ConfigMatchingProvider> configConditions)
+      AspectParameters aspectParameters, Set<ConfigMatchingProvider> configConditions)
       throws EvalException {
     Target target = node.getTarget();
     BuildConfiguration config = node.getConfiguration();
@@ -237,7 +238,7 @@
       Rule rule = (Rule) target;
       ListMultimap<Attribute, LabelAndConfiguration> labelMap =
           resolveAttributes(rule, aspect, config, hostConfig, configConditions);
-      visitRule(rule, aspect, labelMap, outgoingEdges);
+      visitRule(rule, aspect, aspectParameters, labelMap, outgoingEdges);
     } else if (target instanceof PackageGroup) {
       visitPackageGroup(node, (PackageGroup) target, outgoingEdges.get(null));
     } else {
@@ -502,8 +503,8 @@
       TargetAndConfiguration node, BuildConfiguration hostConfig,
       Set<ConfigMatchingProvider> configConditions) {
     try {
-      return ImmutableSet.copyOf(
-          dependentNodeMap(node, hostConfig, null, configConditions).values());
+      return ImmutableSet.copyOf(dependentNodeMap(node, hostConfig, /*aspect=*/null,
+          /*aspectParameters=*/null, configConditions).values());
     } catch (EvalException e) {
       throw new IllegalStateException(e);
     }
@@ -516,12 +517,12 @@
    * @throws IllegalArgumentException if the {@code node} does not refer to a {@link Rule} instance
    */
   public final Collection<Dependency> resolveRuleLabels(
-      TargetAndConfiguration node, AspectDefinition aspect, ListMultimap<Attribute,
+      TargetAndConfiguration node, ListMultimap<Attribute,
       LabelAndConfiguration> labelMap) {
     Preconditions.checkArgument(node.getTarget() instanceof Rule);
     Rule rule = (Rule) node.getTarget();
     ListMultimap<Attribute, Dependency> outgoingEdges = ArrayListMultimap.create();
-    visitRule(rule, aspect, labelMap, outgoingEdges);
+    visitRule(rule, labelMap, outgoingEdges);
     return outgoingEdges.values();
   }
 
@@ -548,39 +549,59 @@
     }
   }
 
-  private ImmutableSet<Class<? extends ConfiguredAspectFactory>> requiredAspects(
-      AspectDefinition aspect, Attribute attribute, Target target) {
+  private ImmutableSet<AspectWithParameters> requiredAspects(AspectDefinition aspectDefinition,
+      AspectParameters aspectParameters, Attribute attribute, Target target, Rule originalRule) {
     if (!(target instanceof Rule)) {
       return ImmutableSet.of();
     }
 
+    Set<AspectWithParameters> aspectCandidates =
+        extractAspectCandidates(aspectDefinition, aspectParameters, attribute, originalRule);
     RuleClass ruleClass = ((Rule) target).getRuleClassObject();
+    ImmutableSet.Builder<AspectWithParameters> result = ImmutableSet.builder();
+    for (AspectWithParameters candidateClass : aspectCandidates) {
+      ConfiguredAspectFactory candidate =
+          (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass.getAspectFactory());
+      if (Sets.difference(
+          candidate.getDefinition().getRequiredProviders(),
+          ruleClass.getAdvertisedProviders()).isEmpty()) {
+        result.add(candidateClass);
+      }
+    }
+    return result.build();
+  }
 
+  private static Set<AspectWithParameters> extractAspectCandidates(
+      AspectDefinition aspectDefinition, AspectParameters aspectParameters,
+      Attribute attribute, Rule originalRule) {
     // The order of this set will be deterministic. This is necessary because this order eventually
     // influences the order in which aspects are merged into the main configured target, which in
     // turn influences which aspect takes precedence if two emit the same provider (maybe this
     // should be an error)
-    Set<Class<? extends AspectFactory<?, ?, ?>>> aspectCandidates = new LinkedHashSet<>();
-    aspectCandidates.addAll(attribute.getAspects());
-    if (aspect != null) {
-      aspectCandidates.addAll(aspect.getAttributeAspects().get(attribute.getName()));
+    Set<AspectWithParameters> aspectCandidates = new LinkedHashSet<>();
+    for (Map.Entry<Class<? extends AspectFactory<?, ?, ?>>, AspectParameters> aspectWithParameters :
+      attribute.getAspectsWithParameters(originalRule).entrySet()) {
+      aspectCandidates.add(new AspectWithParameters(
+          aspectWithParameters.getKey().asSubclass(ConfiguredAspectFactory.class),
+          aspectWithParameters.getValue()));
     }
-
-    ImmutableSet.Builder<Class<? extends ConfiguredAspectFactory>> result = ImmutableSet.builder();
-    for (Class<? extends AspectFactory<?, ?, ?>> candidateClass : aspectCandidates) {
-      ConfiguredAspectFactory candidate =
-          (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass);
-      if (Sets.difference(
-          candidate.getDefinition().getRequiredProviders(),
-          ruleClass.getAdvertisedProviders()).isEmpty()) {
-        result.add(candidateClass.asSubclass(ConfiguredAspectFactory.class));
+    if (aspectDefinition != null) {
+      for (Class<? extends AspectFactory<?, ?, ?>> aspect :
+          aspectDefinition.getAttributeAspects().get(attribute.getName())) {
+        aspectCandidates.add(new AspectWithParameters(
+            aspect.asSubclass(ConfiguredAspectFactory.class),
+            aspectParameters));
       }
     }
-
-    return result.build();
+    return aspectCandidates;
   }
 
-  private void visitRule(Rule rule, AspectDefinition aspect,
+  private void visitRule(Rule rule, ListMultimap<Attribute, LabelAndConfiguration> labelMap,
+      ListMultimap<Attribute, Dependency> outgoingEdges) {
+    visitRule(rule, /*aspect=*/null, /*aspectParameters=*/null, labelMap, outgoingEdges);
+  }
+
+  private void visitRule(Rule rule, AspectDefinition aspect, AspectParameters aspectParameters,
       ListMultimap<Attribute, LabelAndConfiguration> labelMap,
       ListMultimap<Attribute, Dependency> outgoingEdges) {
     Preconditions.checkNotNull(labelMap);
@@ -622,7 +643,7 @@
           config.evaluateTransition(rule, attribute, toTarget, transitionApplier);
         }
         for (Dependency dependency : transitionApplier.getDependencies(label,
-            requiredAspects(aspect, attribute, toTarget))) {
+            requiredAspects(aspect, aspectParameters, attribute, toTarget, rule))) {
           outgoingEdges.put(
               entry.getKey(),
               dependency);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index 29b5f4b..485786f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -32,8 +32,8 @@
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.PackageRootResolver;
 import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.DependencyResolver;
 import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
@@ -1397,7 +1397,7 @@
      * TODO(bazel-team): this is a really ugly reverse dependency: factor this away.
      */
     Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects);
+        ImmutableSet<AspectWithParameters> aspects);
   }
 
   /**
@@ -1471,7 +1471,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       return ImmutableList.of(
           new DependencyResolver.Dependency(label, currentConfiguration, aspects));
     }
@@ -1572,7 +1572,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       return ImmutableList.of(new DependencyResolver.Dependency(label, transition, aspects));
     }
   }
@@ -1639,7 +1639,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       ImmutableList.Builder<DependencyResolver.Dependency> builder = ImmutableList.builder();
       for (TransitionApplier applier : appliers) {
         builder.addAll(applier.getDependencies(label, aspects));
diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
index 6316f1a..8defc66 100644
--- a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.LibraryArtifact;
 import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo;
 import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider;
 import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
@@ -58,7 +59,8 @@
   }
 
   @Override
-  public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+  public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+      AspectParameters parameters) {
     NestedSetBuilder<Artifact> ideBuildFilesBuilder = NestedSetBuilder.stableOrder();
     Iterable<AndroidStudioInfoFilesProvider> deps =
         ruleContext.getPrerequisites("deps", Mode.TARGET, AndroidStudioInfoFilesProvider.class);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectFactory.java b/src/main/java/com/google/devtools/build/lib/packages/AspectFactory.java
index b375dd9..a92084b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectFactory.java
@@ -26,8 +26,10 @@
    * @param base the configured target of the associated rule
    * @param context the context of the associated configured target plus all the attributes the
    *     aspect itself has defined
+   * @param parameters information from attributes of the rule that have requested this
+   *     aspect
    */
-  TAspect create(TConfiguredTarget base, TRuleContext context);
+  TAspect create(TConfiguredTarget base, TRuleContext context, AspectParameters parameters);
 
   /**
    * Returns the definition of the aspect.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java b/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java
new file mode 100644
index 0000000..69f82ce
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java
@@ -0,0 +1,93 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.packages;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
+
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+/**
+ * Objects of this class contain values of some attributes of rules. Used for passing this
+ * information to the aspects.
+ */
+public final class AspectParameters {
+  private final ImmutableMultimap<String, String> attributes;
+
+  private AspectParameters(Multimap<String, String> attributes) {
+    this.attributes = ImmutableMultimap.copyOf(attributes);
+  }
+
+  public static final AspectParameters EMPTY = new AspectParameters.Builder().build();
+
+  /**
+   * A builder for @{link {@link AspectParameters} class.
+   */
+  public static class Builder {
+    private final Multimap<String, String> attributes = ArrayListMultimap.create();
+
+    /**
+     * Adds a new pair of attribute-value.
+     */
+    public Builder addAttribute(String name, String value) {
+      attributes.put(name, value);
+      return this;
+    }
+
+    /**
+     * Creates a new instance of {@link AspectParameters} class.
+     */
+    public AspectParameters build() {
+      return new AspectParameters(attributes);
+    }
+  }
+
+  /**
+   * Returns collection of values for specified key, or null if key is missing.
+   */
+  @Nullable
+  public ImmutableCollection<String> getAttribute(String key) {
+    return attributes.get(key);
+  }
+
+  public boolean isEmpty() {
+    return this.equals(AspectParameters.EMPTY);
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    if (!(other instanceof AspectParameters)) {
+      return false;
+    }
+    AspectParameters that = (AspectParameters) other;
+    return Objects.equals(this.attributes, that.attributes);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(attributes);
+  }
+
+  @Override
+  public String toString() {
+    return attributes.toString();
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 7d06129..391a1da 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -15,10 +15,12 @@
 package com.google.devtools.build.lib.packages;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
@@ -57,6 +59,26 @@
 
   public static final Predicate<RuleClass> NO_RULE = Predicates.alwaysFalse();
 
+  private static final class RuleAspect {
+    private final Class<? extends AspectFactory<?, ?, ?>> aspectFactory;
+    private final Function<Rule, AspectParameters> parametersExtractor;
+
+    RuleAspect(
+        Class<? extends AspectFactory<?, ?, ?>> aspectFactory,
+        Function<Rule, AspectParameters> parametersExtractor) {
+      this.aspectFactory = aspectFactory;
+      this.parametersExtractor = parametersExtractor;
+    }
+
+    Class<? extends AspectFactory<?, ?, ?>> getAspectFactory() {
+      return aspectFactory;
+    }
+    
+    Function<Rule, AspectParameters> getParametersExtractor() {
+      return parametersExtractor;
+    }
+  }
+
   /**
    * A configuration transition.
    */
@@ -274,7 +296,7 @@
     private Set<PropertyFlag> propertyFlags = EnumSet.noneOf(PropertyFlag.class);
     private PredicateWithMessage<Object> allowedValues = null;
     private ImmutableSet<String> mandatoryProviders = ImmutableSet.<String>of();
-    private Set<Class<? extends AspectFactory<?, ?, ?>>> aspects = new LinkedHashSet<>();
+    private Set<RuleAspect> aspects = new LinkedHashSet<>();
 
     /**
      * Creates an attribute builder with given name and type. This attribute is optional, uses
@@ -641,13 +663,31 @@
     }
 
     /**
-     * Asserts that a particular aspect needs to be computed for all direct dependencies through
-     * this attribute.
+     * Asserts that a particular aspect probably needs to be computed for all direct dependencies
+     * through this attribute.
      */
     public Builder<TYPE> aspect(Class<? extends AspectFactory<?, ?, ?>> aspect) {
-      this.aspects.add(aspect);
+      Function<Rule, AspectParameters> noParameters = new Function<Rule, AspectParameters>() {
+        @Override
+        public AspectParameters apply(Rule input) {
+          return AspectParameters.EMPTY;
+        }
+      };
+      return this.aspect(aspect, noParameters);
+    }
+
+    /**
+     * Asserts that a particular parameterized aspect probably needs to be computed for all direct
+     * dependencies through this attribute.
+     *
+     * @param evaluator function that extracts aspect parameters from rule.
+     */
+    public Builder<TYPE> aspect(Class<? extends AspectFactory<?, ?, ?>> aspect,
+        Function<Rule, AspectParameters> evaluator) {
+      this.aspects.add(new RuleAspect(aspect, evaluator));
       return this;
     }
+
     /**
      * Sets the predicate-like edge validity checker.
      */
@@ -1001,7 +1041,7 @@
 
   private final ImmutableSet<String> mandatoryProviders;
 
-  private final ImmutableSet<Class<? extends AspectFactory<?, ?, ?>>> aspects;
+  private final ImmutableSet<RuleAspect> aspects;
 
   /**
    * Constructs a rule attribute with the specified name, type and default
@@ -1028,7 +1068,7 @@
       Predicate<AttributeMap> condition,
       PredicateWithMessage<Object> allowedValues,
       ImmutableSet<String> mandatoryProviders,
-      ImmutableSet<Class<? extends AspectFactory<?, ?, ?>>> aspects) {
+      ImmutableSet<RuleAspect> aspects) {
     Preconditions.checkNotNull(configTransition);
     Preconditions.checkArgument(
         (configTransition == ConfigurationTransition.NONE && configurator == null)
@@ -1252,7 +1292,24 @@
    * Returns the set of aspects required for dependencies through this attribute.
    */
   public ImmutableSet<Class<? extends AspectFactory<?, ?, ?>>> getAspects() {
-    return aspects;
+    ImmutableSet.Builder<Class<? extends AspectFactory<?, ?, ?>>> builder = ImmutableSet.builder();
+    for (RuleAspect aspect : aspects) {
+      builder.add(aspect.getAspectFactory());
+    }
+    return builder.build();
+  }
+
+  /**
+   * Returns set of pairs of aspect factories and corresponding aspect parameters.
+   */
+  public ImmutableMap<Class<? extends AspectFactory<?, ?, ?>>, AspectParameters>
+      getAspectsWithParameters(Rule rule) {
+    ImmutableMap.Builder<Class<? extends AspectFactory<?, ?, ?>>, AspectParameters> builder =
+        ImmutableMap.builder();
+    for (RuleAspect aspect : aspects) {
+      builder.put(aspect.getAspectFactory(), aspect.getParametersExtractor().apply(rule));
+    }
+    return builder.build();
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
index 92207e8..3179e45 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
 import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.rules.java.JavaCommon;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
@@ -44,7 +45,8 @@
           "deps", "exports", "runtime_deps", "binary_under_test", "$instrumentation_test_runner");
 
   @Override
-  public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+  public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+      AspectParameters parameters) {
     if (!JavaCommon.getConstraints(ruleContext).contains("android")
         && !ruleContext.getRule().getRuleClass().startsWith("android_")) {
       return new Aspect.Builder(NAME).build();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
index 2a922ea..130be53 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/J2ObjcAspect.java
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
 import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
@@ -88,7 +89,8 @@
   }
 
   @Override
-  public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+  public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+      AspectParameters parameters) {
     Aspect.Builder builder = new Aspect.Builder(NAME);
 
     JavaCompilationArgsProvider compilationArgsProvider =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index bcb6d3d..eb3b934 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -118,8 +118,8 @@
 
       ListMultimap<Attribute, ConfiguredTarget> depValueMap =
           ConfiguredTargetFunction.computeDependencies(env, resolver, ctgValue,
-              aspectFactory.getDefinition(), configConditions, ruleClassProvider,
-              view.getHostConfiguration(ctgValue.getConfiguration()));
+              aspectFactory.getDefinition(), key.getParameters(), configConditions,
+              ruleClassProvider, view.getHostConfiguration(ctgValue.getConfiguration()));
 
       return createAspect(env, key, associatedTarget, configConditions, depValueMap);
     } catch (DependencyEvaluationException e) {
@@ -143,8 +143,9 @@
 
     ConfiguredAspectFactory aspectFactory =
         (ConfiguredAspectFactory) AspectFactory.Util.create(key.getAspect());
-    Aspect aspect = view.createAspect(analysisEnvironment, associatedTarget, aspectFactory,
-        directDeps, configConditions);
+    Aspect aspect = view.createAspect(
+        analysisEnvironment, associatedTarget, aspectFactory, directDeps, configConditions,
+        key.getParameters());
 
     events.replayOn(env.getListener());
     if (events.hasErrors()) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
index 2657caa..f1260ba 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java
@@ -15,15 +15,20 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
 import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.syntax.Label;
 import com.google.devtools.build.skyframe.SkyFunctionName;
 import com.google.devtools.build.skyframe.SkyKey;
 
+import javax.annotation.Nullable;
+
 /**
  * An aspect in the context of the Skyframe graph.
  */
@@ -34,16 +39,15 @@
   public static final class AspectKey extends ActionLookupKey {
     private final Label label;
     private final BuildConfiguration configuration;
-    // TODO(bazel-team): class objects are not really hashable or comparable for equality other than
-    // by reference. We should identify the aspect here in a way that does not rely on comparison
-    // by reference so that keys can be serialized and deserialized properly.
-    private final Class<? extends ConfiguredAspectFactory> aspectFactory;
+    private final AspectWithParameters aspect;
 
     private AspectKey(Label label, BuildConfiguration configuration,
-        Class<? extends ConfiguredAspectFactory> aspectFactory) {
+        Class<? extends ConfiguredAspectFactory> aspectFactory,
+        AspectParameters parameters) {
+      Preconditions.checkNotNull(parameters);
       this.label = label;
       this.configuration = configuration;
-      this.aspectFactory = aspectFactory;
+      this.aspect = new AspectWithParameters(aspectFactory, parameters);
     }
 
     @Override
@@ -56,7 +60,12 @@
     }
 
     public Class<? extends ConfiguredAspectFactory> getAspect() {
-      return aspectFactory;
+      return aspect.getAspectFactory();
+    }
+
+    @Nullable
+    public AspectParameters getParameters() {
+      return aspect.getParameters();
     }
 
     @Override
@@ -66,7 +75,7 @@
 
     @Override
     public int hashCode() {
-      return Objects.hashCode(label, configuration, aspectFactory);
+      return Objects.hashCode(label, configuration, aspect);
     }
 
     @Override
@@ -82,13 +91,14 @@
       AspectKey that = (AspectKey) other;
       return Objects.equal(label, that.label)
           && Objects.equal(configuration, that.configuration)
-          && Objects.equal(aspectFactory, that.aspectFactory);
+          && Objects.equal(aspect, that.aspect);
     }
 
     @Override
     public String toString() {
-      return label + "#" + aspectFactory.getSimpleName() + " "
-          + (configuration == null ? "null" : configuration.checksum());
+      return label + "#" + aspect.getAspectFactory().getSimpleName() + " "
+          + (configuration == null ? "null" : configuration.checksum()) + " "
+          + aspect.getParameters();
     }
   }
 
@@ -123,8 +133,10 @@
   }
 
   public static SkyKey key(Label label, BuildConfiguration configuration,
-      Class<? extends ConfiguredAspectFactory> aspectFactory) {
-    return new SkyKey(SkyFunctions.ASPECT, new AspectKey(label, configuration, aspectFactory));
+      Class<? extends ConfiguredAspectFactory> aspectFactory,
+      AspectParameters additionalConfiguration) {
+    return new SkyKey(SkyFunctions.ASPECT,
+        new AspectKey(label, configuration, aspectFactory, additionalConfiguration));
   }
 
   public static SkyKey key(AspectKey aspectKey) {
@@ -135,6 +147,6 @@
       Label label,
       BuildConfiguration configuration,
       Class<? extends ConfiguredAspectFactory> aspectFactory) {
-    return new AspectKey(label, configuration, aspectFactory);
+    return new AspectKey(label, configuration, aspectFactory, AspectParameters.EMPTY);
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index 5df28bd..b565f1e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -27,6 +27,7 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
 import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
 import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
 import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -45,6 +46,7 @@
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.InputFile;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
@@ -181,7 +183,7 @@
       }
 
       ListMultimap<Attribute, ConfiguredTarget> depValueMap = computeDependencies(env, resolver,
-          ctgValue, null, configConditions, ruleClassProvider,
+          ctgValue, null, AspectParameters.EMPTY, configConditions, ruleClassProvider,
           view.getHostConfiguration(configuration));
       ConfiguredTargetValue ans = createConfiguredTarget(
           view, env, target, configuration, depValueMap, configConditions);
@@ -202,7 +204,8 @@
    * @param resolver The dependency resolver
    * @param ctgValue The label and the configuration of the node
    * @param aspectDefinition the aspect of the node (if null, the node is a configured target,
-   *     otherwise it's an asect)
+   *     otherwise it's an aspect)
+   * @param aspectParameters additional parameters for aspect construction
    * @param configConditions the configuration conditions for evaluating the attributes of the node
    * @param ruleClassProvider rule class provider for determining the right configuration fragments
    *   to apply to deps
@@ -215,15 +218,16 @@
   @Nullable
   static ListMultimap<Attribute, ConfiguredTarget> computeDependencies(
       Environment env, SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue,
-      AspectDefinition aspectDefinition, Set<ConfigMatchingProvider> configConditions,
-      RuleClassProvider ruleClassProvider, BuildConfiguration hostConfiguration)
+      AspectDefinition aspectDefinition, AspectParameters aspectParameters, 
+      Set<ConfigMatchingProvider> configConditions, RuleClassProvider ruleClassProvider,
+      BuildConfiguration hostConfiguration)
       throws DependencyEvaluationException {
 
     // Create the map from attributes to list of (target, configuration) pairs.
     ListMultimap<Attribute, Dependency> depValueNames;
     try {
       depValueNames = resolver.dependentNodeMap(ctgValue, hostConfiguration, aspectDefinition,
-          configConditions);
+          aspectParameters, configConditions);
     } catch (EvalException e) {
       env.getListener().handle(Event.error(e.getLocation(), e.getMessage()));
       throw new DependencyEvaluationException(new ConfiguredValueCreationException(e.print()));
@@ -479,8 +483,8 @@
     ListMultimap<SkyKey, Aspect> result = ArrayListMultimap.create();
     Set<SkyKey> aspectKeys = new HashSet<>();
     for (Dependency dep : deps) {
-      for (Class<? extends ConfiguredAspectFactory> depAspect : dep.getAspects()) {
-        aspectKeys.add(AspectValue.key(dep.getLabel(), dep.getConfiguration(), depAspect));
+      for (AspectWithParameters depAspect : dep.getAspects()) {
+        aspectKeys.add(createAspectKey(dep.getLabel(), dep.getConfiguration(), depAspect));
       }
     }
 
@@ -497,12 +501,12 @@
         continue;
       }
       ConfiguredTarget depConfiguredTarget = configuredTargetMap.get(depKey);
-      for (Class<? extends ConfiguredAspectFactory> depAspect : dep.getAspects()) {
-        if (!aspectMatchesConfiguredTarget(depConfiguredTarget, depAspect)) {
+      for (AspectWithParameters depAspect : dep.getAspects()) {
+        if (!aspectMatchesConfiguredTarget(depConfiguredTarget, depAspect.getAspectFactory())) {
           continue;
         }
 
-        SkyKey aspectKey = AspectValue.key(dep.getLabel(), dep.getConfiguration(), depAspect);
+        SkyKey aspectKey = createAspectKey(dep.getLabel(), dep.getConfiguration(), depAspect);
         AspectValue aspectValue = null;
         try {
           aspectValue = (AspectValue) depAspects.get(aspectKey).get();
@@ -510,7 +514,8 @@
           // The configured target should have been created in resolveConfiguredTargetDependencies()
           throw new IllegalStateException(e);
         } catch (NoSuchThingException | AspectCreationException e) {
-          AspectFactory<?, ?, ?> depAspectFactory = AspectFactory.Util.create(depAspect);
+          AspectFactory<?, ?, ?> depAspectFactory =
+              AspectFactory.Util.create(depAspect.getAspectFactory());
           throw new DependencyEvaluationException(new ConfiguredValueCreationException(
               String.format("Evaluation of aspect %s on %s failed: %s",
                   depAspectFactory.getDefinition().getName(), dep.getLabel(), e.toString())));
@@ -523,10 +528,17 @@
         result.put(depKey, aspectValue.getAspect());
       }
     }
-
     return result;
   }
 
+  public static SkyKey createAspectKey(Label label, BuildConfiguration buildConfiguration,
+      AspectWithParameters depAspect) {
+    return AspectValue.key(label,
+        buildConfiguration,
+        depAspect.getAspectFactory(),
+        depAspect.getParameters());
+  }
+
   private static boolean aspectMatchesConfiguredTarget(ConfiguredTarget dep,
       Class<? extends ConfiguredAspectFactory> aspectFactory) {
     AspectDefinition aspectDefinition = AspectFactory.Util.create(aspectFactory).getDefinition();
@@ -573,8 +585,7 @@
 
     // Collect the corresponding Skyframe configured target values. Abort early if they haven't
     // been computed yet.
-    Collection<Dependency> configValueNames =
-        resolver.resolveRuleLabels(ctgValue, null, configLabelMap);
+    Collection<Dependency> configValueNames = resolver.resolveRuleLabels(ctgValue, configLabelMap);
 
     // No need to get new configs from Skyframe - config_setting rules always use the current
     // target's config.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
index 5f5d538..d14bf46 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PostConfiguredTargetFunction.java
@@ -100,7 +100,8 @@
     try {
       BuildConfiguration hostConfiguration =
           buildViewProvider.getSkyframeBuildView().getHostConfiguration(ct.getConfiguration());
-      deps = resolver.dependentNodeMap(ctgValue, hostConfiguration, null, configConditions);
+      deps = resolver.dependentNodeMap(ctgValue, hostConfiguration, /*aspect=*/null,
+          /*aspectParameters=*/null, configConditions);
       if (ct.getConfiguration() != null && ct.getConfiguration().useDynamicConfigurations()) {
         deps = ConfiguredTargetFunction.trimConfigurations(env, ctgValue, deps, hostConfiguration,
             ruleClassProvider);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
index 1eecdb7..0e6e419 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
@@ -48,6 +48,7 @@
 import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
 import com.google.devtools.build.lib.packages.Target;
@@ -459,9 +460,11 @@
       AnalysisEnvironment env, RuleConfiguredTarget associatedTarget,
       ConfiguredAspectFactory aspectFactory,
       ListMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
-      Set<ConfigMatchingProvider> configConditions) {
-    return factory.createAspect(env, associatedTarget, aspectFactory, prerequisiteMap,
-        configConditions, getHostConfiguration(associatedTarget.getConfiguration()));
+      Set<ConfigMatchingProvider> configConditions,
+      AspectParameters aspectParameters) {
+    return factory.createAspect(env, associatedTarget, aspectFactory, aspectParameters,
+        prerequisiteMap, configConditions,
+        getHostConfiguration(associatedTarget.getConfiguration()));
   }
 
   @Nullable
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index e5c6cf1..22bd506 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -46,9 +46,9 @@
 import com.google.devtools.build.lib.actions.ResourceManager;
 import com.google.devtools.build.lib.actions.Root;
 import com.google.devtools.build.lib.analysis.Aspect;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
 import com.google.devtools.build.lib.analysis.BuildView.Options;
-import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.DependencyResolver.Dependency;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
@@ -1110,8 +1110,9 @@
     final List<SkyKey> skyKeys = new ArrayList<>();
     for (Dependency key : keys) {
       skyKeys.add(ConfiguredTargetValue.key(key.getLabel(), configs.get(key)));
-      for (Class<? extends ConfiguredAspectFactory> aspect : key.getAspects()) {
-        skyKeys.add(AspectValue.key(key.getLabel(), configs.get(key), aspect));
+      for (AspectWithParameters aspect : key.getAspects()) {
+        skyKeys.add(
+            ConfiguredTargetFunction.createAspectKey(key.getLabel(), configs.get(key), aspect));
       }
     }
 
@@ -1130,8 +1131,9 @@
           ((ConfiguredTargetValue) result.get(configuredTargetKey)).getConfiguredTarget();
       List<Aspect> aspects = new ArrayList<>();
 
-      for (Class<? extends ConfiguredAspectFactory> aspect : key.getAspects()) {
-        SkyKey aspectKey = AspectValue.key(key.getLabel(), configs.get(key), aspect);
+      for (AspectWithParameters aspect : key.getAspects()) {
+        SkyKey aspectKey =
+            ConfiguredTargetFunction.createAspectKey(key.getLabel(), configs.get(key), aspect);
         if (result.get(aspectKey) == null) {
           continue DependentNodeLoop;
         }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
index b4b055a..461738e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectDefinitionTest.java
@@ -17,6 +17,7 @@
 import static org.junit.Assert.fail;
 
 import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Type;
 import com.google.devtools.build.lib.syntax.Label;
 
@@ -46,7 +47,7 @@
     }
 
     @Override
-    public Aspect create(ConfiguredTarget base, RuleContext context) {
+    public Aspect create(ConfiguredTarget base, RuleContext context, AspectParameters parameters) {
       throw new IllegalStateException();
     }
 
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index 7d17a98..02b4f3e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -137,4 +137,18 @@
     assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
         .containsExactly("aspect //a:b", "rule //a:a");
   }
+
+  @Test
+  public void informationFromBaseRulePassedToAspect() throws Exception {
+    setRules(new TestAspects.BaseRule(), new TestAspects.HonestRule(),
+        new TestAspects.AspectRequiringProviderRule());
+
+    pkg("a",
+        "aspect_requiring_provider(name='a', foo=[':b'], baz='hello')",
+        "honest(name='b', foo=[])");
+
+    ConfiguredTarget a = getConfiguredTarget("//a:a");
+    assertThat(a.getProvider(TestAspects.RuleInfo.class).getData())
+        .containsExactly("rule //a:a", "aspect //a:b data hello");
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
index 5365728..2906961 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectValueTest.java
@@ -17,6 +17,7 @@
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
 import com.google.devtools.build.lib.analysis.util.TestAspects;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.skyframe.AspectValue;
 import com.google.devtools.build.lib.syntax.Label;
 
@@ -51,18 +52,26 @@
     Label l1 = Label.parseAbsolute("//a:l1");
     Label l1b = Label.parseAbsolute("//a:l1");
     Label l2 = Label.parseAbsolute("//a:l2");
+    AspectParameters i1 = new AspectParameters.Builder()
+        .addAttribute("foo", "bar")
+        .build();
+    AspectParameters i2 = new AspectParameters.Builder()
+        .addAttribute("foo", "baz")
+        .build();
     Class<? extends ConfiguredAspectFactory> a1 = TestAspects.AttributeAspect.class;
     Class<? extends ConfiguredAspectFactory> a2 = TestAspects.ExtraAttributeAspect.class;
 
     new EqualsTester()
-        .addEqualityGroup(AspectValue.key(l1, c1, a1), AspectValue.key(l1b, c1, a1))
-        .addEqualityGroup(AspectValue.key(l2, c1, a1))
-        .addEqualityGroup(AspectValue.key(l1, c2, a1))
-        .addEqualityGroup(AspectValue.key(l2, c2, a1))
-        .addEqualityGroup(AspectValue.key(l1, c1, a2))
-        .addEqualityGroup(AspectValue.key(l2, c1, a2))
-        .addEqualityGroup(AspectValue.key(l1, c2, a2))
-        .addEqualityGroup(AspectValue.key(l2, c2, a2))
+        .addEqualityGroup(AspectValue.key(l1, c1, a1, null), AspectValue.key(l1b, c1, a1, null))
+        .addEqualityGroup(AspectValue.key(l1, c1, a1, i1))
+        .addEqualityGroup(AspectValue.key(l1, c1, a1, i2))
+        .addEqualityGroup(AspectValue.key(l2, c1, a1, null))
+        .addEqualityGroup(AspectValue.key(l1, c2, a1, null))
+        .addEqualityGroup(AspectValue.key(l2, c2, a1, null))
+        .addEqualityGroup(AspectValue.key(l1, c1, a2, null))
+        .addEqualityGroup(AspectValue.key(l2, c1, a2, null))
+        .addEqualityGroup(AspectValue.key(l1, c2, a2, null))
+        .addEqualityGroup(AspectValue.key(l2, c2, a2, null))
         .addEqualityGroup(l1)  // A random object
         .testEquals();
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java b/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
index fc5b156..e149cb8 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/DependencyResolverTest.java
@@ -116,7 +116,7 @@
         new TargetAndConfiguration(target, getTargetConfiguration()),
         getHostConfiguration(),
         aspectDefinition,
-        ImmutableSet.<ConfigMatchingProvider>of());
+        null, ImmutableSet.<ConfigMatchingProvider>of());
   }
 
   @SafeVarargs
@@ -199,15 +199,15 @@
     BuildConfiguration host = getHostConfiguration();
     BuildConfiguration target = getTargetConfiguration();
 
-    ImmutableSet<Class<? extends ConfiguredAspectFactory>> twoAspects =
-        ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of(
-            TestAspects.SimpleAspect.class, TestAspects.AttributeAspect.class);
-    ImmutableSet<Class<? extends ConfiguredAspectFactory>> inverseAspects =
-        ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of(
-            TestAspects.AttributeAspect.class, TestAspects.SimpleAspect.class);
-    ImmutableSet<Class<? extends ConfiguredAspectFactory>> differentAspects =
-        ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of(
-            TestAspects.AttributeAspect.class, TestAspects.ErrorAspect.class);
+    ImmutableSet<AspectWithParameters> twoAspects = ImmutableSet.of(
+        new AspectWithParameters(TestAspects.SimpleAspect.class), 
+        new AspectWithParameters(TestAspects.AttributeAspect.class));
+    ImmutableSet<AspectWithParameters> inverseAspects = ImmutableSet.of(
+        new AspectWithParameters(TestAspects.AttributeAspect.class), 
+        new AspectWithParameters(TestAspects.SimpleAspect.class));
+    ImmutableSet<AspectWithParameters> differentAspects = ImmutableSet.of(
+        new AspectWithParameters(TestAspects.AttributeAspect.class), 
+        new AspectWithParameters(TestAspects.ErrorAspect.class));
 
     new EqualsTester()
         .addEqualityGroup(
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index 7f7d05b..7068278 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -84,6 +84,7 @@
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.StoredEventHandler;
 import com.google.devtools.build.lib.exec.ExecutionOptions;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
@@ -861,9 +862,9 @@
    * Gets a derived Artifact for testing in the subdirectory of the {@link
    * BuildConfiguration#getBinDirectory()} corresponding to the package of {@code owner},
    * where the given artifact belongs to the given ConfiguredTarget together with the given Aspect.
-   * So to specify a file foo/foo.o owned by target //foo:foo with an apsect from FooAspect,
+   * So to specify a file foo/foo.o owned by target //foo:foo with an aspect from FooAspect,
    * {@code packageRelativePath} should just be "foo.o", and aspectOfOwner should be
-   * FooAspect.class. This method is necessary when an Apsect of the target, not the target itself,
+   * FooAspect.class. This method is necessary when an Aspect of the target, not the target itself,
    * is creating an Artifact.
    */
   protected Artifact getBinArtifact(String packageRelativePath, ConfiguredTarget owner,
@@ -871,7 +872,8 @@
     return getPackageRelativeDerivedArtifact(packageRelativePath,
         owner.getConfiguration().getBinDirectory(),
         (AspectValue.AspectKey) AspectValue.key(
-            owner.getLabel(), owner.getConfiguration(), creatingAspectFactory).argument());
+            owner.getLabel(), owner.getConfiguration(), creatingAspectFactory,
+            AspectParameters.EMPTY).argument());
   }
 
   /**
@@ -930,7 +932,8 @@
     return getPackageRelativeDerivedArtifact(packageRelativePath,
         owner.getConfiguration().getGenfilesDirectory(),
         (AspectValue.AspectKey) AspectValue.key(
-            owner.getLabel(), owner.getConfiguration(), creatingAspectFactory).argument());
+            owner.getLabel(), owner.getConfiguration(), creatingAspectFactory,
+            AspectParameters.EMPTY).argument());
   }
 
   /**
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
index bf564fb..ffea8bc 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -22,6 +22,8 @@
 import static com.google.devtools.build.lib.packages.Type.STRING;
 import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.Aspect;
 import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
@@ -39,6 +41,8 @@
 import com.google.devtools.build.lib.collect.nestedset.Order;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.AspectParameters;
+import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.RuleClass;
 import com.google.devtools.build.lib.packages.RuleClass.Builder;
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
@@ -131,11 +135,16 @@
    */
   public abstract static class BaseAspect implements ConfiguredAspectFactory {
     @Override
-    public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+    public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+        AspectParameters parameters) {
+      String information = parameters.isEmpty()
+          ? ""
+          : " data " + Iterables.getFirst(parameters.getAttribute("baz"), null);
       return new Aspect.Builder(getClass().getName())
           .addProvider(
               AspectInfo.class,
-              new AspectInfo(collectAspectData("aspect " + ruleContext.getLabel(), ruleContext)))
+              new AspectInfo(collectAspectData("aspect " + ruleContext.getLabel() + information, 
+                  ruleContext)))
           .build();
     }
   }
@@ -215,7 +224,8 @@
    */
   public static class ErrorAspect implements ConfiguredAspectFactory {
     @Override
-    public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+    public Aspect create(ConfiguredTarget base, RuleContext ruleContext,
+        AspectParameters parameters) {
       ruleContext.ruleError("Aspect error");
       return null;
     }
@@ -290,11 +300,25 @@
    * A rule that defines an {@link AspectRequiringProvider} on one of its attributes.
    */
   public static class AspectRequiringProviderRule implements RuleDefinition {
+
+    private static final class TestAspectParametersExtractor implements 
+        Function<Rule, AspectParameters> {
+      @Override
+      public AspectParameters apply(Rule rule) {
+        if (rule.isAttrDefined("baz", STRING)) {
+          return new AspectParameters.Builder().addAttribute("baz",
+              rule.getAttributeContainer().getAttr("baz").toString()).build();
+        }
+        return AspectParameters.EMPTY;
+      }
+    }
+
     @Override
     public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
       return builder
           .add(attr("foo", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)
-              .aspect(AspectRequiringProvider.class))
+              .aspect(AspectRequiringProvider.class, new TestAspectParametersExtractor()))
+          .add(attr("baz", STRING))
           .build();
 
     }