Dedupes aspects in BuildView

This change ensures that there is no duplicate aspect in AnalysisResult.

RELNOTES: None
PiperOrigin-RevId: 189086095
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 8c4c28d..e9657f8 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
@@ -320,14 +320,14 @@
     private final ImmutableSet<ConfiguredTarget> parallelTests;
     private final ImmutableSet<ConfiguredTarget> exclusiveTests;
     @Nullable private final TopLevelArtifactContext topLevelContext;
-    private final ImmutableList<AspectValue> aspects;
+    private final ImmutableSet<AspectValue> aspects;
     private final PackageRoots packageRoots;
     private final String workspaceName;
     List<TargetAndConfiguration> topLevelTargetsWithConfigs;
 
     private AnalysisResult(
         Collection<ConfiguredTarget> targetsToBuild,
-        Collection<AspectValue> aspects,
+        ImmutableSet<AspectValue> aspects,
         Collection<ConfiguredTarget> targetsToTest,
         Collection<ConfiguredTarget> targetsToSkip,
         @Nullable String error,
@@ -340,7 +340,7 @@
         String workspaceName,
         List<TargetAndConfiguration> topLevelTargetsWithConfigs) {
       this.targetsToBuild = ImmutableSet.copyOf(targetsToBuild);
-      this.aspects = ImmutableList.copyOf(aspects);
+      this.aspects = aspects;
       this.targetsToTest = targetsToTest == null ? null : ImmutableList.copyOf(targetsToTest);
       this.targetsToSkip = ImmutableSet.copyOf(targetsToSkip);
       this.error = error;
@@ -372,7 +372,7 @@
      * <p>If this list is empty, build the targets returned by {@code getTargetsToBuild()}.
      * Otherwise, only build these aspects of the targets returned by {@code getTargetsToBuild()}.
      */
-    public Collection<AspectValue> getAspects() {
+    public ImmutableSet<AspectValue> getAspects() {
       return aspects;
     }
 
@@ -641,7 +641,7 @@
     Collection<Target> testsToRun = loadingResult.getTestsToRun();
     Set<ConfiguredTarget> configuredTargets =
         Sets.newLinkedHashSet(skyframeAnalysisResult.getConfiguredTargets());
-    Collection<AspectValue> aspects = skyframeAnalysisResult.getAspects();
+    ImmutableSet<AspectValue> aspects = ImmutableSet.copyOf(skyframeAnalysisResult.getAspects());
 
     Set<ConfiguredTarget> allTargetsToTest = null;
     if (testsToRun != null) {
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index 9ec6185..2294258 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -837,4 +837,22 @@
         .isNull();
   }
 
+  @Test
+  public void duplicateAspectsDeduped() throws Exception {
+    AspectApplyingToFiles aspectApplyingToFiles = new AspectApplyingToFiles();
+    setRulesAndAspectsAvailableInTests(
+        ImmutableList.<NativeAspectClass>of(aspectApplyingToFiles),
+        ImmutableList.<RuleDefinition>of());
+    pkg("a", "java_binary(name = 'x', main_class = 'x.FooBar', srcs = ['x.java'])");
+    AnalysisResult analysisResult =
+        update(
+            new EventBus(),
+            defaultFlags(),
+            ImmutableList.of(aspectApplyingToFiles.getName(), aspectApplyingToFiles.getName()),
+            "//a:x_deploy.jar");
+    AspectValue aspect = Iterables.getOnlyElement(analysisResult.getAspects());
+    AspectApplyingToFiles.Provider provider =
+        aspect.getConfiguredAspect().getProvider(AspectApplyingToFiles.Provider.class);
+    assertThat(provider.getLabel()).isEqualTo(Label.parseAbsoluteUnchecked("//a:x_deploy.jar"));
+  }
 }