Skip to content

Commit 48b975a

Browse files
comiuscopybara-github
authored andcommitted
Fix dict types in initializers
PiperOrigin-RevId: 597874318 Change-Id: I7d7135be863c2123242951635af5c10d370c7ef2
1 parent ad3dd45 commit 48b975a

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

src/main/java/com/google/devtools/build/lib/packages/Type.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,24 @@ public Map<KeyT, ValueT> convert(Object x, Object what, LabelConverter labelConv
606606
@Override
607607
public Object copyAndLiftStarlarkValue(
608608
Object x, Object what, @Nullable LabelConverter labelConverter) throws ConversionException {
609-
return Dict.immutableCopyOf(convert(x, what, labelConverter));
609+
if (!(x instanceof Map)) {
610+
throw new ConversionException(this, x, what);
611+
}
612+
Map<?, ?> o = (Map<?, ?>) x;
613+
// It's possible that #convert() calls transform non-equal keys into equal ones so we can't
614+
// just use ImmutableMap.Builder() here (that throws on collisions).
615+
LinkedHashMap<Object, Object> result = new LinkedHashMap<>();
616+
for (Map.Entry<?, ?> elem : o.entrySet()) {
617+
result.put(
618+
keyType.copyAndLiftStarlarkValue(elem.getKey(), "dict key element", labelConverter),
619+
valueType.copyAndLiftStarlarkValue(
620+
elem.getValue(), "dict value element", labelConverter));
621+
}
622+
return Dict.immutableCopyOf(result);
610623
}
611624

625+
626+
612627
@Override
613628
public Map<KeyT, ValueT> concat(Iterable<Map<KeyT, ValueT>> iterable) {
614629
Dict.Builder<KeyT, ValueT> output = new Dict.Builder<>();

src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import java.io.IOException;
8787
import java.util.Arrays;
8888
import java.util.List;
89+
import java.util.Map;
8990
import java.util.Optional;
9091
import java.util.stream.Stream;
9192
import javax.annotation.Nullable;
@@ -2993,6 +2994,73 @@ public void initializer_basic() throws Exception {
29932994
assertThat((List<String>) info.getValue("deps")).containsExactly("@@//:initial", "@@//:added");
29942995
}
29952996

2997+
@Test
2998+
@SuppressWarnings("unchecked")
2999+
public void initializer_stringListDict() throws Exception {
3000+
scratch.file(
3001+
"initializer_testing/b.bzl",
3002+
"def initializer(**kwargs):",
3003+
" return {}",
3004+
"MyInfo = provider()",
3005+
"def impl(ctx): ",
3006+
" return [MyInfo(dict = ctx.attr.dict)]",
3007+
"my_rule = rule(impl,",
3008+
" initializer = initializer,",
3009+
" attrs = {",
3010+
" 'dict': attr.string_list_dict(),",
3011+
" })");
3012+
scratch.file(
3013+
"initializer_testing/BUILD", //
3014+
"load(':b.bzl','my_rule')",
3015+
"my_rule(name = 'my_target', dict = {'k': ['val']})");
3016+
3017+
ConfiguredTarget myTarget = getConfiguredTarget("//initializer_testing:my_target");
3018+
StructImpl info =
3019+
(StructImpl)
3020+
myTarget.get(
3021+
new StarlarkProvider.Key(
3022+
Label.parseCanonical("//initializer_testing:b.bzl"), "MyInfo"));
3023+
3024+
assertThat(((Map<String, List<String>>) info.getValue("dict")).keySet()).containsExactly("k");
3025+
assertThat(((Map<String, List<String>>) info.getValue("dict")).get("k")).containsExactly("val");
3026+
}
3027+
3028+
@Test
3029+
@SuppressWarnings("unchecked")
3030+
public void initializer_labelKeyedStringDict() throws Exception {
3031+
scratch.file(
3032+
"BUILD", //
3033+
"filegroup(name = 'key')");
3034+
scratch.file(
3035+
"initializer_testing/b.bzl",
3036+
"def initializer(**kwargs):",
3037+
" return {}",
3038+
"MyInfo = provider()",
3039+
"def impl(ctx): ",
3040+
" return [MyInfo(dict = ctx.attr.dict)]",
3041+
"my_rule = rule(impl,",
3042+
" initializer = initializer,",
3043+
" attrs = {",
3044+
" 'dict': attr.label_keyed_string_dict(),",
3045+
" })");
3046+
scratch.file(
3047+
"initializer_testing/BUILD", //
3048+
"load(':b.bzl','my_rule')",
3049+
"my_rule(name = 'my_target', dict = {'//:key': 'val'})");
3050+
3051+
ConfiguredTarget myTarget = getConfiguredTarget("//initializer_testing:my_target");
3052+
ConfiguredTarget key = getConfiguredTarget("//:key");
3053+
StructImpl info =
3054+
(StructImpl)
3055+
myTarget.get(
3056+
new StarlarkProvider.Key(
3057+
Label.parseCanonical("//initializer_testing:b.bzl"), "MyInfo"));
3058+
3059+
assertThat(((Map<ConfiguredTarget, String>) info.getValue("dict")).keySet())
3060+
.containsExactly(key);
3061+
assertThat(((Map<ConfiguredTarget, String>) info.getValue("dict")).get(key)).isEqualTo("val");
3062+
}
3063+
29963064
@Test
29973065
public void initializer_legacyAnyType() throws Exception {
29983066
scratch.file(

0 commit comments

Comments
 (0)