diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Depset.java b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Depset.java index b013822bdf49e6..332092a04e0b39 100644 --- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Depset.java +++ b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Depset.java @@ -95,7 +95,7 @@ public final class Depset implements StarlarkValue, Debug.ValueWithDebugAttribut private final ElementType elemType; private final NestedSet set; - private Depset(ElementType elemType, NestedSet set) { + Depset(ElementType elemType, NestedSet set) { this.elemType = Preconditions.checkNotNull(elemType, "element type cannot be null"); this.set = set; } @@ -189,6 +189,9 @@ private static void checkElement(Object x, boolean strict) throws EvalException // two arguments: of(Class elemType, NestedSet set). We could also avoid the allocations // done by ElementType.of(). public static Depset of(ElementType elemType, NestedSet set) { + if (set.isEmpty()) { + return set.getOrder().emptyDepset(); + } return new Depset(elemType, set); } @@ -280,15 +283,11 @@ public static NestedSet cast(Object x, Class type, String what) throws public static NestedSet noneableCast(Object x, Class type, String what) throws EvalException { if (x == Starlark.NONE) { - @SuppressWarnings("unchecked") - NestedSet empty = (NestedSet) EMPTY; - return empty; + return NestedSetBuilder.emptySet(Order.STABLE_ORDER); } return cast(x, type, what); } - private static final NestedSet EMPTY = NestedSetBuilder.emptySet(Order.STABLE_ORDER); - public boolean isEmpty() { return set.isEmpty(); } @@ -390,6 +389,9 @@ static Depset fromDirectAndTransitive( } } + if (builder.isEmpty()) { + return builder.getOrder().emptyDepset(); + } return new Depset(type, builder.build()); } diff --git a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java index 1a62d054fba06c..3f0ea09422ad4c 100644 --- a/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java +++ b/src/main/java/com/google/devtools/build/lib/collect/nestedset/Order.java @@ -112,10 +112,12 @@ public enum Order { private final String starlarkName; private final NestedSet emptySet; + private final Depset emptyDepset; - private Order(String starlarkName) { + Order(String starlarkName) { this.starlarkName = starlarkName; this.emptySet = new NestedSet<>(this); + this.emptyDepset = new Depset(Depset.ElementType.EMPTY, this.emptySet); } @SerializationConstant @AutoCodec.VisibleForSerialization @@ -150,6 +152,11 @@ NestedSet emptySet() { return (NestedSet) emptySet; } + /** Returns an empty depset of the given ordering. */ + Depset emptyDepset() { + return emptyDepset; + } + public String getStarlarkName() { return starlarkName; } diff --git a/src/test/java/com/google/devtools/build/lib/collect/nestedset/DepsetTest.java b/src/test/java/com/google/devtools/build/lib/collect/nestedset/DepsetTest.java index cc6d597833fdd0..a2139858beb8f6 100644 --- a/src/test/java/com/google/devtools/build/lib/collect/nestedset/DepsetTest.java +++ b/src/test/java/com/google/devtools/build/lib/collect/nestedset/DepsetTest.java @@ -404,4 +404,17 @@ ev.new Scenario() + " NoneType'", "depset(direct='hello')"); } + + @Test + public void testEmptyDepsetInternedPerOrder() throws Exception { + ev.exec( + "stable1 = depset()", + "stable2 = depset()", + "preorder1 = depset(order = 'preorder')", + "preorder2 = depset(order = 'preorder')"); + assertThat(ev.lookup("stable1")).isSameInstanceAs(ev.lookup("stable2")); + assertThat(ev.lookup("preorder1")).isSameInstanceAs(ev.lookup("preorder2")); + assertThat(ev.lookup("stable1")).isNotSameInstanceAs(ev.lookup("preorder1")); + assertThat(ev.lookup("stable2")).isNotSameInstanceAs(ev.lookup("preorder2")); + } }