bazel syntax: rationalize the type check operators
This change introduces {Dict,Sequence}.{,noneable}Cast.
These four conversion operators cast an arbitrary value
to a Sequence<T> or Dict<K,V>, replacing these 9 previous functions:
- Dict.{castSkylarkDictOrNoneToDict,getContents}
- Sequence.{castList,castSkylarkListOrNoneToList,getContents}
- SkylarkType.{cast,cast',checkType,castMap}
The functions don't allocate an unmodifiable wrapper,
as Dict and List are already unmodifiable through the java.util
interfaces, so this is just wasteful allocation and indirection.
Also, there is no a priori allocation of Formattable error messages.
A number of messes (e.g. unsound casts) were cleaned up throughout.
The new operators do not accept a Location, and report error
using Starlark.errorf. (This whole CL started as a subtask of a
subtask to eliminate the Location parameter of EvalException,
and this sub-sub-task is an experiment to see whether removing
Location parameters that don't correspond to program counter
locations is a UI regression. SRCTU.createTarget is the only
place where this appears to be a problem. For now I've added a
small kludge, but in a follow-up I will change it to report
events, not throw exceptions, so that it can report multiple
errors at arbitrary locations.
Depset might benefit from a similar {noneable,}Cast treatment,
but this too is left for a follow-up.
This is a breaking API change for copybara.
RELNOTES: N/A
PiperOrigin-RevId: 306925434
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
index 3b6c73b..d61e56f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
@@ -283,10 +283,9 @@
@Override
public OutputGroupInfoApi constructor(Dict<?, ?> kwargs) throws EvalException {
- Map<String, Object> kwargsMap = kwargs.getContents(String.class, Object.class, "kwargs");
-
ImmutableMap.Builder<String, NestedSet<Artifact>> builder = ImmutableMap.builder();
- for (Map.Entry<String, Object> entry : kwargsMap.entrySet()) {
+ for (Map.Entry<String, Object> entry :
+ Dict.cast(kwargs, String.class, Object.class, "kwargs").entrySet()) {
builder.put(
entry.getKey(),
SkylarkRuleConfiguredTargetUtil.convertToOutputGroupValue(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
index 647d910..f93c1ab 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TemplateVariableInfo.java
@@ -43,8 +43,7 @@
@Override
public TemplateVariableInfo templateVariableInfo(Dict<?, ?> vars, StarlarkThread thread)
throws EvalException {
- Map<String, String> varsMap =
- Dict.castSkylarkDictOrNoneToDict(vars, String.class, String.class, "vars");
+ Map<String, String> varsMap = Dict.noneableCast(vars, String.class, String.class, "vars");
return new TemplateVariableInfo(ImmutableMap.copyOf(varsMap), thread.getCallerLocation());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
index c7e0fec..478520e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
@@ -204,7 +204,6 @@
*/
// TODO(bazel-team): integrate dict-of-dicts return type with ctx.split_attr
@Override
- @SuppressWarnings("rawtypes")
public ImmutableMap<String, Map<String, Object>> evaluate(
Map<String, Object> previousSettings, StructImpl attributeMapper, EventHandler eventHandler)
throws EvalException, InterruptedException {
@@ -227,16 +226,13 @@
// TODO(bazel-team): integrate keys with ctx.split_attr. Currently ctx.split_attr always
// keys on cpu value - we should be able to key on the keys returned here.
try {
- @SuppressWarnings("rawtypes")
- Map<String, Dict> dictOfDict =
- ((Dict<?, ?>) result)
- .getContents(String.class, Dict.class, "dictionary of options dictionaries");
+ Map<String, ?> dictOfDict =
+ Dict.cast(result, String.class, Dict.class, "dictionary of options dictionaries");
ImmutableMap.Builder<String, Map<String, Object>> builder = ImmutableMap.builder();
- for (Map.Entry<String, Dict> entry : dictOfDict.entrySet()) { // rawtypes error
- Map<String, Object> dict =
- ((Dict<?, ?>) entry.getValue())
- .getContents(String.class, Object.class, "an option dictionary");
- builder.put(entry.getKey(), dict);
+ for (Map.Entry<String, ?> entry : dictOfDict.entrySet()) {
+ builder.put(
+ entry.getKey(),
+ Dict.cast(entry.getValue(), String.class, Object.class, "an option dictionary"));
}
return builder.build();
} catch (EvalException e) {
@@ -246,8 +242,7 @@
// Try if this is a patch transition.
return ImmutableMap.of(
PATCH_TRANSITION_KEY,
- ((Dict<?, ?>) result)
- .getContents(String.class, Object.class, "dictionary of options"));
+ Dict.cast(result, String.class, Object.class, "dictionary of options"));
} catch (EvalException e) {
throw new EvalException(impl.getLocation(), e.getMessage());
}
@@ -256,12 +251,11 @@
try {
int i = 0;
for (Dict<?, ?> toOptions :
- ((Sequence<?>) result)
- .getContents(Dict.class, "dictionary of options dictionaries")) {
+ Sequence.cast(result, Dict.class, "dictionary of options dictionaries")) {
// TODO(b/146347033): Document this behavior.
builder.put(
Integer.toString(i++),
- toOptions.getContents(String.class, Object.class, "dictionary of options"));
+ Dict.cast(toOptions, String.class, Object.class, "dictionary of options"));
}
} catch (EvalException e) {
throw new EvalException(impl.getLocation(), e.getMessage());
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformInfo.java
index 034d41b..c084542 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformInfo.java
@@ -80,11 +80,12 @@
}
if (!constraintValuesUnchecked.isEmpty()) {
builder.addConstraints(
- constraintValuesUnchecked.getContents(ConstraintValueInfo.class, "constraint_values"));
+ Sequence.cast(
+ constraintValuesUnchecked, ConstraintValueInfo.class, "constraint_values"));
}
if (execPropertiesUnchecked != null) {
- Map<String, String> execProperties =
- Dict.castSkylarkDictOrNoneToDict(
+ Dict<String, String> execProperties =
+ Dict.noneableCast(
execPropertiesUnchecked, String.class, String.class, "exec_properties");
builder.setExecProperties(ImmutableMap.copyOf(execProperties));
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
index 3b1d5db..cd1d711 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
@@ -200,7 +200,7 @@
inputs instanceof Depset
? ((Depset) inputs).getSetFromParam(Artifact.class, "inputs")
: NestedSetBuilder.<Artifact>compileOrder()
- .addAll(((Sequence<?>) inputs).getContents(Artifact.class, "inputs"))
+ .addAll(Sequence.cast(inputs, Artifact.class, "inputs"))
.build();
Action action =
new PseudoAction<>(
@@ -404,7 +404,7 @@
if (argumentList.size() > 0) {
throw Starlark.errorf("'arguments' must be empty if 'command' is a sequence of strings");
}
- List<String> command = commandList.getContents(String.class, "command");
+ List<String> command = Sequence.cast(commandList, String.class, "command");
builder.setShellCommand(command);
} else {
throw new EvalException(
@@ -479,7 +479,7 @@
throws EvalException {
Iterable<Artifact> inputArtifacts;
if (inputs instanceof Sequence) {
- inputArtifacts = ((Sequence<?>) inputs).getContents(Artifact.class, "inputs");
+ inputArtifacts = Sequence.cast(inputs, Artifact.class, "inputs");
builder.addInputs(inputArtifacts);
} else {
NestedSet<Artifact> inputSet = ((Depset) inputs).getSetFromParam(Artifact.class, "inputs");
@@ -487,7 +487,7 @@
inputArtifacts = inputSet.toList();
}
- List<Artifact> outputArtifacts = outputs.getContents(Artifact.class, "outputs");
+ List<Artifact> outputArtifacts = Sequence.cast(outputs, Artifact.class, "outputs");
if (outputArtifacts.isEmpty()) {
throw Starlark.errorf("param 'outputs' may not be empty");
}
@@ -513,7 +513,7 @@
if (toolsUnchecked != Starlark.UNBOUND) {
Iterable<?> toolsIterable;
if (toolsUnchecked instanceof Sequence) {
- toolsIterable = ((Sequence<?>) toolsUnchecked).getContents(Object.class, "tools");
+ toolsIterable = Sequence.cast(toolsUnchecked, Object.class, "tools");
} else {
toolsIterable = ((Depset) toolsUnchecked).getSet().toList();
}
@@ -583,8 +583,7 @@
builder.setMnemonic(mnemonic);
if (envUnchecked != Starlark.NONE) {
builder.setEnvironment(
- ImmutableMap.copyOf(
- Dict.castSkylarkDictOrNoneToDict(envUnchecked, String.class, String.class, "env")));
+ ImmutableMap.copyOf(Dict.cast(envUnchecked, String.class, String.class, "env")));
}
if (progressMessage != Starlark.NONE) {
builder.setProgressMessageNonLazy((String) progressMessage);
@@ -602,8 +601,7 @@
if (inputManifestsUnchecked != Starlark.NONE) {
for (RunfilesSupplier supplier :
- Sequence.castSkylarkListOrNoneToList(
- inputManifestsUnchecked, RunfilesSupplier.class, "runfiles suppliers")) {
+ Sequence.cast(inputManifestsUnchecked, RunfilesSupplier.class, "runfiles suppliers")) {
builder.addRunfilesSupplier(supplier);
}
}
@@ -630,9 +628,7 @@
context.checkMutable("actions.expand_template");
ImmutableList.Builder<Substitution> substitutionsBuilder = ImmutableList.builder();
for (Map.Entry<String, String> substitution :
- substitutionsUnchecked
- .getContents(String.class, String.class, "substitutions")
- .entrySet()) {
+ Dict.cast(substitutionsUnchecked, String.class, String.class, "substitutions").entrySet()) {
// ParserInput.create(Path) uses Latin1 when reading BUILD files, which might
// contain UTF-8 encoded symbols as part of template substitution.
// As a quick fix, the substitution values are corrected before being passed on.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
index 38609a3..bae0993 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
@@ -18,7 +18,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
@@ -49,7 +48,6 @@
import com.google.devtools.build.lib.syntax.Module;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkThread;
@@ -70,6 +68,8 @@
// Arguments
+ // TODO(adonovan): opt: this class does a lot of redundant hashtable lookups.
+
private static boolean containsNonNoneKey(Map<String, Object> arguments, String key) {
return arguments.containsKey(key) && arguments.get(key) != Starlark.NONE;
}
@@ -82,9 +82,7 @@
builder.allowedFileTypes(FileTypeSet.NO_FILE);
} else if (fileTypesObj instanceof Sequence) {
ImmutableList<String> arg =
- ImmutableList.copyOf(
- Sequence.castSkylarkListOrNoneToList(
- fileTypesObj, String.class, "allow_files argument"));
+ ImmutableList.copyOf(Sequence.cast(fileTypesObj, String.class, "allow_files argument"));
builder.allowedFileTypes(FileType.of(arg));
} else {
throw new EvalException(null, attr + " should be a boolean or a string list");
@@ -146,9 +144,11 @@
}
}
- for (String flag :
- Sequence.castSkylarkListOrNoneToList(arguments.get(FLAGS_ARG), String.class, FLAGS_ARG)) {
- builder.setPropertyFlag(flag);
+ Object flagsArg = arguments.get(FLAGS_ARG);
+ if (flagsArg != null) {
+ for (String flag : Sequence.noneableCast(flagsArg, String.class, FLAGS_ARG)) {
+ builder.setPropertyFlag(flag);
+ }
}
if (containsNonNoneKey(arguments, MANDATORY_ARG) && (Boolean) arguments.get(MANDATORY_ARG)) {
@@ -220,21 +220,22 @@
Object ruleClassesObj = arguments.get(ALLOW_RULES_ARG);
if (ruleClassesObj != null && ruleClassesObj != Starlark.NONE) {
builder.allowedRuleClasses(
- Sequence.castSkylarkListOrNoneToList(
+ Sequence.cast(
ruleClassesObj, String.class, "allowed rule classes for attribute definition"));
}
- List<Object> values =
- Sequence.castSkylarkListOrNoneToList(arguments.get(VALUES_ARG), Object.class, VALUES_ARG);
- if (!Iterables.isEmpty(values)) {
- builder.allowedValues(new AllowedValueSet(values));
+ Object valuesArg = arguments.get(VALUES_ARG);
+ if (valuesArg != null) {
+ List<Object> values = Sequence.noneableCast(valuesArg, Object.class, VALUES_ARG);
+ if (!values.isEmpty()) {
+ builder.allowedValues(new AllowedValueSet(values));
+ }
}
if (containsNonNoneKey(arguments, PROVIDERS_ARG)) {
Object obj = arguments.get(PROVIDERS_ARG);
- SkylarkType.checkType(obj, Sequence.class, PROVIDERS_ARG);
ImmutableList<ImmutableSet<SkylarkProviderIdentifier>> providersList =
- buildProviderPredicate((Sequence<?>) obj, PROVIDERS_ARG);
+ buildProviderPredicate(Sequence.cast(obj, Object.class, PROVIDERS_ARG), PROVIDERS_ARG);
// If there is at least one empty set, there is no restriction.
if (providersList.stream().noneMatch(ImmutableSet::isEmpty)) {
@@ -284,10 +285,7 @@
if (containsNonNoneKey(arguments, ASPECTS_ARG)) {
Object obj = arguments.get(ASPECTS_ARG);
- SkylarkType.checkType(obj, Sequence.class, ASPECTS_ARG);
-
- List<SkylarkAspect> aspects = ((Sequence<?>) obj).getContents(SkylarkAspect.class, "aspects");
- for (SkylarkAspect aspect : aspects) {
+ for (SkylarkAspect aspect : Sequence.cast(obj, SkylarkAspect.class, "aspects")) {
aspect.attachToAttribute(builder);
}
}
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 bde937a..d42fce7 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
@@ -24,7 +24,6 @@
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
-import static com.google.devtools.build.lib.syntax.SkylarkType.castMap;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
@@ -89,7 +88,6 @@
import com.google.devtools.build.lib.syntax.Module;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkCallable;
import com.google.devtools.build.lib.syntax.StarlarkFunction;
@@ -253,27 +251,12 @@
@Override
public Provider provider(String doc, Object fields, StarlarkThread thread) throws EvalException {
- Collection<String> fieldNames = null;
- if (fields instanceof Sequence) {
- @SuppressWarnings("unchecked")
- Sequence<String> list =
- (Sequence<String>)
- SkylarkType.cast(
- fields,
- Sequence.class,
- String.class,
- null,
- "Expected list of strings or dictionary of string -> string for 'fields'");
- fieldNames = list;
- } else if (fields instanceof Dict) {
- Map<String, String> dict =
- SkylarkType.castMap(
- fields,
- String.class,
- String.class,
- "Expected list of strings or dictionary of string -> string for 'fields'");
- fieldNames = dict.keySet();
- }
+ Collection<String> fieldNames =
+ fields instanceof Sequence
+ ? Sequence.cast(fields, String.class, "fields")
+ : fields instanceof Dict
+ ? Dict.cast(fields, String.class, String.class, "fields").keySet()
+ : null;
return SkylarkProvider.createUnexportedSchemaful(fieldNames, thread.getCallerLocation());
}
@@ -345,7 +328,7 @@
builder.setImplicitOutputsFunction(
new SkylarkImplicitOutputsFunctionWithMap(
ImmutableMap.copyOf(
- castMap(
+ Dict.cast(
implicitOutputs,
String.class,
String.class,
@@ -358,10 +341,10 @@
}
builder.requiresConfigurationFragmentsBySkylarkModuleName(
- fragments.getContents(String.class, "fragments"));
+ Sequence.cast(fragments, String.class, "fragments"));
ConfigAwareRuleClassBuilder.of(builder)
.requiresHostConfigurationFragmentsBySkylarkModuleName(
- hostFragments.getContents(String.class, "host_fragments"));
+ Sequence.cast(hostFragments, String.class, "host_fragments"));
builder.setConfiguredTargetFunction(implementation);
builder.setRuleDefinitionEnvironmentLabelAndHashCode(
(Label) Module.ofInnermostEnclosingStarlarkFunction(thread).getLabel(),
@@ -370,7 +353,7 @@
builder.addRequiredToolchains(parseToolchains(toolchains, thread));
if (execGroups != Starlark.NONE) {
- builder.addExecGroups(castMap(execGroups, String.class, ExecGroup.class, "exec_group"));
+ builder.addExecGroups(Dict.cast(execGroups, String.class, ExecGroup.class, "exec_group"));
}
if (!buildSetting.equals(Starlark.NONE) && !cfg.equals(Starlark.NONE)) {
@@ -423,7 +406,7 @@
if (attrs != Starlark.NONE) {
for (Map.Entry<String, Descriptor> attr :
- castMap(attrs, String.class, Descriptor.class, "attrs").entrySet()) {
+ Dict.cast(attrs, String.class, Descriptor.class, "attrs").entrySet()) {
Descriptor attrDescriptor = attr.getValue();
AttributeValueSource source = attrDescriptor.getValueSource();
checkAttributeName(attr.getKey());
@@ -472,7 +455,7 @@
private static ImmutableList<Label> parseToolchains(Sequence<?> inputs, StarlarkThread thread)
throws EvalException {
return parseLabels(
- inputs.getContents(String.class, "toolchains"),
+ Sequence.cast(inputs, String.class, "toolchains"),
BazelStarlarkContext.from(thread).getRepoMapping(),
"toolchain");
}
@@ -480,7 +463,7 @@
private static ImmutableList<Label> parseExecCompatibleWith(
Sequence<?> inputs, StarlarkThread thread) throws EvalException {
return parseLabels(
- inputs.getContents(String.class, "exec_compatible_with"),
+ Sequence.cast(inputs, String.class, "exec_compatible_with"),
BazelStarlarkContext.from(thread).getRepoMapping(),
"constraint");
}
@@ -576,9 +559,9 @@
SkylarkAttr.buildProviderPredicate(requiredAspectProvidersArg, "required_aspect_providers"),
SkylarkAttr.getSkylarkProviderIdentifiers(providesArg),
requiredParams.build(),
- ImmutableSet.copyOf(fragments.getContents(String.class, "fragments")),
+ ImmutableSet.copyOf(Sequence.cast(fragments, String.class, "fragments")),
HostTransition.INSTANCE,
- ImmutableSet.copyOf(hostFragments.getContents(String.class, "host_fragments")),
+ ImmutableSet.copyOf(Sequence.cast(hostFragments, String.class, "host_fragments")),
parseToolchains(toolchains, thread),
applyToGeneratingRules);
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
index eba1161..0462f78 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
@@ -50,15 +50,14 @@
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
-import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.Depset;
+import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalExceptionWithStackTrace;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkCallable;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
@@ -226,7 +225,27 @@
.getRuleClassObject()
.getConfiguredTargetFunction()
.getLocation();
- addProviders(context, builder, target, loc);
+
+ // TODO(adonovan): clean up addProviders' error handling,
+ // reporting provider validity errors through ruleError
+ // where possible. This allows for multiple events, with independent
+ // locations, even for the same root cause.
+ // EvalException is the wrong exception for createTarget to throw
+ // since it is neither called by Starlark nor does it call Starlak.
+ //
+ // In the meantime, ensure that any EvalException has a location.
+ try {
+ addProviders(context, builder, target, loc);
+ } catch (EvalException ex) {
+ if (ex.getLocation() == null) {
+ // Prefer target struct's creation location in error messages.
+ if (target instanceof Info) {
+ loc = ((Info) target).getCreationLoc();
+ }
+ ex = new EvalException(loc, ex.getMessage());
+ }
+ throw ex;
+ }
try {
return builder.build();
@@ -235,36 +254,37 @@
}
}
- private static void addOutputGroups(Object value, RuleConfiguredTargetBuilder builder)
+ private static void addOutputGroups(Object outputGroups, RuleConfiguredTargetBuilder builder)
throws EvalException {
- Map<String, StarlarkValue> outputGroups =
- SkylarkType.castMap(value, String.class, StarlarkValue.class, "output_groups");
-
- for (String outputGroup : outputGroups.keySet()) {
- StarlarkValue objects = outputGroups.get(outputGroup);
- NestedSet<Artifact> artifacts = convertToOutputGroupValue(outputGroup, objects);
+ for (Map.Entry<String, StarlarkValue> entry :
+ Dict.cast(outputGroups, String.class, StarlarkValue.class, "output_groups").entrySet()) {
+ String outputGroup = entry.getKey();
+ NestedSet<Artifact> artifacts = convertToOutputGroupValue(outputGroup, entry.getValue());
builder.addOutputGroup(outputGroup, artifacts);
}
}
- @SuppressWarnings("unchecked") // Casting Sequence to List<String> is checked by cast().
private static void addInstrumentedFiles(
StructImpl insStruct, RuleContext ruleContext, RuleConfiguredTargetBuilder builder)
throws EvalException {
- Location insLoc = insStruct.getCreationLoc();
List<String> extensions = null;
if (insStruct.getFieldNames().contains("extensions")) {
- extensions = cast("extensions", insStruct, Sequence.class, String.class, insLoc);
+ extensions = Sequence.cast(insStruct.getValue("extensions"), String.class, "extensions");
}
+
List<String> dependencyAttributes = Collections.emptyList();
if (insStruct.getFieldNames().contains("dependency_attributes")) {
dependencyAttributes =
- cast("dependency_attributes", insStruct, Sequence.class, String.class, insLoc);
+ Sequence.cast(
+ insStruct.getValue("dependency_attributes"), String.class, "dependency_attributes");
}
+
List<String> sourceAttributes = Collections.emptyList();
if (insStruct.getFieldNames().contains("source_attributes")) {
- sourceAttributes = cast("source_attributes", insStruct, Sequence.class, String.class, insLoc);
+ sourceAttributes =
+ Sequence.cast(insStruct.getValue("source_attributes"), String.class, "source_attributes");
}
+
InstrumentedFilesInfo instrumentedFilesProvider =
CoverageCommon.createInstrumentedFilesInfo(
ruleContext,
@@ -293,28 +313,23 @@
}
}
return nestedSetBuilder.build();
- } else {
- Depset artifactsSet =
- SkylarkType.cast(
- objects,
- Depset.class,
- Artifact.class,
- null,
- typeErrorMessage,
- outputGroup,
- EvalUtils.getDataTypeName(objects, true));
+ }
+
+ if (objects instanceof Depset) {
try {
- return artifactsSet.getSet(Artifact.class);
+ return ((Depset) objects).getSet(Artifact.class);
} catch (Depset.TypeException exception) {
throw new EvalException(
null,
String.format(
typeErrorMessage,
outputGroup,
- "depset of type '" + artifactsSet.getContentType() + "'"),
+ "depset of type '" + ((Depset) objects).getContentType() + "'"),
exception);
}
}
+
+ throw Starlark.errorf(typeErrorMessage, outputGroup, Starlark.type(objects));
}
private static void addProviders(
@@ -333,8 +348,7 @@
if (getProviderKey(loc, info).equals(StructProvider.STRUCT.getKey())) {
if (context.getSkylarkSemantics().incompatibleDisallowStructProviderSyntax()) {
- throw new EvalException(
- loc,
+ throw Starlark.errorf(
"Returning a struct from a rule implementation function is deprecated and will "
+ "be removed soon. It may be temporarily re-enabled by setting "
+ "--incompatible_disallow_struct_provider_syntax=false . See "
@@ -345,17 +359,11 @@
StructImpl struct = (StructImpl) target;
oldStyleProviders = struct;
- if (struct.getValue("providers") != null) {
- Iterable<?> iterable = cast("providers", struct, Iterable.class, loc);
- for (Object o : iterable) {
- Info declaredProvider =
- SkylarkType.cast(
- o,
- Info.class,
- loc,
- "The value of 'providers' should be a sequence of declared providers");
- Provider.Key providerKey = getProviderKey(loc, declaredProvider);
- if (declaredProviders.put(providerKey, declaredProvider) != null) {
+ Object providersField = struct.getValue("providers");
+ if (providersField != null) {
+ for (Info provider : Sequence.cast(providersField, Info.class, "providers")) {
+ Provider.Key providerKey = getProviderKey(loc, provider);
+ if (declaredProviders.put(providerKey, provider) != null) {
context
.getRuleContext()
.ruleError("Multiple conflicting returned providers with key " + providerKey);
@@ -367,18 +375,12 @@
// Single declared provider
declaredProviders.put(providerKey, info);
}
- } else if (target instanceof Iterable) {
+ } else if (target instanceof Sequence) {
// Sequence of declared providers
- for (Object o : (Iterable) target) {
- Info declaredProvider =
- SkylarkType.cast(
- o,
- Info.class,
- loc,
- "A return value of a rule implementation function should be "
- + "a sequence of declared providers");
- Provider.Key providerKey = getProviderKey(loc, declaredProvider);
- if (declaredProviders.put(providerKey, declaredProvider) != null) {
+ for (Info provider :
+ Sequence.cast(target, Info.class, "result of rule implementation function")) {
+ Provider.Key providerKey = getProviderKey(loc, provider);
+ if (declaredProviders.put(providerKey, provider) != null) {
context
.getRuleContext()
.ruleError("Multiple conflicting returned providers with key " + providerKey);
@@ -416,8 +418,10 @@
} else if (field.equals("output_groups")) {
addOutputGroups(oldStyleProviders.getValue(field), builder);
} else if (field.equals("instrumented_files")) {
- StructImpl insStruct = cast("instrumented_files", oldStyleProviders, StructImpl.class, loc);
- addInstrumentedFiles(insStruct, context.getRuleContext(), builder);
+ addInstrumentedFiles(
+ oldStyleProviders.getValue("instrumented_files", StructImpl.class),
+ context.getRuleContext(),
+ builder);
} else if (!field.equals("providers")) { // "providers" already handled above.
addProviderFromLegacySyntax(
builder, oldStyleProviders, field, oldStyleProviders.getValue(field));
@@ -536,15 +540,26 @@
// TODO(cparsons): Look into deprecating this option.
for (String field : provider.getFieldNames()) {
if (field.equals("files")) {
- files = cast("files", provider, Depset.class, Artifact.class, loc);
+ Object x = provider.getValue("files");
+ // TODO(adonovan): factor with Depset.getSetFromParam and simplify.
+ try {
+ files = (Depset) x; // (ClassCastException)
+ files.getSet(Artifact.class); // (TypeException)
+ } catch (@SuppressWarnings("UnusedException")
+ ClassCastException
+ | Depset.TypeException ex) {
+ throw Starlark.errorf(
+ "expected depset of Files for 'files' but got %s instead",
+ EvalUtils.getDataTypeName(x, true));
+ }
} else if (field.equals("runfiles")) {
- statelessRunfiles = cast("runfiles", provider, Runfiles.class, loc);
+ statelessRunfiles = provider.getValue("runfiles", Runfiles.class);
} else if (field.equals("data_runfiles")) {
- dataRunfiles = cast("data_runfiles", provider, Runfiles.class, loc);
+ dataRunfiles = provider.getValue("data_runfiles", Runfiles.class);
} else if (field.equals("default_runfiles")) {
- defaultRunfiles = cast("default_runfiles", provider, Runfiles.class, loc);
+ defaultRunfiles = provider.getValue("default_runfiles", Runfiles.class);
} else if (field.equals("executable") && provider.getValue("executable") != null) {
- executable = cast("executable", provider, Artifact.class, loc);
+ executable = provider.getValue("executable", Artifact.class);
}
}
@@ -701,24 +716,6 @@
}
}
- private static <T> T cast(String paramName, ClassObject struct, Class<T> expectedGenericType,
- Class<?> expectedArgumentType, Location loc) throws EvalException {
- Object value = struct.getValue(paramName);
- return SkylarkType.cast(value, expectedGenericType, expectedArgumentType, loc,
- "expected %s for '%s' but got %s instead: %s",
- SkylarkType.of(expectedGenericType, expectedArgumentType),
- paramName, EvalUtils.getDataTypeName(value, true), value);
- }
-
- private static <T> T cast(String paramName, ClassObject struct, Class<T> expectedType,
- Location loc) throws EvalException {
- Object value = struct.getValue(paramName);
- return SkylarkType.cast(value, expectedType, loc,
- "expected %s for '%s' but got %s instead: %s",
- SkylarkType.of(expectedType),
- paramName, EvalUtils.getDataTypeName(value, false), value);
- }
-
private static Runfiles mergeFiles(
Runfiles runfiles, Artifact executable, RuleContext ruleContext) {
if (executable == null) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 0d05107..33e45fc 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -723,7 +723,7 @@
checkMutable("expand");
try {
Map<Label, Iterable<Artifact>> labelMap = new HashMap<>();
- for (Artifact artifact : artifacts.getContents(Artifact.class, "artifacts")) {
+ for (Artifact artifact : Sequence.cast(artifacts, Artifact.class, "artifacts")) {
labelMap.put(artifactsLabelMap.get(artifact), ImmutableList.of(artifact));
}
return LabelExpander.expand(expression, labelMap, labelResolver);
@@ -802,7 +802,8 @@
checkMutable("check_placeholders");
List<String> actualPlaceHolders = new LinkedList<>();
Set<String> allowedPlaceholderSet =
- ImmutableSet.copyOf(allowedPlaceholders.getContents(String.class, "allowed_placeholders"));
+ ImmutableSet.copyOf(
+ Sequence.cast(allowedPlaceholders, String.class, "allowed_placeholders"));
ImplicitOutputsFunction.createPlaceholderSubstitutionFormatString(template, actualPlaceHolders);
for (String placeholder : actualPlaceHolders) {
if (!allowedPlaceholderSet.contains(placeholder)) {
@@ -818,7 +819,7 @@
throws EvalException {
checkMutable("expand_make_variables");
final Map<String, String> additionalSubstitutionsMap =
- additionalSubstitutions.getContents(String.class, String.class, "additional_substitutions");
+ Dict.cast(additionalSubstitutions, String.class, String.class, "additional_substitutions");
return expandMakeVariables(attributeName, command, additionalSubstitutionsMap);
}
@@ -936,7 +937,7 @@
try {
return LocationExpander.withExecPaths(
getRuleContext(),
- makeLabelMap(targets.getContents(TransitiveInfoCollection.class, "targets")))
+ makeLabelMap(Sequence.cast(targets, TransitiveInfoCollection.class, "targets")))
.expand(input);
} catch (IllegalStateException ise) {
throw new EvalException(null, ise);
@@ -997,7 +998,7 @@
builder.addRunfiles(getRuleContext(), RunfilesProvider.DEFAULT_RUNFILES);
}
if (!files.isEmpty()) {
- builder.addArtifacts(files.getContents(Artifact.class, "files"));
+ builder.addArtifacts(Sequence.cast(files, Artifact.class, "files"));
}
if (transitiveFiles != Starlark.NONE) {
builder.addTransitiveArtifacts(
@@ -1007,14 +1008,14 @@
// If Starlark code directly manipulates symlinks, activate more stringent validity checking.
checkConflicts = true;
for (Map.Entry<String, Artifact> entry :
- symlinks.getContents(String.class, Artifact.class, "symlinks").entrySet()) {
+ Dict.cast(symlinks, String.class, Artifact.class, "symlinks").entrySet()) {
builder.addSymlink(PathFragment.create(entry.getKey()), entry.getValue());
}
}
if (!rootSymlinks.isEmpty()) {
checkConflicts = true;
for (Map.Entry<String, Artifact> entry :
- rootSymlinks.getContents(String.class, Artifact.class, "root_symlinks").entrySet()) {
+ Dict.cast(rootSymlinks, String.class, Artifact.class, "root_symlinks").entrySet()) {
builder.addRootSymlink(PathFragment.create(entry.getKey()), entry.getValue());
}
}
@@ -1042,7 +1043,7 @@
// The best way to fix this probably is to convert CommandHelper to Starlark.
CommandHelper helper =
CommandHelper.builder(getRuleContext())
- .addToolDependencies(tools.getContents(TransitiveInfoCollection.class, "tools"))
+ .addToolDependencies(Sequence.cast(tools, TransitiveInfoCollection.class, "tools"))
.addLabelMap(labelDict)
.build();
String attribute = Type.STRING.convertOptional(attributeUnchecked, "attribute", ruleLabel);
@@ -1063,7 +1064,7 @@
ImmutableMap<String, String> executionRequirements =
ImmutableMap.copyOf(
- Dict.castSkylarkDictOrNoneToDict(
+ Dict.noneableCast(
executionRequirementsUnchecked,
String.class,
String.class,
@@ -1089,7 +1090,7 @@
checkMutable("resolve_tools");
CommandHelper helper =
CommandHelper.builder(getRuleContext())
- .addToolDependencies(tools.getContents(TransitiveInfoCollection.class, "tools"))
+ .addToolDependencies(Sequence.cast(tools, TransitiveInfoCollection.class, "tools"))
.build();
return Tuple.<Object>of(
Depset.of(Artifact.TYPE, helper.getResolvedTools()), helper.getToolsRunfilesSuppliers());
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/CoverageCommon.java b/src/main/java/com/google/devtools/build/lib/analysis/test/CoverageCommon.java
index ecd1252..d42cfab 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/test/CoverageCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/test/CoverageCommon.java
@@ -36,7 +36,6 @@
public class CoverageCommon implements CoverageCommonApi<ConstraintValueInfo, SkylarkRuleContext> {
@Override
- @SuppressWarnings("unchecked") // Casting extensions param is verified by Starlark interpreter.
public InstrumentedFilesInfoApi instrumentedFilesInfo(
SkylarkRuleContext skylarkRuleContext,
Sequence<?> sourceAttributes, // <String>
@@ -44,14 +43,12 @@
Object extensions)
throws EvalException {
List<String> extensionsList =
- extensions == Starlark.NONE
- ? null
- : Sequence.castList((List<?>) extensions, String.class, "extensions");
+ extensions == Starlark.NONE ? null : Sequence.cast(extensions, String.class, "extensions");
return createInstrumentedFilesInfo(
skylarkRuleContext.getRuleContext(),
- sourceAttributes.getContents(String.class, "source_attributes"),
- dependencyAttributes.getContents(String.class, "dependency_attributes"),
+ Sequence.cast(sourceAttributes, String.class, "source_attributes"),
+ Sequence.cast(dependencyAttributes, String.class, "dependency_attributes"),
extensionsList);
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index 0762485..705e09e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -315,7 +315,7 @@
SkylarkPath p = getPath("template()", path);
SkylarkPath t = getPath("template()", template);
Map<String, String> substitutionMap =
- substitutions.getContents(String.class, String.class, "substitutions");
+ Dict.cast(substitutions, String.class, String.class, "substitutions");
WorkspaceRuleEvent w =
WorkspaceRuleEvent.newTemplateEvent(
p.toString(),
@@ -407,13 +407,10 @@
return featureEnabled && isRemotable() && remoteExecEnabled;
}
- @SuppressWarnings("unchecked")
private ImmutableMap<String, String> getExecProperties() throws EvalException {
- Dict<String, String> execPropertiesDict =
- (Dict<String, String>) getAttr().getValue("exec_properties", Dict.class);
- Map<String, String> execPropertiesMap =
- execPropertiesDict.getContents(String.class, String.class, "exec_properties");
- return ImmutableMap.copyOf(execPropertiesMap);
+ return ImmutableMap.copyOf(
+ Dict.cast(
+ getAttr().getValue("exec_properties"), String.class, String.class, "exec_properties"));
}
private Map.Entry<PathFragment, Path> getRemotePathFromLabel(Label label)
@@ -502,7 +499,7 @@
validateExecuteArguments(arguments);
Map<String, String> environment =
- uncheckedEnvironment.getContents(String.class, String.class, "environment");
+ Dict.cast(uncheckedEnvironment, String.class, String.class, "environment");
if (canExecuteRemote()) {
try (SilentCloseable c =
@@ -652,17 +649,12 @@
reportProgress("Will fail after download of " + url + ". " + errorMessage);
}
- @SuppressWarnings({"unchecked", "rawtypes"}) // Explained in method comment
- private static Map<String, Dict<?, ?>> getAuthContents(
- Dict<?, ?> authUnchecked, @Nullable String description) throws EvalException {
- // This method would not be worth having (Dict#getContents could be called
- // instead), except that some trickery is required to cast Map<String, Dict> to
- // Map<String, Dict<?, ?>>.
-
- // getContents can only guarantee raw types, so Dict is the raw type here.
- Map<String, Dict> result = authUnchecked.getContents(String.class, Dict.class, description);
-
- return (Map<String, Dict<?, ?>>) (Map<String, ? extends Dict>) result;
+ private static Map<String, Dict<?, ?>> getAuthContents(Dict<?, ?> x, String what)
+ throws EvalException {
+ // Dict.cast returns Dict<String, raw Dict>.
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ Map<String, Dict<?, ?>> res = (Map) Dict.cast(x, String.class, Dict.class, what);
+ return res;
}
@Override
@@ -673,7 +665,7 @@
Boolean executable,
Boolean allowFail,
String canonicalId,
- Dict<?, ?> authUnchecked, // <String, Dict<?, ?>> expected
+ Dict<?, ?> authUnchecked, // <String, Dict> expected
String integrity,
StarlarkThread thread)
throws RepositoryFunctionException, EvalException, InterruptedException {
@@ -789,7 +781,7 @@
String stripPrefix,
Boolean allowFail,
String canonicalId,
- Dict<?, ?> auth, // <String, Dict<?, ?>> expected
+ Dict<?, ?> auth, // <String, Dict> expected
String integrity,
StarlarkThread thread)
throws RepositoryFunctionException, InterruptedException, EvalException {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
index d76ac93..ee33c55 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryModule.java
@@ -18,7 +18,6 @@
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
-import static com.google.devtools.build.lib.syntax.SkylarkType.castMap;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
@@ -88,7 +87,7 @@
builder.add(attr("expect_failure", STRING));
if (attrs != Starlark.NONE) {
for (Map.Entry<String, Descriptor> attr :
- castMap(attrs, String.class, Descriptor.class, "attrs").entrySet()) {
+ Dict.cast(attrs, String.class, Descriptor.class, "attrs").entrySet()) {
Descriptor attrDescriptor = attr.getValue();
AttributeValueSource source = attrDescriptor.getValueSource();
String attrName = source.convertToNativeName(attr.getKey());
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
index ea93db3..94b3962 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/cpp/BazelCcModule.java
@@ -109,7 +109,7 @@
/* grepIncludes= */ null,
/* headersForClifDoNotUseThisParam= */ ImmutableList.of(),
StarlarkList.immutableCopyOf(
- additionalInputs.getContents(Artifact.class, "additional_inputs")),
+ Sequence.cast(additionalInputs, Artifact.class, "additional_inputs")),
thread);
}
@@ -158,7 +158,7 @@
throws EvalException {
CcCompilationOutputs.Builder ccCompilationOutputsBuilder = CcCompilationOutputs.builder();
for (CcCompilationOutputs ccCompilationOutputs :
- compilationOutputs.getContents(CcCompilationOutputs.class, "compilation_outputs")) {
+ Sequence.cast(compilationOutputs, CcCompilationOutputs.class, "compilation_outputs")) {
ccCompilationOutputsBuilder.merge(ccCompilationOutputs);
}
return ccCompilationOutputsBuilder.build();
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
index c8dd28a..a1d6576 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.packages;
-import static com.google.devtools.build.lib.syntax.SkylarkType.castMap;
import static java.util.Collections.singleton;
import static java.util.stream.Collectors.toCollection;
@@ -31,6 +30,7 @@
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.syntax.ClassObject;
+import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.syntax.Starlark;
@@ -112,7 +112,7 @@
try {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (Map.Entry<String, String> entry :
- castMap(
+ Dict.cast(
callback.call(eventHandler, attrs),
String.class,
String.class,
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java b/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
index 762c0ee..26bd781 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StructImpl.java
@@ -24,7 +24,6 @@
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.protobuf.TextFormat;
import java.util.ArrayList;
@@ -83,8 +82,15 @@
if (obj == null) {
return null;
}
- SkylarkType.checkType(obj, type, key);
- return type.cast(obj);
+ try {
+ return type.cast(obj);
+ } catch (
+ @SuppressWarnings("UnusedException")
+ ClassCastException unused) {
+ throw Starlark.errorf(
+ "for %s field, got %s, want %s",
+ key, Starlark.type(obj), EvalUtils.getDataTypeNameFromClass(type));
+ }
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
index 302c856..7bc58b0 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
@@ -275,15 +275,17 @@
* SkylarkSematicOptions#experimentalAllowTagsPropagation}
*/
public static ImmutableMap<String, String> getFilteredExecutionInfo(
- Object executionRequirementsUnchecked, Rule rule, boolean allowTagsPropagation)
+ @Nullable Object executionRequirementsUnchecked, Rule rule, boolean allowTagsPropagation)
throws EvalException {
Map<String, String> checkedExecutionRequirements =
TargetUtils.filter(
- Dict.castSkylarkDictOrNoneToDict(
- executionRequirementsUnchecked,
- String.class,
- String.class,
- "execution_requirements"));
+ executionRequirementsUnchecked == null
+ ? ImmutableMap.of()
+ : Dict.noneableCast(
+ executionRequirementsUnchecked,
+ String.class,
+ String.class,
+ "execution_requirements"));
Map<String, String> executionInfoBuilder = new HashMap<>();
// adding filtered execution requirements to the execution info map
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
index 412ea2d..4c51fb4 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
@@ -25,8 +25,8 @@
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
+import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import java.util.Map;
@@ -121,9 +121,8 @@
throws EvalException, LabelSyntaxException {
Object repoMapping = kwargs.get("repo_mapping");
if (repoMapping != null) {
- Map<String, String> map =
- SkylarkType.castMap(repoMapping, String.class, String.class, "repo_mapping");
- for (Map.Entry<String, String> e : map.entrySet()) {
+ for (Map.Entry<String, String> e :
+ Dict.cast(repoMapping, String.class, String.class, "repo_mapping").entrySet()) {
// Create repository names with validation; may throw LabelSyntaxException.
builder.addRepositoryMappingEntry(
RepositoryName.create("@" + externalRepoName),
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 9a5ae1c..d363b94 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
@@ -106,14 +106,14 @@
builder.addRepositoryMappingEntry(
RepositoryName.MAIN, RepositoryName.createFromValidStrippedName(name), RepositoryName.MAIN);
parseManagedDirectories(
- managedDirectories.getContents(String.class, Object.class, "managed_directories"));
+ Dict.cast(managedDirectories, String.class, Object.class, "managed_directories"));
return NONE;
}
@Override
public NoneType dontSymlinkDirectoriesInExecroot(Sequence<?> paths, StarlarkThread thread)
throws EvalException, InterruptedException {
- List<String> pathsList = paths.getContents(String.class, "paths");
+ List<String> pathsList = Sequence.cast(paths, String.class, "paths");
Set<String> set = Sets.newHashSet();
for (String path : pathsList) {
PathFragment pathFragment = PathFragment.create(path);
@@ -250,7 +250,7 @@
throws EvalException, InterruptedException {
// Add to the package definition for later.
Package.Builder builder = PackageFactory.getContext(thread).pkgBuilder;
- List<String> patterns = platformLabels.getContents(String.class, "platform_labels");
+ List<String> patterns = Sequence.cast(platformLabels, String.class, "platform_labels");
builder.addRegisteredExecutionPlatforms(renamePatterns(patterns, builder, thread));
return NONE;
}
@@ -260,7 +260,7 @@
throws EvalException, InterruptedException {
// Add to the package definition for later.
Package.Builder builder = PackageFactory.getContext(thread).pkgBuilder;
- List<String> patterns = toolchainLabels.getContents(String.class, "toolchain_labels");
+ List<String> patterns = Sequence.cast(toolchainLabels, String.class, "toolchain_labels");
builder.addRegisteredToolchains(renamePatterns(patterns, builder, thread));
return NONE;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
index 937f9b4..69a8f25 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidFeatureFlagSetProvider.java
@@ -160,7 +160,7 @@
public AndroidFeatureFlagSetProvider create(Dict<?, ?> flags) // <Label, String>
throws EvalException {
return new AndroidFeatureFlagSetProvider(
- Optional.of(Dict.castSkylarkDictOrNoneToDict(flags, Label.class, String.class, "flags")));
+ Optional.of(Dict.noneableCast(flags, Label.class, String.class, "flags")));
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
index 343a9fc..d9eeb4e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidIdeInfoProvider.java
@@ -335,7 +335,7 @@
Dict<?, ?> nativeLibs) // <String, Depset>
throws EvalException {
Map<String, Depset> nativeLibsMap =
- nativeLibs.getContents(String.class, Depset.class, "native_libs");
+ Dict.cast(nativeLibs, String.class, Depset.class, "native_libs");
ImmutableMap.Builder<String, NestedSet<Artifact>> builder = ImmutableMap.builder();
for (Map.Entry<String, Depset> entry : nativeLibsMap.entrySet()) {
@@ -353,10 +353,10 @@
fromNoneable(resourceJar, OutputJar.class),
definesAndroidResources,
fromNoneable(aar, Artifact.class),
- ImmutableList.copyOf(idlSrcs.getContents(Artifact.class, "idl_srcs")),
+ ImmutableList.copyOf(Sequence.cast(idlSrcs, Artifact.class, "idl_srcs")),
ImmutableList.copyOf(
- idlGeneratedJavaFiles.getContents(Artifact.class, "idl_generated_java_files")),
- ImmutableList.copyOf(apksUnderTest.getContents(Artifact.class, "apks_under_test")),
+ Sequence.cast(idlGeneratedJavaFiles, Artifact.class, "idl_generated_java_files")),
+ ImmutableList.copyOf(Sequence.cast(apksUnderTest, Artifact.class, "apks_under_test")),
builder.build(),
fromNoneable(resourceApk, Artifact.class));
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidProguardInfo.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidProguardInfo.java
index 355a028..49af24d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidProguardInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidProguardInfo.java
@@ -59,7 +59,7 @@
throws EvalException {
return new AndroidProguardInfo(
ImmutableList.copyOf(
- localProguardSpecs.getContents(Artifact.class, "local_proguard_specs")));
+ Sequence.cast(localProguardSpecs, Artifact.class, "local_proguard_specs")));
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
index f226df1..ef74036 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
@@ -80,7 +80,7 @@
// We assume this is an analysis-phase thread.
Label label = BazelStarlarkContext.from(thread).getAnalysisRuleLabel();
return AssetDependencies.fromProviders(
- deps.getContents(AndroidAssetsInfo.class, "deps"), neverlink)
+ Sequence.cast(deps, AndroidAssetsInfo.class, "deps"), neverlink)
.toInfo(label);
}
@@ -98,10 +98,10 @@
ctx,
DataBinding.getDisabledDataBindingContext(ctx),
ResourceDependencies.fromProviders(
- deps.getContents(AndroidResourcesInfo.class, "deps"),
+ Sequence.cast(deps, AndroidResourcesInfo.class, "deps"),
/* neverlink = */ neverlink),
AssetDependencies.fromProviders(
- assets.getContents(AndroidAssetsInfo.class, "assets"),
+ Sequence.cast(assets, AndroidAssetsInfo.class, "assets"),
/* neverlink = */ neverlink),
StampedAndroidManifest.createEmpty(
ctx.getActionConstructionContext(), customPackage, /* exported = */ false))
@@ -140,12 +140,12 @@
try {
return AndroidAssets.from(
errorReporter,
- listFromNoneable(assets, ConfiguredTarget.class),
- isNone(assetsDir) ? null : PathFragment.create(fromNoneable(assetsDir, String.class)))
+ isNone(assets) ? null : Sequence.cast(assets, ConfiguredTarget.class, "assets"),
+ isNone(assetsDir) ? null : PathFragment.create((String) assetsDir))
.process(
ctx,
AssetDependencies.fromProviders(
- deps.getContents(AndroidAssetsInfo.class, "deps"), neverlink))
+ Sequence.cast(deps, AndroidAssetsInfo.class, "deps"), neverlink))
.toProvider();
} catch (RuleErrorException e) {
throw handleRuleException(errorReporter, e);
@@ -165,13 +165,13 @@
try {
return AndroidResources.from(
errorReporter,
- getFileProviders(resources.getContents(ConfiguredTarget.class, "resources")),
+ getFileProviders(Sequence.cast(resources, ConfiguredTarget.class, "resources")),
"resources")
.process(
ctx,
manifest.asStampedManifest(),
ResourceDependencies.fromProviders(
- deps.getContents(AndroidResourcesInfo.class, "deps"), neverlink),
+ Sequence.cast(deps, AndroidResourcesInfo.class, "deps"), neverlink),
DataBinding.contextFrom(
enableDataBinding, ctx.getActionConstructionContext(), ctx.getAndroidConfig()));
} catch (RuleErrorException e) {
@@ -250,8 +250,9 @@
resourcesInfo.getRTxt(),
libraryClassJar,
ImmutableList.copyOf(
- localProguardSpecs.getContents(Artifact.class, "local_proguard_specs")))
- .toProvider(deps.getContents(AndroidLibraryAarInfo.class, "deps"), definesLocalResources);
+ Sequence.cast(localProguardSpecs, Artifact.class, "local_proguard_specs")))
+ .toProvider(
+ Sequence.cast(deps, AndroidLibraryAarInfo.class, "deps"), definesLocalResources);
}
@Override
@@ -262,7 +263,7 @@
Artifact androidManifestArtifact,
Sequence<?> deps) // <ConfiguredTarget>
throws InterruptedException, EvalException {
- List<ConfiguredTarget> depsTargets = deps.getContents(ConfiguredTarget.class, "deps");
+ List<ConfiguredTarget> depsTargets = Sequence.cast(deps, ConfiguredTarget.class, "deps");
ValidatedAndroidResources validatedResources =
AndroidResources.forAarImport(resources)
@@ -303,7 +304,7 @@
Sequence<?> densities) // <String>)
throws InterruptedException, EvalException {
SkylarkErrorReporter errorReporter = SkylarkErrorReporter.from(ctx.getRuleErrorConsumer());
- List<ConfiguredTarget> depsTargets = deps.getContents(ConfiguredTarget.class, "deps");
+ List<ConfiguredTarget> depsTargets = Sequence.cast(deps, ConfiguredTarget.class, "deps");
try {
AndroidManifest rawManifest =
@@ -323,11 +324,12 @@
rawManifest,
AndroidResources.from(
errorReporter,
- getFileProviders(resources.getContents(ConfiguredTarget.class, "resource_files")),
+ getFileProviders(
+ Sequence.cast(resources, ConfiguredTarget.class, "resource_files")),
"resource_files"),
AndroidAssets.from(
errorReporter,
- listFromNoneable(assets, ConfiguredTarget.class),
+ isNone(assets) ? null : Sequence.cast(assets, ConfiguredTarget.class, "assets"),
isNone(assetsDir)
? null
: PathFragment.create(fromNoneable(assetsDir, String.class))),
@@ -336,12 +338,12 @@
/* neverlink = */ false),
AssetDependencies.fromProviders(
getProviders(depsTargets, AndroidAssetsInfo.PROVIDER), /* neverlink = */ false),
- manifestValues.getContents(String.class, String.class, "manifest_values"),
- noCompressExtensions.getContents(String.class, "nocompress_extensions"),
+ Dict.cast(manifestValues, String.class, String.class, "manifest_values"),
+ Sequence.cast(noCompressExtensions, String.class, "nocompress_extensions"),
ResourceFilterFactory.from(
- resourceConfigurationFilters.getContents(
- String.class, "resource_configuration_filters"),
- densities.getContents(String.class, "densities")));
+ Sequence.cast(
+ resourceConfigurationFilters, String.class, "resource_configuration_filters"),
+ Sequence.cast(densities, String.class, "densities")));
ImmutableMap.Builder<Provider, NativeInfo> builder = ImmutableMap.builder();
builder.putAll(getNativeInfosFrom(resourceApk, ctx.getLabel()));
@@ -380,11 +382,11 @@
fromNoneableOrDefault(
shrinkResources, Boolean.class, ctx.getAndroidConfig().useAndroidResourceShrinking()),
ResourceFilterFactory.from(
- resourceConfigurationFilters.getContents(
- String.class, "resource_configuration_filters"),
- densities.getContents(String.class, "densities")),
+ Sequence.cast(
+ resourceConfigurationFilters, String.class, "resource_configuration_filters"),
+ Sequence.cast(densities, String.class, "densities")),
ImmutableList.copyOf(
- noCompressExtensions.getContents(String.class, "nocompress_extensions")));
+ Sequence.cast(noCompressExtensions, String.class, "nocompress_extensions")));
}
@Override
@@ -433,9 +435,9 @@
boolean dataBindingEnabled)
throws InterruptedException, EvalException {
SkylarkErrorReporter errorReporter = SkylarkErrorReporter.from(ctx.getRuleErrorConsumer());
- List<ConfiguredTarget> depsTargets = deps.getContents(ConfiguredTarget.class, "deps");
+ List<ConfiguredTarget> depsTargets = Sequence.cast(deps, ConfiguredTarget.class, "deps");
Map<String, String> manifestValueMap =
- manifestValues.getContents(String.class, String.class, "manifest_values");
+ Dict.cast(manifestValues, String.class, String.class, "manifest_values");
try {
BinaryDataSettings settings =
@@ -475,14 +477,14 @@
AndroidResources.from(
errorReporter,
getFileProviders(
- resources.getContents(ConfiguredTarget.class, "resource_files")),
+ Sequence.cast(resources, ConfiguredTarget.class, "resource_files")),
"resource_files"),
AndroidAssets.from(
errorReporter,
- listFromNoneable(assets, ConfiguredTarget.class),
- isNone(assetsDir)
+ isNone(assets)
? null
- : PathFragment.create(fromNoneable(assetsDir, String.class))),
+ : Sequence.cast(assets, ConfiguredTarget.class, "assets"),
+ isNone(assetsDir) ? null : PathFragment.create((String) assetsDir)),
resourceDeps,
AssetDependencies.fromProviders(
getProviders(depsTargets, AndroidAssetsInfo.PROVIDER),
@@ -522,7 +524,7 @@
BinaryDataSettings settings =
fromNoneableOrDefault(
maybeSettings, BinaryDataSettings.class, defaultBinaryDataSettings(ctx));
- List<ConfiguredTarget> depsTargets = deps.getContents(ConfiguredTarget.class, "deps");
+ List<ConfiguredTarget> depsTargets = Sequence.cast(deps, ConfiguredTarget.class, "deps");
if (!settings.shrinkResources) {
return binaryDataInfo;
@@ -535,9 +537,9 @@
binaryDataInfo.getResourceProguardConfig(),
binaryDataInfo.getManifestInfo().getManifest(),
filesFromConfiguredTargets(
- localProguardSpecs.getContents(ConfiguredTarget.class, "proguard_specs")),
+ Sequence.cast(localProguardSpecs, ConfiguredTarget.class, "proguard_specs")),
filesFromConfiguredTargets(
- extraProguardSpecs.getContents(ConfiguredTarget.class, "extra_proguard_specs")),
+ Sequence.cast(extraProguardSpecs, ConfiguredTarget.class, "extra_proguard_specs")),
getProviders(depsTargets, ProguardSpecProvider.PROVIDER));
// TODO(asteinb): There should never be more than one direct resource exposed in the provider.
@@ -646,22 +648,6 @@
return value;
}
- /**
- * Converts a "Noneable" Object passed by Starlark to a List of the appropriate type.
- *
- * <p>This first calls {@link #fromNoneable(Object, Class)} to get a Sequence<?>, then safely
- * casts it to a list with the appropriate generic.
- */
- @Nullable
- public static <T> List<T> listFromNoneable(Object object, Class<T> clazz) throws EvalException {
- Sequence<?> asList = fromNoneable(object, Sequence.class);
- if (asList == null) {
- return null;
- }
-
- return Sequence.castList(asList, clazz, null);
- }
-
private static ImmutableList<Artifact> filesFromConfiguredTargets(
List<ConfiguredTarget> targets) {
ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Provider.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Provider.java
index c28bb4c..f5a0ca2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Provider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Provider.java
@@ -193,13 +193,17 @@
databindingV2ProvidersInDeps == null
? null
: ImmutableList.copyOf(
- databindingV2ProvidersInDeps.getContents(
- DataBindingV2Provider.class, "databinding_v2_providers_in_deps")),
+ Sequence.cast(
+ databindingV2ProvidersInDeps,
+ DataBindingV2Provider.class,
+ "databinding_v2_providers_in_deps")),
databindingV2ProvidersInExports == null
? null
: ImmutableList.copyOf(
- databindingV2ProvidersInExports.getContents(
- DataBindingV2Provider.class, "databinding_v2_providers_in_exports")));
+ Sequence.cast(
+ databindingV2ProvidersInExports,
+ DataBindingV2Provider.class,
+ "databinding_v2_providers_in_exports")));
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/UsesDataBindingProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/UsesDataBindingProvider.java
index f90d502..c54c9a3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/UsesDataBindingProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/UsesDataBindingProvider.java
@@ -56,7 +56,7 @@
public UsesDataBindingProvider createInfo(Sequence<?> metadataOutputs) // <Artifact>
throws EvalException {
return new UsesDataBindingProvider(
- metadataOutputs.getContents(Artifact.class, "metadata_outputs"));
+ Sequence.cast(metadataOutputs, Artifact.class, "metadata_outputs"));
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
index 2b0d099..30b9926 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
@@ -48,8 +48,8 @@
StarlarkThread thread)
throws EvalException {
StarlarkSemantics semantics = thread.getSemantics();
- List<String> inputsList = inputs.getContents(String.class, "inputs");
- List<String> outputsList = outputs.getContents(String.class, "outputs");
+ List<String> inputsList = Sequence.cast(inputs, String.class, "inputs");
+ List<String> outputsList = Sequence.cast(outputs, String.class, "outputs");
validateBuildSettingKeys(
inputsList, Settings.INPUTS, semantics.experimentalStarlarkConfigTransitions());
validateBuildSettingKeys(
@@ -64,7 +64,7 @@
StarlarkThread thread)
throws EvalException {
Map<String, Object> changedSettingsMap =
- changedSettings.getContents(String.class, Object.class, "changed_settings dict");
+ Dict.cast(changedSettings, String.class, Object.class, "changed_settings dict");
validateBuildSettingKeys(changedSettingsMap.keySet(), Settings.OUTPUTS, true);
return StarlarkDefinedConfigTransition.newAnalysisTestTransition(
changedSettingsMap, thread.getCallerLocation());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
index 6bf2eed..8681613 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java
@@ -1239,8 +1239,7 @@
return null;
}
ImmutableList<String> exports =
- ImmutableList.copyOf(
- Sequence.castSkylarkListOrNoneToList(exportsField, String.class, "exports"));
+ ImmutableList.copyOf(Sequence.noneableCast(exportsField, String.class, "exports"));
Object linkerInputField = ccSharedLibraryInfo.getValue("linker_input");
if (linkerInputField == null) {
@@ -1262,7 +1261,7 @@
}
ImmutableList<String> linkOnceStaticLibs =
ImmutableList.copyOf(
- Sequence.castSkylarkListOrNoneToList(
+ Sequence.noneableCast(
linkOnceStaticLibsField, String.class, "link_once_static_libs"));
directMergedCcSharedLibraryInfos.add(
@@ -1289,12 +1288,12 @@
for (Tuple<Object> exportsAndLinkerInput : dynamicDeps.toList()) {
List<String> exportsFromDynamicDep =
- Sequence.castSkylarkListOrNoneToList(
+ Sequence.noneableCast(
exportsAndLinkerInput.get(0), String.class, "exports_from_dynamic_dep");
CcLinkingContext.LinkerInput linkerInputFromDynamicDep =
(CcLinkingContext.LinkerInput) exportsAndLinkerInput.get(1);
List<String> linkOnceStaticLibsFromDynamicDep =
- Sequence.castSkylarkListOrNoneToList(
+ Sequence.noneableCast(
exportsAndLinkerInput.get(0),
String.class,
"link_once_static_libs_from_dynamic_dep");
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
index 1fb4ede..e0de3d0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
@@ -135,7 +135,8 @@
throws EvalException {
SkylarkRuleContext ruleContext = nullIfNone(ruleContextOrNone, SkylarkRuleContext.class);
ImmutableSet<String> unsupportedFeaturesSet =
- ImmutableSet.copyOf(unsupportedFeatures.getContents(String.class, "unsupported_features"));
+ ImmutableSet.copyOf(
+ Sequence.cast(unsupportedFeatures, String.class, "unsupported_features"));
final CppConfiguration cppConfiguration;
final BuildOptions buildOptions;
if (ruleContext == null) {
@@ -166,7 +167,8 @@
}
return FeatureConfigurationForStarlark.from(
CcCommon.configureFeaturesOrThrowEvalException(
- ImmutableSet.copyOf(requestedFeatures.getContents(String.class, "requested_features")),
+ ImmutableSet.copyOf(
+ Sequence.cast(requestedFeatures, String.class, "requested_features")),
unsupportedFeaturesSet,
toolchain,
cppConfiguration),
@@ -594,7 +596,7 @@
@Override
public CcInfo mergeCcInfos(Sequence<?> ccInfos) throws EvalException {
- return CcInfo.merge(ccInfos.getContents(CcInfo.class, /* description= */ null));
+ return CcInfo.merge(Sequence.cast(ccInfos, CcInfo.class, "infos"));
}
@Override
@@ -723,7 +725,7 @@
Sequence<String> nonCodeInputs = nullIfNone(nonCodeInputsObject, Sequence.class);
if (nonCodeInputs != null) {
ccLinkingContextBuilder.addNonCodeInputs(
- nonCodeInputs.getContents(Artifact.class, "additional_inputs"));
+ Sequence.cast(nonCodeInputs, Artifact.class, "additional_inputs"));
}
return ccLinkingContextBuilder.build();
}
@@ -792,9 +794,8 @@
throws EvalException {
List<String> cxxBuiltInIncludeDirectories =
- cxxBuiltInIncludeDirectoriesUnchecked.getContents(
- String.class, "cxx_builtin_include_directories");
-
+ Sequence.cast(
+ cxxBuiltInIncludeDirectoriesUnchecked, String.class, "cxx_builtin_include_directories");
ImmutableList.Builder<Feature> featureBuilder = ImmutableList.builder();
for (Object feature : features) {
@@ -1412,25 +1413,28 @@
/** Returns a list of strings from a field of a {@link SkylarkInfo}. */
private static ImmutableList<String> getStringListFromSkylarkProviderField(
SkylarkInfo provider, String fieldName) throws EvalException {
- return ImmutableList.copyOf(
- Sequence.castSkylarkListOrNoneToList(
- getValueOrNull(provider, fieldName), String.class, fieldName));
+ Object v = getValueOrNull(provider, fieldName);
+ return v == null
+ ? ImmutableList.of()
+ : ImmutableList.copyOf(Sequence.noneableCast(v, String.class, fieldName));
}
/** Returns a set of strings from a field of a {@link SkylarkInfo}. */
private static ImmutableSet<String> getStringSetFromSkylarkProviderField(
SkylarkInfo provider, String fieldName) throws EvalException {
- return ImmutableSet.copyOf(
- Sequence.castSkylarkListOrNoneToList(
- getValueOrNull(provider, fieldName), String.class, fieldName));
+ Object v = getValueOrNull(provider, fieldName);
+ return v == null
+ ? ImmutableSet.of()
+ : ImmutableSet.copyOf(Sequence.noneableCast(v, String.class, fieldName));
}
/** Returns a list of SkylarkInfo providers from a field of a {@link SkylarkInfo}. */
private static ImmutableList<SkylarkInfo> getSkylarkProviderListFromSkylarkField(
SkylarkInfo provider, String fieldName) throws EvalException {
- return ImmutableList.copyOf(
- Sequence.castSkylarkListOrNoneToList(
- getValueOrNull(provider, fieldName), SkylarkInfo.class, fieldName));
+ Object v = getValueOrNull(provider, fieldName);
+ return v == null
+ ? ImmutableList.of()
+ : ImmutableList.copyOf(Sequence.noneableCast(v, SkylarkInfo.class, fieldName));
}
private static void getLegacyArtifactNamePatterns(
@@ -1522,7 +1526,7 @@
actions.getRuleContext().isAllowTagsPropagation()))
.setGrepIncludes(convertFromNoneable(grepIncludes, /* defaultValue= */ null))
.addNonCodeLinkerInputs(
- additionalInputs.getContents(Artifact.class, "additional_inputs"))
+ Sequence.cast(additionalInputs, Artifact.class, "additional_inputs"))
.setShouldCreateStaticLibraries(!disallowStaticLibraries)
.setShouldCreateDynamicLibrary(
!disallowDynamicLibraries
@@ -1531,7 +1535,7 @@
.isEnabled(CppRuleClasses.TARGETS_WINDOWS))
.setStaticLinkType(staticLinkTargetType)
.setDynamicLinkType(LinkTargetType.NODEPS_DYNAMIC_LIBRARY)
- .addLinkopts(userLinkFlags.getContents(String.class, "user_link_flags"));
+ .addLinkopts(Sequence.cast(userLinkFlags, String.class, "user_link_flags"));
try {
CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
ImmutableList<LibraryToLink> libraryToLink = ImmutableList.of();
@@ -1552,7 +1556,8 @@
CcLinkingContext.merge(
ImmutableList.<CcLinkingContext>builder()
.add(linkingContext)
- .addAll(linkingContexts.getContents(CcLinkingContext.class, "linking_contexts"))
+ .addAll(
+ Sequence.cast(linkingContexts, CcLinkingContext.class, "linking_contexts"))
.build()),
ccLinkingOutputs);
} catch (RuleErrorException e) {
@@ -1623,9 +1628,9 @@
Sequence<?> additionalInputs,
StarlarkThread thread)
throws EvalException, InterruptedException {
- List<Artifact> sources = sourcesUnchecked.getContents(Artifact.class, "srcs");
- List<Artifact> publicHeaders = publicHeadersUnchecked.getContents(Artifact.class, "srcs");
- List<Artifact> privateHeaders = privateHeadersUnchecked.getContents(Artifact.class, "srcs");
+ List<Artifact> sources = Sequence.cast(sourcesUnchecked, Artifact.class, "srcs");
+ List<Artifact> publicHeaders = Sequence.cast(publicHeadersUnchecked, Artifact.class, "srcs");
+ List<Artifact> privateHeaders = Sequence.cast(privateHeadersUnchecked, Artifact.class, "srcs");
SkylarkActionFactory actions = skylarkActionFactoryApi;
CcToolchainProvider ccToolchainProvider = convertFromNoneable(skylarkCcToolchainProvider, null);
@@ -1671,32 +1676,32 @@
.addPrivateHeaders(privateHeaders)
.addSources(sources)
.addCcCompilationContexts(
- ccCompilationContexts.getContents(
- CcCompilationContext.class, "compilation_contexts"))
+ Sequence.cast(
+ ccCompilationContexts, CcCompilationContext.class, "compilation_contexts"))
.addIncludeDirs(
- includes.getContents(String.class, "includes").stream()
+ Sequence.cast(includes, String.class, "includes").stream()
.map(PathFragment::create)
.collect(ImmutableList.toImmutableList()))
.addQuoteIncludeDirs(
- quoteIncludes.getContents(String.class, "quote_includes").stream()
+ Sequence.cast(quoteIncludes, String.class, "quote_includes").stream()
.map(PathFragment::create)
.collect(ImmutableList.toImmutableList()))
.addSystemIncludeDirs(
- systemIncludes.getContents(String.class, "system_includes").stream()
+ Sequence.cast(systemIncludes, String.class, "system_includes").stream()
.map(PathFragment::create)
.collect(ImmutableList.toImmutableList()))
.addFrameworkIncludeDirs(
- frameworkIncludes.getContents(String.class, "framework_includes").stream()
+ Sequence.cast(frameworkIncludes, String.class, "framework_includes").stream()
.map(PathFragment::create)
.collect(ImmutableList.toImmutableList()))
- .addDefines(defines.getContents(String.class, "defines"))
- .addNonTransitiveDefines(localDefines.getContents(String.class, "local_defines"))
+ .addDefines(Sequence.cast(defines, String.class, "defines"))
+ .addNonTransitiveDefines(Sequence.cast(localDefines, String.class, "local_defines"))
.setCopts(
ImmutableList.copyOf(
- userCompileFlags.getContents(String.class, "user_compile_flags")))
+ Sequence.cast(userCompileFlags, String.class, "user_compile_flags")))
.addAdditionalCompilationInputs(headersForClifDoNotUseThisParam)
.addAdditionalCompilationInputs(
- additionalInputs.getContents(Artifact.class, "additional_inputs"))
+ Sequence.cast(additionalInputs, Artifact.class, "additional_inputs"))
.addAditionalIncludeScanningRoots(headersForClifDoNotUseThisParam)
.setPurpose(common.getPurpose(getSemantics()));
if (disallowNopicOutputs) {
@@ -1783,12 +1788,12 @@
.setLinkingMode(linkDepsStatically ? LinkingMode.STATIC : LinkingMode.DYNAMIC)
.setIsStampingEnabled(isStampingEnabled)
.addNonCodeLinkerInputs(
- additionalInputs.getContents(Artifact.class, "additional_inputs"))
+ Sequence.cast(additionalInputs, Artifact.class, "additional_inputs"))
.setDynamicLinkType(dynamicLinkTargetType)
.addCcLinkingContexts(
- linkingContexts.getContents(CcLinkingContext.class, "linking_contexts"))
+ Sequence.cast(linkingContexts, CcLinkingContext.class, "linking_contexts"))
.setShouldCreateStaticLibraries(false)
- .addLinkopts(userLinkFlags.getContents(String.class, "user_link_flags"))
+ .addLinkopts(Sequence.cast(userLinkFlags, String.class, "user_link_flags"))
.emitInterfaceSharedLibraries(
dynamicLinkTargetType == LinkTargetType.DYNAMIC_LIBRARY
&& actualFeatureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/BootClassPathInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/BootClassPathInfo.java
index 7b78c72..c2e6cf9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/BootClassPathInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/BootClassPathInfo.java
@@ -30,7 +30,6 @@
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.StarlarkValue;
@@ -84,16 +83,17 @@
private static NestedSet<Artifact> getBootClassPath(Sequence<?> bootClassPathList)
throws EvalException {
return NestedSetBuilder.wrap(
- Order.STABLE_ORDER,
- Sequence.castList(bootClassPathList, Artifact.class, "bootclasspath"));
+ Order.STABLE_ORDER, Sequence.cast(bootClassPathList, Artifact.class, "bootclasspath"));
}
private static Artifact getSystem(Object systemOrNone) throws EvalException {
if (systemOrNone == Starlark.NONE) {
return null;
}
- SkylarkType.checkType(systemOrNone, Artifact.class, "system");
- return (Artifact) systemOrNone;
+ if (systemOrNone instanceof Artifact) {
+ return (Artifact) systemOrNone;
+ }
+ throw Starlark.errorf("for system, got %s, want File or None", Starlark.type(systemOrNone));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
index 64bfdd9..e12a4fa 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
@@ -79,26 +79,32 @@
return JavaInfoBuildHelper.getInstance()
.createJavaCompileAction(
skylarkRuleContext,
- sourceJars.getContents(Artifact.class, "source_jars"),
- sourceFiles.getContents(Artifact.class, "source_files"),
+ Sequence.cast(sourceJars, Artifact.class, "source_jars"),
+ Sequence.cast(sourceFiles, Artifact.class, "source_files"),
outputJar,
outputSourceJar == Starlark.NONE ? null : (Artifact) outputSourceJar,
- javacOpts.getContents(String.class, "javac_opts"),
- deps.getContents(JavaInfo.class, "deps"),
- experimentalLocalCompileTimeDeps.getContents(
- JavaInfo.class, "experimental_local_compile_time_deps"),
- exports.getContents(JavaInfo.class, "exports"),
- plugins.getContents(JavaInfo.class, "plugins"),
- exportedPlugins.getContents(JavaInfo.class, "exported_plugins"),
- annotationProcessorAdditionalInputs.getContents(
- Artifact.class, "annotation_processor_additional_inputs"),
- annotationProcessorAdditionalOutputs.getContents(
- Artifact.class, "annotation_processor_additional_outputs"),
+ Sequence.cast(javacOpts, String.class, "javac_opts"),
+ Sequence.cast(deps, JavaInfo.class, "deps"),
+ Sequence.cast(
+ experimentalLocalCompileTimeDeps,
+ JavaInfo.class,
+ "experimental_local_compile_time_deps"),
+ Sequence.cast(exports, JavaInfo.class, "exports"),
+ Sequence.cast(plugins, JavaInfo.class, "plugins"),
+ Sequence.cast(exportedPlugins, JavaInfo.class, "exported_plugins"),
+ Sequence.cast(
+ annotationProcessorAdditionalInputs,
+ Artifact.class,
+ "annotation_processor_additional_inputs"),
+ Sequence.cast(
+ annotationProcessorAdditionalOutputs,
+ Artifact.class,
+ "annotation_processor_additional_outputs"),
strictDepsMode,
javaToolchain,
hostJavabase,
- ImmutableList.copyOf(sourcepathEntries.getContents(Artifact.class, "sourcepath")),
- resources.getContents(Artifact.class, "resources"),
+ ImmutableList.copyOf(Sequence.cast(sourcepathEntries, Artifact.class, "sourcepath")),
+ Sequence.cast(resources, Artifact.class, "resources"),
neverlink,
javaSemantics,
thread);
@@ -140,8 +146,8 @@
actions,
outputJar,
/* outputSourceJar= */ null,
- sourceFiles.getContents(Artifact.class, "sources"),
- sourceJars.getContents(Artifact.class, "source_jars"),
+ Sequence.cast(sourceFiles, Artifact.class, "sources"),
+ Sequence.cast(sourceJars, Artifact.class, "source_jars"),
javaToolchain,
hostJavabase);
}
@@ -158,7 +164,7 @@
@Override
public JavaInfo mergeJavaProviders(Sequence<?> providers /* <JavaInfo> expected. */)
throws EvalException {
- return JavaInfo.merge(providers.getContents(JavaInfo.class, "providers"));
+ return JavaInfo.merge(Sequence.cast(providers, JavaInfo.class, "providers"));
}
// TODO(b/65113771): Remove this method because it's incorrect.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java b/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
index 5b6c461..8bfe28e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/MessageBundleInfo.java
@@ -63,7 +63,7 @@
useStarlarkThread = true)
public MessageBundleInfo messageBundleInfo(Sequence<?> messages, StarlarkThread thread)
throws EvalException {
- List<Artifact> messagesList = Sequence.castList(messages, Artifact.class, "messages");
+ List<Artifact> messagesList = Sequence.cast(messages, Artifact.class, "messages");
return new MessageBundleInfo(ImmutableList.copyOf(messagesList), thread.getCallerLocation());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
index 8f6827c..4c18e8a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/AppleSkylarkCommon.java
@@ -243,8 +243,8 @@
AppleBinaryOutput appleBinaryOutput =
AppleBinary.linkMultiArchBinary(
ruleContext,
- ImmutableList.copyOf(extraLinkopts.getContents(String.class, "extra_linkopts")),
- Sequence.castList(extraLinkInputs, Artifact.class, "extra_link_inputs"));
+ ImmutableList.copyOf(Sequence.cast(extraLinkopts, String.class, "extra_linkopts")),
+ Sequence.cast(extraLinkInputs, Artifact.class, "extra_link_inputs"));
return createAppleBinaryOutputSkylarkStruct(appleBinaryOutput, thread);
} catch (RuleErrorException | ActionConflictException exception) {
throw new EvalException(null, exception);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyProviderUtils.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyProviderUtils.java
index d363eeb..50995e0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyProviderUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyProviderUtils.java
@@ -24,7 +24,7 @@
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.util.FileType;
/**
@@ -63,15 +63,15 @@
*/
public static StructImpl getLegacyProvider(TransitiveInfoCollection target) throws EvalException {
Object info = target.get(PyStructUtils.PROVIDER_NAME);
- if (info == null) {
- throw new EvalException(/*location=*/ null, "Target does not have 'py' provider");
+ if (info instanceof StructImpl) {
+ return (StructImpl) info;
}
- return SkylarkType.cast(
- info,
- StructImpl.class,
- null,
- "'%s' provider should be a struct",
- PyStructUtils.PROVIDER_NAME);
+ if (info == null) {
+ throw Starlark.errorf("Target does not have '%s' provider", PyStructUtils.PROVIDER_NAME);
+ }
+ throw Starlark.errorf(
+ "'%s' provider should be a struct (got %s)",
+ PyStructUtils.PROVIDER_NAME, Starlark.type(info));
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
index 245a274..bf67b96 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyStructUtils.java
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkType;
+import com.google.devtools.build.lib.syntax.Starlark;
/** Static helper class for creating and accessing instances of the legacy "py" struct provider. */
// TODO(b/153363654): Remove this file.
@@ -101,34 +102,21 @@
*/
public static NestedSet<Artifact> getTransitiveSources(StructImpl info) throws EvalException {
Object fieldValue = getValue(info, TRANSITIVE_SOURCES);
- Depset castValue =
- SkylarkType.cast(
- fieldValue,
- Depset.class,
- Artifact.class,
- null,
- "'%s' provider's '%s' field should be a depset of Files (got a '%s')",
- PROVIDER_NAME,
- TRANSITIVE_SOURCES,
- EvalUtils.getDataTypeName(fieldValue, /*fullDetails=*/ true));
+ // TODO(adonovan): factor with Depset.getSetFromParam and simplify.
try {
- NestedSet<Artifact> unwrappedValue = castValue.getSet(Artifact.class);
- if (!unwrappedValue.getOrder().isCompatible(Order.COMPILE_ORDER)) {
- throw new EvalException(
- /*location=*/ null,
- String.format(
- "Incompatible depset order for 'transitive_sources': expected 'default' or "
- + "'postorder', but got '%s'",
- unwrappedValue.getOrder().getSkylarkName()));
+ Depset depset = (Depset) fieldValue; // (ClassCastException)
+ NestedSet<Artifact> set = depset.getSet(Artifact.class); // (TypeException)
+ if (!set.getOrder().isCompatible(Order.COMPILE_ORDER)) {
+ throw Starlark.errorf(
+ "Incompatible depset order for 'transitive_sources': expected 'default' or "
+ + "'postorder', but got '%s'",
+ set.getOrder().getSkylarkName());
}
- return unwrappedValue;
- } catch (Depset.TypeException exception) {
- throw new EvalException(
- null,
- String.format(
- "expected field '%s' to be a depset of type 'file', but was a depset of type '%s'",
- TRANSITIVE_SOURCES, castValue.getContentType()),
- exception);
+ return set;
+ } catch (@SuppressWarnings("UnusedException") ClassCastException | Depset.TypeException ex) {
+ throw Starlark.errorf(
+ "'%s' provider's '%s' field was %s, want depset of Files",
+ PROVIDER_NAME, TRANSITIVE_SOURCES, EvalUtils.getDataTypeName(fieldValue, true));
}
}
@@ -138,15 +126,13 @@
* @throws EvalException if the field exists and is not a boolean
*/
public static boolean getUsesSharedLibraries(StructImpl info) throws EvalException {
- Object fieldValue = getValue(info, USES_SHARED_LIBRARIES);
- return SkylarkType.cast(
- fieldValue,
- Boolean.class,
- null,
- "'%s' provider's '%s' field should be a boolean (got a '%s')",
- PROVIDER_NAME,
- USES_SHARED_LIBRARIES,
- EvalUtils.getDataTypeName(fieldValue, /*fullDetails=*/ true));
+ Object v = getValue(info, USES_SHARED_LIBRARIES);
+ if (v instanceof Boolean) {
+ return (Boolean) v;
+ }
+ throw Starlark.errorf(
+ "'%s' provider's '%s' field was %s, want bool",
+ PROVIDER_NAME, USES_SHARED_LIBRARIES, Starlark.type(v));
}
/**
@@ -156,25 +142,14 @@
*/
public static NestedSet<String> getImports(StructImpl info) throws EvalException {
Object fieldValue = getValue(info, IMPORTS);
- Depset castValue =
- SkylarkType.cast(
- fieldValue,
- Depset.class,
- String.class,
- null,
- "'%s' provider's '%s' field should be a depset of strings (got a '%s')",
- PROVIDER_NAME,
- IMPORTS,
- EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
+ // TODO(adonovan): factor with Depset.getSetFromParam and simplify.
try {
- return castValue.getSet(String.class);
- } catch (Depset.TypeException exception) {
- throw new EvalException(
- null,
- String.format(
- "expected field '%s' to be a depset of type 'file', but was a depset of type '%s'",
- IMPORTS, castValue.getContentType()),
- exception);
+ Depset depset = (Depset) fieldValue; // (ClassCastException)
+ return depset.getSet(String.class); // (TypeException)
+ } catch (@SuppressWarnings("UnusedException") ClassCastException | Depset.TypeException ex) {
+ throw Starlark.errorf(
+ "'%s' provider's '%s' field was %s, want depset of strings",
+ PROVIDER_NAME, IMPORTS, EvalUtils.getDataTypeName(fieldValue, true));
}
}
@@ -184,15 +159,13 @@
* @throws EvalException if the field exists and is not a boolean
*/
public static boolean getHasPy2OnlySources(StructImpl info) throws EvalException {
- Object fieldValue = getValue(info, HAS_PY2_ONLY_SOURCES);
- return SkylarkType.cast(
- fieldValue,
- Boolean.class,
- null,
- "'%s' provider's '%s' field should be a boolean (got a '%s')",
- PROVIDER_NAME,
- HAS_PY2_ONLY_SOURCES,
- EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
+ Object v = getValue(info, HAS_PY2_ONLY_SOURCES);
+ if (v instanceof Boolean) {
+ return (Boolean) v;
+ }
+ throw Starlark.errorf(
+ "'%s' provider's '%s' field was %s, want bool",
+ PROVIDER_NAME, HAS_PY2_ONLY_SOURCES, Starlark.type(v));
}
/**
@@ -201,15 +174,13 @@
* @throws EvalException if the field exists and is not a boolean
*/
public static boolean getHasPy3OnlySources(StructImpl info) throws EvalException {
- Object fieldValue = getValue(info, HAS_PY3_ONLY_SOURCES);
- return SkylarkType.cast(
- fieldValue,
- Boolean.class,
- null,
- "'%s' provider's '%s' field should be a boolean (got a '%s')",
- PROVIDER_NAME,
- HAS_PY3_ONLY_SOURCES,
- EvalUtils.getDataTypeNameFromClass(fieldValue.getClass()));
+ Object v = getValue(info, HAS_PY3_ONLY_SOURCES);
+ if (v instanceof Boolean) {
+ return (Boolean) v;
+ }
+ throw Starlark.errorf(
+ "'%s' provider's '%s' field was %s, want bool",
+ PROVIDER_NAME, HAS_PY3_ONLY_SOURCES, Starlark.type(v));
}
public static Builder builder() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java b/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java
index bc8bc28..f2b9703 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/SkylarkTestingModule.java
@@ -25,13 +25,13 @@
@Override
public ExecutionInfo executionInfo(Dict<?, ?> requirements /* <String, String> */)
throws EvalException {
- return new ExecutionInfo(requirements.getContents(String.class, String.class, "requirements"));
+ return new ExecutionInfo(Dict.cast(requirements, String.class, String.class, "requirements"));
}
@Override
public TestEnvironmentInfo testEnvironment(Dict<?, ?> environment /* <String, String> */)
throws EvalException {
return new TestEnvironmentInfo(
- environment.getContents(String.class, String.class, "environment"));
+ Dict.cast(environment, String.class, String.class, "environment"));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
index 56cf240..79aec7b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkAspectFactory.java
@@ -33,11 +33,11 @@
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.StructProvider;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalExceptionWithStackTrace;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Mutability;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.StarlarkValue;
@@ -142,16 +142,15 @@
if (field.equals("output_groups")) {
addOutputGroups(struct.getValue(field), builder);
} else if (field.equals("providers")) {
- Object value = struct.getValue(field);
- Iterable<?> providers =
- SkylarkType.cast(
- value,
- Iterable.class,
- null,
- "The value for \"providers\" should be a list of declared providers, "
- + "got %s instead",
- EvalUtils.getDataTypeName(value, false));
- addDeclaredProviders(builder, providers);
+ Object providers = struct.getValue(field);
+ // TODO(adonovan): can we be more specific than iterable, and use Sequence.cast?
+ if (!(providers instanceof Iterable)) {
+ throw Starlark.errorf(
+ "The value for \"providers\" should be a list of declared providers, "
+ + "got %s instead",
+ Starlark.type(providers));
+ }
+ addDeclaredProviders(builder, (Iterable<?>) providers);
} else {
builder.addSkylarkTransitiveInfo(field, struct.getValue(field));
}
@@ -170,31 +169,25 @@
ConfiguredAspect.Builder builder, Iterable<?> aspectSkylarkObject) throws EvalException {
int i = 0;
for (Object o : aspectSkylarkObject) {
- Info declaredProvider =
- SkylarkType.cast(
- o,
- Info.class,
- null,
- "A return value of an aspect implementation function should be "
- + "a sequence of declared providers, instead got a %s at index %d",
- o.getClass(),
- i);
- builder.addSkylarkDeclaredProvider(declaredProvider);
+ if (!(o instanceof Info)) {
+ throw Starlark.errorf(
+ "A return value of an aspect implementation function should be "
+ + "a sequence of declared providers, instead got a %s at index %d",
+ Starlark.type(o), i);
+ }
+ builder.addSkylarkDeclaredProvider((Info) o);
i++;
}
}
- private static void addOutputGroups(Object value, ConfiguredAspect.Builder builder)
+ private static void addOutputGroups(Object outputGroups, ConfiguredAspect.Builder builder)
throws EvalException {
- Map<String, StarlarkValue> outputGroups =
- SkylarkType.castMap(value, String.class, StarlarkValue.class, "output_groups");
-
- for (String outputGroup : outputGroups.keySet()) {
- StarlarkValue objects = outputGroups.get(outputGroup);
-
+ for (Map.Entry<String, StarlarkValue> entry :
+ Dict.cast(outputGroups, String.class, StarlarkValue.class, "output_groups").entrySet()) {
builder.addOutputGroup(
- outputGroup,
- SkylarkRuleConfiguredTargetUtil.convertToOutputGroupValue(outputGroup, objects));
+ entry.getKey(),
+ SkylarkRuleConfiguredTargetUtil.convertToOutputGroupValue(
+ entry.getKey(), entry.getValue()));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Dict.java b/src/main/java/com/google/devtools/build/lib/syntax/Dict.java
index 85c86bb..3c70d4e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Dict.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Dict.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.syntax;
+import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
@@ -477,65 +478,42 @@
}
/**
- * If {@code obj} is a {@code Dict}, casts it to an unmodifiable {@code Map<K, V>} after checking
- * that each of its entries has key type {@code keyType} and value type {@code valueType}. If
- * {@code obj} is {@code None} or null, treats it as an empty dict.
- *
- * <p>The returned map may or may not be a view that is affected by updates to the original dict.
- *
- * @param obj the object to cast. null and None are treated as an empty dict.
- * @param keyType the expected type of all the dict's keys
- * @param valueType the expected type of all the dict's values
- * @param description a description of the argument being converted, or null, for debugging
+ * Casts a non-null Starlark value {@code x} to a {@code Dict<K, V>} after checking that all keys
+ * and values are instances of {@code keyType} and {@code valueType}, respectively. On error, it
+ * throws an EvalException whose message includes {@code what}, ideally a string literal, as a
+ * description of the role of {@code x}. If x is null, it returns an immutable empty dict.
*/
- public static <K, V> Map<K, V> castSkylarkDictOrNoneToDict(
- Object obj, Class<K> keyType, Class<V> valueType, @Nullable String description)
+ public static <K, V> Dict<K, V> cast(Object x, Class<K> keyType, Class<V> valueType, String what)
throws EvalException {
- if (EvalUtils.isNullOrNone(obj)) {
- return empty();
+ Preconditions.checkNotNull(x);
+ if (!(x instanceof Dict)) {
+ throw Starlark.errorf("got %s for '%s', want dict", Starlark.type(x), what);
}
- if (obj instanceof Dict) {
- return ((Dict<?, ?>) obj).getContents(keyType, valueType, description);
- }
- throw Starlark.errorf(
- "%s is not of expected type dict or NoneType",
- description == null ? Starlark.repr(obj) : String.format("'%s'", description));
- }
- /**
- * Returns an unmodifiable view of this Dict coerced to type {@code Dict<X, Y>}, after
- * superficially checking that all keys and values are of class {@code keyType} and {@code
- * valueType} respectively.
- *
- * <p>The returned map is a view that reflects subsequent updates to the original dict. If such
- * updates should insert keys or values of types other than X or Y respectively, the reference
- * returned by getContents will have a false type that may cause the program to fail in unexpected
- * and hard-to-debug ways.
- *
- * <p>The dynamic checks are necessarily superficial if either of X or Y is itself a parameterized
- * type. For example, if Y is {@code List<String>}, getContents checks that the dict values are
- * instances of List, but it does not and cannot check that all the elements of those lists are
- * Strings. If one of the dict values in fact a List of Integer, the returned reference will again
- * have a false type.
- *
- * @param keyType the expected class of keys
- * @param valueType the expected class of values
- * @param description a description of the argument being converted, or null, for debugging
- */
- @SuppressWarnings("unchecked")
- public <X, Y> Map<X, Y> getContents(
- Class<X> keyType, Class<Y> valueType, @Nullable String description) throws EvalException {
- Object keyDescription =
- description == null ? null : Printer.formattable("'%s' key", description);
- Object valueDescription =
- description == null ? null : Printer.formattable("'%s' value", description);
- for (Map.Entry<?, ?> e : this.entrySet()) {
- SkylarkType.checkType(e.getKey(), keyType, keyDescription);
- if (e.getValue() != null) {
- SkylarkType.checkType(e.getValue(), valueType, valueDescription);
+ for (Map.Entry<?, ?> e : ((Map<?, ?>) x).entrySet()) {
+ if (!keyType.isAssignableFrom(e.getKey().getClass())
+ || !valueType.isAssignableFrom(e.getValue().getClass())) {
+ // TODO(adonovan): change message to "found <K2, V2> entry",
+ // without suggesting that the entire dict is <K2, V2>.
+ throw Starlark.errorf(
+ "got dict<%s, %s> for '%s', want dict<%s, %s>",
+ Starlark.type(e.getKey()),
+ Starlark.type(e.getValue()),
+ what,
+ EvalUtils.getDataTypeNameFromClass(keyType),
+ EvalUtils.getDataTypeNameFromClass(valueType));
}
}
- return Collections.unmodifiableMap((Dict<X, Y>) this);
+
+ @SuppressWarnings("unchecked") // safe
+ Dict<K, V> res = (Dict<K, V>) x;
+ return res;
+ }
+
+ /** Like {@link #cast}, but if x is None, returns an empty Dict. */
+ public static <K, V> Dict<K, V> noneableCast(
+ Object x, Class<K> keyType, Class<V> valueType, String what) throws EvalException {
+ return x == Starlark.NONE ? empty() : cast(x, keyType, valueType, what);
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 2dc79e7..6ff8840 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -15,7 +15,6 @@
package com.google.devtools.build.lib.syntax;
import com.google.common.base.Ascii;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
@@ -928,8 +927,8 @@
result =
Depset.fromDirectAndTransitive(
order,
- listFromNoneable(direct, Object.class, "direct"),
- listFromNoneable(transitive, Depset.class, "transitive"),
+ Sequence.noneableCast(direct, Object.class, "direct"),
+ Sequence.noneableCast(transitive, Depset.class, "transitive"),
semantics.incompatibleAlwaysCheckDepsetElements());
} else {
if (x != Starlark.NONE) {
@@ -956,16 +955,6 @@
return result;
}
- private static <T> List<T> listFromNoneable(
- Object listOrNone, Class<T> objectType, String paramName) throws EvalException {
- if (listOrNone != Starlark.NONE) {
- SkylarkType.checkType(listOrNone, Sequence.class, paramName);
- return ((Sequence<?>) listOrNone).getContents(objectType, paramName);
- } else {
- return ImmutableList.of();
- }
- }
-
private static Depset legacyDepsetConstructor(
Object items, Order order, Object direct, Object transitive, StarlarkSemantics semantics)
throws EvalException {
@@ -981,22 +970,13 @@
}
// Non-legacy behavior: either 'transitive' or 'direct' were specified.
- List<Object> directElements;
- if (direct != Starlark.NONE) {
- SkylarkType.checkType(direct, Sequence.class, "direct");
- directElements = ((Sequence<?>) direct).getContents(Object.class, "direct");
- } else {
- SkylarkType.checkType(items, Sequence.class, "items");
- directElements = ((Sequence<?>) items).getContents(Object.class, "items");
- }
+ List<Object> directElements =
+ direct != Starlark.NONE
+ ? Sequence.cast(direct, Object.class, "direct")
+ : Sequence.cast(items, Object.class, "items");
- List<Depset> transitiveList;
- if (transitive != Starlark.NONE) {
- SkylarkType.checkType(transitive, Sequence.class, "transitive");
- transitiveList = ((Sequence<?>) transitive).getContents(Depset.class, "transitive");
- } else {
- transitiveList = ImmutableList.of();
- }
+ List<Depset> transitiveList = Sequence.noneableCast(transitive, Depset.class, "transitive");
+
return Depset.fromDirectAndTransitive(
order, directElements, transitiveList, semantics.incompatibleAlwaysCheckDepsetElements());
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
index ccaf69a..838a588 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
@@ -16,8 +16,6 @@
import com.google.common.base.Strings;
import java.io.IOException;
import java.util.Arrays;
-import java.util.Formattable;
-import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;
@@ -132,28 +130,6 @@
private Printer() {}
/**
- * Perform Python-style string formatting, lazily.
- *
- * @param pattern a format string.
- * @param arguments positional arguments.
- * @return the formatted string.
- */
- static Formattable formattable(final String pattern, Object... arguments) {
- final List<Object> args = Arrays.asList(arguments);
- return new Formattable() {
- @Override
- public String toString() {
- return Starlark.formatWithList(pattern, args);
- }
-
- @Override
- public void formatTo(Formatter formatter, int flags, int width, int precision) {
- Printer.getPrinter(formatter.out()).formatWithList(pattern, args);
- }
- };
- }
-
- /**
* Append a char to a buffer. In case of {@link IOException} throw an {@link AssertionError}
* instead
*
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Sequence.java b/src/main/java/com/google/devtools/build/lib/syntax/Sequence.java
index d743ca0..726a3ba 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Sequence.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Sequence.java
@@ -14,13 +14,12 @@
package com.google.devtools.build.lib.syntax;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
-import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
-import javax.annotation.Nullable;
/**
* A Sequence is a finite iterable sequence of Starlark values, such as a list or tuple.
@@ -73,64 +72,32 @@
Sequence<E> getSlice(Mutability mu, int start, int stop, int step);
/**
- * Casts a {@code List<?>} to an unmodifiable {@code List<T>}, after checking that its contents
- * all have type {@code type}.
- *
- * <p>The returned list may or may not be a view that is affected by updates to the original list.
- *
- * @param list the original list to cast
- * @param type the expected type of all the list's elements
- * @param description a description of the argument being converted, or null, for debugging
+ * Casts a non-null Starlark value {@code x} to a {@code Sequence<T>}, after checking that each
+ * element is an instance of {@code elemType}. On error, it throws an EvalException whose message
+ * includes {@code what}, ideally a string literal, as a description of the role of {@code x}.
*/
- // We could have used bounded generics to ensure that only downcasts are possible (i.e. cast
- // List<S> to List<T extends S>), but this would be less convenient for some callers, and it would
- // disallow casting an empty list to any type.
- // TODO(adonovan): this method doesn't belong here.
- @SuppressWarnings("unchecked")
- public static <T> List<T> castList(List<?> list, Class<T> type, @Nullable String description)
+ public static <T> Sequence<T> cast(Object x, Class<T> elemType, String what)
throws EvalException {
- Object desc = description == null ? null : Printer.formattable("'%s' element", description);
- for (Object value : list) {
- SkylarkType.checkType(value, type, desc);
+ Preconditions.checkNotNull(x);
+ if (!(x instanceof Sequence)) {
+ throw Starlark.errorf("for %s, got %s, want sequence", what, Starlark.type(x));
}
- return Collections.unmodifiableList((List<T>) list);
+ int i = 0;
+ for (Object elem : (Sequence) x) {
+ if (!elemType.isAssignableFrom(elem.getClass())) {
+ throw Starlark.errorf(
+ "at index %d of %s, got element of type %s, want %s",
+ i, what, Starlark.type(elem), EvalUtils.getDataTypeNameFromClass(elemType));
+ }
+ }
+ @SuppressWarnings("unchecked") // safe
+ Sequence<T> result = (Sequence) x;
+ return result;
}
- /**
- * If {@code obj} is a {@code Sequence}, casts it to an unmodifiable {@code List<T>} after
- * checking that each element has type {@code type}. If {@code obj} is {@code None} or null,
- * treats it as an empty list. For all other values, throws an {@link EvalException}.
- *
- * <p>The returned list may or may not be a view that is affected by updates to the original list.
- *
- * @param obj the object to cast. null and None are treated as an empty list.
- * @param type the expected type of all the list's elements
- * @param description a description of the argument being converted, or null, for debugging
- */
- // TODO(adonovan): this method doesn't belong here.
- public static <T> List<T> castSkylarkListOrNoneToList(
- Object obj, Class<T> type, @Nullable String description) throws EvalException {
- if (EvalUtils.isNullOrNone(obj)) {
- return ImmutableList.of();
- }
- if (obj instanceof Sequence) {
- return ((Sequence<?>) obj).getContents(type, description);
- }
- throw Starlark.errorf(
- "Illegal argument: %s is not of expected type list or NoneType",
- description == null ? Starlark.repr(obj) : String.format("'%s'", description));
- }
-
- /**
- * Casts this list as an unmodifiable {@code List<T>}, after checking that each element has type
- * {@code type}.
- *
- * @param type the expected type of all the list's elements
- * @param description a description of the argument being converted, or null, for debugging
- */
- // TODO(adonovan): this method doesn't belong here.
- default <T> List<T> getContents(Class<T> type, @Nullable String description)
+ /** Like {@link #cast}, but if x is None, returns an immutable empty list. */
+ public static <T> Sequence<T> noneableCast(Object x, Class<T> type, String what)
throws EvalException {
- return castList(this, type, description);
+ return x == Starlark.NONE ? StarlarkList.empty() : cast(x, type, what);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
index d3e4d83..141ba52 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
@@ -19,16 +19,13 @@
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
-import com.google.errorprone.annotations.FormatMethod;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import javax.annotation.Nullable;
/**
@@ -595,8 +592,6 @@
}
}
- // Utility functions regarding types
-
private static SkylarkType getGenericArgType(Object value) {
if (value instanceof Depset) {
return ((Depset) value).getContentType();
@@ -604,99 +599,4 @@
return TOP;
}
}
-
- /**
- * General purpose type-casting facility.
- *
- * @param value - the actual value of the parameter
- * @param type - the expected Class for the value
- * @param loc - the location info used in the EvalException
- * @param format - a String.format-style format string
- * @param args - arguments to format, in case there's an exception
- */
- // TODO(adonovan): irrelevant; eliminate.
- @FormatMethod
- public static <T> T cast(Object value, Class<T> type, Location loc, String format, Object... args)
- throws EvalException {
- try {
- return type.cast(value);
- } catch (ClassCastException e) {
- throw new EvalException(loc, String.format(format, args));
- }
- }
-
- /**
- * General purpose type-casting facility.
- *
- * @param value - the actual value of the parameter
- * @param genericType - a generic class of one argument for the value
- * @param argType - a covariant argument for the generic class
- * @param loc - the location info used in the EvalException
- * @param format - a format String
- * @param args - arguments to format, in case there's an exception
- */
- @SuppressWarnings("unchecked")
- @FormatMethod
- public static <T> T cast(
- Object value,
- Class<T> genericType,
- Class<?> argType,
- Location loc,
- String format,
- Object... args)
- throws EvalException {
- if (of(genericType, argType).contains(value)) {
- return (T) value;
- } else {
- throw new EvalException(loc, String.format(format, args));
- }
- }
-
- /**
- * Cast a Map object into an Iterable of Map entries of the given key, value types.
- * @param obj the Map object, where null designates an empty map
- * @param keyType the class of map keys
- * @param valueType the class of map values
- * @param what a string indicating what this is about, to include in case of error
- */
- @SuppressWarnings("unchecked")
- public static <KEY_TYPE, VALUE_TYPE> Map<KEY_TYPE, VALUE_TYPE> castMap(Object obj,
- Class<KEY_TYPE> keyType, Class<VALUE_TYPE> valueType, String what)
- throws EvalException {
- if (obj == null) {
- return ImmutableMap.of();
- }
- if (!(obj instanceof Map<?, ?>)) {
- throw Starlark.errorf("got '%s' for '%s', want 'dict'", EvalUtils.getDataTypeName(obj), what);
- }
-
- for (Map.Entry<?, ?> input : ((Map<?, ?>) obj).entrySet()) {
- if (!keyType.isAssignableFrom(input.getKey().getClass())
- || !valueType.isAssignableFrom(input.getValue().getClass())) {
- throw Starlark.errorf(
- "got dict<%s, %s> for '%s', want dict<%s, %s>",
- Starlark.type(input.getKey()),
- Starlark.type(input.getValue()),
- what,
- EvalUtils.getDataTypeNameFromClass(keyType),
- EvalUtils.getDataTypeNameFromClass(valueType));
- }
- }
-
- return (Map<KEY_TYPE, VALUE_TYPE>) obj;
- }
-
- // TODO(adonovan): eliminate 4 uses outside this package and make it private.
- // The check is trivial (instanceof) and clients can usually produce a better
- // error in context, without prematurely constructing a description.
- public static void checkType(Object object, Class<?> type, @Nullable Object description)
- throws EvalException {
- if (!type.isInstance(object)) {
- throw Starlark.errorf(
- "expected type '%s' %sbut got type '%s' instead",
- Starlark.repr(type),
- description == null ? "" : String.format("for %s ", description),
- EvalUtils.getDataTypeName(object));
- }
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
index 9dd13af..cf7ac6c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StringModule.java
@@ -930,10 +930,7 @@
if (sub instanceof String) {
return str.endsWith((String) sub);
}
-
- @SuppressWarnings("unchecked")
- Tuple<Object> subs = (Tuple<Object>) sub;
- for (String s : subs.getContents(String.class, "string")) {
+ for (String s : Sequence.cast(sub, String.class, "sub")) {
if (str.endsWith(s)) {
return true;
}
@@ -980,7 +977,7 @@
@SuppressWarnings("unchecked")
List<Object> argObjects = (List<Object>) args.getImmutableList();
return new FormatParser()
- .format(self, argObjects, kwargs.getContents(String.class, Object.class, "kwargs"));
+ .format(self, argObjects, Dict.cast(kwargs, String.class, Object.class, "kwargs"));
}
@SkylarkCallable(
@@ -1016,10 +1013,7 @@
if (sub instanceof String) {
return str.startsWith((String) sub);
}
-
- @SuppressWarnings("unchecked")
- Tuple<Object> subs = (Tuple<Object>) sub;
- for (String s : subs.getContents(String.class, "string")) {
+ for (String s : Sequence.cast(sub, String.class, "sub")) {
if (str.startsWith(s)) {
return true;
}
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 36b7d4d..ecf1f40 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
@@ -29,7 +29,6 @@
import com.google.devtools.build.lib.syntax.FunctionSignature;
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.syntax.Sequence;
-import com.google.devtools.build.lib.syntax.SkylarkType;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkFunction;
import com.google.devtools.build.lib.syntax.StarlarkThread;
@@ -92,25 +91,13 @@
// Field documentation will be output preserving the order in which the fields are listed.
ImmutableList.Builder<ProviderFieldInfo> providerFieldInfos = ImmutableList.builder();
if (fields instanceof Sequence) {
- @SuppressWarnings("unchecked")
- Sequence<String> fieldNames =
- (Sequence<String>)
- SkylarkType.cast(
- fields,
- Sequence.class,
- String.class,
- null,
- "Expected list of strings or dictionary of string -> string for 'fields'");
- for (String fieldName : fieldNames) {
- providerFieldInfos.add(asProviderFieldInfo(fieldName, "(Undocumented)"));
+ for (String name : Sequence.cast(fields, String.class, "fields")) {
+ providerFieldInfos.add(asProviderFieldInfo(name, "(Undocumented)"));
}
} else if (fields instanceof Dict) {
- Map<String, String> dict = SkylarkType.castMap(
- fields,
- String.class, String.class,
- "Expected list of strings or dictionary of string -> string for 'fields'");
- for (Map.Entry<String, String> fieldEntry : dict.entrySet()) {
- providerFieldInfos.add(asProviderFieldInfo(fieldEntry.getKey(), fieldEntry.getValue()));
+ for (Map.Entry<String, String> e :
+ Dict.cast(fields, String.class, String.class, "fields").entrySet()) {
+ providerFieldInfos.add(asProviderFieldInfo(e.getKey(), e.getValue()));
}
} else {
// fields is NONE, so there is no field information to add.
@@ -153,8 +140,7 @@
throws EvalException {
ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
if (attrs != null && attrs != Starlark.NONE) {
- Dict<?, ?> attrsDict = (Dict<?, ?>) attrs;
- attrsMapBuilder.putAll(attrsDict.getContents(String.class, FakeDescriptor.class, "attrs"));
+ attrsMapBuilder.putAll(Dict.cast(attrs, String.class, FakeDescriptor.class, "attrs"));
}
attrsMapBuilder.put("name", IMPLICIT_NAME_ATTRIBUTE_DESCRIPTOR);
@@ -206,8 +192,7 @@
FakeSkylarkAspect fakeAspect = new FakeSkylarkAspect();
ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
if (attrs != null && attrs != Starlark.NONE) {
- Dict<?, ?> attrsDict = (Dict<?, ?>) attrs;
- attrsMapBuilder.putAll(attrsDict.getContents(String.class, FakeDescriptor.class, "attrs"));
+ attrsMapBuilder.putAll(Dict.cast(attrs, String.class, FakeDescriptor.class, "attrs"));
}
attrsMapBuilder.put("name", IMPLICIT_NAME_ATTRIBUTE_DESCRIPTOR);
@@ -218,10 +203,10 @@
.collect(Collectors.toList());
attrInfos.sort(new AttributeNameComparator());
- List<String> aspectAttrs = new ArrayList<>();
- if (attributeAspects != null) {
- aspectAttrs = attributeAspects.getContents(String.class, "aspectAttrs");
- }
+ List<String> aspectAttrs =
+ attributeAspects != null
+ ? Sequence.cast(attributeAspects, String.class, "aspectAttrs")
+ : new ArrayList<>();
aspectAttrs =
aspectAttrs.stream().filter(entry -> !entry.startsWith("_")).collect(Collectors.toList());
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
index 9749c26..07e900f 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/repository/FakeRepositoryModule.java
@@ -63,8 +63,7 @@
List<AttributeInfo> attrInfos;
ImmutableMap.Builder<String, FakeDescriptor> attrsMapBuilder = ImmutableMap.builder();
if (attrs != null && attrs != Starlark.NONE) {
- Dict<?, ?> attrsDict = (Dict<?, ?>) attrs;
- attrsMapBuilder.putAll(attrsDict.getContents(String.class, FakeDescriptor.class, "attrs"));
+ attrsMapBuilder.putAll(Dict.cast(attrs, String.class, FakeDescriptor.class, "attrs"));
}
attrsMapBuilder.put("name", IMPLICIT_NAME_ATTRIBUTE_DESCRIPTOR);
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 ad60ded..7d1e676 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
@@ -175,10 +175,10 @@
@Test
public void testRepoMappingNotAStringStringDict() throws Exception {
helper.parse("local_repository(name='foo', path='/foo', repo_mapping=1)");
- assertThat(helper.getParserError()).contains("got 'int' for 'repo_mapping', want 'dict'");
+ assertThat(helper.getParserError()).contains("got int for 'repo_mapping', want dict");
helper.parse("local_repository(name='foo', path='/foo', repo_mapping='hello')");
- assertThat(helper.getParserError()).contains("got 'string' for 'repo_mapping', want 'dict'");
+ assertThat(helper.getParserError()).contains("got string for 'repo_mapping', want dict");
helper.parse("local_repository(name='foo', path='/foo', repo_mapping={1: 1})");
assertThat(helper.getParserError())
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
index 43efec1..58464d6 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
@@ -2376,9 +2376,7 @@
EvalException e =
assertThrows(
EvalException.class, () -> CcModule.withFeatureSetFromSkylark(withFeatureSetProvider));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'features' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for features, got struct, want sequence");
}
@Test
@@ -2392,9 +2390,7 @@
EvalException e =
assertThrows(
EvalException.class, () -> CcModule.withFeatureSetFromSkylark(withFeatureSetProvider));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'not_features' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for not_features, got struct, want sequence");
}
@Test
@@ -2410,7 +2406,7 @@
EvalException.class, () -> CcModule.withFeatureSetFromSkylark(withFeatureSetProvider));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'features' element but got type 'struct' instead");
+ .contains("at index 0 of features, got element of type struct, want string");
}
@Test
@@ -2426,8 +2422,7 @@
EvalException.class, () -> CcModule.withFeatureSetFromSkylark(withFeatureSetProvider));
assertThat(e)
.hasMessageThat()
- .contains(
- "expected type 'string' for 'not_features' element but got type 'struct' instead");
+ .contains("at index 0 of not_features, got element of type struct, want string");
}
private void createCustomWithFeatureSetRule(String pkg, String features, String notFeatures)
@@ -2588,9 +2583,7 @@
assertThat(envSetProvider).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.envSetFromSkylark(envSetProvider));
- assertThat(e)
- .hasMessageThat()
- .contains("'env_entries' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for env_entries, got struct, want sequence");
}
@Test
@@ -2624,9 +2617,7 @@
assertThat(envSetProvider).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.envSetFromSkylark(envSetProvider));
- assertThat(e)
- .hasMessageThat()
- .contains("'with_features' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for with_features, got string, want sequence");
}
@Test
@@ -3170,9 +3161,7 @@
EvalException e = assertThrows(EvalException.class, () -> CcModule.toolFromSkylark(toolStruct));
assertThat(e)
.hasMessageThat()
- .contains(
- "expected type 'string' for 'execution_requirements' "
- + "element but got type 'struct' instead");
+ .contains("at index 0 of execution_requirements, got element of type struct, want string");
}
@Test
@@ -3245,9 +3234,7 @@
SkylarkInfo toolStruct = (SkylarkInfo) getMyInfoFromTarget(t).getValue("tool");
assertThat(toolStruct).isNotNull();
EvalException e = assertThrows(EvalException.class, () -> CcModule.toolFromSkylark(toolStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'with_features' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for with_features, got struct, want sequence");
}
@Test
@@ -3280,8 +3267,7 @@
EvalException e = assertThrows(EvalException.class, () -> CcModule.toolFromSkylark(toolStruct));
assertThat(e)
.hasMessageThat()
- .contains(
- "llegal argument: 'execution_requirements' is not of expected type list or NoneType");
+ .contains("for execution_requirements, got string, want sequence");
}
@Test
@@ -3296,9 +3282,7 @@
EvalException e = assertThrows(EvalException.class, () -> CcModule.toolFromSkylark(toolStruct));
assertThat(e)
.hasMessageThat()
- .contains(
- "expected type 'string' for 'execution_requirements' "
- + "element but got type 'struct' instead");
+ .contains("at index 0 of execution_requirements, got element of type struct, want string");
}
private void createCustomToolRule(
@@ -3359,7 +3343,7 @@
() -> CcModule.flagSetFromSkylark(flagSetStruct, /* actionName= */ null));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'actions' element but got type 'struct' instead");
+ .contains("at index 0 of actions, got element of type struct, want string");
}
@Test
@@ -3499,9 +3483,7 @@
assertThrows(
EvalException.class,
() -> CcModule.flagSetFromSkylark(flagSetStruct, /* actionName */ null));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'flag_groups' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for flag_groups, got struct, want sequence");
}
@Test
@@ -3517,9 +3499,7 @@
assertThrows(
EvalException.class,
() -> CcModule.flagSetFromSkylark(flagSetStruct, /* actionName */ null));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'with_features' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for with_features, got struct, want sequence");
}
@Test
@@ -3535,9 +3515,7 @@
assertThrows(
EvalException.class,
() -> CcModule.flagSetFromSkylark(flagSetStruct, /* actionName */ null));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'actions' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for actions, got struct, want sequence");
}
private void createCustomFlagSetRule(
@@ -3669,7 +3647,7 @@
EvalException.class, () -> CcModule.actionConfigFromSkylark(actionConfigStruct));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'implies' element but got type 'struct' instead");
+ .contains("at index 0 of implies, got element of type struct, want string");
}
@Test
@@ -3691,7 +3669,7 @@
EvalException.class, () -> CcModule.actionConfigFromSkylark(actionConfigStruct));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'implies' element but got type 'struct' instead");
+ .contains("at index 0 of implies, got element of type struct, want string");
}
@Test
@@ -3843,9 +3821,7 @@
EvalException e =
assertThrows(
EvalException.class, () -> CcModule.actionConfigFromSkylark(actionConfigStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'tools' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for tools, got struct, want sequence");
}
@Test
@@ -3865,9 +3841,7 @@
EvalException e =
assertThrows(
EvalException.class, () -> CcModule.actionConfigFromSkylark(actionConfigStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'flag_sets' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for flag_sets, got bool, want sequence");
}
@Test
@@ -3887,9 +3861,7 @@
EvalException e =
assertThrows(
EvalException.class, () -> CcModule.actionConfigFromSkylark(actionConfigStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'implies' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for implies, got struct, want sequence");
}
private void createCustomActionConfigRule(
@@ -4040,7 +4012,7 @@
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'implies' element but got type 'struct' instead");
+ .contains("at index 0 of implies, got element of type struct, want string");
}
@Test
@@ -4064,7 +4036,7 @@
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
assertThat(e)
.hasMessageThat()
- .contains("expected type 'string' for 'provides' element but got type 'struct' instead");
+ .contains("at index 0 of provides, got element of type struct, want string");
}
@Test
@@ -4226,9 +4198,7 @@
assertThat(featureStruct).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'flag_sets' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for flag_sets, got struct, want sequence");
}
@Test
@@ -4249,9 +4219,7 @@
assertThat(featureStruct).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'env_sets' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for env_sets, got struct, want sequence");
}
@Test
@@ -4272,9 +4240,7 @@
assertThat(featureStruct).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'requires' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for requires, got struct, want sequence");
}
@Test
@@ -4295,9 +4261,7 @@
assertThat(featureStruct).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'implies' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for implies, got struct, want sequence");
}
@Test
@@ -4318,9 +4282,7 @@
assertThat(featureStruct).isNotNull();
EvalException e =
assertThrows(EvalException.class, () -> CcModule.featureFromSkylark(featureStruct));
- assertThat(e)
- .hasMessageThat()
- .contains("Illegal argument: 'provides' is not of expected type list or NoneType");
+ assertThat(e).hasMessageThat().contains("for provides, got struct, want sequence");
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PyStructUtilsTest.java b/src/test/java/com/google/devtools/build/lib/rules/python/PyStructUtilsTest.java
index 2fe94e3..b77aadf 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/python/PyStructUtilsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/python/PyStructUtilsTest.java
@@ -91,8 +91,7 @@
ThrowingRunnable access, String fieldName, String expectedType) {
assertThrowsEvalExceptionContaining(
access,
- String.format(
- "\'py' provider's '%s' field should be a %s (got a 'int')", fieldName, expectedType));
+ String.format("\'py' provider's '%s' field was int, want %s", fieldName, expectedType));
}
/** We need this because {@code NestedSet}s don't have value equality. */
@@ -154,7 +153,7 @@
public void getUsesSharedLibraries_WrongType() {
StructImpl info = makeStruct(ImmutableMap.of(PyStructUtils.USES_SHARED_LIBRARIES, 123));
assertHasWrongTypeMessage(
- () -> PyStructUtils.getUsesSharedLibraries(info), "uses_shared_libraries", "boolean");
+ () -> PyStructUtils.getUsesSharedLibraries(info), "uses_shared_libraries", "bool");
}
@Test
@@ -191,7 +190,7 @@
public void getHasPy2OnlySources_WrongType() {
StructImpl info = makeStruct(ImmutableMap.of(PyStructUtils.HAS_PY2_ONLY_SOURCES, 123));
assertHasWrongTypeMessage(
- () -> PyStructUtils.getHasPy2OnlySources(info), "has_py2_only_sources", "boolean");
+ () -> PyStructUtils.getHasPy2OnlySources(info), "has_py2_only_sources", "bool");
}
@Test
@@ -209,7 +208,7 @@
public void getHasPy3OnlySources_WrongType() {
StructImpl info = makeStruct(ImmutableMap.of(PyStructUtils.HAS_PY3_ONLY_SOURCES, 123));
assertHasWrongTypeMessage(
- () -> PyStructUtils.getHasPy3OnlySources(info), "has_py3_only_sources", "boolean");
+ () -> PyStructUtils.getHasPy3OnlySources(info), "has_py3_only_sources", "bool");
}
/** Checks values set by the builder. */
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
index 11ef9a4..8a59f59 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java
@@ -401,7 +401,7 @@
@Test
public void testLabelListWithAspectsError() throws Exception {
checkEvalErrorContains(
- "expected type 'Aspect' for 'aspects' element but got type 'int' instead",
+ "at index 0 of aspects, got element of type int, want Aspect",
"def _impl(target, ctx):",
" pass",
"my_aspect = aspect(implementation = _impl)",
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
index 65637e4..77bdd6d 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
@@ -401,7 +401,7 @@
public void testCreateSpawnActionBadGenericArg() throws Exception {
setRuleContext(createRuleContext("//foo:foo"));
checkEvalErrorContains(
- "expected type 'File' for 'outputs' element but got type 'string' instead",
+ "at index 0 of outputs, got element of type string, want File",
"l = ['a', 'b']",
"ruleContext.actions.run_shell(",
" outputs = l,",
@@ -841,7 +841,7 @@
public void testRunfilesBadListGenericType() throws Exception {
setRuleContext(createRuleContext("//foo:foo"));
checkEvalErrorContains(
- "expected type 'File' for 'files' element but got type 'string' instead",
+ "at index 0 of files, got element of type string, want File",
"ruleContext.runfiles(files = ['some string'])");
}
@@ -857,16 +857,16 @@
public void testRunfilesBadMapGenericType() throws Exception {
setRuleContext(createRuleContext("//foo:foo"));
checkEvalErrorContains(
- "expected type 'string' for 'symlinks' key but got type 'int' instead",
+ "got dict<int, File> for 'symlinks', want dict<string, File>",
"ruleContext.runfiles(symlinks = {123: ruleContext.files.srcs[0]})");
checkEvalErrorContains(
- "expected type 'File' for 'symlinks' value but got type 'int' instead",
+ "got dict<string, int> for 'symlinks', want dict<string, File>",
"ruleContext.runfiles(symlinks = {'some string': 123})");
checkEvalErrorContains(
- "expected type 'string' for 'root_symlinks' key but got type 'int' instead",
+ "got dict<int, File> for 'root_symlinks', want dict<string, File>",
"ruleContext.runfiles(root_symlinks = {123: ruleContext.files.srcs[0]})");
checkEvalErrorContains(
- "expected type 'File' for 'root_symlinks' value but got type 'int' instead",
+ "got dict<string, int> for 'root_symlinks', want dict<string, File>",
"ruleContext.runfiles(root_symlinks = {'some string': 123})");
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java b/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
index f1592ca..431cbee 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/DepsetTest.java
@@ -234,7 +234,7 @@
public void testItemsAndTransitive() throws Exception {
new Scenario()
.testIfExactError(
- "expected type 'sequence' for items but got type 'depset' instead",
+ "for items, got depset, want sequence",
"depset(items = depset(), transitive = [depset()])");
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index 428a7b1..78aeeac 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -716,9 +716,7 @@
@Test
public void testDepsetDirectInvalidType() throws Exception {
new Scenario()
- .testIfErrorContains(
- "expected type 'sequence' for direct but got type 'string' instead",
- "depset(direct='hello')");
+ .testIfErrorContains("for direct, got string, want sequence", "depset(direct='hello')");
}
@Test
diff --git a/src/test/starlark/testdata/string_misc.sky b/src/test/starlark/testdata/string_misc.sky
index fd909ed..4ba76e3 100644
--- a/src/test/starlark/testdata/string_misc.sky
+++ b/src/test/starlark/testdata/string_misc.sky
@@ -91,9 +91,9 @@
---
'a'.endswith(['a']) ### got .* 'list', want 'string or tuple of strings
---
-'1'.endswith((1,)) ### expected type 'string' for 'string' element but got type 'int' instead
+'1'.endswith((1,)) ### at index 0 of sub, got element of type int, want string
---
-'a'.endswith(('1', 1)) ### expected type 'string' for 'string' element but got type 'int' instead
+'a'.endswith(('1', 1)) ### at index 0 of sub, got element of type int, want string
---
# startswith
@@ -119,9 +119,9 @@
---
'a'.startswith(['a']) ### got .* 'list', want 'string or tuple of strings'
---
-'1'.startswith((1,)) ### expected type 'string' for 'string' element but got type 'int' instead
+'1'.startswith((1,)) ### at index 0 of sub, got element of type int, want string
---
-'a'.startswith(('1', 1)) ### expected type 'string' for 'string' element but got type 'int' instead
+'a'.startswith(('1', 1)) ### at index 0 of sub, got element of type int, want string
---
# substring