Skip to content

Commit a5e1033

Browse files
Wyveraldcomius
andauthored
[8.2.1] Cherry-pick of flag/StarlarkSemantics related changes (#25850)
Original commits: - 85dd88a - a5799c3 - f934630 Fixes #25846 for 8.2.1. --------- Co-authored-by: Googler <ilist@google.com>
1 parent 74da5dd commit a5e1033

File tree

17 files changed

+150
-265
lines changed

17 files changed

+150
-265
lines changed

src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileGlobals.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,7 @@ public void registerToolchains(
444444
named = true,
445445
positional = false,
446446
defaultValue = "False",
447-
enableOnlyWithFlag = "-experimental_isolated_extension_usages",
448-
valueWhenDisabled = "False"),
447+
enableOnlyWithFlag = "-experimental_isolated_extension_usages"),
449448
},
450449
useStarlarkThread = true)
451450
public ModuleExtensionProxy useExtension(

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ Descriptor stringAttribute(
352352
name = MATERIALIZER_ARG,
353353
enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_DORMANT_DEPS,
354354
allowedTypes = {@ParamType(type = StarlarkFunction.class)},
355-
valueWhenDisabled = "None",
356355
defaultValue = "None",
357356
named = true,
358357
positional = false,
@@ -637,7 +636,6 @@ Descriptor intListAttribute(
637636
name = MATERIALIZER_ARG,
638637
enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_DORMANT_DEPS,
639638
allowedTypes = {@ParamType(type = StarlarkFunction.class)},
640-
valueWhenDisabled = "None",
641639
defaultValue = "None",
642640
named = true,
643641
positional = false,

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkRuleFunctionsApi.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ name to an attribute object (see
493493
named = true,
494494
positional = false,
495495
defaultValue = "None",
496-
valueWhenDisabled = "None",
497496
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_NO_RULE_OUTPUTS_PARAM,
498497
doc =
499498
"This parameter has been deprecated. Migrate rules to use"

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,6 @@ LinkerInputT createLinkerInput(
15031503
named = true,
15041504
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_REQUIRE_LINKER_INPUT_CC_API,
15051505
defaultValue = "None",
1506-
valueWhenDisabled = "None",
15071506
allowedTypes = {@ParamType(type = NoneType.class), @ParamType(type = Sequence.class)}),
15081507
@Param(
15091508
name = "user_link_flags",
@@ -1512,7 +1511,6 @@ LinkerInputT createLinkerInput(
15121511
named = true,
15131512
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_REQUIRE_LINKER_INPUT_CC_API,
15141513
defaultValue = "None",
1515-
valueWhenDisabled = "None",
15161514
allowedTypes = {@ParamType(type = NoneType.class), @ParamType(type = Sequence.class)}),
15171515
@Param(
15181516
name = "additional_inputs",
@@ -1521,7 +1519,6 @@ LinkerInputT createLinkerInput(
15211519
named = true,
15221520
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_REQUIRE_LINKER_INPUT_CC_API,
15231521
defaultValue = "None",
1524-
valueWhenDisabled = "None",
15251522
allowedTypes = {@ParamType(type = NoneType.class), @ParamType(type = Sequence.class)}),
15261523
@Param(
15271524
name = "extra_link_time_library",

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ default JavaInfoT mergeJavaProviders(Sequence<?> providers /* <JavaInfoT> expect
9090
"Deprecated: The output jar of the rule. Used to name the resulting source jar. "
9191
+ "The parameter sets output_source_jar parameter to `{output_jar}-src.jar`."
9292
+ "Use output_source_jar parameter directly instead.",
93-
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS,
94-
valueWhenDisabled = "None"),
93+
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS),
9594
@Param(
9695
name = "output_source_jar",
9796
positional = false,
@@ -129,8 +128,7 @@ default JavaInfoT mergeJavaProviders(Sequence<?> providers /* <JavaInfoT> expect
129128
"Deprecated: You can drop this parameter (host_javabase is provided with "
130129
+ "java_toolchain)",
131130
defaultValue = "None",
132-
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS,
133-
valueWhenDisabled = "None"),
131+
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS),
134132
})
135133
default FileApi packSources(
136134
StarlarkActionFactoryT actions,
@@ -360,8 +358,7 @@ default FileApi runIjar(
360358
"Deprecated: You can drop this parameter (host_javabase is provided with "
361359
+ "java_toolchain)",
362360
defaultValue = "None",
363-
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS,
364-
valueWhenDisabled = "None"),
361+
disableWithFlag = BuildLanguageOptions.INCOMPATIBLE_JAVA_COMMON_PARAMETERS),
365362
@Param(
366363
name = "sourcepath",
367364
positional = false,

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/repository/RepositoryModuleApi.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ dependency on a label to a file (a repository rule cannot depend on a generated
109109
doc = "Compatible with remote execution",
110110
named = true,
111111
positional = false,
112-
enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_REPO_REMOTE_EXEC,
113-
valueWhenDisabled = "False"),
112+
enableOnlyWithFlag = BuildLanguageOptions.EXPERIMENTAL_REPO_REMOTE_EXEC),
114113
@Param(
115114
name = "doc",
116115
allowedTypes = {

src/main/java/net/starlark/java/annot/Param.java

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
*
101101
* <p>Note that at most one of {@link #enableOnlyWithFlag} and {@link #disableWithFlag} can be
102102
* non-empty.
103+
*
104+
* <p>If {@link #enableOnlyWithFlag} is non-empty, then {@link #defaultValue} must also be
105+
* non-empty; mandatory parameters cannot be toggled by a flag.
103106
*/
104107
String enableOnlyWithFlag() default "";
105108

@@ -110,27 +113,9 @@
110113
*
111114
* <p>Note that at most one of {@link #enableOnlyWithFlag} and {@link #disableWithFlag} can be
112115
* non-empty.
113-
*/
114-
String disableWithFlag() default "";
115-
116-
/**
117-
* Value for the parameter when the parameter is "disabled" based on semantic flags. (When the
118-
* parameter is disabled, it may not be set from Starlark, but an argument of the given value is
119-
* passed to the annotated Java method when invoked.) (See {@link #enableOnlyWithFlag()} and
120-
* {@link #disableWithFlag()} for toggling a parameter with semantic flags.
121116
*
122-
* <p>The parameter value is written as a Starlark expression (for example: "False", "True", "[]",
123-
* "None").
124-
*
125-
* <p>This should be set (non-empty) if and only if the parameter may be disabled with a semantic
126-
* flag.
127-
*
128-
* <p>Note that this is very similar to {@link #defaultValue}; it may be considered "the default
129-
* value if no parameter is specified". It is important that this is distinct, however, in cases
130-
* where it is desired to have a normally-mandatory parameter toggled by flag. Such a parameter
131-
* should have no {@link #defaultValue} set, but should have a sensible {@link
132-
* #valueWhenDisabled()} set. ("unbound" may be used in cases where no value would be valid. See
133-
* {@link #defaultValue}.)
117+
* <p>If {@link #disableWithFlag} is non-empty, then {@link #defaultValue} must also be non-empty;
118+
* mandatory parameters cannot be toggled by a flag.
134119
*/
135-
String valueWhenDisabled() default "";
120+
String disableWithFlag() default "";
136121
}

src/main/java/net/starlark/java/annot/processor/StarlarkMethodProcessor.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,10 @@ private void checkParameter(Element param, Param paramAnnot) {
381381
}
382382
hasFlag = true;
383383
}
384-
if (hasFlag == paramAnnot.valueWhenDisabled().isEmpty()) {
384+
if (hasFlag && paramAnnot.defaultValue().isEmpty()) {
385385
errorf(
386386
param,
387-
hasFlag
388-
? "Parameter '%s' may be disabled by semantic flag, thus valueWhenDisabled must be"
389-
+ " set"
390-
: "Parameter '%s' has valueWhenDisabled set, but is always enabled",
387+
"Parameter '%s' may be disabled by semantic flag, thus defaultValue must be" + " set",
391388
paramAnnot.name());
392389
}
393390

src/main/java/net/starlark/java/eval/BuiltinFunction.java

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,11 @@ public final class BuiltinFunction implements StarlarkCallable {
4141

4242
private final Object obj;
4343
private final String methodName;
44-
@Nullable private final MethodDescriptor desc;
45-
46-
/**
47-
* Constructs a BuiltinFunction for a StarlarkMethod-annotated method of the given name (as seen
48-
* by Starlark, not Java).
49-
*/
50-
BuiltinFunction(Object obj, String methodName) {
51-
this.obj = obj;
52-
this.methodName = methodName;
53-
this.desc = null; // computed later
54-
}
44+
private final MethodDescriptor desc;
5545

5646
/**
5747
* Constructs a BuiltinFunction for a StarlarkMethod-annotated method (not field) of the given
5848
* name (as seen by Starlark, not Java).
59-
*
60-
* <p>This constructor should be used only for ephemeral BuiltinFunction values created
61-
* transiently during a call such as {@code x.f()}, when the caller has already looked up the
62-
* MethodDescriptor using the same semantics as the thread that will be used in the call. Use the
63-
* other (slower) constructor if there is any possibility that the semantics of the {@code x.f}
64-
* operation differ from those of the thread used in the call.
6549
*/
6650
BuiltinFunction(Object obj, String methodName, MethodDescriptor desc) {
6751
Preconditions.checkArgument(!desc.isStructField());
@@ -73,28 +57,17 @@ public final class BuiltinFunction implements StarlarkCallable {
7357
@Override
7458
public Object fastcall(StarlarkThread thread, Object[] positional, Object[] named)
7559
throws EvalException, InterruptedException {
76-
MethodDescriptor desc = getMethodDescriptor(thread.getSemantics());
60+
desc.checkEnabled(thread);
7761
Object[] vector = getArgumentVector(thread, desc, positional, named);
7862
return desc.call(
7963
obj instanceof String ? StringModule.INSTANCE : obj, vector, thread.mutability());
8064
}
8165

82-
private MethodDescriptor getMethodDescriptor(StarlarkSemantics semantics) {
83-
MethodDescriptor desc = this.desc;
84-
if (desc == null) {
85-
desc = CallUtils.getAnnotatedMethods(semantics, obj.getClass()).get(methodName);
86-
Preconditions.checkArgument(
87-
!desc.isStructField(),
88-
"BuiltinFunction constructed for MethodDescriptor(structField=True)");
89-
}
90-
return desc;
91-
}
92-
9366
/**
9467
* Returns the StarlarkMethod annotation of this Starlark-callable Java method.
9568
*/
9669
public StarlarkMethod getAnnotation() {
97-
return getMethodDescriptor(StarlarkSemantics.DEFAULT).getAnnotation();
70+
return desc.getAnnotation();
9871
}
9972

10073
@Override
@@ -126,7 +99,6 @@ public String toString() {
12699
* StarlarkMethod-annotated Java method.
127100
*
128101
* @param thread the Starlark thread for the call
129-
* @param loc the location of the call expression, or BUILTIN for calls from Java
130102
* @param desc descriptor for the StarlarkMethod-annotated method
131103
* @param positional an array of positional arguments; as an optimization, in simple cases, this
132104
* array may be reused as the method's return value
@@ -196,7 +168,7 @@ private Object[] getArgumentVector(
196168
}
197169

198170
// disabled?
199-
if (param.disabledByFlag() != null) {
171+
if (!param.isEnabled(thread)) {
200172
// Skip disabled parameter as if not present at all.
201173
// The default value will be filled in below.
202174
continue;
@@ -269,13 +241,12 @@ private Object[] getArgumentVector(
269241
}
270242

271243
// disabled?
272-
String flag = param.disabledByFlag();
273-
if (flag != null) {
244+
if (!param.isEnabled(thread)) {
274245
// spill to **kwargs
275246
if (kwargs == null) {
276247
throw Starlark.errorf(
277248
"in call to %s(), parameter '%s' is %s",
278-
methodName, param.getName(), disabled(flag, thread.getSemantics()));
249+
methodName, param.getName(), param.getDisabledErrorMessage());
279250
}
280251

281252
// duplicate named argument?
@@ -375,21 +346,4 @@ private void checkParamValue(ParamDescriptor param, Object value) throws EvalExc
375346
methodName, param.getName(), Starlark.type(value), param.getTypeErrorMessage());
376347
}
377348
}
378-
379-
// Returns a phrase meaning "disabled" appropriate to the specified flag.
380-
private static String disabled(String flag, StarlarkSemantics semantics) {
381-
// If the flag is True, it must be a deprecation flag. Otherwise it's an experimental flag.
382-
// TODO(adonovan): is that assumption sound?
383-
if (semantics.getBool(flag)) {
384-
return String.format(
385-
"deprecated and will be removed soon. It may be temporarily re-enabled by setting"
386-
+ " --%s=false",
387-
flag.substring(1)); // remove [+-] prefix
388-
} else {
389-
return String.format(
390-
"experimental and thus unavailable with the current flags. It may be enabled by setting"
391-
+ " --%s",
392-
flag.substring(1)); // remove [+-] prefix
393-
}
394-
}
395349
}

src/main/java/net/starlark/java/eval/CallUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ private static StarlarkClassDescriptor buildStarlarkClassDescriptor(
148148
continue;
149149
}
150150

151-
MethodDescriptor descriptor = MethodDescriptor.of(method, callable, semantics);
151+
MethodDescriptor descriptor = MethodDescriptor.of(method, callable);
152152

153153
// self-call method?
154154
if (callable.selfCall()) {
@@ -200,7 +200,7 @@ static Object getAnnotatedField(StarlarkSemantics semantics, Object x, String fi
200200
if (desc == null) {
201201
throw Starlark.errorf("value of type %s has no .%s field", Starlark.type(x), fieldName);
202202
}
203-
return desc.callField(x, semantics, /*mu=*/ null);
203+
return desc.callField(x, semantics, /* mu= */ null);
204204
}
205205

206206
/** Returns the names of the Starlark fields of {@code x} under the specified semantics. */

src/main/java/net/starlark/java/eval/MethodDescriptor.java

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
import java.util.Arrays;
2525
import javax.annotation.Nullable;
2626
import net.starlark.java.annot.Param;
27+
import net.starlark.java.annot.StarlarkAnnotations;
2728
import net.starlark.java.annot.StarlarkMethod;
29+
import net.starlark.java.eval.ParamDescriptor.ConditionalCheck;
2830

2931
/**
3032
* A value class to store Methods with their corresponding {@link StarlarkMethod} annotation
@@ -35,7 +37,7 @@
3537
*/
3638
final class MethodDescriptor {
3739
private final Method method;
38-
private final StarlarkMethod annotation;
40+
@Nullable private transient StarlarkMethod annotation;
3941

4042
private final String name;
4143
private final String doc;
@@ -50,6 +52,8 @@ final class MethodDescriptor {
5052
private final boolean useStarlarkSemantics;
5153
private final boolean positionalsReusableAsJavaArgsVectorIfArgumentCountValid;
5254

55+
@Nullable private final ConditionalCheck conditionalCheck;
56+
5357
private enum HowToHandleReturn {
5458
NULL_TO_NONE, // any Starlark value; null -> None
5559
ERROR_ON_NULL, // any Starlark value; null -> error
@@ -110,30 +114,40 @@ private MethodDescriptor(
110114
&& !useStarlarkSemantics
111115
&& !useStarlarkThread
112116
&& stream(parameters).allMatch(MethodDescriptor::paramUsableAsPositionalWithoutChecks);
117+
118+
if (!annotation.enableOnlyWithFlag().isEmpty() || !annotation.disableWithFlag().isEmpty()) {
119+
conditionalCheck =
120+
new ConditionalCheck(annotation.enableOnlyWithFlag(), annotation.disableWithFlag());
121+
} else {
122+
conditionalCheck = null;
123+
}
113124
}
114125

115126
private static boolean paramUsableAsPositionalWithoutChecks(ParamDescriptor param) {
116127
return param.isPositional()
117-
&& param.disabledByFlag() == null
128+
&& param.conditionalCheck == null
118129
&& param.getAllowedClasses() == null;
119130
}
120131

121132
/** Returns the StarlarkMethod annotation corresponding to this method. */
122133
StarlarkMethod getAnnotation() {
134+
if (annotation == null) {
135+
// Annotation is null on deserialization, becuase deserializer can't handle annotations
136+
annotation = StarlarkAnnotations.getStarlarkMethod(method);
137+
}
123138
return annotation;
124139
}
125140

126-
/** @return Starlark method descriptor for provided Java method and signature annotation. */
127-
static MethodDescriptor of(
128-
Method method, StarlarkMethod annotation, StarlarkSemantics semantics) {
141+
/** Returns starlark method descriptor for provided Java method and signature annotation. */
142+
static MethodDescriptor of(Method method, StarlarkMethod annotation) {
129143
// This happens when the interface is public but the implementation classes
130144
// have reduced visibility.
131145
method.setAccessible(true);
132146

133147
Class<?>[] paramClasses = method.getParameterTypes();
134148
Param[] paramAnnots = annotation.parameters();
135149
ParamDescriptor[] params = new ParamDescriptor[paramAnnots.length];
136-
Arrays.setAll(params, i -> ParamDescriptor.of(paramAnnots[i], paramClasses[i], semantics));
150+
Arrays.setAll(params, i -> ParamDescriptor.of(paramAnnots[i], paramClasses[i]));
137151

138152
return new MethodDescriptor(
139153
method,
@@ -317,4 +331,31 @@ boolean isSelfCall() {
317331
boolean isPositionalsReusableAsJavaArgsVectorIfArgumentCountValid() {
318332
return positionalsReusableAsJavaArgsVectorIfArgumentCountValid;
319333
}
334+
335+
/** Returns true if parameter is enabled. */
336+
void checkEnabled(StarlarkThread thread) throws EvalException {
337+
if (conditionalCheck == null) { // fast path
338+
return;
339+
}
340+
341+
// TODO(b/407506132): A method enabled by a non-experimental flag should not be marked as
342+
// experimental
343+
if (!thread
344+
.getSemantics()
345+
.isFeatureEnabledBasedOnTogglingFlags(
346+
conditionalCheck.enableOnlyWithFlag(), conditionalCheck.disableWithFlag())) {
347+
if (!conditionalCheck.enableOnlyWithFlag().isEmpty()) {
348+
throw Starlark.errorf(
349+
"function %s() is experimental and thus unavailable with the current flags. It may be"
350+
+ " enabled by setting --%s",
351+
name, conditionalCheck.enableOnlyWithFlag().substring(1)); // remove [+-] prefix
352+
}
353+
if (!conditionalCheck.disableWithFlag().isEmpty()) {
354+
throw Starlark.errorf(
355+
"function %s() is deprecated and will be removed soon. It may be temporarily re-enabled"
356+
+ " by setting --%s",
357+
name, conditionalCheck.disableWithFlag().substring(1)); // remove [+-] prefix
358+
}
359+
}
360+
}
320361
}

0 commit comments

Comments
 (0)