[cfe] Eliminate Nullability.legacy in transformers

Nullability.legacy is replaced with an appropriate invocation of a
method on Library to retrieve the appropriate nullability.  Only
transformers in pkg/kernel and pkg/front_end are affected.  The
inference transformers are excluded from the scope of this CL.

Change-Id: I691c4343def913388a1277227b760fd7e1aa194c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/125666
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Dmitry Stefantsov 2019-11-21 09:12:05 +00:00 committed by commit-bot@chromium.org
parent 539b0093e1
commit f692a2fbb8
11 changed files with 217 additions and 63 deletions

View file

@ -238,7 +238,7 @@ class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
Not wrapper = new Not(initializer);
SourceLoader loader = library.loader;
loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
bodyBuilder.transformCollections);
bodyBuilder.transformCollections, library.library);
initializer = wrapper.operand;
}
buildBody(initializer);

View file

@ -184,8 +184,11 @@ class FormalParameterBuilder extends ModifierBuilderImpl
variable.initializer = initializer..parent = variable;
if (library.loader is SourceLoader) {
SourceLoader loader = library.loader;
loader.transformPostInference(variable,
bodyBuilder.transformSetLiterals, bodyBuilder.transformCollections);
loader.transformPostInference(
variable,
bodyBuilder.transformSetLiterals,
bodyBuilder.transformCollections,
library.library);
}
initializerWasInferred = true;
bodyBuilder.resolveRedirectingFactoryTargets();

View file

@ -553,8 +553,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
void inferAnnotations(TreeNode parent, List<Expression> annotations) {
if (annotations != null) {
typeInferrer?.inferMetadata(this, parent, annotations);
libraryBuilder.loader.transformListPostInference(
annotations, transformSetLiterals, transformCollections);
libraryBuilder.loader.transformListPostInference(annotations,
transformSetLiterals, transformCollections, libraryBuilder.library);
}
}
@ -692,7 +692,10 @@ class BodyBuilder extends ScopeListener<JumpTarget>
// transformations need a parent relation.
Not wrapper = new Not(initializer);
libraryBuilder.loader.transformPostInference(
wrapper, transformSetLiterals, transformCollections);
wrapper,
transformSetLiterals,
transformCollections,
libraryBuilder.library);
initializer = wrapper.operand;
}
fieldBuilder.buildBody(initializer);
@ -869,7 +872,10 @@ class BodyBuilder extends ScopeListener<JumpTarget>
this, initializer, originParameter.type);
originParameter.initializer = initializer..parent = originParameter;
libraryBuilder.loader.transformPostInference(
originParameter, transformSetLiterals, transformCollections);
originParameter,
transformSetLiterals,
transformCollections,
libraryBuilder.library);
}
VariableDeclaration extensionTearOffParameter =
@ -882,7 +888,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
libraryBuilder.loader.transformPostInference(
extensionTearOffParameter,
transformSetLiterals,
transformCollections);
transformCollections,
libraryBuilder.library);
}
}
}
@ -894,8 +901,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
asyncModifier,
builder.member.function,
body);
libraryBuilder.loader.transformPostInference(
body, transformSetLiterals, transformCollections);
libraryBuilder.loader.transformPostInference(body, transformSetLiterals,
transformCollections, libraryBuilder.library);
}
if (builder.returnType != null) {
@ -1351,8 +1358,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
constructor.initializers.add(initializer);
}
setParents(constructor.initializers, constructor);
libraryBuilder.loader.transformListPostInference(
constructor.initializers, transformSetLiterals, transformCollections);
libraryBuilder.loader.transformListPostInference(constructor.initializers,
transformSetLiterals, transformCollections, libraryBuilder.library);
if (constructor.function.body == null) {
/// >If a generative constructor c is not a redirecting constructor
/// >and no body is provided, then c implicitly has an empty body {}.

View file

@ -24,6 +24,7 @@ import 'package:kernel/ast.dart'
IfStatement,
InterfaceType,
Let,
Library,
ListConcatenation,
ListLiteral,
MapConcatenation,
@ -32,7 +33,6 @@ import 'package:kernel/ast.dart'
MethodInvocation,
Name,
Not,
Nullability,
NullLiteral,
Procedure,
PropertyGet,
@ -85,6 +85,12 @@ class CollectionTransformer extends Transformer {
final Field mapEntryValue;
final SourceLoaderDataForTesting dataForTesting;
/// Library that contains the transformed nodes.
///
/// The transformation of the nodes is affected by the NNBD opt-in status of
/// the library.
Library _currentLibrary;
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
RedirectingFactoryBody body = factory?.function?.body;
@ -132,13 +138,13 @@ class CollectionTransformer extends Transformer {
new StaticInvocation(
setFactory, new Arguments([], types: [elementType])),
type: new InterfaceType(
coreTypes.setClass, Nullability.legacy, [elementType]),
coreTypes.setClass, _currentLibrary.nonNullable, [elementType]),
isFinal: true);
} else {
result = new VariableDeclaration.forValue(
new ListLiteral([], typeArgument: elementType),
type: new InterfaceType(
coreTypes.listClass, Nullability.legacy, [elementType]),
coreTypes.listClass, _currentLibrary.nonNullable, [elementType]),
isFinal: true);
}
List<Statement> body = [result];
@ -335,7 +341,7 @@ class CollectionTransformer extends Transformer {
// Build a block expression and create an empty map.
VariableDeclaration result = new VariableDeclaration.forValue(
new MapLiteral([], keyType: node.keyType, valueType: node.valueType),
type: new InterfaceType(coreTypes.mapClass, Nullability.legacy,
type: new InterfaceType(coreTypes.mapClass, _currentLibrary.nonNullable,
[node.keyType, node.valueType]),
isFinal: true);
List<Statement> body = [result];
@ -448,14 +454,16 @@ class CollectionTransformer extends Transformer {
}
DartType entryType = new InterfaceType(
mapEntryClass, Nullability.legacy, <DartType>[keyType, valueType]);
mapEntryClass,
_currentLibrary.nullableIfTrue(entry.isNullAware),
<DartType>[keyType, valueType]);
VariableDeclaration elt;
Statement loopBody;
if (entry.entryType == null ||
!typeEnvironment.isSubtypeOf(entry.entryType, entryType,
SubtypeCheckMode.ignoringNullabilities)) {
elt = new VariableDeclaration(null,
type: new InterfaceType(mapEntryClass, Nullability.legacy,
type: new InterfaceType(mapEntryClass, _currentLibrary.nonNullable,
<DartType>[const DynamicType(), const DynamicType()]),
isFinal: true);
VariableDeclaration keyVar = new VariableDeclaration.forValue(
@ -653,4 +661,18 @@ class CollectionTransformer extends Transformer {
return new MapConcatenation(parts,
keyType: node.keyType, valueType: node.valueType);
}
void enterLibrary(Library library) {
assert(
_currentLibrary == null,
"Attempting to enter library '${library.fileUri}' "
"without having exited library '${_currentLibrary.fileUri}'.");
_currentLibrary = library;
}
void exitLibrary() {
assert(_currentLibrary != null,
"Attempting to exit a library without having entered one.");
_currentLibrary = null;
}
}

View file

@ -12,9 +12,9 @@ import 'package:kernel/ast.dart'
Expression,
InterfaceType,
Let,
Library,
MethodInvocation,
Name,
Nullability,
Procedure,
SetLiteral,
StaticInvocation,
@ -36,6 +36,12 @@ class SetLiteralTransformer extends Transformer {
final Procedure setFactory;
final Procedure addMethod;
/// Library that contains the transformed nodes.
///
/// The transformation of the nodes is affected by the NNBD opt-in status of
/// the library.
Library _currentLibrary;
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
RedirectingFactoryBody body = factory?.function?.body;
@ -58,8 +64,8 @@ class SetLiteralTransformer extends Transformer {
VariableDeclaration setVar = new VariableDeclaration.forValue(
new StaticInvocation(
setFactory, new Arguments([], types: [node.typeArgument])),
type: new InterfaceType(
coreTypes.setClass, Nullability.legacy, [node.typeArgument]));
type: new InterfaceType(coreTypes.setClass, _currentLibrary.nonNullable,
[node.typeArgument]));
// Innermost body of let chain: setVar
Expression setExp = new VariableGet(setVar);
for (int i = node.expressions.length - 1; i >= 0; i--) {
@ -75,4 +81,18 @@ class SetLiteralTransformer extends Transformer {
}
return new Let(setVar, setExp);
}
void enterLibrary(Library library) {
assert(
_currentLibrary == null,
"Attempting to enter library '${library.fileUri}' "
"without having exited library '${_currentLibrary.fileUri}'.");
_currentLibrary = library;
}
void exitLibrary() {
assert(_currentLibrary != null,
"Attempting to exit a library without having entered one.");
_currentLibrary = null;
}
}

View file

@ -1046,31 +1046,44 @@ class SourceLoader extends Loader {
ticker.logMs("Performed top level inference");
}
void transformPostInference(
TreeNode node, bool transformSetLiterals, bool transformCollections) {
void transformPostInference(TreeNode node, bool transformSetLiterals,
bool transformCollections, Library clientLibrary) {
if (transformCollections) {
node.accept(collectionTransformer ??= new CollectionTransformer(this));
collectionTransformer ??= new CollectionTransformer(this);
collectionTransformer.enterLibrary(clientLibrary);
node.accept(collectionTransformer);
collectionTransformer.exitLibrary();
}
if (transformSetLiterals) {
node.accept(setLiteralTransformer ??= new SetLiteralTransformer(this));
setLiteralTransformer ??= new SetLiteralTransformer(this);
setLiteralTransformer.enterLibrary(clientLibrary);
node.accept(setLiteralTransformer);
setLiteralTransformer.exitLibrary();
}
}
void transformListPostInference(List<TreeNode> list,
bool transformSetLiterals, bool transformCollections) {
void transformListPostInference(
List<TreeNode> list,
bool transformSetLiterals,
bool transformCollections,
Library clientLibrary) {
if (transformCollections) {
CollectionTransformer transformer =
collectionTransformer ??= new CollectionTransformer(this);
transformer.enterLibrary(clientLibrary);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
transformer.exitLibrary();
}
if (transformSetLiterals) {
SetLiteralTransformer transformer =
setLiteralTransformer ??= new SetLiteralTransformer(this);
transformer.enterLibrary(clientLibrary);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
transformer.exitLibrary();
}
}

View file

@ -73,6 +73,7 @@ advances
advancing
advice
affect
affected
affects
after
again

View file

@ -78,7 +78,18 @@ class ExpressionLifter extends Transformer {
final VariableDeclaration asyncResult = new VariableDeclaration(':result');
final List<VariableDeclaration> variables = <VariableDeclaration>[];
ExpressionLifter(this.continuationRewriter);
/// Library that contains the transformed nodes.
///
/// The transformation of the nodes is affected by the NNBD opt-in status of
/// the library.
Library _currentLibrary;
ExpressionLifter(this.continuationRewriter, this._currentLibrary) {
assert(
_currentLibrary != null,
"Attempting to create an expression lifter "
"without the client library.");
}
Block blockOf(List<Statement> statements) {
return new Block(statements.reversed.toList());
@ -506,7 +517,10 @@ class ExpressionLifter extends Transformer {
visitFunctionNode(FunctionNode node) {
var nestedRewriter =
new RecursiveContinuationRewriter(continuationRewriter.helper);
return node.accept(nestedRewriter);
nestedRewriter.enterLibrary(_currentLibrary);
TreeNode result = node.accept(nestedRewriter);
nestedRewriter.exitLibrary();
return result;
}
TreeNode visitBlockExpression(BlockExpression expr) {

View file

@ -45,7 +45,10 @@ Procedure transformProcedure(CoreTypes coreTypes, Procedure procedure,
{bool productMode}) {
var helper = new HelperNodes.fromCoreTypes(coreTypes, productMode);
var rewriter = new RecursiveContinuationRewriter(helper);
return rewriter.visitProcedure(procedure);
rewriter.enterLibrary(procedure.enclosingLibrary);
Procedure result = rewriter.visitProcedure(procedure);
rewriter.exitLibrary();
return result;
}
class RecursiveContinuationRewriter extends Transformer {
@ -57,6 +60,12 @@ class RecursiveContinuationRewriter extends Transformer {
final VariableDeclaration asyncContextVariable =
new VariableDeclaration(ContinuationVariables.awaitContextVar);
/// Library that contains the transformed nodes.
///
/// The transformation of the nodes is affected by the NNBD opt-in status of
/// the library.
Library _currentLibrary;
RecursiveContinuationRewriter(this.helper);
Component rewriteComponent(Component node) {
@ -67,26 +76,54 @@ class RecursiveContinuationRewriter extends Transformer {
return node.accept<TreeNode>(this);
}
@override
visitLibrary(Library node) {
enterLibrary(node);
Library result = super.visitLibrary(node);
exitLibrary();
return result;
}
@override
visitProcedure(Procedure node) {
return node.isAbstract ? node : super.visitProcedure(node);
}
@override
visitFunctionNode(FunctionNode node) {
switch (node.asyncMarker) {
case AsyncMarker.Sync:
case AsyncMarker.SyncYielding:
node.transformChildren(new RecursiveContinuationRewriter(helper));
node.transformChildren(new RecursiveContinuationRewriter(helper)
..enterLibrary(_currentLibrary));
return node;
case AsyncMarker.SyncStar:
return new SyncStarFunctionRewriter(helper, node).rewrite();
return new SyncStarFunctionRewriter(helper, node, _currentLibrary)
.rewrite();
case AsyncMarker.Async:
return new AsyncFunctionRewriter(helper, node).rewrite();
return new AsyncFunctionRewriter(helper, node, _currentLibrary)
.rewrite();
case AsyncMarker.AsyncStar:
return new AsyncStarFunctionRewriter(helper, node).rewrite();
return new AsyncStarFunctionRewriter(helper, node, _currentLibrary)
.rewrite();
default:
return null;
}
}
void enterLibrary(Library library) {
assert(
_currentLibrary == null,
"Attempting to enter library '${library.fileUri}' "
"without having exited library '${_currentLibrary.fileUri}'.");
_currentLibrary = library;
}
void exitLibrary() {
assert(_currentLibrary != null,
"Attempting to exit a library without having entered one.");
_currentLibrary = null;
}
}
abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
@ -97,8 +134,15 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
int capturedTryDepth = 0; // Deepest yield point within a try-block.
int capturedCatchDepth = 0; // Deepest yield point within a catch-block.
ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction)
: super(helper);
ContinuationRewriterBase(
HelperNodes helper, this.enclosingFunction, Library enclosingLibrary)
: super(helper) {
assert(
enclosingLibrary != null,
"Attempting to create a continuation rewriter "
"without the client library.");
_currentLibrary = enclosingLibrary;
}
/// Given a container [type], which is an instantiation of the given
/// [containerClass] extract its element type.
@ -184,14 +228,15 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
class SyncStarFunctionRewriter extends ContinuationRewriterBase {
final VariableDeclaration iteratorVariable;
SyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
SyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
Library enclosingLibrary)
: iteratorVariable = new VariableDeclaration(':iterator')
..type =
new InterfaceType(helper.syncIteratorClass, Nullability.legacy, [
..type = new InterfaceType(
helper.syncIteratorClass, enclosingLibrary.nullable, [
ContinuationRewriterBase.elementTypeFrom(
helper.iterableClass, enclosingFunction.returnType)
]),
super(helper, enclosingFunction);
super(helper, enclosingFunction, enclosingLibrary);
FunctionNode rewrite() {
// :sync_op(:iterator) {
@ -286,11 +331,12 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
ExpressionLifter expressionRewriter;
AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction)
: super(helper, enclosingFunction) {}
AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction,
Library enclosingLibrary)
: super(helper, enclosingFunction, enclosingLibrary);
void setupAsyncContinuations(List<Statement> statements) {
expressionRewriter = new ExpressionLifter(this);
expressionRewriter = new ExpressionLifter(this, _currentLibrary);
// var :async_stack_trace;
statements.add(stackTraceVariable);
@ -751,7 +797,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
new Arguments(<Expression>[new VariableGet(streamVariable)],
types: [valueVariable.type])),
type: new InterfaceType(helper.streamIteratorClass,
Nullability.legacy, [valueVariable.type]));
_currentLibrary.nullable, [valueVariable.type]));
// await :for-iterator.moveNext()
var condition = new AwaitExpression(new MethodInvocation(
@ -905,8 +951,9 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
class AsyncStarFunctionRewriter extends AsyncRewriterBase {
VariableDeclaration controllerVariable;
AsyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
: super(helper, enclosingFunction);
AsyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
Library enclosingLibrary)
: super(helper, enclosingFunction, enclosingLibrary);
FunctionNode rewrite() {
var statements = <Statement>[];
@ -916,7 +963,7 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
// _AsyncStarStreamController<T> :controller;
controllerVariable = new VariableDeclaration(":controller",
type: new InterfaceType(helper.asyncStarStreamControllerClass,
Nullability.legacy, [elementType]));
_currentLibrary.nullable, [elementType]));
statements.add(controllerVariable);
// dynamic :controller_stream;
@ -1022,8 +1069,9 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
VariableDeclaration completerVariable;
VariableDeclaration returnVariable;
AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
: super(helper, enclosingFunction);
AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
Library enclosingLibrary)
: super(helper, enclosingFunction, enclosingLibrary);
FunctionNode rewrite() {
var statements = <Statement>[];
@ -1038,11 +1086,11 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
valueType = elementTypeFromReturnType(helper.futureOrClass);
}
final DartType returnType = new InterfaceType(
helper.futureOrClass, Nullability.legacy, <DartType>[valueType]);
helper.futureOrClass, _currentLibrary.nullable, <DartType>[valueType]);
var completerTypeArguments = <DartType>[valueType];
final completerType = new InterfaceType(helper.asyncAwaitCompleterClass,
Nullability.legacy, completerTypeArguments);
_currentLibrary.nonNullable, completerTypeArguments);
// final Completer<T> :async_completer = new _AsyncAwaitCompleter<T>();
completerVariable = new VariableDeclaration(":async_completer",
initializer: new ConstructorInvocation(

View file

@ -129,6 +129,12 @@ class _WidgetCallSiteTransformer extends Transformer {
WidgetCreatorTracker _tracker;
/// Library that contains the transformed call sites.
///
/// The transformation of the call sites is affected by the NNBD opt-in status
/// of the library.
Library _currentLibrary;
_WidgetCallSiteTransformer(
{@required Class widgetClass,
@required Class locationClass,
@ -271,11 +277,26 @@ class _WidgetCallSiteTransformer extends Transformer {
location,
parameterLocations: new ListLiteral(
parameterLocations,
typeArgument: new InterfaceType(_locationClass, Nullability.legacy),
typeArgument:
new InterfaceType(_locationClass, _currentLibrary.nonNullable),
isConst: true,
),
);
}
void enterLibrary(Library library) {
assert(
_currentLibrary == null,
"Attempting to enter library '${library.fileUri}' "
"without having exited library '${_currentLibrary.fileUri}'.");
_currentLibrary = library;
}
void exitLibrary() {
assert(_currentLibrary != null,
"Attempting to exit a library without having entered one.");
_currentLibrary = null;
}
}
/// Rewrites all widget constructors and constructor invocations to add a
@ -345,7 +366,8 @@ class WidgetCreatorTracker {
_hasCreationLocationClass.enclosingLibrary,
);
final Field locationField = new Field(fieldName,
type: new InterfaceType(_locationClass, Nullability.legacy),
type: new InterfaceType(
_locationClass, clazz.enclosingLibrary.nonNullable),
isFinal: true,
reference: clazz.reference.canonicalName
?.getChildFromFieldWithName(fieldName)
@ -365,7 +387,8 @@ class WidgetCreatorTracker {
));
final VariableDeclaration variable = new VariableDeclaration(
_creationLocationParameterName,
type: new InterfaceType(_locationClass, Nullability.legacy),
type: new InterfaceType(
_locationClass, clazz.enclosingLibrary.nonNullable),
);
if (!_maybeAddNamedParameter(constructor.function, variable)) {
return;
@ -458,7 +481,9 @@ class WidgetCreatorTracker {
if (library.isExternal) {
continue;
}
callsiteTransformer.enterLibrary(library);
library.transformChildren(callsiteTransformer);
callsiteTransformer.exitLibrary();
}
}
@ -497,10 +522,10 @@ class WidgetCreatorTracker {
if (procedure.isFactory) {
_maybeAddNamedParameter(
procedure.function,
new VariableDeclaration(
_creationLocationParameterName,
type: new InterfaceType(_locationClass, Nullability.legacy),
),
new VariableDeclaration(_creationLocationParameterName,
type: new InterfaceType(
_locationClass, clazz.enclosingLibrary.nonNullable),
isRequired: clazz.enclosingLibrary.isNonNullableByDefault),
);
}
}
@ -521,9 +546,10 @@ class WidgetCreatorTracker {
}
final VariableDeclaration variable = new VariableDeclaration(
_creationLocationParameterName,
type: new InterfaceType(_locationClass, Nullability.legacy),
);
_creationLocationParameterName,
type: new InterfaceType(
_locationClass, clazz.enclosingLibrary.nonNullable),
isRequired: clazz.enclosingLibrary.isNonNullableByDefault);
if (_hasNamedParameter(
constructor.function, _creationLocationParameterName)) {
// Constructor was already rewritten. TODO(jacobr): is this case actually hit?

View file

@ -438,7 +438,7 @@ class TypeCheckingVisitor
handleCall(arguments, target.function.thisFunctionType,
typeParameters: class_.typeParameters);
return new InterfaceType(
target.enclosingClass, Nullability.legacy, arguments.types);
target.enclosingClass, currentLibrary.nonNullable, arguments.types);
}
@override
@ -748,7 +748,7 @@ class TypeCheckingVisitor
checkAssignable(node, fieldType, valueType);
});
return new InterfaceType(
node.classNode, Nullability.legacy, node.typeArguments);
node.classNode, currentLibrary.nonNullable, node.typeArguments);
}
@override