Skip to content

Commit 4aba581

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Handle bool.hasEnvironment constructor in constant evaluation
.fromEnvironment environment constructor handling is updated to read the default value from the declaration instead of hardcoding it. Closes #41051 Closes #40501 Change-Id: I8eb4018dc7d6bea466a645d7762702914d9887db Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/139642 Reviewed-by: Jens Johansen <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent 0ae8697 commit 4aba581

File tree

3 files changed

+113
-50
lines changed

3 files changed

+113
-50
lines changed

pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:_fe_analyzer_shared/src/parser/parser.dart'
1414
show FormalParameterKind;
1515

1616
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
17+
import 'package:front_end/src/fasta/builder/procedure_builder.dart';
1718

1819
import 'package:kernel/ast.dart'
1920
show DynamicType, Expression, VariableDeclaration;
@@ -171,8 +172,9 @@ class FormalParameterBuilder extends ModifierBuilderImpl
171172
// needed to generated noSuchMethod forwarders.
172173
bool isConstConstructorParameter = false;
173174
if (parent is ConstructorBuilder) {
174-
ConstructorBuilder constructorBuilder = parent;
175-
isConstConstructorParameter = constructorBuilder.constructor.isConst;
175+
isConstConstructorParameter = parent.isConst;
176+
} else if (parent is ProcedureBuilder) {
177+
isConstConstructorParameter = parent.isFactory && parent.isConst;
176178
}
177179
if ((isConstConstructorParameter || parent.isClassInstanceMember) &&
178180
initializerToken != null) {

pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,25 +1843,34 @@ class ConstantEvaluator extends RecursiveVisitor<Constant> {
18431843
return reportInvalid(node, 'Variable get of a non-const variable.');
18441844
}
18451845

1846+
/// Computes the constant for [expression] defined in the context of [member].
1847+
///
1848+
/// This compute the constant as seen in the current evaluation mode even when
1849+
/// the constant is defined in a library compiled with the agnostic evaluation
1850+
/// mode.
1851+
Constant _evaluateExpressionInContext(Member member, Expression expression) {
1852+
StaticTypeContext oldStaticTypeContext = _staticTypeContext;
1853+
_staticTypeContext = new StaticTypeContext(member, typeEnvironment);
1854+
Constant constant = runInsideContext(member, () {
1855+
Constant constant = _evaluateSubexpression(expression);
1856+
if (_staticTypeContext.nonNullableByDefaultCompiledMode ==
1857+
NonNullableByDefaultCompiledMode.Agnostic &&
1858+
evaluationMode == EvaluationMode.weak) {
1859+
constant = _weakener.visitConstant(constant) ?? constant;
1860+
}
1861+
return constant;
1862+
});
1863+
_staticTypeContext = oldStaticTypeContext;
1864+
return constant;
1865+
}
1866+
18461867
@override
18471868
Constant visitStaticGet(StaticGet node) {
18481869
return withNewEnvironment(() {
18491870
final Member target = node.target;
18501871
if (target is Field) {
18511872
if (target.isConst) {
1852-
StaticTypeContext oldStaticTypeContext = _staticTypeContext;
1853-
_staticTypeContext = new StaticTypeContext(target, typeEnvironment);
1854-
Constant constant = runInsideContext(target, () {
1855-
Constant constant = _evaluateSubexpression(target.initializer);
1856-
if (_staticTypeContext.nonNullableByDefaultCompiledMode ==
1857-
NonNullableByDefaultCompiledMode.Agnostic &&
1858-
evaluationMode == EvaluationMode.weak) {
1859-
constant = _weakener.visitConstant(constant) ?? constant;
1860-
}
1861-
return constant;
1862-
});
1863-
_staticTypeContext = oldStaticTypeContext;
1864-
return constant;
1873+
return _evaluateExpressionInContext(target, target.initializer);
18651874
}
18661875
return report(
18671876
node,
@@ -1932,6 +1941,77 @@ class ConstantEvaluator extends RecursiveVisitor<Constant> {
19321941
return canonicalize(new StringConstant(concatenated.single.toString()));
19331942
}
19341943

1944+
Constant _getFromEnvironmentDefaultValue(Procedure target) {
1945+
VariableDeclaration variable = target.function.namedParameters
1946+
.singleWhere((v) => v.name == 'defaultValue');
1947+
return variable.initializer != null
1948+
? _evaluateExpressionInContext(target, variable.initializer)
1949+
: nullConstant;
1950+
}
1951+
1952+
Constant _handleFromEnvironment(
1953+
Procedure target, StringConstant name, Map<String, Constant> named) {
1954+
String value = environmentDefines[name.value];
1955+
Constant defaultValue = named["defaultValue"];
1956+
if (target.enclosingClass == coreTypes.boolClass) {
1957+
Constant boolConstant;
1958+
if (value == "true") {
1959+
boolConstant = trueConstant;
1960+
} else if (value == "false") {
1961+
boolConstant = falseConstant;
1962+
} else if (defaultValue != null) {
1963+
if (defaultValue is BoolConstant) {
1964+
boolConstant = makeBoolConstant(defaultValue.value);
1965+
} else if (defaultValue is NullConstant) {
1966+
boolConstant = nullConstant;
1967+
} else {
1968+
boolConstant = falseConstant;
1969+
}
1970+
} else {
1971+
boolConstant = _getFromEnvironmentDefaultValue(target);
1972+
}
1973+
return boolConstant;
1974+
} else if (target.enclosingClass == coreTypes.intClass) {
1975+
int intValue = value != null ? int.tryParse(value) : null;
1976+
Constant intConstant;
1977+
if (intValue != null) {
1978+
bool negated = value.startsWith('-');
1979+
intConstant = intFolder.makeIntConstant(intValue, unsigned: !negated);
1980+
} else if (defaultValue != null) {
1981+
if (intFolder.isInt(defaultValue)) {
1982+
intConstant = defaultValue;
1983+
} else {
1984+
intConstant = nullConstant;
1985+
}
1986+
} else {
1987+
intConstant = _getFromEnvironmentDefaultValue(target);
1988+
}
1989+
return canonicalize(intConstant);
1990+
} else if (target.enclosingClass == coreTypes.stringClass) {
1991+
Constant stringConstant;
1992+
if (value != null) {
1993+
stringConstant = canonicalize(new StringConstant(value));
1994+
} else if (defaultValue != null) {
1995+
if (defaultValue is StringConstant) {
1996+
stringConstant = defaultValue;
1997+
} else {
1998+
stringConstant = nullConstant;
1999+
}
2000+
} else {
2001+
stringConstant = _getFromEnvironmentDefaultValue(target);
2002+
}
2003+
return stringConstant;
2004+
}
2005+
throw new UnsupportedError(
2006+
'Unexpected fromEnvironment constructor: $target');
2007+
}
2008+
2009+
Constant _handleHasEnvironment(StringConstant name) {
2010+
return environmentDefines.containsKey(name.value)
2011+
? trueConstant
2012+
: falseConstant;
2013+
}
2014+
19352015
@override
19362016
Constant visitStaticInvocation(StaticInvocation node) {
19372017
final Procedure target = node.target;
@@ -1947,45 +2027,18 @@ class ConstantEvaluator extends RecursiveVisitor<Constant> {
19472027
}
19482028
if (target.kind == ProcedureKind.Factory) {
19492029
if (target.isConst &&
1950-
target.name.name == "fromEnvironment" &&
19512030
target.enclosingLibrary == coreTypes.coreLibrary &&
1952-
positionals.length == 1) {
2031+
positionals.length == 1 &&
2032+
(target.name.name == "fromEnvironment" ||
2033+
target.name.name == "hasEnvironment")) {
19532034
if (environmentDefines != null) {
19542035
// Evaluate environment constant.
19552036
Constant name = positionals.single;
19562037
if (name is StringConstant) {
1957-
String value = environmentDefines[name.value];
1958-
Constant defaultValue = named["defaultValue"];
1959-
1960-
if (target.enclosingClass == coreTypes.boolClass) {
1961-
Constant boolConstant = value == "true"
1962-
? trueConstant
1963-
: value == "false"
1964-
? falseConstant
1965-
: defaultValue is BoolConstant
1966-
? makeBoolConstant(defaultValue.value)
1967-
: defaultValue is NullConstant
1968-
? nullConstant
1969-
: falseConstant;
1970-
return boolConstant;
1971-
} else if (target.enclosingClass == coreTypes.intClass) {
1972-
int intValue = value != null ? int.tryParse(value) : null;
1973-
Constant intConstant;
1974-
if (intValue != null) {
1975-
bool negated = value.startsWith('-');
1976-
intConstant =
1977-
intFolder.makeIntConstant(intValue, unsigned: !negated);
1978-
} else if (intFolder.isInt(defaultValue)) {
1979-
intConstant = defaultValue;
1980-
} else {
1981-
intConstant = nullConstant;
1982-
}
1983-
return canonicalize(intConstant);
1984-
} else if (target.enclosingClass == coreTypes.stringClass) {
1985-
value ??=
1986-
defaultValue is StringConstant ? defaultValue.value : null;
1987-
if (value == null) return nullConstant;
1988-
return canonicalize(new StringConstant(value));
2038+
if (target.name.name == "fromEnvironment") {
2039+
return _handleFromEnvironment(target, name, named);
2040+
} else {
2041+
return _handleHasEnvironment(name);
19892042
}
19902043
} else if (name is NullConstant) {
19912044
return report(node, messageConstEvalNullValue);

pkg/vm/bin/kernel_service.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,20 @@ class CompilerResult {
250250
// new String.fromEnvironment, since the VM currently does not support providing
251251
// the full (isolate specific) environment as a finite, static map.
252252
class EnvironmentMap extends UnmodifiableMapBase<String, String> {
253+
@override
254+
bool containsKey(Object key) {
255+
return new bool.hasEnvironment(key);
256+
}
257+
253258
@override
254259
String operator [](Object key) {
255260
// The fromEnvironment constructor is specified to throw when called using
256261
// new. However, the VM implementation actually looks up the given name in
257262
// the environment.
258-
return new String.fromEnvironment(key);
263+
if (containsKey(key)) {
264+
return new String.fromEnvironment(key);
265+
}
266+
return null;
259267
}
260268

261269
@override

0 commit comments

Comments
 (0)