Start the process of getting Target out of ConfiguredTarget: add a new container, ConfiguredTargetAndTarget, that can be used to access Targets, and deprecate ConfiguredTarget#getTarget. ConfiguredAndTargetObjects are intended to be limited in scope, not being persisted to Skyframe.

The eventual plan is to remove the target field from ConfiguredTarget.

This CL is mostly straightforward, except for dealing with AliasConfiguredTargets, which cause some complications.

A significant cleanup is still needed before #getTarget can be removed, but I don't see any impossible blockers. We will may still need to store a Target-like object in ConfiguredTarget (that has the RuleClass, or at least a string representation of it, for instance), but that will let us avoid storing a full Target together with its associated Package.

PiperOrigin-RevId: 182371566
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AliasProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/AliasProvider.java
index e792cb6..e650ec5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AliasProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AliasProvider.java
@@ -18,6 +18,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 
 /**
  * A provider that gives information about the aliases a rule was resolved through.
@@ -65,12 +66,12 @@
     return aliasChain;
   }
 
-  public static String printLabelWithAliasChain(ConfiguredTarget target) {
-    AliasProvider aliasProvider = target.getProvider(AliasProvider.class);
+  public static String printLabelWithAliasChain(ConfiguredTargetAndTarget target) {
+    AliasProvider aliasProvider = target.getConfiguredTarget().getProvider(AliasProvider.class);
     String suffix = aliasProvider == null
         ? ""
         : " (aliased through '" + Joiner.on("' -> '").join(aliasProvider.getAliasChain()) + "')";
 
-    return "'" + target.getLabel() + "'" + suffix;
+    return "'" + target.getTarget().getLabel() + "'" + suffix;
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java
index 35eeae8..79baad0 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java
@@ -25,6 +25,7 @@
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.skyframe.AspectFunction;
 import com.google.devtools.build.lib.skyframe.AspectValue;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
 import com.google.devtools.build.lib.util.OrderedSetMultimap;
 import com.google.devtools.build.skyframe.SkyFunction;
@@ -49,7 +50,7 @@
   @Nullable
   public static OrderedSetMultimap<Dependency, ConfiguredAspect> resolveAspectDependencies(
       SkyFunction.Environment env,
-      Map<SkyKey, ConfiguredTarget> configuredTargetMap,
+      Map<SkyKey, ConfiguredTargetAndTarget> configuredTargetMap,
       Iterable<Dependency> deps,
       @Nullable NestedSetBuilder<Package> transitivePackages)
       throws AspectFunction.AspectCreationException, InterruptedException {
@@ -89,8 +90,9 @@
         }
 
         // Validate that aspect is applicable to "bare" configured target.
-        ConfiguredTarget associatedTarget = configuredTargetMap
-            .get(ConfiguredTargetValue.key(dep.getLabel(), dep.getConfiguration()));
+        ConfiguredTargetAndTarget associatedTarget =
+            configuredTargetMap.get(
+                ConfiguredTargetValue.key(dep.getLabel(), dep.getConfiguration()));
         if (!aspectMatchesConfiguredTarget(associatedTarget, aspectValue.getAspect())) {
           continue;
         }
@@ -113,20 +115,23 @@
    * combinations of aspects for a particular configured target, so it would result in a
    * combinatorial explosion of Skyframe nodes.
    */
-  public static OrderedSetMultimap<Attribute, ConfiguredTarget> mergeAspects(
+  public static OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> mergeAspects(
       OrderedSetMultimap<Attribute, Dependency> depValueNames,
-      Map<SkyKey, ConfiguredTarget> depConfiguredTargetMap,
+      Map<SkyKey, ConfiguredTargetAndTarget> depConfiguredTargetMap,
       OrderedSetMultimap<Dependency, ConfiguredAspect> depAspectMap)
       throws MergedConfiguredTarget.DuplicateException {
-    OrderedSetMultimap<Attribute, ConfiguredTarget> result = OrderedSetMultimap.create();
+    OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> result = OrderedSetMultimap.create();
 
     for (Map.Entry<Attribute, Dependency> entry : depValueNames.entries()) {
       Dependency dep = entry.getValue();
       SkyKey depKey = ConfiguredTargetValue.key(dep.getLabel(), dep.getConfiguration());
-      ConfiguredTarget depConfiguredTarget = depConfiguredTargetMap.get(depKey);
+      ConfiguredTargetAndTarget depConfiguredTarget = depConfiguredTargetMap.get(depKey);
 
-      result.put(entry.getKey(),
-          MergedConfiguredTarget.of(depConfiguredTarget, depAspectMap.get(dep)));
+      result.put(
+          entry.getKey(),
+          depConfiguredTarget.fromConfiguredTarget(
+              MergedConfiguredTarget.of(
+                  depConfiguredTarget.getConfiguredTarget(), depAspectMap.get(dep))));
     }
 
     return result;
@@ -160,7 +165,8 @@
     return aspectKey;
   }
 
-  public static boolean aspectMatchesConfiguredTarget(final ConfiguredTarget dep, Aspect aspect) {
+  public static boolean aspectMatchesConfiguredTarget(
+      ConfiguredTargetAndTarget dep, Aspect aspect) {
     if (!aspect.getDefinition().applyToFiles() && !(dep.getTarget() instanceof Rule)) {
       return false;
     }
@@ -168,6 +174,6 @@
       // even aspects that 'apply to files' cannot apply to input files.
       return false;
     }
-    return dep.satisfies(aspect.getDefinition().getRequiredProviders());
+    return dep.getConfiguredTarget().satisfies(aspect.getDefinition().getRequiredProviders());
   }
 }
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 4b58054..95ea703 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
@@ -21,6 +21,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
@@ -80,6 +81,7 @@
 import com.google.devtools.build.lib.skyframe.AspectValue;
 import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
 import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
 import com.google.devtools.build.lib.skyframe.CoverageReportValue;
 import com.google.devtools.build.lib.skyframe.SkyframeAnalysisResult;
@@ -894,13 +896,15 @@
       BuildConfigurationCollection configurations)
       throws EvalException, InvalidConfigurationException,
       InterruptedException, InconsistentAspectOrderException {
-    return skyframeExecutor.getConfiguredTargets(
-        eventHandler,
-        ct.getConfiguration(),
-        ImmutableSet.copyOf(
-            getDirectPrerequisiteDependenciesForTesting(
-                    eventHandler, ct, configurations, /*toolchainContext=*/ null)
-                .values()));
+    return Collections2.transform(
+        skyframeExecutor.getConfiguredTargets(
+            eventHandler,
+            ct.getConfiguration(),
+            ImmutableSet.copyOf(
+                getDirectPrerequisiteDependenciesForTesting(
+                        eventHandler, ct, configurations, /*toolchainContext=*/ null)
+                    .values())),
+        ConfiguredTargetAndTarget::getConfiguredTarget);
   }
 
   @VisibleForTesting
@@ -1002,7 +1006,7 @@
     return ImmutableMap.copyOf(keys);
   }
 
-  private OrderedSetMultimap<Attribute, ConfiguredTarget> getPrerequisiteMapForTesting(
+  private OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> getPrerequisiteMapForTesting(
       final ExtendedEventHandler eventHandler,
       ConfiguredTarget target,
       BuildConfigurationCollection configurations,
@@ -1013,11 +1017,11 @@
         getDirectPrerequisiteDependenciesForTesting(
             eventHandler, target, configurations, toolchainContext);
 
-    ImmutableMultimap<Dependency, ConfiguredTarget> cts = skyframeExecutor.getConfiguredTargetMap(
-        eventHandler,
-        target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()));
+    ImmutableMultimap<Dependency, ConfiguredTargetAndTarget> cts =
+        skyframeExecutor.getConfiguredTargetMap(
+            eventHandler, target.getConfiguration(), ImmutableSet.copyOf(depNodeNames.values()));
 
-    OrderedSetMultimap<Attribute, ConfiguredTarget> result = OrderedSetMultimap.create();
+    OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> result = OrderedSetMultimap.create();
     for (Map.Entry<Attribute, Dependency> entry : depNodeNames.entries()) {
       result.putAll(entry.getKey(), cts.get(entry.getValue()));
     }
@@ -1111,7 +1115,7 @@
     ToolchainContext toolchainContext =
         skyframeExecutor.getToolchainContextForTesting(
             requiredToolchains, targetConfig, eventHandler);
-    OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap =
+    OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap =
         getPrerequisiteMapForTesting(eventHandler, target, configurations, toolchainContext);
     toolchainContext.resolveToolchains(prerequisiteMap);
 
@@ -1147,13 +1151,13 @@
       BuildConfigurationCollection configurations)
       throws EvalException, InvalidConfigurationException, InterruptedException,
              InconsistentAspectOrderException {
-    Collection<ConfiguredTarget> configuredTargets =
+    Collection<ConfiguredTargetAndTarget> configuredTargets =
         getPrerequisiteMapForTesting(
                 eventHandler, dependentTarget, configurations, /*toolchainContext=*/ null)
             .values();
-    for (ConfiguredTarget ct : configuredTargets) {
-      if (ct.getLabel().equals(desiredTarget)) {
-        return ct;
+    for (ConfiguredTargetAndTarget ct : configuredTargets) {
+      if (ct.getTarget().getLabel().equals(desiredTarget)) {
+        return ct.getConfiguredTarget();
       }
     }
     return null;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index 76fc7d3..c52b947 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -52,6 +52,7 @@
 import com.google.devtools.build.lib.packages.RuleErrorConsumer;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.Environment.Extension;
@@ -85,14 +86,16 @@
    */
   public interface PrerequisiteValidator {
     /**
-     * Checks whether the rule in {@code contextBuilder} is allowed to depend on
-     * {@code prerequisite} through the attribute {@code attribute}.
+     * Checks whether the rule in {@code contextBuilder} is allowed to depend on {@code
+     * prerequisite} through the attribute {@code attribute}.
      *
      * <p>Can be used for enforcing any organization-specific policies about the layout of the
      * workspace.
      */
     void validate(
-        RuleContext.Builder contextBuilder, ConfiguredTarget prerequisite, Attribute attribute);
+        RuleContext.Builder contextBuilder,
+        ConfiguredTargetAndTarget prerequisite,
+        Attribute attribute);
   }
 
   /** Validator to check for and warn on the deprecation of dependencies. */
@@ -100,7 +103,9 @@
     /** Checks if the given prerequisite is deprecated and prints a warning if so. */
     @Override
     public void validate(
-        RuleContext.Builder contextBuilder, ConfiguredTarget prerequisite, Attribute attribute) {
+        RuleContext.Builder contextBuilder,
+        ConfiguredTargetAndTarget prerequisite,
+        Attribute attribute) {
       validateDirectPrerequisiteForDeprecation(
           contextBuilder, contextBuilder.getRule(), prerequisite, contextBuilder.forAspect());
     }
@@ -148,7 +153,10 @@
 
     /** Checks if the given prerequisite is deprecated and prints a warning if so. */
     public static void validateDirectPrerequisiteForDeprecation(
-        RuleErrorConsumer errors, Rule rule, ConfiguredTarget prerequisite, boolean forAspect) {
+        RuleErrorConsumer errors,
+        Rule rule,
+        ConfiguredTargetAndTarget prerequisite,
+        boolean forAspect) {
       Target prerequisiteTarget = prerequisite.getTarget();
       Label prerequisiteLabel = prerequisiteTarget.getLabel();
       PackageIdentifier thatPackage = prerequisiteLabel.getPackageIdentifier();
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
index d1aa887..78391b4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
@@ -45,10 +45,13 @@
    */
   String FILES_FIELD = "files";
 
-
   /**
-   * Returns the Target with which this {@link ConfiguredTarget} is associated.
+   * Returns the {@link Target} with which this {@link ConfiguredTarget} is associated.
+   *
+   * <p>Do not add new usages if possible. Prefer {@link #getLabel}, or use {@code
+   * ConfiguredTargetAndTarget} objects.
    */
+  @Deprecated
   Target getTarget();
 
   /**
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 af99802..bcb3748 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
@@ -65,6 +65,7 @@
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.profiler.memory.CurrentRuleTracker;
 import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
 import com.google.devtools.build.lib.util.OrderedSetMultimap;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -98,7 +99,7 @@
    * to the {@code AnalysisEnvironment}.
    */
   private NestedSet<PackageGroupContents> convertVisibility(
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
       EventHandler reporter,
       Target target,
       BuildConfiguration packageGroupConfiguration) {
@@ -116,7 +117,7 @@
       NestedSetBuilder<PackageGroupContents> result = NestedSetBuilder.stableOrder();
       for (Label groupLabel : packageGroupsVisibility.getPackageGroups()) {
         // PackageGroupsConfiguredTargets are always in the package-group configuration.
-        ConfiguredTarget group =
+        TransitiveInfoCollection group =
             findPrerequisite(prerequisiteMap, groupLabel, packageGroupConfiguration);
         PackageSpecificationProvider provider = null;
         // group == null can only happen if the package group list comes
@@ -145,12 +146,14 @@
     }
   }
 
-  private ConfiguredTarget findPrerequisite(
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap, Label label,
+  private TransitiveInfoCollection findPrerequisite(
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
+      Label label,
       BuildConfiguration config) {
-    for (ConfiguredTarget prerequisite : prerequisiteMap.get(null)) {
-      if (prerequisite.getLabel().equals(label) && (prerequisite.getConfiguration() == config)) {
-        return prerequisite;
+    for (ConfiguredTargetAndTarget prerequisite : prerequisiteMap.get(null)) {
+      if (prerequisite.getTarget().getLabel().equals(label)
+          && (prerequisite.getConfiguredTarget().getConfiguration() == config)) {
+        return prerequisite.getConfiguredTarget();
       }
     }
     return null;
@@ -227,7 +230,7 @@
       Target target,
       BuildConfiguration config,
       BuildConfiguration hostConfig,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       @Nullable ToolchainContext toolchainContext)
       throws InterruptedException {
@@ -301,7 +304,7 @@
       Rule rule,
       BuildConfiguration configuration,
       BuildConfiguration hostConfiguration,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       @Nullable ToolchainContext toolchainContext)
       throws InterruptedException {
@@ -406,11 +409,11 @@
    */
   public ConfiguredAspect createAspect(
       AnalysisEnvironment env,
-      ConfiguredTarget associatedTarget,
+      ConfiguredTargetAndTarget associatedTarget,
       ImmutableList<Aspect> aspectPath,
       ConfiguredAspectFactory aspectFactory,
       Aspect aspect,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       @Nullable ToolchainContext toolchainContext,
       BuildConfiguration aspectConfiguration,
@@ -449,8 +452,9 @@
       return null;
     }
 
-    ConfiguredAspect configuredAspect = aspectFactory
-        .create(associatedTarget, ruleContext, aspect.getParameters());
+    ConfiguredAspect configuredAspect =
+        aspectFactory.create(
+            associatedTarget.getConfiguredTarget(), ruleContext, aspect.getParameters());
     if (configuredAspect != null) {
       validateAdvertisedProviders(
           configuredAspect, aspect.getDefinition().getAdvertisedProviders(),
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 674fd55..a02d410 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -29,6 +29,7 @@
 import com.google.common.collect.ImmutableSortedSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.actions.Action;
@@ -86,6 +87,7 @@
 import com.google.devtools.build.lib.packages.RuleErrorConsumer;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.packages.TargetUtils;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.syntax.Type.LabelClass;
@@ -169,7 +171,7 @@
    */
   private final ImmutableList<Aspect> aspects;
   private final ImmutableList<AspectDescriptor> aspectDescriptors;
-  private final ListMultimap<String, ConfiguredTarget> targetMap;
+  private final ListMultimap<String, ConfiguredTargetAndTarget> targetMap;
   private final ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap;
   private final ImmutableMap<Label, ConfigMatchingProvider> configConditions;
   private final AspectAwareAttributeMapper attributes;
@@ -189,7 +191,7 @@
   private RuleContext(
       Builder builder,
       AttributeMap attributes,
-      ListMultimap<String, ConfiguredTarget> targetMap,
+      ListMultimap<String, ConfiguredTargetAndTarget> targetMap,
       ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       Class<? extends BuildConfiguration.Fragment> universalFragment,
@@ -368,7 +370,11 @@
    * Returns an immutable map from attribute name to list of configured targets for that attribute.
    */
   public ListMultimap<String, ? extends TransitiveInfoCollection> getConfiguredTargetMap() {
-    return targetMap;
+    return Multimaps.transformValues(targetMap, ConfiguredTargetAndTarget::getConfiguredTarget);
+  }
+
+  private List<? extends TransitiveInfoCollection> getDeps(String key) {
+    return Lists.transform(targetMap.get(key), ConfiguredTargetAndTarget::getConfiguredTarget);
   }
 
   /**
@@ -726,8 +732,8 @@
     ImmutableMap.Builder<String, TransitiveInfoCollection> result = ImmutableMap.builder();
     Map<String, Label> dict = attributes().get(attributeName, BuildType.LABEL_DICT_UNARY);
     Map<Label, ConfiguredTarget> labelToDep = new HashMap<>();
-    for (ConfiguredTarget dep : targetMap.get(attributeName)) {
-      labelToDep.put(dep.getLabel(), dep);
+    for (ConfiguredTargetAndTarget dep : targetMap.get(attributeName)) {
+      labelToDep.put(dep.getTarget().getLabel(), dep.getConfiguredTarget());
     }
 
     for (Map.Entry<String, Label> entry : dict.entrySet()) {
@@ -758,7 +764,7 @@
     }
 
     checkAttribute(attributeName, mode);
-    return targetMap.get(attributeName);
+    return getDeps(attributeName);
   }
 
   /**
@@ -773,7 +779,7 @@
     Attribute attributeDefinition = attributes().getAttributeDefinition(attributeName);
     SplitTransition transition = attributeDefinition.getSplitTransition(
         ConfiguredAttributeMapper.of(rule, configConditions));
-    List<ConfiguredTarget> deps = targetMap.get(attributeName);
+    List<? extends TransitiveInfoCollection> deps = getDeps(attributeName);
 
     List<BuildOptions> splitOptions = transition.split(getConfiguration().getOptions());
     if (splitOptions.isEmpty()) {
@@ -823,7 +829,7 @@
    */
   public TransitiveInfoCollection getPrerequisite(String attributeName, Mode mode) {
     checkAttribute(attributeName, mode);
-    List<? extends TransitiveInfoCollection> elements = targetMap.get(attributeName);
+    List<? extends TransitiveInfoCollection> elements = getDeps(attributeName);
     if (elements.size() > 1) {
       throw new IllegalStateException(getRuleClassNameForLogging() + " attribute " + attributeName
           + " produces more than one prerequisite");
@@ -1392,7 +1398,7 @@
     private final BuildConfiguration hostConfiguration;
     private final PrerequisiteValidator prerequisiteValidator;
     private final ErrorReporter reporter;
-    private OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap;
+    private OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap;
     private ImmutableMap<Label, ConfigMatchingProvider> configConditions;
     private NestedSet<PackageGroupContents> visibility;
     private ImmutableMap<String, Attribute> aspectAttributes;
@@ -1423,7 +1429,7 @@
       Preconditions.checkNotNull(visibility);
       AttributeMap attributes = ConfiguredAttributeMapper.of(rule, configConditions);
       validateAttributes(attributes);
-      ListMultimap<String, ConfiguredTarget> targetMap = createTargetMap();
+      ListMultimap<String, ConfiguredTargetAndTarget> targetMap = createTargetMap();
       ListMultimap<String, ConfiguredFilesetEntry> filesetEntryMap =
           createFilesetEntryMap(rule, configConditions);
       return new RuleContext(
@@ -1451,7 +1457,8 @@
      * Sets the prerequisites and checks their visibility. It also generates appropriate error or
      * warning messages and sets the error flag as appropriate.
      */
-    Builder setPrerequisites(OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap) {
+    Builder setPrerequisites(
+        OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap) {
       this.prerequisiteMap = Preconditions.checkNotNull(prerequisiteMap);
       return this;
     }
@@ -1500,8 +1507,8 @@
       return this;
     }
 
-    private boolean validateFilesetEntry(FilesetEntry filesetEntry, ConfiguredTarget src) {
-      if (src.getProvider(FilesetProvider.class) != null) {
+    private boolean validateFilesetEntry(FilesetEntry filesetEntry, ConfiguredTargetAndTarget src) {
+      if (src.getConfiguredTarget().getProvider(FilesetProvider.class) != null) {
         return true;
       }
       if (filesetEntry.isSourceFileset()) {
@@ -1538,25 +1545,27 @@
           continue;
         }
         String attributeName = attr.getName();
-        Map<Label, ConfiguredTarget> ctMap = new HashMap<>();
-        for (ConfiguredTarget prerequisite : prerequisiteMap.get(attr)) {
-          ctMap.put(AliasProvider.getDependencyLabel(prerequisite), prerequisite);
+        Map<Label, ConfiguredTargetAndTarget> ctMap = new HashMap<>();
+        for (ConfiguredTargetAndTarget prerequisite : prerequisiteMap.get(attr)) {
+          ctMap.put(
+              AliasProvider.getDependencyLabel(prerequisite.getConfiguredTarget()), prerequisite);
         }
         List<FilesetEntry> entries = ConfiguredAttributeMapper.of(rule, configConditions)
             .get(attributeName, BuildType.FILESET_ENTRY_LIST);
         for (FilesetEntry entry : entries) {
           if (entry.getFiles() == null) {
             Label label = entry.getSrcLabel();
-            ConfiguredTarget src = ctMap.get(label);
+            ConfiguredTargetAndTarget src = ctMap.get(label);
             if (!validateFilesetEntry(entry, src)) {
               continue;
             }
 
-            mapBuilder.put(attributeName, new ConfiguredFilesetEntry(entry, src));
+            mapBuilder.put(
+                attributeName, new ConfiguredFilesetEntry(entry, src.getConfiguredTarget()));
           } else {
             ImmutableList.Builder<TransitiveInfoCollection> files = ImmutableList.builder();
             for (Label file : entry.getFiles()) {
-              files.add(ctMap.get(file));
+              files.add(ctMap.get(file).getConfiguredTarget());
             }
             mapBuilder.put(attributeName, new ConfiguredFilesetEntry(entry, files.build()));
           }
@@ -1565,14 +1574,12 @@
       return mapBuilder.build();
     }
 
-    /**
-     * Determines and returns a map from attribute name to list of configured targets.
-     */
-    private ImmutableSortedKeyListMultimap<String, ConfiguredTarget> createTargetMap() {
-      ImmutableSortedKeyListMultimap.Builder<String, ConfiguredTarget> mapBuilder =
+    /** Determines and returns a map from attribute name to list of configured targets. */
+    private ImmutableSortedKeyListMultimap<String, ConfiguredTargetAndTarget> createTargetMap() {
+      ImmutableSortedKeyListMultimap.Builder<String, ConfiguredTargetAndTarget> mapBuilder =
           ImmutableSortedKeyListMultimap.builder();
 
-      for (Map.Entry<Attribute, Collection<ConfiguredTarget>> entry :
+      for (Map.Entry<Attribute, Collection<ConfiguredTargetAndTarget>> entry :
           prerequisiteMap.asMap().entrySet()) {
         Attribute attribute = entry.getKey();
         if (attribute == null) {
@@ -1586,7 +1593,7 @@
 
         if (attribute.isSilentRuleClassFilter()) {
           Predicate<RuleClass> filter = attribute.getAllowedRuleClassesPredicate();
-          for (ConfiguredTarget configuredTarget : entry.getValue()) {
+          for (ConfiguredTargetAndTarget configuredTarget : entry.getValue()) {
             Target prerequisiteTarget = configuredTarget.getTarget();
             if ((prerequisiteTarget instanceof Rule)
                 && filter.apply(((Rule) prerequisiteTarget).getRuleClassObject())) {
@@ -1595,7 +1602,7 @@
             }
           }
         } else {
-          for (ConfiguredTarget configuredTarget : entry.getValue()) {
+          for (ConfiguredTargetAndTarget configuredTarget : entry.getValue()) {
             validateDirectPrerequisite(attribute, configuredTarget);
             mapBuilder.put(attribute.getName(), configuredTarget);
           }
@@ -1657,8 +1664,11 @@
       reporter.assertNoErrors();
     }
 
-    private String badPrerequisiteMessage(String targetKind, ConfiguredTarget prerequisite,
-        String reason, boolean isWarning) {
+    private String badPrerequisiteMessage(
+        String targetKind,
+        ConfiguredTargetAndTarget prerequisite,
+        String reason,
+        boolean isWarning) {
       String msgPrefix = targetKind != null ? targetKind + " " : "";
       String msgReason = reason != null ? " (" + reason + ")" : "";
       if (isWarning) {
@@ -1671,8 +1681,12 @@
           msgPrefix, AliasProvider.printLabelWithAliasChain(prerequisite), msgReason);
     }
 
-    private void reportBadPrerequisite(Attribute attribute, String targetKind,
-        ConfiguredTarget prerequisite, String reason, boolean isWarning) {
+    private void reportBadPrerequisite(
+        Attribute attribute,
+        String targetKind,
+        ConfiguredTargetAndTarget prerequisite,
+        String reason,
+        boolean isWarning) {
       String message = badPrerequisiteMessage(targetKind, prerequisite, reason, isWarning);
       if (isWarning) {
         attributeWarning(attribute.getName(), message);
@@ -1681,8 +1695,8 @@
       }
     }
 
-    private void validateDirectPrerequisiteType(ConfiguredTarget prerequisite,
-        Attribute attribute) {
+    private void validateDirectPrerequisiteType(
+        ConfiguredTargetAndTarget prerequisite, Attribute attribute) {
       Target prerequisiteTarget = prerequisite.getTarget();
       Label prerequisiteLabel = prerequisiteTarget.getLabel();
 
@@ -1764,8 +1778,8 @@
       return RuleContext.isVisible(rule, prerequisite);
     }
 
-    private void validateDirectPrerequisiteFileTypes(ConfiguredTarget prerequisite,
-        Attribute attribute) {
+    private void validateDirectPrerequisiteFileTypes(
+        ConfiguredTargetAndTarget prerequisite, Attribute attribute) {
       if (attribute.isSkipAnalysisTimeFileTypeCheck()) {
         return;
       }
@@ -1785,11 +1799,12 @@
       // If we performed this check when allowedFileTypes == NO_FILE this would
       // always throw an error in those cases
       if (allowedFileTypes != FileTypeSet.NO_FILE) {
-        Iterable<Artifact> artifacts = prerequisite.getProvider(FileProvider.class)
-            .getFilesToBuild();
+        Iterable<Artifact> artifacts =
+            prerequisite.getConfiguredTarget().getProvider(FileProvider.class).getFilesToBuild();
         if (attribute.isSingleArtifact() && Iterables.size(artifacts) != 1) {
-          attributeError(attribute.getName(),
-              "'" + prerequisite.getLabel() + "' must produce a single file");
+          attributeError(
+              attribute.getName(),
+              "'" + prerequisite.getTarget().getLabel() + "' must produce a single file");
           return;
         }
         for (Artifact sourceArtifact : artifacts) {
@@ -1797,9 +1812,17 @@
             return;
           }
         }
-        attributeError(attribute.getName(), "'" + prerequisite.getLabel()
-            + "' does not produce any " + getRuleClassNameForLogging() + " " + attribute.getName()
-            + " files (expected " + allowedFileTypes + ")");
+        attributeError(
+            attribute.getName(),
+            "'"
+                + prerequisite.getTarget().getLabel()
+                + "' does not produce any "
+                + getRuleClassNameForLogging()
+                + " "
+                + attribute.getName()
+                + " files (expected "
+                + allowedFileTypes
+                + ")");
       }
     }
 
@@ -1808,7 +1831,8 @@
      * dependency is valid if it is from a rule in allowedRuledClasses, OR if all of the providers
      * in requiredProviders are provided by the target.
      */
-    private void validateRuleDependency(ConfiguredTarget prerequisite, Attribute attribute) {
+    private void validateRuleDependency(
+        ConfiguredTargetAndTarget prerequisite, Attribute attribute) {
 
       Set<String> unfulfilledRequirements = new LinkedHashSet<>();
       if (checkRuleDependencyClass(prerequisite, attribute, unfulfilledRequirements)) {
@@ -1832,7 +1856,9 @@
 
     /** Check if prerequisite should be allowed based on its rule class. */
     private boolean checkRuleDependencyClass(
-        ConfiguredTarget prerequisite, Attribute attribute, Set<String> unfulfilledRequirements) {
+        ConfiguredTargetAndTarget prerequisite,
+        Attribute attribute,
+        Set<String> unfulfilledRequirements) {
       if (attribute.getAllowedRuleClassesPredicate() != Predicates.<RuleClass>alwaysTrue()) {
         if (attribute
             .getAllowedRuleClassesPredicate()
@@ -1858,7 +1884,7 @@
      * <p>If yes, also issues said warning.
      */
     private boolean checkRuleDependencyClassWarnings(
-        ConfiguredTarget prerequisite, Attribute attribute) {
+        ConfiguredTargetAndTarget prerequisite, Attribute attribute) {
       if (attribute
           .getAllowedRuleClassesWarningPredicate()
           .apply(((Rule) prerequisite.getTarget()).getRuleClassObject())) {
@@ -1879,7 +1905,9 @@
 
     /** Check if prerequisite should be allowed based on required providers on the attribute. */
     private boolean checkRuleDependencyMandatoryProviders(
-        ConfiguredTarget prerequisite, Attribute attribute, Set<String> unfulfilledRequirements) {
+        ConfiguredTargetAndTarget prerequisite,
+        Attribute attribute,
+        Set<String> unfulfilledRequirements) {
       RequiredProviders requiredProviders = attribute.getRequiredProviders();
 
       if (requiredProviders.acceptsAny()) {
@@ -1887,20 +1915,24 @@
         return false;
       }
 
-      if (prerequisite.satisfies(requiredProviders)) {
+      if (prerequisite.getConfiguredTarget().satisfies(requiredProviders)) {
         return true;
       }
 
       unfulfilledRequirements.add(
           String.format(
               "'%s' does not have mandatory providers: %s",
-              prerequisite.getLabel(),
-              prerequisite.missingProviders(requiredProviders).getDescription()));
+              prerequisite.getTarget().getLabel(),
+              prerequisite
+                  .getConfiguredTarget()
+                  .missingProviders(requiredProviders)
+                  .getDescription()));
 
       return false;
     }
 
-    private void validateDirectPrerequisite(Attribute attribute, ConfiguredTarget prerequisite) {
+    private void validateDirectPrerequisite(
+        Attribute attribute, ConfiguredTargetAndTarget prerequisite) {
       validateDirectPrerequisiteType(prerequisite, attribute);
       validateDirectPrerequisiteFileTypes(prerequisite, attribute);
       if (attribute.performPrereqValidatorCheck()) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TargetContext.java b/src/main/java/com/google/devtools/build/lib/analysis/TargetContext.java
index 85fd697..cd1fa08 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TargetContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TargetContext.java
@@ -24,7 +24,9 @@
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.packages.PackageSpecification.PackageGroupContents;
 import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import java.util.List;
+import java.util.Set;
 import javax.annotation.Nullable;
 
 /**
@@ -46,7 +48,7 @@
    * exception of visibility (i.e., visibility is represented here, even though it is a rule
    * attribute in case of a rule). Rule attributes are handled by the {@link RuleContext} subclass.
    */
-  private final List<ConfiguredTarget> directPrerequisites;
+  private final List<ConfiguredTargetAndTarget> directPrerequisites;
 
   private final NestedSet<PackageGroupContents> visibility;
 
@@ -59,12 +61,12 @@
       AnalysisEnvironment env,
       Target target,
       BuildConfiguration configuration,
-      Iterable<ConfiguredTarget> directPrerequisites,
+      Set<ConfiguredTargetAndTarget> directPrerequisites,
       NestedSet<PackageGroupContents> visibility) {
     this.env = env;
     this.target = target;
     this.configuration = configuration;
-    this.directPrerequisites = ImmutableList.<ConfiguredTarget>copyOf(directPrerequisites);
+    this.directPrerequisites = ImmutableList.copyOf(directPrerequisites);
     this.visibility = visibility;
   }
 
@@ -113,10 +115,10 @@
    */
   public TransitiveInfoCollection maybeFindDirectPrerequisite(Label label,
       BuildConfiguration config) {
-    for (ConfiguredTarget prerequisite : directPrerequisites) {
-      if (prerequisite.getLabel().equals(label)
-          && (Objects.equal(prerequisite.getConfiguration(), config))) {
-        return prerequisite;
+    for (ConfiguredTargetAndTarget prerequisite : directPrerequisites) {
+      if (prerequisite.getTarget().getLabel().equals(label)
+          && (Objects.equal(prerequisite.getConfiguredTarget().getConfiguration(), config))) {
+        return prerequisite.getConfiguredTarget();
       }
     }
     return null;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java
index de1fc37..490462f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
@@ -111,7 +112,8 @@
     return requiredToolchains;
   }
 
-  public void resolveToolchains(OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap) {
+  public void resolveToolchains(
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap) {
     if (!this.requiredToolchains.isEmpty()) {
       this.resolvedToolchainProviders =
           new ResolvedToolchainProviders(findToolchains(resolvedToolchainLabels, prerequisiteMap));
@@ -162,7 +164,7 @@
 
   private static ImmutableMap<Label, ToolchainInfo> findToolchains(
       ResolvedToolchainLabels resolvedToolchainLabels,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap) {
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap) {
     // Find the prerequisites associated with the $toolchains attribute.
     Optional<Attribute> toolchainAttribute =
         prerequisiteMap
@@ -176,11 +178,11 @@
         "No toolchains attribute found while loading resolved toolchains");
 
     ImmutableMap.Builder<Label, ToolchainInfo> toolchains = new ImmutableMap.Builder<>();
-    for (ConfiguredTarget target : prerequisiteMap.get(toolchainAttribute.get())) {
-      Label discoveredLabel = target.getLabel();
+    for (ConfiguredTargetAndTarget target : prerequisiteMap.get(toolchainAttribute.get())) {
+      Label discoveredLabel = target.getTarget().getLabel();
       Label toolchainType = resolvedToolchainLabels.getType(discoveredLabel);
       if (toolchainType != null) {
-        ToolchainInfo toolchainInfo = PlatformProviderUtils.toolchain(target);
+        ToolchainInfo toolchainInfo = PlatformProviderUtils.toolchain(target.getConfiguredTarget());
         toolchains.put(toolchainType, toolchainInfo);
       }
     }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
index afdcb18..f6033ad 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
@@ -16,7 +16,6 @@
 
 import com.google.devtools.build.lib.analysis.AliasProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
-import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
@@ -25,6 +24,7 @@
 import com.google.devtools.build.lib.packages.RequiredProviders;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndTarget;
 import com.google.devtools.build.lib.syntax.Type;
 
 /** Ensures that a target's prerequisites are visible to it and match its testonly status. */
@@ -33,7 +33,7 @@
 
   @Override
   public void validate(
-      RuleContext.Builder context, ConfiguredTarget prerequisite, Attribute attribute) {
+      RuleContext.Builder context, ConfiguredTargetAndTarget prerequisite, Attribute attribute) {
     validateDirectPrerequisiteVisibility(context, prerequisite, attribute.getName());
     validateDirectPrerequisiteForTestOnly(context, prerequisite);
     ConfiguredRuleClassProvider.DeprecationValidator.validateDirectPrerequisiteForDeprecation(
@@ -41,15 +41,17 @@
   }
 
   private void validateDirectPrerequisiteVisibility(
-      RuleContext.Builder context, ConfiguredTarget prerequisite, String attrName) {
+      RuleContext.Builder context, ConfiguredTargetAndTarget prerequisite, String attrName) {
     Rule rule = context.getRule();
     Target prerequisiteTarget = prerequisite.getTarget();
     if (!context
             .getRule()
             .getLabel()
             .getPackageIdentifier()
-            .equals(AliasProvider.getDependencyLabel(prerequisite).getPackageIdentifier())
-        && !context.isVisible(prerequisite)) {
+            .equals(
+                AliasProvider.getDependencyLabel(prerequisite.getConfiguredTarget())
+                    .getPackageIdentifier())
+        && !context.isVisible(prerequisite.getConfiguredTarget())) {
       String errorMessage;
       if (!context.getConfiguration().checkVisibility()) {
         errorMessage =
@@ -98,7 +100,7 @@
   }
 
   private void validateDirectPrerequisiteForTestOnly(
-      RuleContext.Builder context, ConfiguredTarget prerequisite) {
+      RuleContext.Builder context, ConfiguredTargetAndTarget prerequisite) {
     Rule rule = context.getRule();
 
     if (rule.getRuleClassObject().getAdvertisedProviders().canHaveAnyProvider()) {
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 56599c1..630830d 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
@@ -45,6 +45,7 @@
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
 import com.google.devtools.build.lib.packages.NativeAspectClass;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
@@ -244,13 +245,24 @@
 
     ConfiguredTarget associatedTarget = configuredTargetValue.getConfiguredTarget();
 
-    Target target = associatedTarget.getTarget();
+    ConfiguredTargetAndTarget associatedConfiguredTargetAndTarget;
+    Package targetPkg =
+        ((PackageValue)
+                env.getValue(PackageValue.key(associatedTarget.getLabel().getPackageIdentifier())))
+            .getPackage();
+    try {
+      associatedConfiguredTargetAndTarget =
+          new ConfiguredTargetAndTarget(
+              associatedTarget, targetPkg.getTarget(associatedTarget.getLabel().getName()));
+    } catch (NoSuchTargetException e) {
+      throw new IllegalStateException("Name already verified", e);
+    }
 
     if (configuredTargetValue.getConfiguredTarget().getProvider(AliasProvider.class) != null) {
       return createAliasAspect(
           env,
           view.getActionKeyContext(),
-          target,
+          associatedConfiguredTargetAndTarget.getTarget(),
           aspect,
           key,
           configuredTargetValue.getConfiguredTarget());
@@ -286,6 +298,8 @@
 
       }
     }
+    associatedConfiguredTargetAndTarget =
+        associatedConfiguredTargetAndTarget.fromConfiguredTarget(associatedTarget);
     aspectPathBuilder.add(aspect);
 
     SkyframeDependencyResolver resolver = view.createDependencyResolver(env);
@@ -299,13 +313,14 @@
     // required by all dependencies (both those of the aspect and those of the base target)
     // will be present this way.
     TargetAndConfiguration originalTargetAndAspectConfiguration =
-        new TargetAndConfiguration(target, key.getAspectConfiguration());
+        new TargetAndConfiguration(
+            associatedConfiguredTargetAndTarget.getTarget(), key.getAspectConfiguration());
     ImmutableList<Aspect> aspectPath = aspectPathBuilder.build();
     try {
       // Get the configuration targets that trigger this rule's configurable attributes.
       ImmutableMap<Label, ConfigMatchingProvider> configConditions =
           ConfiguredTargetFunction.getConfigConditions(
-              target,
+              associatedConfiguredTargetAndTarget.getTarget(),
               env,
               resolver,
               originalTargetAndAspectConfiguration,
@@ -325,7 +340,8 @@
                 env,
                 String.format(
                     "aspect %s applied to %s",
-                    aspect.getDescriptor().getDescription(), target.toString()),
+                    aspect.getDescriptor().getDescription(),
+                    associatedConfiguredTargetAndTarget.getTarget().toString()),
                 requiredToolchains,
                 key.getAspectConfiguration());
       } catch (ToolchainContextException e) {
@@ -336,7 +352,7 @@
         return null;
       }
 
-      OrderedSetMultimap<Attribute, ConfiguredTarget> depValueMap;
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> depValueMap;
       try {
         depValueMap =
             ConfiguredTargetFunction.computeDependencies(
@@ -368,7 +384,7 @@
           aspectPath,
           aspect,
           aspectFactory,
-          associatedTarget,
+          associatedConfiguredTargetAndTarget,
           key.getAspectConfiguration(),
           configConditions,
           toolchainContext,
@@ -496,11 +512,11 @@
       ImmutableList<Aspect> aspectPath,
       Aspect aspect,
       ConfiguredAspectFactory aspectFactory,
-      ConfiguredTarget associatedTarget,
+      ConfiguredTargetAndTarget associatedTarget,
       BuildConfiguration aspectConfiguration,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       ToolchainContext toolchainContext,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> directDeps,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> directDeps,
       @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution)
       throws AspectFunctionException, InterruptedException {
 
@@ -540,8 +556,11 @@
     events.replayOn(env.getListener());
     if (events.hasErrors()) {
       analysisEnvironment.disable(associatedTarget.getTarget());
-      throw new AspectFunctionException(new AspectCreationException(
-          "Analysis of target '" + associatedTarget.getLabel() + "' failed; build aborted"));
+      throw new AspectFunctionException(
+          new AspectCreationException(
+              "Analysis of target '"
+                  + associatedTarget.getTarget().getLabel()
+                  + "' failed; build aborted"));
     }
     Preconditions.checkState(!analysisEnvironment.hasErrors(),
         "Analysis environment hasError() but no errors reported");
@@ -556,7 +575,7 @@
     return new AspectValue(
         key,
         aspect,
-        associatedTarget.getLabel(),
+        associatedTarget.getTarget().getLabel(),
         associatedTarget.getTarget().getLocation(),
         configuredAspect,
         actionKeyContext,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetAndTarget.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetAndTarget.java
new file mode 100644
index 0000000..82ce77e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetAndTarget.java
@@ -0,0 +1,64 @@
+// Copyright 2018 The Bazel Authors. 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.skyframe;
+
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.Target;
+
+/**
+ * A container class for a {@link ConfiguredTarget} and {@link Target}. In the future, {@link
+ * ConfiguredTarget} objects will no longer contain their associated {@link Target}. Consumers that
+ * need the {@link Target} must therefore have access to one of these objects.
+ *
+ * <p>These objects are intended to be short-lived, never stored in Skyframe, since they pair two
+ * heavyweight objects, a {@link ConfiguredTarget} and a {@link Target}, which holds a {@link
+ * Package}.
+ */
+public class ConfiguredTargetAndTarget {
+  private final ConfiguredTarget configuredTarget;
+  private final Target target;
+
+  ConfiguredTargetAndTarget(ConfiguredTarget configuredTarget, Target target) {
+    this.configuredTarget = configuredTarget;
+    this.target = target;
+    Preconditions.checkState(
+        configuredTarget.getTarget().equals(target),
+        "%s %s %s",
+        configuredTarget,
+        target,
+        configuredTarget.getTarget());
+  }
+
+  /**
+   * For use with {@code MergedConfiguredTarget} and similar, where we create a virtual {@link
+   * ConfiguredTarget} corresponding to the same {@link Target}.
+   */
+  public ConfiguredTargetAndTarget fromConfiguredTarget(ConfiguredTarget maybeNew) {
+    if (configuredTarget.equals(maybeNew)) {
+      return this;
+    }
+    return new ConfiguredTargetAndTarget(maybeNew, this.target);
+  }
+
+  public Target getTarget() {
+    return target;
+  }
+
+  public ConfiguredTarget getConfiguredTarget() {
+    return configuredTarget;
+  }
+}
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 4a80c7a..d737228 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
@@ -64,8 +64,11 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import com.google.devtools.build.skyframe.ValueOrException;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Semaphore;
@@ -250,7 +253,7 @@
       }
 
       // Calculate the dependencies of this target.
-      OrderedSetMultimap<Attribute, ConfiguredTarget> depValueMap =
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> depValueMap =
           computeDependencies(
               env,
               resolver,
@@ -370,7 +373,7 @@
    *     the host configuration as early as possible and pass this reference to all consumers
    */
   @Nullable
-  static OrderedSetMultimap<Attribute, ConfiguredTarget> computeDependencies(
+  static OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> computeDependencies(
       Environment env,
       SkyframeDependencyResolver resolver,
       TargetAndConfiguration ctgValue,
@@ -420,7 +423,7 @@
     }
 
     // Resolve configured target dependencies and handle errors.
-    Map<SkyKey, ConfiguredTarget> depValues =
+    Map<SkyKey, ConfiguredTargetAndTarget> depValues =
         resolveConfiguredTargetDependencies(
             env,
             depValueNames.values(),
@@ -510,7 +513,7 @@
     }
     configValueNames = staticConfigs.build();
 
-    Map<SkyKey, ConfiguredTarget> configValues =
+    Map<SkyKey, ConfiguredTargetAndTarget> configValues =
         resolveConfiguredTargetDependencies(
             env,
             configValueNames,
@@ -523,7 +526,7 @@
     // Get the configured targets as ConfigMatchingProvider interfaces.
     for (Dependency entry : configValueNames) {
       SkyKey baseKey = ConfiguredTargetValue.key(entry.getLabel(), entry.getConfiguration());
-      ConfiguredTarget value = configValues.get(baseKey);
+      ConfiguredTarget value = configValues.get(baseKey).getConfiguredTarget();
       // The code above guarantees that value is non-null here.
       ConfigMatchingProvider provider = value.getProvider(ConfigMatchingProvider.class);
       if (provider != null) {
@@ -542,13 +545,13 @@
   }
 
   /**
-   * * Resolves the targets referenced in depValueNames and returns their ConfiguredTarget
-   * instances.
+   * Resolves the targets referenced in depValueNames and returns their {@link
+   * ConfiguredTargetAndTarget} instances.
    *
    * <p>Returns null if not all instances are available yet.
    */
   @Nullable
-  private static Map<SkyKey, ConfiguredTarget> resolveConfiguredTargetDependencies(
+  private static Map<SkyKey, ConfiguredTargetAndTarget> resolveConfiguredTargetDependencies(
       Environment env,
       Collection<Dependency> deps,
       @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution,
@@ -556,33 +559,92 @@
       throws DependencyEvaluationException, InterruptedException {
     boolean missedValues = env.valuesMissing();
     boolean failed = false;
-    Iterable<SkyKey> depKeys = Iterables.transform(deps,
-        input -> ConfiguredTargetValue.key(input.getLabel(), input.getConfiguration()));
+    // Naively we would like to just fetch all requested ConfiguredTargets, together with their
+    // Packages. However, some ConfiguredTargets are AliasConfiguredTargets, which means that their
+    // associated Targets (and therefore associated Packages) don't correspond to their own Labels.
+    // We don't know the associated Package until we fetch the ConfiguredTarget. Therefore, we have
+    // to do a potential second pass, in which we fetch all the Packages for AliasConfiguredTargets.
+    Iterable<SkyKey> depKeys =
+        Iterables.concat(
+            Iterables.transform(
+                deps,
+                input -> ConfiguredTargetValue.key(input.getLabel(), input.getConfiguration())),
+            Iterables.transform(
+                deps, input -> PackageValue.key(input.getLabel().getPackageIdentifier())));
     Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> depValuesOrExceptions =
             env.getValuesOrThrow(depKeys, ConfiguredValueCreationException.class);
-    Map<SkyKey, ConfiguredTarget> result =
-        Maps.newHashMapWithExpectedSize(depValuesOrExceptions.size());
-    for (Map.Entry<SkyKey, ValueOrException<ConfiguredValueCreationException>> entry
-        : depValuesOrExceptions.entrySet()) {
-      try {
-        ConfiguredTargetValue depValue = (ConfiguredTargetValue) entry.getValue().get();
-        if (depValue == null) {
-          missedValues = true;
-        } else {
-          result.put(entry.getKey(), depValue.getConfiguredTarget());
-          if (transitivePackagesForPackageRootResolution != null) {
-            transitivePackagesForPackageRootResolution.addTransitive(
-                depValue.getTransitivePackagesForPackageRootResolution());
+    Map<SkyKey, ConfiguredTargetAndTarget> result = Maps.newHashMapWithExpectedSize(deps.size());
+    Set<SkyKey> aliasPackagesToFetch = new HashSet<>();
+    List<Dependency> aliasDepsToRedo = new ArrayList<>();
+    Map<SkyKey, SkyValue> aliasPackageValues = null;
+    Collection<Dependency> depsToProcess = deps;
+    for (int i = 0; i < 2; i++) {
+      for (Dependency dep : depsToProcess) {
+        SkyKey key = ConfiguredTargetValue.key(dep.getLabel(), dep.getConfiguration());
+        try {
+          ConfiguredTargetValue depValue =
+              (ConfiguredTargetValue) depValuesOrExceptions.get(key).get();
+
+          if (depValue == null) {
+            missedValues = true;
+          } else {
+            ConfiguredTarget depCt = depValue.getConfiguredTarget();
+            Label depLabel = depCt.getLabel();
+            SkyKey packageKey = PackageValue.key(depLabel.getPackageIdentifier());
+            PackageValue pkgValue;
+            if (i == 0) {
+              ValueOrException<ConfiguredValueCreationException> packageResult =
+                  depValuesOrExceptions.get(packageKey);
+              if (packageResult == null) {
+                aliasPackagesToFetch.add(packageKey);
+                aliasDepsToRedo.add(dep);
+                continue;
+              } else {
+                pkgValue =
+                    Preconditions.checkNotNull(
+                        (PackageValue) packageResult.get(),
+                        "Package should have been loaded during dep resolution: %s",
+                        dep);
+              }
+            } else {
+              // We were doing AliasConfiguredTarget mop-up.
+              pkgValue = (PackageValue) aliasPackageValues.get(packageKey);
+              if (pkgValue == null) {
+                // This is unexpected: on the second iteration, all packages should be present,
+                // since the configured targets that depend on them are present. But since that is
+                // not a guarantee Skyframe makes, we tolerate their absence.
+                missedValues = true;
+                continue;
+              }
+            }
+            try {
+              result.put(
+                  key,
+                  new ConfiguredTargetAndTarget(
+                      depValue.getConfiguredTarget(),
+                      pkgValue.getPackage().getTarget(depLabel.getName())));
+            } catch (NoSuchTargetException e) {
+              throw new IllegalStateException("Target already verified for " + dep, e);
+            }
+            if (transitivePackagesForPackageRootResolution != null) {
+              transitivePackagesForPackageRootResolution.addTransitive(
+                  depValue.getTransitivePackagesForPackageRootResolution());
+            }
           }
+        } catch (ConfiguredValueCreationException e) {
+          // TODO(ulfjack): If there is an analysis root cause, we drop all loading root causes.
+          if (e.getAnalysisRootCause() != null) {
+            throw new DependencyEvaluationException(e);
+          }
+          transitiveLoadingRootCauses.addTransitive(e.loadingRootCauses);
+          failed = true;
         }
-      } catch (ConfiguredValueCreationException e) {
-        // TODO(ulfjack): If there is an analysis root cause, we drop all loading root causes.
-        if (e.getAnalysisRootCause() != null) {
-          throw new DependencyEvaluationException(e);
-        }
-        transitiveLoadingRootCauses.addTransitive(e.loadingRootCauses);
-        failed = true;
       }
+      if (aliasDepsToRedo.isEmpty()) {
+        break;
+      }
+      aliasPackageValues = env.getValues(aliasPackagesToFetch);
+      depsToProcess = aliasDepsToRedo;
     }
     if (missedValues) {
       return null;
@@ -594,7 +656,6 @@
     }
   }
 
-
   @Override
   public String extractTag(SkyKey skyKey) {
     return Label.print(((ConfiguredTargetKey) skyKey.argument()).getLabel());
@@ -606,7 +667,7 @@
       Environment env,
       Target target,
       BuildConfiguration configuration,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> depValueMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> depValueMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       @Nullable ToolchainContext toolchainContext,
       @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution)
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 d724a90..5d4e24a 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
@@ -500,7 +500,7 @@
       Target target,
       BuildConfiguration configuration,
       CachingAnalysisEnvironment analysisEnvironment,
-      OrderedSetMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
+      OrderedSetMultimap<Attribute, ConfiguredTargetAndTarget> prerequisiteMap,
       ImmutableMap<Label, ConfigMatchingProvider> configConditions,
       @Nullable ToolchainContext toolchainContext)
       throws InterruptedException {
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 29cb592..52687e2 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
@@ -92,6 +92,7 @@
 import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
 import com.google.devtools.build.lib.packages.BuildFileName;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.PackageFactory;
@@ -1267,7 +1268,7 @@
   }
 
   /**
-   * Returns the {@link ConfiguredTarget}s corresponding to the given keys.
+   * Returns the {@link ConfiguredTargetAndTarget}s corresponding to the given keys.
    *
    * <p>For use for legacy support and tests calling through {@code BuildView} only.
    *
@@ -1276,7 +1277,7 @@
    */
   @ThreadSafety.ThreadSafe
   // TODO(bazel-team): rename this and below methods to something that discourages general use
-  public ImmutableList<ConfiguredTarget> getConfiguredTargets(
+  public ImmutableList<ConfiguredTargetAndTarget> getConfiguredTargets(
       ExtendedEventHandler eventHandler,
       BuildConfiguration originalConfig,
       Iterable<Dependency> keys) {
@@ -1285,8 +1286,8 @@
   }
 
   /**
-   * Returns a map from {@link Dependency} inputs to the {@link ConfiguredTarget}s corresponding to
-   * those dependencies.
+   * Returns a map from {@link Dependency} inputs to the {@link ConfiguredTargetAndTarget}s
+   * corresponding to those dependencies.
    *
    * <p>For use for legacy support and tests calling through {@code BuildView} only.
    *
@@ -1294,7 +1295,7 @@
    * returned list.
    */
   @ThreadSafety.ThreadSafe
-  public ImmutableMultimap<Dependency, ConfiguredTarget> getConfiguredTargetMap(
+  public ImmutableMultimap<Dependency, ConfiguredTargetAndTarget> getConfiguredTargetMap(
       ExtendedEventHandler eventHandler,
       BuildConfiguration originalConfig,
       Iterable<Dependency> keys) {
@@ -1324,6 +1325,7 @@
               AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig));
         }
       }
+      skyKeys.add(PackageValue.key(key.getLabel().getPackageIdentifier()));
     }
 
     EvaluationResult<SkyValue> result = evaluateSkyKeys(eventHandler, skyKeys);
@@ -1331,45 +1333,75 @@
       reportCycles(eventHandler, entry.getValue().getCycleInfo(), entry.getKey());
     }
 
-    ImmutableMultimap.Builder<Dependency, ConfiguredTarget> cts =
-        ImmutableMultimap.<Dependency, ConfiguredTarget>builder();
+    ImmutableMultimap.Builder<Dependency, ConfiguredTargetAndTarget> cts =
+        ImmutableMultimap.builder();
 
-  DependentNodeLoop:
-    for (Dependency key : keys) {
-      if (!configs.containsKey(key)) {
-        // If we couldn't compute a configuration for this target, the target was in error (e.g.
-        // it couldn't be loaded). Exclude it from the results.
-        continue;
-      }
-      for (BuildConfiguration depConfig : configs.get(key)) {
-        SkyKey configuredTargetKey = ConfiguredTargetValue.key(
-            key.getLabel(), depConfig);
-        if (result.get(configuredTargetKey) == null) {
+    // Logic copied from ConfiguredTargetFunction#computeDependencies.
+    Set<SkyKey> aliasPackagesToFetch = new HashSet<>();
+    List<Dependency> aliasKeysToRedo = new ArrayList<>();
+    EvaluationResult<SkyValue> aliasPackageValues = null;
+    Iterable<Dependency> keysToProcess = keys;
+    for (int i = 0; i < 2; i++) {
+      DependentNodeLoop:
+      for (Dependency key : keysToProcess) {
+        if (!configs.containsKey(key)) {
+          // If we couldn't compute a configuration for this target, the target was in error (e.g.
+          // it couldn't be loaded). Exclude it from the results.
           continue;
         }
-
-        ConfiguredTarget configuredTarget =
-            ((ConfiguredTargetValue) result.get(configuredTargetKey)).getConfiguredTarget();
-        List<ConfiguredAspect> configuredAspects = new ArrayList<>();
-
-        for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
-          SkyKey aspectKey =
-              AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig);
-          if (result.get(aspectKey) == null) {
-            continue DependentNodeLoop;
+        for (BuildConfiguration depConfig : configs.get(key)) {
+          SkyKey configuredTargetKey = ConfiguredTargetValue.key(key.getLabel(), depConfig);
+          if (result.get(configuredTargetKey) == null) {
+            continue;
           }
 
-          configuredAspects.add(((AspectValue) result.get(aspectKey)).getConfiguredAspect());
-        }
+          ConfiguredTarget configuredTarget =
+              ((ConfiguredTargetValue) result.get(configuredTargetKey)).getConfiguredTarget();
+          Label label = configuredTarget.getLabel();
+          SkyKey packageKey = PackageValue.key(label.getPackageIdentifier());
+          PackageValue packageValue;
+          if (i == 0) {
+            packageValue = (PackageValue) result.get(packageKey);
+            if (packageValue == null) {
+              aliasPackagesToFetch.add(packageKey);
+              aliasKeysToRedo.add(key);
+              continue;
+            }
+          } else {
+            packageValue =
+                (PackageValue)
+                    Preconditions.checkNotNull(aliasPackageValues.get(packageKey), packageKey);
+          }
+          List<ConfiguredAspect> configuredAspects = new ArrayList<>();
 
-        try {
-          cts.put(key, MergedConfiguredTarget.of(configuredTarget, configuredAspects));
-        } catch (DuplicateException e) {
-          throw new IllegalStateException(
-              String.format("Error creating %s", configuredTarget.getTarget().getLabel()),
-              e);
+          for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
+            SkyKey aspectKey =
+                AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig);
+            if (result.get(aspectKey) == null) {
+              continue DependentNodeLoop;
+            }
+
+            configuredAspects.add(((AspectValue) result.get(aspectKey)).getConfiguredAspect());
+          }
+
+          try {
+            cts.put(
+                key,
+                new ConfiguredTargetAndTarget(
+                    MergedConfiguredTarget.of(configuredTarget, configuredAspects),
+                    packageValue.getPackage().getTarget(configuredTarget.getLabel().getName())));
+
+          } catch (DuplicateException | NoSuchTargetException e) {
+            throw new IllegalStateException(
+                String.format("Error creating %s", configuredTarget.getLabel()), e);
+          }
         }
       }
+      if (aliasKeysToRedo.isEmpty()) {
+        break;
+      }
+      aliasPackageValues = evaluateSkyKeys(eventHandler, aliasPackagesToFetch);
+      keysToProcess = aliasKeysToRedo;
     }
 
     return cts.build();
@@ -1611,14 +1643,20 @@
       Label label,
       BuildConfiguration configuration,
       Transition transition) {
-    return Iterables.getFirst(
-        getConfiguredTargets(
-            eventHandler,
-            configuration,
-            ImmutableList.of(configuration == null
-                ? Dependency.withNullConfiguration(label)
-                : Dependency.withTransitionAndAspects(label, transition, AspectCollection.EMPTY))),
-        null);
+    ConfiguredTargetAndTarget configuredTargetAndTarget =
+        Iterables.getFirst(
+            getConfiguredTargets(
+                eventHandler,
+                configuration,
+                ImmutableList.of(
+                    configuration == null
+                        ? Dependency.withNullConfiguration(label)
+                        : Dependency.withTransitionAndAspects(
+                            label, transition, AspectCollection.EMPTY))),
+            null);
+    return configuredTargetAndTarget == null
+        ? null
+        : configuredTargetAndTarget.getConfiguredTarget();
   }
 
   /**