Make target pattern parsing repository-renaming aware.

Platform and toolchain resolution rely on the target pattern parsing code to turn target pattern strings into Labels. Since most of the target pattern parsing codepaths turn target patterns that originated from the command line, they don't need to pass along the repository renaming map. But instances that affect platform and toolchain target patterns, we need to pass the map.

This allows us to turn on the --incompatible_remap_main_repo flag on by default in Bazel.

Closes #7902.
Fixes #7755, #7773, #7654.

RELNOTES: None
PiperOrigin-RevId: 246199440
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ResolvedToolchainContext.java b/src/main/java/com/google/devtools/build/lib/analysis/ResolvedToolchainContext.java
index 9a19b10..182328b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ResolvedToolchainContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ResolvedToolchainContext.java
@@ -1,4 +1,4 @@
-// Copyright 2017 The Bazel Authors. All rights reserved.
+// Copyright 2019 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.
@@ -17,6 +17,7 @@
 import static java.util.stream.Collectors.joining;
 
 import com.google.auto.value.AutoValue;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -24,6 +25,7 @@
 import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
 import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
 import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo;
+import com.google.devtools.build.lib.analysis.skylark.BazelStarlarkContext;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -185,7 +187,8 @@
     printer.append(">");
   }
 
-  private Label transformKey(Object key, Location loc) throws EvalException {
+  private Label transformKey(Object key, Location loc, BazelStarlarkContext context)
+      throws EvalException {
     if (key instanceof Label) {
       return (Label) key;
     } else if (key instanceof ToolchainTypeInfo) {
@@ -194,7 +197,7 @@
       Label toolchainType;
       String rawLabel = (String) key;
       try {
-        toolchainType = Label.parseAbsolute(rawLabel, ImmutableMap.of());
+        toolchainType = Label.parseAbsolute(rawLabel, context.getRepoMapping());
       } catch (LabelSyntaxException e) {
         throw new EvalException(
             loc, String.format("Unable to parse toolchain %s: %s", rawLabel, e.getMessage()), e);
@@ -212,7 +215,8 @@
   @Override
   public ToolchainInfo getIndex(Object key, Location loc, StarlarkContext context)
       throws EvalException {
-    Label toolchainTypeLabel = transformKey(key, loc);
+    Preconditions.checkArgument(context instanceof BazelStarlarkContext);
+    Label toolchainTypeLabel = transformKey(key, loc, (BazelStarlarkContext) context);
 
     if (!containsKey(key, loc, context)) {
       throw new EvalException(
@@ -232,7 +236,8 @@
   @Override
   public boolean containsKey(Object key, Location loc, StarlarkContext context)
       throws EvalException {
-    Label toolchainTypeLabel = transformKey(key, loc);
+    Preconditions.checkArgument(context instanceof BazelStarlarkContext);
+    Label toolchainTypeLabel = transformKey(key, loc, (BazelStarlarkContext) context);
     Optional<Label> matching =
         toolchains().keySet().stream()
             .map(ToolchainTypeInfo::typeLabel)
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index d465c70..5372e4f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -43,6 +43,7 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.cmdline.LabelValidator;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.AttributeMap;
@@ -289,6 +290,7 @@
       throws EvalException {
     SkylarkUtils.checkLoadingOrWorkspacePhase(funcallEnv, "rule", ast.getLocation());
 
+    Preconditions.checkArgument(context instanceof BazelStarlarkContext);
     BazelStarlarkContext bazelContext = (BazelStarlarkContext) context;
     // analysis_test=true implies test=true.
     test |= Boolean.TRUE.equals(analysisTest);
@@ -355,7 +357,9 @@
         funcallEnv.getGlobals().getLabel(), funcallEnv.getTransitiveContentHashCode());
     builder.addRequiredToolchains(
         collectToolchainLabels(
-            toolchains.getContents(String.class, "toolchains"), ast.getLocation()));
+            toolchains.getContents(String.class, "toolchains"),
+            bazelContext.getRepoMapping(),
+            ast.getLocation()));
 
     if (!buildSetting.equals(Runtime.NONE) && !cfg.equals(Runtime.NONE)) {
       throw new EvalException(
@@ -396,6 +400,7 @@
       builder.addExecutionPlatformConstraints(
           collectConstraintLabels(
               execCompatibleWith.getContents(String.class, "exec_compatile_with"),
+              bazelContext.getRepoMapping(),
               ast.getLocation()));
     }
 
@@ -434,11 +439,14 @@
   }
 
   private static ImmutableList<Label> collectToolchainLabels(
-      Iterable<String> rawLabels, Location loc) throws EvalException {
+      Iterable<String> rawLabels,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping,
+      Location loc)
+      throws EvalException {
     ImmutableList.Builder<Label> requiredToolchains = new ImmutableList.Builder<>();
     for (String rawLabel : rawLabels) {
       try {
-        Label toolchainLabel = Label.parseAbsolute(rawLabel, ImmutableMap.of());
+        Label toolchainLabel = Label.parseAbsolute(rawLabel, repoMapping);
         requiredToolchains.add(toolchainLabel);
       } catch (LabelSyntaxException e) {
         throw new EvalException(
@@ -450,11 +458,14 @@
   }
 
   private static ImmutableList<Label> collectConstraintLabels(
-      Iterable<String> rawLabels, Location loc) throws EvalException {
+      Iterable<String> rawLabels,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping,
+      Location loc)
+      throws EvalException {
     ImmutableList.Builder<Label> constraintLabels = new ImmutableList.Builder<>();
     for (String rawLabel : rawLabels) {
       try {
-        Label constraintLabel = Label.parseAbsolute(rawLabel, ImmutableMap.of());
+        Label constraintLabel = Label.parseAbsolute(rawLabel, repoMapping);
         constraintLabels.add(constraintLabel);
       } catch (LabelSyntaxException e) {
         throw new EvalException(
@@ -477,8 +488,10 @@
       SkylarkList<?> toolchains,
       String doc,
       FuncallExpression ast,
-      Environment funcallEnv)
+      Environment funcallEnv,
+      StarlarkContext context)
       throws EvalException {
+    Preconditions.checkArgument(context instanceof BazelStarlarkContext);
     Location location = ast.getLocation();
     ImmutableList.Builder<String> attrAspects = ImmutableList.builder();
     for (Object attributeAspect : attributeAspects) {
@@ -566,7 +579,9 @@
         HostTransition.INSTANCE,
         ImmutableSet.copyOf(hostFragments.getContents(String.class, "host_fragments")),
         collectToolchainLabels(
-            toolchains.getContents(String.class, "toolchains"), ast.getLocation()));
+            toolchains.getContents(String.class, "toolchains"),
+            ((BazelStarlarkContext) context).getRepoMapping(),
+            ast.getLocation()));
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
index be65076..53d8354 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
@@ -144,14 +144,15 @@
   }
 
   /**
-   * Evaluates the current target pattern, excluding targets under directories in both
-   * {@code blacklistedSubdirectories} and {@code excludedSubdirectories}, and returns the result.
+   * Evaluates the current target pattern, excluding targets under directories in both {@code
+   * blacklistedSubdirectories} and {@code excludedSubdirectories}, and returns the result.
    *
-   * @throws IllegalArgumentException if either {@code blacklistedSubdirectories} or
-   *      {@code excludedSubdirectories} is nonempty and this pattern does not have type
-   *      {@code Type.TARGETS_BELOW_DIRECTORY}.
+   * @throws IllegalArgumentException if either {@code blacklistedSubdirectories} or {@code
+   *     excludedSubdirectories} is nonempty and this pattern does not have type {@code
+   *     Type.TARGETS_BELOW_DIRECTORY}.
    */
   public abstract <T, E extends Exception> void eval(
+      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
       TargetPatternResolver<T> resolver,
       ImmutableSet<PathFragment> blacklistedSubdirectories,
       ImmutableSet<PathFragment> excludedSubdirectories,
@@ -160,21 +161,28 @@
       throws TargetParsingException, E, InterruptedException;
 
   /**
-   * Evaluates this {@link TargetPattern} synchronously, feeding the result to the given
-   * {@code callback}, and then returns an appropriate immediate {@link ListenableFuture}.
+   * Evaluates this {@link TargetPattern} synchronously, feeding the result to the given {@code
+   * callback}, and then returns an appropriate immediate {@link ListenableFuture}.
    *
-   * <p>If the returned {@link ListenableFuture}'s {@link ListenableFuture#get} throws an
-   * {@link ExecutionException}, the cause will be an instance of either
-   * {@link TargetParsingException} or the given {@code exceptionClass}.
+   * <p>If the returned {@link ListenableFuture}'s {@link ListenableFuture#get} throws an {@link
+   * ExecutionException}, the cause will be an instance of either {@link TargetParsingException} or
+   * the given {@code exceptionClass}.
    */
   public final <T, E extends Exception> ListenableFuture<Void> evalAdaptedForAsync(
+      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
       TargetPatternResolver<T> resolver,
       ImmutableSet<PathFragment> blacklistedSubdirectories,
       ImmutableSet<PathFragment> excludedSubdirectories,
       ThreadSafeBatchCallback<T, E> callback,
       Class<E> exceptionClass) {
     try {
-      eval(resolver, blacklistedSubdirectories, excludedSubdirectories, callback, exceptionClass);
+      eval(
+          repositoryMapping,
+          resolver,
+          blacklistedSubdirectories,
+          excludedSubdirectories,
+          callback,
+          exceptionClass);
       return Futures.immediateFuture(null);
     } catch (TargetParsingException e) {
       return Futures.immediateFailedFuture(e);
@@ -189,14 +197,15 @@
   }
 
   /**
-   * Returns a {@link ListenableFuture} representing the asynchronous evaluation of this
-   * {@link TargetPattern} that feeds the results to the given {@code callback}.
+   * Returns a {@link ListenableFuture} representing the asynchronous evaluation of this {@link
+   * TargetPattern} that feeds the results to the given {@code callback}.
    *
-   * <p>If the returned {@link ListenableFuture}'s {@link ListenableFuture#get} throws an
-   * {@link ExecutionException}, the cause will be an instance of either
-   * {@link TargetParsingException} or the given {@code exceptionClass}.
+   * <p>If the returned {@link ListenableFuture}'s {@link ListenableFuture#get} throws an {@link
+   * ExecutionException}, the cause will be an instance of either {@link TargetParsingException} or
+   * the given {@code exceptionClass}.
    */
   public <T, E extends Exception> ListenableFuture<Void> evalAsync(
+      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
       TargetPatternResolver<T> resolver,
       ImmutableSet<PathFragment> blacklistedSubdirectories,
       ImmutableSet<PathFragment> excludedSubdirectories,
@@ -204,7 +213,12 @@
       Class<E> exceptionClass,
       ListeningExecutorService executor) {
     return evalAdaptedForAsync(
-        resolver, blacklistedSubdirectories, excludedSubdirectories, callback, exceptionClass);
+        repositoryMapping,
+        resolver,
+        blacklistedSubdirectories,
+        excludedSubdirectories,
+        callback,
+        exceptionClass);
   }
 
   /**
@@ -276,8 +290,8 @@
   /**
    * For patterns of type {@link Type#PATH_AS_TARGET}, returns the path in question.
    *
-   * <p>The interpretation of this path, of course, depends on the existence of packages.
-   * See {@link InterpretPathAsTarget#eval}.
+   * <p>The interpretation of this path, of course, depends on the existence of packages. See {@link
+   * TargetPattern#eval}.
    */
   public String getPathForPathAsTarget() {
     throw new IllegalStateException();
@@ -318,12 +332,15 @@
 
     @Override
     public <T, E extends Exception> void eval(
+        ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
         TargetPatternResolver<T> resolver,
         ImmutableSet<PathFragment> blacklistedSubdirectories,
         ImmutableSet<PathFragment> excludedSubdirectories,
         BatchCallback<T, E> callback,
-        Class<E> exceptionClass) throws TargetParsingException, E, InterruptedException {
-      callback.process(resolver.getExplicitTarget(label(targetName)).getTargets());
+        Class<E> exceptionClass)
+        throws TargetParsingException, E, InterruptedException {
+      callback.process(
+          resolver.getExplicitTarget(label(targetName, repositoryMapping)).getTargets());
     }
 
     @Override
@@ -375,14 +392,17 @@
 
     @Override
     public <T, E extends Exception> void eval(
+        ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
         TargetPatternResolver<T> resolver,
         ImmutableSet<PathFragment> blacklistedSubdirectories,
         ImmutableSet<PathFragment> excludedSubdirectories,
-        BatchCallback<T, E> callback, Class<E> exceptionClass)
+        BatchCallback<T, E> callback,
+        Class<E> exceptionClass)
         throws TargetParsingException, E, InterruptedException {
       if (resolver.isPackage(PackageIdentifier.createInMainRepo(path))) {
         // User has specified a package name. lookout for default target.
-        callback.process(resolver.getExplicitTarget(label("//" + path)).getTargets());
+        callback.process(
+            resolver.getExplicitTarget(label("//" + path, repositoryMapping)).getTargets());
       } else {
 
         List<String> pieces = SLASH_SPLITTER.splitToList(path);
@@ -395,7 +415,8 @@
             String targetName = SLASH_JOINER.join(pieces.subList(i, pieces.size()));
             callback.process(
                 resolver
-                    .getExplicitTarget(label("//" + packageName + ":" + targetName))
+                    .getExplicitTarget(
+                        label("//" + packageName + ":" + targetName, repositoryMapping))
                     .getTargets());
             return;
           }
@@ -460,10 +481,12 @@
 
     @Override
     public <T, E extends Exception> void eval(
+        ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
         TargetPatternResolver<T> resolver,
         ImmutableSet<PathFragment> blacklistedSubdirectories,
         ImmutableSet<PathFragment> excludedSubdirectories,
-        BatchCallback<T, E> callback, Class<E> exceptionClass)
+        BatchCallback<T, E> callback,
+        Class<E> exceptionClass)
         throws TargetParsingException, E, InterruptedException {
       if (checkWildcardConflict) {
         ResolvedTargets<T> targets = getWildcardConflict(resolver);
@@ -569,6 +592,7 @@
 
     @Override
     public <T, E extends Exception> void eval(
+        ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
         TargetPatternResolver<T> resolver,
         ImmutableSet<PathFragment> blacklistedSubdirectories,
         ImmutableSet<PathFragment> excludedSubdirectories,
@@ -588,6 +612,7 @@
 
     @Override
     public <T, E extends Exception> ListenableFuture<Void> evalAsync(
+        ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
         TargetPatternResolver<T> resolver,
         ImmutableSet<PathFragment> blacklistedSubdirectories,
         ImmutableSet<PathFragment> excludedSubdirectories,
@@ -882,9 +907,11 @@
 
   // Parse 'label' as a Label, mapping LabelSyntaxException into
   // TargetParsingException.
-  private static Label label(String label) throws TargetParsingException {
+  private static Label label(
+      String label, ImmutableMap<RepositoryName, RepositoryName> repositoryMapping)
+      throws TargetParsingException {
     try {
-      return Label.parseAbsolute(label, ImmutableMap.of());
+      return Label.parseAbsolute(label, repositoryMapping);
     } catch (LabelSyntaxException e) {
       throw new TargetParsingException("invalid target format: '"
           + StringUtilities.sanitizeControlChars(label) + "'; "
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index 11b0fa4..8663a60 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -17,6 +17,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedSet;
@@ -215,8 +216,8 @@
   private ImmutableList<Event> events;
   private ImmutableList<Postable> posts;
 
-  private ImmutableList<String> registeredExecutionPlatforms;
-  private ImmutableList<String> registeredToolchains;
+  private ImmutableListMultimap<RepositoryName, String> registeredExecutionPlatforms;
+  private ImmutableListMultimap<RepositoryName, String> registeredToolchains;
 
   /**
    * Package initialization, part 1 of 3: instantiates a new package with the
@@ -404,8 +405,8 @@
     this.features = ImmutableSortedSet.copyOf(builder.features);
     this.events = ImmutableList.copyOf(builder.events);
     this.posts = ImmutableList.copyOf(builder.posts);
-    this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms);
-    this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains);
+    this.registeredExecutionPlatforms = builder.registeredExecutionPlatforms.build();
+    this.registeredToolchains = builder.registeredToolchains.build();
     this.repositoryMapping = Preconditions.checkNotNull(builder.repositoryMapping);
     ImmutableMap.Builder<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>>
         repositoryMappingsBuilder = ImmutableMap.builder();
@@ -697,11 +698,11 @@
     return defaultRestrictedTo;
   }
 
-  public ImmutableList<String> getRegisteredExecutionPlatforms() {
+  public ImmutableListMultimap<RepositoryName, String> getRegisteredExecutionPlatforms() {
     return registeredExecutionPlatforms;
   }
 
-  public ImmutableList<String> getRegisteredToolchains() {
+  public ImmutableListMultimap<RepositoryName, String> getRegisteredToolchains() {
     return registeredToolchains;
   }
 
@@ -835,8 +836,10 @@
 
     private ImmutableList<Label> skylarkFileDependencies = ImmutableList.of();
 
-    private final List<String> registeredExecutionPlatforms = new ArrayList<>();
-    private final List<String> registeredToolchains = new ArrayList<>();
+    private final ImmutableListMultimap.Builder<RepositoryName, String>
+        registeredExecutionPlatforms = ImmutableListMultimap.builder();
+    private final ImmutableListMultimap.Builder<RepositoryName, String> registeredToolchains =
+        ImmutableListMultimap.builder();
 
     private ThirdPartyLicenseExistencePolicy thirdPartyLicenceExistencePolicy =
         ThirdPartyLicenseExistencePolicy.USER_CONTROLLABLE;
@@ -1401,12 +1404,21 @@
       addRuleUnchecked(rule);
     }
 
-    void addRegisteredExecutionPlatforms(List<String> platforms) {
-      this.registeredExecutionPlatforms.addAll(platforms);
+    void addRegisteredToolchains(RepositoryName repositoryName, List<String> toolchains) {
+      this.registeredToolchains.putAll(repositoryName, toolchains);
     }
 
-    void addRegisteredToolchains(List<String> toolchains) {
-      this.registeredToolchains.addAll(toolchains);
+    void addRegisteredToolchains(ImmutableListMultimap<RepositoryName, String> toolchains) {
+      this.registeredToolchains.putAll(toolchains);
+    }
+
+    void addRegisteredExecutionPlatforms(RepositoryName repositoryName, List<String> platforms) {
+      this.registeredExecutionPlatforms.putAll(repositoryName, platforms);
+    }
+
+    void addRegisteredExecutionPlatforms(
+        ImmutableListMultimap<RepositoryName, String> executionPlatforms) {
+      this.registeredExecutionPlatforms.putAll(executionPlatforms);
     }
 
     private Builder beforeBuild(boolean discoverAssumedInputFiles) throws NoSuchPackageException {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 409fbb9..2cea873 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -191,7 +191,7 @@
                 new BazelStarlarkContext(
                     /* toolsRepository= */ null,
                     /* fragmentNameToClass= */ null,
-                    ImmutableMap.of(),
+                    /* repoMapping= */ ImmutableMap.of(),
                     new SymbolGenerator<>(workspaceFileKey)))
             .build();
     SkylarkUtils.setPhase(workspaceEnv, Phase.WORKSPACE);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
index f4e02f3..fb37437 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
@@ -201,8 +201,9 @@
       throws EvalException, InterruptedException {
     // Add to the package definition for later.
     Package.Builder builder = PackageFactory.getContext(env, location).pkgBuilder;
+    RepositoryName repositoryName = getRepositoryName(env.getGlobals().getLabel());
     builder.addRegisteredExecutionPlatforms(
-        platformLabels.getContents(String.class, "platform_labels"));
+        repositoryName, platformLabels.getContents(String.class, "platform_labels"));
 
     return NONE;
   }
@@ -213,11 +214,25 @@
       throws EvalException, InterruptedException {
     // Add to the package definition for later.
     Package.Builder builder = PackageFactory.getContext(env, location).pkgBuilder;
-    builder.addRegisteredToolchains(toolchainLabels.getContents(String.class, "toolchain_labels"));
+    RepositoryName repositoryName = getRepositoryName(env.getGlobals().getLabel());
+    builder.addRegisteredToolchains(
+        repositoryName, toolchainLabels.getContents(String.class, "toolchain_labels"));
 
     return NONE;
   }
 
+  private RepositoryName getRepositoryName(Label bzlLabel) {
+    RepositoryName repositoryName;
+    if (bzlLabel == null) {
+      // registration happened directly in the main WORKSPACE
+      repositoryName = RepositoryName.MAIN;
+    } else {
+      // registeration happened in a loaded bzl file
+      repositoryName = bzlLabel.getPackageIdentifier().getRepository();
+    }
+    return repositoryName;
+  }
+
   @Override
   public NoneType bind(String name, Object actual, FuncallExpression ast, Environment env)
       throws EvalException, InterruptedException {
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java
index 593157b..4163538 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/ActionGraphQueryEnvironment.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.query2;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.Futures;
@@ -272,7 +273,7 @@
       QueryExpression owner, String pattern, Callback<ConfiguredTargetValue> callback) {
     TargetPattern patternToEval;
     try {
-      patternToEval = getPattern(pattern);
+      patternToEval = getPatternKey(pattern);
     } catch (TargetParsingException tpe) {
       try {
         reportBuildFileError(owner, tpe.getMessage());
@@ -291,6 +292,7 @@
       return QueryTaskFutureImpl.ofDelegate(
           Futures.catchingAsync(
               patternToEval.evalAdaptedForAsync(
+                  /* repositoryMapping= */ ImmutableMap.of(),
                   resolver,
                   getBlacklistedPackagePrefixesPathFragments(),
                   /* excludedSubdirectories= */ ImmutableSet.of(),
diff --git a/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
index fcbc15f0..a6f84db 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/ConfiguredTargetQueryEnvironment.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.query2;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.Futures;
@@ -212,7 +213,7 @@
       QueryExpression owner, String pattern, Callback<ConfiguredTarget> callback) {
     TargetPattern patternToEval;
     try {
-      patternToEval = getPattern(pattern);
+      patternToEval = getPatternKey(pattern);
     } catch (TargetParsingException tpe) {
       try {
         reportBuildFileError(owner, tpe.getMessage());
@@ -231,6 +232,7 @@
       return QueryTaskFutureImpl.ofDelegate(
           Futures.catchingAsync(
               patternToEval.evalAdaptedForAsync(
+                  /* repositoryMapping = */ ImmutableMap.of(),
                   resolver,
                   getBlacklistedPackagePrefixesPathFragments(),
                   /* excludedSubdirectories= */ ImmutableSet.of(),
diff --git a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
index edefd40..aaab632 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/PostAnalysisQueryEnvironment.java
@@ -27,6 +27,7 @@
 import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.cmdline.TargetPattern;
 import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
@@ -114,7 +115,12 @@
     ALL_PATTERNS =
         ImmutableList.of(
             new TargetPatternKey(
-                targetPattern, FilteringPolicies.NO_FILTER, false, "", ImmutableSet.of()));
+                targetPattern,
+                FilteringPolicies.NO_FILTER,
+                false,
+                "",
+                ImmutableSet.of(),
+                RepositoryName.MAIN));
   }
 
   protected RecursivePackageProviderBackedTargetPatternResolver resolver;
@@ -239,7 +245,7 @@
   @Nullable
   protected abstract T getValueFromKey(SkyKey key) throws InterruptedException;
 
-  protected TargetPattern getPattern(String pattern) throws TargetParsingException {
+  protected TargetPattern getPatternKey(String pattern) throws TargetParsingException {
     TargetPatternKey targetPatternKey =
         ((TargetPatternKey)
             TargetPatternValue.key(
diff --git a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
index 5c168958..3aee5dc 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
@@ -741,6 +741,7 @@
     }
     ListenableFuture<Void> evalFuture =
         patternToEval.evalAsync(
+            /* repositoryMapping= */ ImmutableMap.of(),
             resolver,
             blacklistedSubdirectoriesToExclude,
             additionalSubdirectoriesToExclude,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
index 6112c72..3bbc298 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternFunction.java
@@ -99,8 +99,16 @@
     DepsOfPatternPreparer preparer =
         new DepsOfPatternPreparer(env, pkgPath.get(), traverseTestSuites);
 
+    RepositoryMappingValue repositoryMappingValue =
+        (RepositoryMappingValue)
+            env.getValue(RepositoryMappingValue.key(patternKey.getRepositoryName()));
+    if (repositoryMappingValue == null) {
+      return null;
+    }
+
     try {
       parsedPattern.eval(
+          repositoryMappingValue.getRepositoryMapping(),
           preparer,
           blacklistedSubdirectories,
           excludedSubdirectories,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java
index bfbb45d..d891af2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java
@@ -14,7 +14,9 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.Interner;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.cmdline.TargetPattern;
 import com.google.devtools.build.lib.cmdline.TargetPattern.Type;
@@ -91,8 +93,12 @@
         ImmutableList.builder();
     ImmutableList.Builder<PrepareDepsOfPatternSkyKeyException> resultExceptionsBuilder =
         ImmutableList.builder();
+    ImmutableListMultimap.Builder<RepositoryName, String> builder = ImmutableListMultimap.builder();
+    builder.putAll(RepositoryName.MAIN, patterns);
+    ImmutableListMultimap<RepositoryName, String> patternsMap = builder.build();
+
     Iterable<TargetPatternSkyKeyOrException> keysMaybe =
-        TargetPatternValue.keys(patterns, FilteringPolicies.NO_FILTER, offset);
+        TargetPatternValue.keys(patternsMap, FilteringPolicies.NO_FILTER, offset);
     ImmutableList.Builder<TargetPatternKey> targetPatternKeysBuilder = ImmutableList.builder();
     for (TargetPatternSkyKeyOrException keyMaybe : keysMaybe) {
       try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
index 255fe0e..3e2fed6 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
@@ -21,6 +21,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.PlatformConfiguration;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -28,6 +29,7 @@
 import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelConstants;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.RuleClass;
@@ -62,22 +64,19 @@
     }
     BuildConfiguration configuration = buildConfigurationValue.getConfiguration();
 
-    ImmutableList.Builder<String> targetPatternBuilder = new ImmutableList.Builder<>();
-
     // Get the execution platforms from the configuration.
     PlatformConfiguration platformConfiguration =
         configuration.getFragment(PlatformConfiguration.class);
-    if (platformConfiguration != null) {
-      targetPatternBuilder.addAll(platformConfiguration.getExtraExecutionPlatforms());
-    }
 
     // Get the registered execution platforms from the WORKSPACE.
-    List<String> workspaceExecutionPlatforms = getWorkspaceExecutionPlatforms(env);
+    ImmutableListMultimap<RepositoryName, String> workspaceExecutionPlatforms =
+        getWorkspaceExecutionPlatforms(env);
     if (workspaceExecutionPlatforms == null) {
       return null;
     }
-    targetPatternBuilder.addAll(workspaceExecutionPlatforms);
-    ImmutableList<String> targetPatterns = targetPatternBuilder.build();
+
+    ImmutableListMultimap<RepositoryName, String> targetPatterns =
+        mergeExecutionPlatforms(workspaceExecutionPlatforms, platformConfiguration);
 
     // Expand target patterns.
     ImmutableList<Label> platformLabels;
@@ -110,8 +109,8 @@
    */
   @Nullable
   @VisibleForTesting
-  public static List<String> getWorkspaceExecutionPlatforms(Environment env)
-      throws InterruptedException {
+  public static ImmutableListMultimap<RepositoryName, String> getWorkspaceExecutionPlatforms(
+      Environment env) throws InterruptedException {
     PackageValue externalPackageValue =
         (PackageValue) env.getValue(PackageValue.key(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER));
     if (externalPackageValue == null) {
@@ -122,6 +121,19 @@
     return externalPackage.getRegisteredExecutionPlatforms();
   }
 
+  private ImmutableListMultimap<RepositoryName, String> mergeExecutionPlatforms(
+      ImmutableListMultimap<RepositoryName, String> workspaceExecutionPlatforms,
+      @Nullable PlatformConfiguration platformConfiguration) {
+
+    ImmutableListMultimap.Builder<RepositoryName, String> builder = ImmutableListMultimap.builder();
+    // This ensures that execution platforms specified via a flag are considered first
+    if (platformConfiguration != null) {
+      builder.putAll(RepositoryName.MAIN, platformConfiguration.getExtraExecutionPlatforms());
+    }
+    builder.putAll(workspaceExecutionPlatforms);
+    return builder.build();
+  }
+
   private ImmutableList<ConfiguredTargetKey> configureRegisteredExecutionPlatforms(
       Environment env,
       BuildConfiguration configuration,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
index 7d7b054..7aa1169 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
@@ -18,12 +18,14 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.PlatformConfiguration;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
 import com.google.devtools.build.lib.analysis.platform.DeclaredToolchainInfo;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelConstants;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
@@ -56,19 +58,18 @@
     }
     BuildConfiguration configuration = buildConfigurationValue.getConfiguration();
 
-    ImmutableList.Builder<String> targetPatternBuilder = new ImmutableList.Builder<>();
-
     // Get the toolchains from the configuration.
     PlatformConfiguration platformConfiguration =
         configuration.getFragment(PlatformConfiguration.class);
-    targetPatternBuilder.addAll(platformConfiguration.getExtraToolchains());
 
-    // Get the registered toolchains from the WORKSPACE.
-    targetPatternBuilder.addAll(getWorkspaceToolchains(env));
+    // Get the registered toolchains from the WORKSPACE
+    ImmutableListMultimap<RepositoryName, String> workspaceToolchains = getWorkspaceToolchains(env);
     if (env.valuesMissing()) {
       return null;
     }
-    ImmutableList<String> targetPatterns = targetPatternBuilder.build();
+
+    ImmutableListMultimap<RepositoryName, String> targetPatterns =
+        mergeToolchains(workspaceToolchains, platformConfiguration);
 
     // Expand target patterns.
     ImmutableList<Label> toolchainLabels;
@@ -94,23 +95,15 @@
     return RegisteredToolchainsValue.create(registeredToolchains);
   }
 
-  private Iterable<? extends String> getWorkspaceToolchains(Environment env)
-      throws InterruptedException {
-    List<String> patterns = getRegisteredToolchains(env);
-    if (patterns == null) {
-      return ImmutableList.of();
-    }
-    return patterns;
-  }
-
   /**
-   * Loads the external package and then returns the registered toolchains.
+   * Loads the external package and then returns the registered toolchains with repository name.
    *
    * @param env the environment to use for lookups
    */
   @Nullable
   @VisibleForTesting
-  public static List<String> getRegisteredToolchains(Environment env) throws InterruptedException {
+  public static ImmutableListMultimap<RepositoryName, String> getWorkspaceToolchains(
+      Environment env) throws InterruptedException {
     PackageValue externalPackageValue =
         (PackageValue) env.getValue(PackageValue.key(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER));
     if (externalPackageValue == null) {
@@ -121,6 +114,19 @@
     return externalPackage.getRegisteredToolchains();
   }
 
+  private ImmutableListMultimap<RepositoryName, String> mergeToolchains(
+      ImmutableListMultimap<RepositoryName, String> workspaceToolchains,
+      @Nullable PlatformConfiguration platformConfiguration) {
+
+    ImmutableListMultimap.Builder<RepositoryName, String> builder = ImmutableListMultimap.builder();
+    // This ensures that toolchains specified via a flag are considered first
+    if (platformConfiguration != null) {
+      builder.putAll(RepositoryName.MAIN, platformConfiguration.getExtraToolchains());
+    }
+    builder.putAll(workspaceToolchains);
+    return builder.build();
+  }
+
   private ImmutableList<DeclaredToolchainInfo> configureRegisteredToolchains(
       Environment env,
       BuildConfiguration configuration,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java
index e9849ac..4c177bc 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeTargetPatternEvaluator.java
@@ -15,9 +15,11 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.ResolvedTargets;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.events.Event;
@@ -110,8 +112,14 @@
       ImmutableList<String> targetPatterns,
       FilteringPolicy policy,
       boolean keepGoing) throws TargetParsingException {
+
+    ImmutableListMultimap.Builder<RepositoryName, String> patternsBuilder =
+        ImmutableListMultimap.builder();
+    patternsBuilder.putAll(RepositoryName.MAIN, targetPatterns);
+    ImmutableListMultimap<RepositoryName, String> patternsMap = patternsBuilder.build();
+
     Iterable<TargetPatternSkyKeyOrException> keysMaybe =
-        TargetPatternValue.keys(targetPatterns, policy, offset);
+        TargetPatternValue.keys(patternsMap, policy, offset);
     ImmutableList.Builder<TargetPatternKey> builder = ImmutableList.builder();
     for (TargetPatternSkyKeyOrException skyKeyOrException : keysMaybe) {
       try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
index b195308..25f7033 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternFunction.java
@@ -74,7 +74,14 @@
               Iterables.addAll(results, partialResult);
             }
           };
+      RepositoryMappingValue repositoryMappingValue =
+          (RepositoryMappingValue)
+              env.getValue(RepositoryMappingValue.key(patternKey.getRepositoryName()));
+      if (repositoryMappingValue == null) {
+        return null;
+      }
       parsedPattern.eval(
+          repositoryMappingValue.getRepositoryMapping(),
           resolver,
           blacklisted.getPatterns(),
           excludedSubdirectories,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
index 969d656a..984e142f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternPhaseFunction.java
@@ -18,12 +18,14 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelConstants;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.ResolvedTargets;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.events.Event;
@@ -261,9 +263,14 @@
       Environment env, TargetPatternPhaseKey options, List<String> failedPatterns)
       throws InterruptedException {
     List<TargetPatternKey> patternSkyKeys = new ArrayList<>(options.getTargetPatterns().size());
+
+    ImmutableListMultimap.Builder<RepositoryName, String> builder = ImmutableListMultimap.builder();
+    builder.putAll(RepositoryName.MAIN, options.getTargetPatterns());
+    ImmutableListMultimap<RepositoryName, String> patternsMap = builder.build();
+
     for (TargetPatternSkyKeyOrException keyOrException :
         TargetPatternValue.keys(
-            options.getTargetPatterns(),
+            patternsMap,
             options.getBuildManualTests()
                 ? FilteringPolicies.NO_FILTER
                 : FilteringPolicies.FILTER_MANUAL,
@@ -383,8 +390,13 @@
       Environment env, List<String> targetPatterns, String offset, TestFilter testFilter)
       throws InterruptedException {
     List<TargetPatternKey> patternSkyKeys = new ArrayList<>();
+
+    ImmutableListMultimap.Builder<RepositoryName, String> builder = ImmutableListMultimap.builder();
+    builder.putAll(RepositoryName.MAIN, targetPatterns);
+    ImmutableListMultimap<RepositoryName, String> patternsMap = builder.build();
+
     for (TargetPatternSkyKeyOrException keyOrException :
-        TargetPatternValue.keys(targetPatterns, FilteringPolicies.FILTER_TESTS, offset)) {
+        TargetPatternValue.keys(patternsMap, FilteringPolicies.FILTER_TESTS, offset)) {
       try {
         patternSkyKeys.add(keyOrException.getSkyKey());
       } catch (TargetParsingException e) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternUtil.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternUtil.java
index 56602b2..67f094a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternUtil.java
@@ -15,9 +15,10 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
-import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
 import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
 import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyKey;
@@ -33,25 +34,15 @@
 public class TargetPatternUtil {
 
   /**
-   * Expand the given {@code targetPatterns}. This handles the needed underlying Skyframe calls (via
-   * {@code env}), and will return {@code null} to signal a Skyframe restart.
-   */
-  @Nullable
-  public static ImmutableList<Label> expandTargetPatterns(
-      Environment env, List<String> targetPatterns)
-      throws InvalidTargetPatternException, InterruptedException {
-
-    return expandTargetPatterns(env, targetPatterns, FilteringPolicies.NO_FILTER);
-  }
-
-  /**
    * Expand the given {@code targetPatterns}, using the {@code filteringPolicy}. This handles the
    * needed underlying Skyframe calls (via {@code env}), and will return {@code null} to signal a
    * Skyframe restart.
    */
   @Nullable
   public static ImmutableList<Label> expandTargetPatterns(
-      Environment env, List<String> targetPatterns, FilteringPolicy filteringPolicy)
+      Environment env,
+      ImmutableListMultimap<RepositoryName, String> targetPatterns,
+      FilteringPolicy filteringPolicy)
       throws InvalidTargetPatternException, InterruptedException {
 
     // First parse the patterns, and throw any errors immediately.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
index 1aea611..d9cdcee 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetPatternValue.java
@@ -15,12 +15,14 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.cmdline.ResolvedTargets;
 import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.cmdline.TargetPattern;
@@ -114,7 +116,9 @@
   @ThreadSafe
   public static TargetPatternKey key(String pattern, FilteringPolicy policy, String offset)
       throws TargetParsingException {
-    return Iterables.getOnlyElement(keys(ImmutableList.of(pattern), policy, offset)).getSkyKey();
+    ImmutableListMultimap<RepositoryName, String> patternMap =
+        ImmutableListMultimap.of(RepositoryName.MAIN, pattern);
+    return Iterables.getOnlyElement(keys(patternMap, policy, offset)).getSkyKey();
   }
 
   /**
@@ -123,34 +127,41 @@
    * fails to parse, the element in the returned iterable corresponding to it will throw when its
    * {@link TargetPatternSkyKeyOrException#getSkyKey} method is called.
    *
-   * @param patterns The list of patterns, eg "-foo/biz...". If a pattern's first character is "-",
-   *     it is treated as a negative pattern.
+   * @param patterns A multimap from {@code RepositoryName}s of where the pattern originated ({@code
+   *     "@"}, i.e. main repository if the pattern appeared on the command line), to patterns, eg
+   *     "-foo/biz...". If a pattern's first character is "-", it is treated as a negative pattern.
    * @param policy The filtering policy, eg "only return test targets"
    * @param offset The offset to apply to relative target patterns.
    */
   @ThreadSafe
-  public static Iterable<TargetPatternSkyKeyOrException> keys(List<String> patterns,
-      FilteringPolicy policy, String offset) {
+  public static Iterable<TargetPatternSkyKeyOrException> keys(
+      ImmutableListMultimap<RepositoryName, String> patterns,
+      FilteringPolicy policy,
+      String offset) {
     TargetPattern.Parser parser = new TargetPattern.Parser(offset);
     ImmutableList.Builder<TargetPatternSkyKeyOrException> builder = ImmutableList.builder();
-    for (String pattern : patterns) {
-      boolean positive = !pattern.startsWith("-");
-      String absoluteValueOfPattern = positive ? pattern : pattern.substring(1);
-      TargetPattern targetPattern;
-      try {
-        targetPattern = parser.parse(absoluteValueOfPattern);
-      } catch (TargetParsingException e) {
-        builder.add(new TargetPatternSkyKeyException(e, absoluteValueOfPattern));
-        continue;
+
+    for (RepositoryName repositoryName : patterns.keySet()) {
+      for (String pattern : patterns.get(repositoryName)) {
+        boolean positive = !pattern.startsWith("-");
+        String absoluteValueOfPattern = positive ? pattern : pattern.substring(1);
+        TargetPattern targetPattern;
+        try {
+          targetPattern = parser.parse(absoluteValueOfPattern);
+        } catch (TargetParsingException e) {
+          builder.add(new TargetPatternSkyKeyException(e, absoluteValueOfPattern));
+          continue;
+        }
+        TargetPatternKey targetPatternKey =
+            new TargetPatternKey(
+                targetPattern,
+                positive ? policy : FilteringPolicies.NO_FILTER,
+                /*isNegative=*/ !positive,
+                offset,
+                ImmutableSet.<PathFragment>of(),
+                repositoryName);
+        builder.add(new TargetPatternSkyKeyValue(targetPatternKey));
       }
-      TargetPatternKey targetPatternKey =
-          new TargetPatternKey(
-              targetPattern,
-              positive ? policy : FilteringPolicies.NO_FILTER,
-              /*isNegative=*/ !positive,
-              offset,
-              ImmutableSet.<PathFragment>of());
-      builder.add(new TargetPatternSkyKeyValue(targetPatternKey));
     }
     return builder.build();
   }
@@ -196,7 +207,8 @@
         policy,
         original.isNegative(),
         original.getOffset(),
-        excludedSubdirectories);
+        excludedSubdirectories,
+        RepositoryName.MAIN);
   }
 
   private static class TargetPatternKeyWithExclusionsResult {
@@ -287,17 +299,21 @@
     private final String offset;
     private final ImmutableSet<PathFragment> excludedSubdirectories;
 
+    private final RepositoryName repositoryName;
+
     public TargetPatternKey(
         TargetPattern parsedPattern,
         FilteringPolicy policy,
         boolean isNegative,
         String offset,
-        ImmutableSet<PathFragment> excludedSubdirectories) {
+        ImmutableSet<PathFragment> excludedSubdirectories,
+        RepositoryName repositoryName) {
       this.parsedPattern = Preconditions.checkNotNull(parsedPattern);
       this.policy = Preconditions.checkNotNull(policy);
       this.isNegative = isNegative;
       this.offset = offset;
       this.excludedSubdirectories = Preconditions.checkNotNull(excludedSubdirectories);
+      this.repositoryName = Preconditions.checkNotNull(repositoryName);
     }
 
     @Override
@@ -329,6 +345,10 @@
       return excludedSubdirectories;
     }
 
+    public RepositoryName getRepositoryName() {
+      return repositoryName;
+    }
+
     ImmutableSet<PathFragment> getAllSubdirectoriesToExclude(
         Iterable<PathFragment> blacklistedPackagePrefixes) throws InterruptedException {
       ImmutableSet.Builder<PathFragment> excludedPathsBuilder = ImmutableSet.builder();
@@ -375,8 +395,8 @@
 
     @Override
     public int hashCode() {
-      return Objects.hash(parsedPattern, isNegative, policy, offset,
-          excludedSubdirectories);
+      return Objects.hash(
+          parsedPattern, isNegative, policy, offset, excludedSubdirectories, repositoryName);
     }
 
     @Override
@@ -386,9 +406,12 @@
       }
       TargetPatternKey other = (TargetPatternKey) obj;
 
-      return other.isNegative == this.isNegative && other.parsedPattern.equals(this.parsedPattern)
-          && other.offset.equals(this.offset) && other.policy.equals(this.policy)
-          && other.excludedSubdirectories.equals(this.excludedSubdirectories);
+      return other.isNegative == this.isNegative
+          && other.parsedPattern.equals(this.parsedPattern)
+          && other.offset.equals(this.offset)
+          && other.policy.equals(this.policy)
+          && other.excludedSubdirectories.equals(this.excludedSubdirectories)
+          && other.repositoryName.equals(this.repositoryName);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
index a35c698..90ffcf3 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
@@ -472,7 +472,8 @@
                     + "tools.")
       },
       useEnvironment = true,
-      useAst = true)
+      useAst = true,
+      useContext = true)
   public SkylarkAspectApi aspect(
       BaseFunction implementation,
       SkylarkList<?> attributeAspects,
@@ -484,7 +485,8 @@
       SkylarkList<?> toolchains,
       String doc,
       FuncallExpression ast,
-      Environment funcallEnv)
+      Environment funcallEnv,
+      StarlarkContext context)
       throws EvalException;
 
   @SkylarkCallable(
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
index 9201d4d..f3a6a38 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeSkylarkRuleFunctionsApi.java
@@ -170,10 +170,20 @@
   }
 
   @Override
-  public SkylarkAspectApi aspect(BaseFunction implementation, SkylarkList<?> attributeAspects,
-      Object attrs, SkylarkList<?> requiredAspectProvidersArg, SkylarkList<?> providesArg,
-      SkylarkList<?> fragments, SkylarkList<?> hostFragments, SkylarkList<?> toolchains, String doc,
-      FuncallExpression ast, Environment funcallEnv) throws EvalException {
+  public SkylarkAspectApi aspect(
+      BaseFunction implementation,
+      SkylarkList<?> attributeAspects,
+      Object attrs,
+      SkylarkList<?> requiredAspectProvidersArg,
+      SkylarkList<?> providesArg,
+      SkylarkList<?> fragments,
+      SkylarkList<?> hostFragments,
+      SkylarkList<?> toolchains,
+      String doc,
+      FuncallExpression ast,
+      Environment funcallEnv,
+      StarlarkContext context)
+      throws EvalException {
     return new FakeSkylarkAspect();
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
index bcd395f..a17c61d 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
@@ -84,14 +84,14 @@
   @Test
   public void testRegisterExecutionPlatforms() throws Exception {
     helper.parse("register_execution_platforms('//platform:ep1')");
-    assertThat(helper.getPackage().getRegisteredExecutionPlatforms())
+    assertThat(helper.getPackage().getRegisteredExecutionPlatforms().values())
         .containsExactly("//platform:ep1");
   }
 
   @Test
   public void testRegisterExecutionPlatforms_multipleLabels() throws Exception {
     helper.parse("register_execution_platforms(", "  '//platform:ep1',", "  '//platform:ep2')");
-    assertThat(helper.getPackage().getRegisteredExecutionPlatforms())
+    assertThat(helper.getPackage().getRegisteredExecutionPlatforms().values())
         .containsExactly("//platform:ep1", "//platform:ep2");
   }
 
@@ -101,20 +101,21 @@
         "register_execution_platforms('//platform:ep1')",
         "register_execution_platforms('//platform:ep2')",
         "register_execution_platforms('//platform/...')");
-    assertThat(helper.getPackage().getRegisteredExecutionPlatforms())
+    assertThat(helper.getPackage().getRegisteredExecutionPlatforms().values())
         .containsExactly("//platform:ep1", "//platform:ep2", "//platform/...");
   }
 
   @Test
   public void testRegisterToolchains() throws Exception {
     helper.parse("register_toolchains('//toolchain:tc1')");
-    assertThat(helper.getPackage().getRegisteredToolchains()).containsExactly("//toolchain:tc1");
+    assertThat(helper.getPackage().getRegisteredToolchains().values())
+        .containsExactly("//toolchain:tc1");
   }
 
   @Test
   public void testRegisterToolchains_multipleLabels() throws Exception {
     helper.parse("register_toolchains(", "  '//toolchain:tc1',", "  '//toolchain:tc2')");
-    assertThat(helper.getPackage().getRegisteredToolchains())
+    assertThat(helper.getPackage().getRegisteredToolchains().values())
         .containsExactly("//toolchain:tc1", "//toolchain:tc2");
   }
 
@@ -124,7 +125,7 @@
         "register_toolchains('//toolchain:tc1')",
         "register_toolchains('//toolchain:tc2')",
         "register_toolchains('//toolchain/...')");
-    assertThat(helper.getPackage().getRegisteredToolchains())
+    assertThat(helper.getPackage().getRegisteredToolchains().values())
         .containsExactly("//toolchain:tc1", "//toolchain:tc2", "//toolchain/...");
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/repository/ExternalPackageUtilTest.java b/src/test/java/com/google/devtools/build/lib/repository/ExternalPackageUtilTest.java
index e427037..f18bc53 100644
--- a/src/test/java/com/google/devtools/build/lib/repository/ExternalPackageUtilTest.java
+++ b/src/test/java/com/google/devtools/build/lib/repository/ExternalPackageUtilTest.java
@@ -20,6 +20,7 @@
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.FileStateValue;
 import com.google.devtools.build.lib.actions.FileValue;
@@ -28,6 +29,7 @@
 import com.google.devtools.build.lib.analysis.util.AnalysisMock;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.NullEventHandler;
 import com.google.devtools.build.lib.packages.PackageFactory;
 import com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension;
@@ -72,7 +74,6 @@
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.annotation.Nullable;
@@ -212,7 +213,7 @@
 
     assertThatEvaluationResult(result).hasNoError();
 
-    assertThat(result.get(key).registeredToolchains())
+    assertThat(result.get(key).registeredToolchains().values())
         // There are default toolchains that are always registered, so just check for the ones added
         .containsAtLeast("//toolchain:tc1", "//toolchain:tc2")
         .inOrder();
@@ -234,7 +235,7 @@
 
     assertThatEvaluationResult(result).hasNoError();
 
-    assertThat(result.get(key).registeredExecutionPlatforms())
+    assertThat(result.get(key).registeredExecutionPlatforms().values())
         .containsExactly("//platform:ep1", "//platform:ep2")
         .inOrder();
   }
@@ -296,11 +297,12 @@
 
   @AutoValue
   abstract static class GetRegisteredToolchainsValue implements SkyValue {
-    abstract ImmutableList<String> registeredToolchains();
+    abstract ImmutableListMultimap<RepositoryName, String> registeredToolchains();
 
-    static GetRegisteredToolchainsValue create(Iterable<String> registeredToolchains) {
+    static GetRegisteredToolchainsValue create(
+        ImmutableListMultimap<RepositoryName, String> registeredToolchains) {
       return new AutoValue_ExternalPackageUtilTest_GetRegisteredToolchainsValue(
-          ImmutableList.copyOf(registeredToolchains));
+          registeredToolchains);
     }
   }
 
@@ -310,7 +312,8 @@
     @Override
     public SkyValue compute(SkyKey skyKey, Environment env)
         throws SkyFunctionException, InterruptedException {
-      List<String> registeredToolchains = RegisteredToolchainsFunction.getRegisteredToolchains(env);
+      ImmutableListMultimap<RepositoryName, String> registeredToolchains =
+          RegisteredToolchainsFunction.getWorkspaceToolchains(env);
       if (registeredToolchains == null) {
         return null;
       }
@@ -334,12 +337,12 @@
 
   @AutoValue
   abstract static class GetRegisteredExecutionPlatformsValue implements SkyValue {
-    abstract ImmutableList<String> registeredExecutionPlatforms();
+    abstract ImmutableListMultimap<RepositoryName, String> registeredExecutionPlatforms();
 
     static GetRegisteredExecutionPlatformsValue create(
-        Iterable<String> registeredExecutionPlatforms) {
+        ImmutableListMultimap<RepositoryName, String> registeredExecutionPlatforms) {
       return new AutoValue_ExternalPackageUtilTest_GetRegisteredExecutionPlatformsValue(
-          ImmutableList.copyOf(registeredExecutionPlatforms));
+          registeredExecutionPlatforms);
     }
   }
 
@@ -349,7 +352,7 @@
     @Override
     public SkyValue compute(SkyKey skyKey, Environment env)
         throws SkyFunctionException, InterruptedException {
-      List<String> registeredExecutionPlatforms =
+      ImmutableListMultimap<RepositoryName, String> registeredExecutionPlatforms =
           RegisteredExecutionPlatformsFunction.getWorkspaceExecutionPlatforms(env);
       if (registeredExecutionPlatforms == null) {
         return null;
diff --git a/src/test/shell/bazel/toolchain_test.sh b/src/test/shell/bazel/toolchain_test.sh
index 44c6f24..33b6240 100755
--- a/src/test/shell/bazel/toolchain_test.sh
+++ b/src/test/shell/bazel/toolchain_test.sh
@@ -144,6 +144,86 @@
 EOF
 }
 
+function test_toolchain_with_repository_remapping() {
+  write_test_toolchain
+  write_register_toolchain
+
+  # NOTE: fully qualified label "@main//toolchain:test_toolchain"
+  # is used here, but "//toolchain:test_toolchain" is used in
+  # the toolchain registration in the WORKSPACE file and the
+  # toolchain declaration. Bazel should treat those two labels
+  # as the same
+  rule_name="use_toolchain"
+  toolchain_name="test_toolchain"
+  mkdir -p toolchain
+  cat >> toolchain/rule_${rule_name}.bzl <<EOF
+def _impl(ctx):
+  toolchain = ctx.toolchains['@main//toolchain:${toolchain_name}']
+  message = ctx.attr.message
+  print(
+      'Using toolchain: rule message: "%s", toolchain extra_str: "%s"' %
+         (message, toolchain.extra_str))
+  return []
+
+${rule_name} = rule(
+    implementation = _impl,
+    attrs = {
+        'message': attr.string(),
+    },
+    toolchains = ['@main//toolchain:${toolchain_name}'],
+)
+EOF
+
+  mkdir -p demo
+  cat >> demo/BUILD <<EOF
+load('//toolchain:rule_use_toolchain.bzl', 'use_toolchain')
+use_toolchain(
+    name = 'use',
+    message = 'this is the rule')
+EOF
+
+  bazel build //demo:use --incompatible_remap_main_repo &> $TEST_log \
+      || fail "Build failed"
+  expect_log 'Using toolchain: rule message: "this is the rule", toolchain extra_str: "foo from test_toolchain"'
+}
+
+function test_platform_with_repository_remapping() {
+  cat > WORKSPACE <<EOF
+workspace(name = "main_ws")
+register_execution_platforms("@main_ws//platforms:my_host_platform")
+EOF
+
+  mkdir -p code
+  cat > code/BUILD <<EOF
+sh_library(
+  name = "foo",
+  srcs = ["foo.sh"],
+  exec_compatible_with = ["@main_ws//platforms:large_machine"]
+)
+EOF
+  echo "exit 0" > code/foo.sh
+
+  mkdir -p platforms
+  cat >> platforms/BUILD << EOF
+package(default_visibility = ["//visibility:public"])
+
+constraint_setting(name = "machine_size")
+constraint_value(name = "large_machine", constraint_setting = ":machine_size")
+
+platform(
+    name = "my_host_platform",
+    parents = ["@bazel_tools//platforms:host_platform"],
+    constraint_values = [
+        ":large_machine"
+    ]
+)
+EOF
+
+  # run both with flag and without
+  bazel build //code:foo || fail "Build failed without flag"
+  bazel build //code:foo --experimental_remap_main_repo || "Build failed with flag"
+}
+
 function test_toolchain_provider() {
   write_test_toolchain