Skip to content

Commit a56b4ee

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
authored andcommitted
[cfe] Thread nullability from source for function types
Closes #38216. Bug: http://dartbug.com/38216 Change-Id: I33def8e24555099a74fae04d658cbde7af08d7c1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117727 Commit-Queue: Dmitry Stefantsov <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 0c94852 commit a56b4ee

18 files changed

+228
-41
lines changed

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
library fasta.function_type_builder;
66

7-
import 'builder.dart' show LibraryBuilder, TypeBuilder, TypeVariableBuilder;
7+
import 'builder.dart'
8+
show LibraryBuilder, NullabilityBuilder, TypeBuilder, TypeVariableBuilder;
89

910
import 'package:kernel/ast.dart'
1011
show
@@ -32,8 +33,10 @@ class FunctionTypeBuilder extends TypeBuilder {
3233
final TypeBuilder returnType;
3334
final List<TypeVariableBuilder> typeVariables;
3435
final List<FormalParameterBuilder> formals;
36+
final NullabilityBuilder nullabilityBuilder;
3537

36-
FunctionTypeBuilder(this.returnType, this.typeVariables, this.formals);
38+
FunctionTypeBuilder(this.returnType, this.typeVariables, this.formals,
39+
this.nullabilityBuilder);
3740

3841
@override
3942
String get name => null;
@@ -68,7 +71,9 @@ class FunctionTypeBuilder extends TypeBuilder {
6871
buffer.write(t?.fullNameForErrors);
6972
}
7073
}
71-
buffer.write(") -> ");
74+
buffer.write(") ->");
75+
nullabilityBuilder.writeNullabilityOn(buffer);
76+
buffer.write(" ");
7277
buffer.write(returnType?.fullNameForErrors);
7378
return buffer;
7479
}
@@ -106,7 +111,8 @@ class FunctionTypeBuilder extends TypeBuilder {
106111
namedParameters: namedParameters ?? const <NamedType>[],
107112
typeParameters: typeParameters ?? const <TypeParameter>[],
108113
requiredParameterCount: requiredParameterCount,
109-
typedefType: origin);
114+
typedefType: origin,
115+
nullability: nullabilityBuilder.build(library));
110116
}
111117

112118
Supertype buildSupertype(
@@ -143,7 +149,10 @@ class FunctionTypeBuilder extends TypeBuilder {
143149
}
144150
}
145151
FunctionTypeBuilder newType = new FunctionTypeBuilder(
146-
returnType?.clone(newTypes), clonedTypeVariables, clonedFormals);
152+
returnType?.clone(newTypes),
153+
clonedTypeVariables,
154+
clonedFormals,
155+
nullabilityBuilder);
147156
newTypes.add(newType);
148157
return newType;
149158
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ class NullabilityBuilder {
3535
const NullabilityBuilder.omitted()
3636
: _syntacticNullability = SyntacticNullability.omitted;
3737

38+
factory NullabilityBuilder.fromNullability(Nullability nullability) {
39+
switch (nullability) {
40+
case Nullability.nullable:
41+
return const NullabilityBuilder.nullable();
42+
case Nullability.legacy:
43+
return const NullabilityBuilder.legacy();
44+
case Nullability.nonNullable:
45+
case Nullability.neither:
46+
default:
47+
return const NullabilityBuilder.omitted();
48+
}
49+
}
50+
3851
/// Used temporarily in the places that need proper handling of NNBD features.
3952
///
4053
/// Over time the uses of [NullabilityBuilder.pendingImplementation] should be

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

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2835,7 +2835,10 @@ class BodyBuilder extends ScopeListener<JumpTarget>
28352835
FormalParameters formals = pop();
28362836
UnresolvedType returnType = pop();
28372837
List<TypeVariableBuilder> typeVariables = pop();
2838-
UnresolvedType type = formals.toFunctionType(returnType, typeVariables);
2838+
UnresolvedType type = formals.toFunctionType(
2839+
returnType,
2840+
libraryBuilder.computeNullabilityFromToken(questionMark != null),
2841+
typeVariables);
28392842
exitLocalScope();
28402843
push(type);
28412844
}
@@ -3056,7 +3059,10 @@ class BodyBuilder extends ScopeListener<JumpTarget>
30563059
if (!libraryBuilder.loader.target.enableNonNullable) {
30573060
reportErrorIfNullableType(question);
30583061
}
3059-
UnresolvedType type = formals.toFunctionType(returnType, typeVariables);
3062+
UnresolvedType type = formals.toFunctionType(
3063+
returnType,
3064+
libraryBuilder.computeNullabilityFromToken(question != null),
3065+
typeVariables);
30603066
exitLocalScope();
30613067
push(type);
30623068
functionNestingLevel--;
@@ -4046,8 +4052,14 @@ class BodyBuilder extends ScopeListener<JumpTarget>
40464052
if (!isFunctionExpression) {
40474053
annotations = pop(); // Metadata.
40484054
}
4049-
FunctionNode function = formals.buildFunctionNode(libraryBuilder,
4050-
returnType, typeParameters, asyncModifier, body, token.charOffset);
4055+
FunctionNode function = formals.buildFunctionNode(
4056+
libraryBuilder,
4057+
returnType,
4058+
typeParameters,
4059+
asyncModifier,
4060+
body,
4061+
const NullabilityBuilder.pendingImplementation(),
4062+
token.charOffset);
40514063

40524064
if (declaration is FunctionDeclaration) {
40534065
VariableDeclaration variable = declaration.variable;
@@ -4128,8 +4140,14 @@ class BodyBuilder extends ScopeListener<JumpTarget>
41284140
FormalParameters formals = pop();
41294141
exitFunction();
41304142
List<TypeVariableBuilder> typeParameters = pop();
4131-
FunctionNode function = formals.buildFunctionNode(libraryBuilder, null,
4132-
typeParameters, asyncModifier, body, token.charOffset)
4143+
FunctionNode function = formals.buildFunctionNode(
4144+
libraryBuilder,
4145+
null,
4146+
typeParameters,
4147+
asyncModifier,
4148+
body,
4149+
const NullabilityBuilder.pendingImplementation(),
4150+
token.charOffset)
41334151
..fileOffset = beginToken.charOffset;
41344152

41354153
if (constantContext != ConstantContext.none) {
@@ -5545,9 +5563,12 @@ class FormalParameters {
55455563
List<TypeVariableBuilder> typeParameters,
55465564
AsyncMarker asyncModifier,
55475565
Statement body,
5566+
NullabilityBuilder nullabilityBuilder,
55485567
int fileEndOffset) {
55495568
FunctionType type =
5550-
toFunctionType(returnType, typeParameters).builder.build(library);
5569+
toFunctionType(returnType, nullabilityBuilder, typeParameters)
5570+
.builder
5571+
.build(library);
55515572
List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
55525573
List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
55535574
if (parameters != null) {
@@ -5573,11 +5594,12 @@ class FormalParameters {
55735594
..fileEndOffset = fileEndOffset;
55745595
}
55755596

5576-
UnresolvedType toFunctionType(UnresolvedType returnType,
5597+
UnresolvedType toFunctionType(
5598+
UnresolvedType returnType, NullabilityBuilder nullabilityBuilder,
55775599
[List<TypeVariableBuilder> typeParameters]) {
55785600
return new UnresolvedType(
5579-
new FunctionTypeBuilder(
5580-
returnType?.builder, typeParameters, parameters),
5601+
new FunctionTypeBuilder(returnType?.builder, typeParameters, parameters,
5602+
nullabilityBuilder),
55815603
charOffset,
55825604
uri);
55835605
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ TypeBuilder substituteRange(
209209
}
210210

211211
if (changed) {
212-
return new FunctionTypeBuilder(returnType, variables, formals);
212+
return new FunctionTypeBuilder(
213+
returnType, variables, formals, type.nullabilityBuilder);
213214
}
214215

215216
return type;

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,17 @@ class TypeBuilderComputer implements DartTypeVisitor<TypeBuilder> {
114114
new FormalParameterBuilder(null, 0, type, parameter.name, null, -1)
115115
..kind = FormalParameterKind.optionalNamed;
116116
}
117-
118-
return new FunctionTypeBuilder(returnType, typeVariables, formals);
117+
return new FunctionTypeBuilder(returnType, typeVariables, formals,
118+
new NullabilityBuilder.fromNullability(node.nullability));
119119
}
120120

121121
TypeBuilder visitTypeParameterType(TypeParameterType node) {
122122
TypeParameter parameter = node.parameter;
123123
Class kernelClass = parameter.parent;
124124
Library kernelLibrary = kernelClass.enclosingLibrary;
125125
LibraryBuilder library = loader.builders[kernelLibrary.importUri];
126-
// TODO(dmitryas): Compute the nullabilityBuilder field for the result from
127-
// the nullability field of 'node'.
128-
return new NamedTypeBuilder(
129-
parameter.name, const NullabilityBuilder.pendingImplementation(), null)
126+
return new NamedTypeBuilder(parameter.name,
127+
new NullabilityBuilder.fromNullability(node.nullability), null)
130128
..bind(new TypeVariableBuilder.fromKernel(parameter, library));
131129
}
132130

pkg/front_end/lib/src/fasta/source/outline_builder.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,11 @@ class OutlineBuilder extends StackListener {
13881388
TypeBuilder returnType = pop();
13891389
List<TypeVariableBuilder> typeVariables = pop();
13901390
push(library.addFunctionType(
1391-
returnType, typeVariables, formals, functionToken.charOffset));
1391+
returnType,
1392+
typeVariables,
1393+
formals,
1394+
library.computeNullabilityFromToken(questionMark != null),
1395+
functionToken.charOffset));
13921396
}
13931397

13941398
@override
@@ -1401,8 +1405,8 @@ class OutlineBuilder extends StackListener {
14011405
if (!library.loader.target.enableNonNullable) {
14021406
reportErrorIfNullableType(question);
14031407
}
1404-
push(library.addFunctionType(
1405-
returnType, typeVariables, formals, formalsOffset));
1408+
push(library.addFunctionType(returnType, typeVariables, formals,
1409+
library.computeNullabilityFromToken(question != null), formalsOffset));
14061410
}
14071411

14081412
@override
@@ -1432,8 +1436,9 @@ class OutlineBuilder extends StackListener {
14321436
library.beginNestedDeclaration(
14331437
TypeParameterScopeKind.functionType, "#function_type",
14341438
hasMembers: false);
1435-
functionType =
1436-
library.addFunctionType(returnType, null, formals, charOffset);
1439+
// TODO(dmitryas): Make sure that RHS of typedefs can't have '?'.
1440+
functionType = library.addFunctionType(returnType, null, formals,
1441+
const NullabilityBuilder.omitted(), charOffset);
14371442
} else {
14381443
Object type = pop();
14391444
typeVariables = pop();

pkg/front_end/lib/src/fasta/source/source_library_builder.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,9 +1991,10 @@ class SourceLibraryBuilder extends LibraryBuilder {
19911991
TypeBuilder returnType,
19921992
List<TypeVariableBuilder> typeVariables,
19931993
List<FormalParameterBuilder> formals,
1994+
NullabilityBuilder nullabilityBuilder,
19941995
int charOffset) {
1995-
FunctionTypeBuilder builder =
1996-
new FunctionTypeBuilder(returnType, typeVariables, formals);
1996+
FunctionTypeBuilder builder = new FunctionTypeBuilder(
1997+
returnType, typeVariables, formals, nullabilityBuilder);
19971998
checkTypeVariables(typeVariables, null);
19981999
// Nested declaration began in `OutlineBuilder.beginFunctionType` or
19992000
// `OutlineBuilder.beginFunctionTypedFormalParameter`.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
typedef F = void Function();
6+
7+
void foo() {}
8+
F bar() => foo;
9+
F? baz() => foo;
10+
void Function() hest() => foo;
11+
void Function()? fisk() => foo;
12+
13+
Function()? foobar(Function()? x) => null;
14+
15+
class A<T> {}
16+
class B extends A<Function()?> {
17+
Function()? method(Function()? x) => null;
18+
}
19+
20+
main() {
21+
void Function() g;
22+
void Function()? f = g;
23+
24+
var fBar = bar();
25+
var fBaz = baz();
26+
var fHest = hest();
27+
var fFisk = fisk();
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = () → void;
6+
class A<T extends core::Object* = dynamic> extends core::Object {
7+
synthetic constructor •() → self::A<self::A::T*>*
8+
;
9+
}
10+
class B extends self::A<() →? dynamic> {
11+
synthetic constructor •() → self::B*
12+
;
13+
method method(() →? dynamic x) → () →? dynamic
14+
;
15+
}
16+
static method foo() → void
17+
;
18+
static method bar() → () → void
19+
;
20+
static method baz() → () → void
21+
;
22+
static method hest() → () → void
23+
;
24+
static method fisk() → () →? void
25+
;
26+
static method foobar(() →? dynamic x) → () →? dynamic
27+
;
28+
static method main() → dynamic
29+
;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = () → void;
6+
class A<T extends core::Object* = dynamic> extends core::Object {
7+
synthetic constructor •() → self::A<self::A::T*>*
8+
: super core::Object::•()
9+
;
10+
}
11+
class B extends self::A<() →? dynamic> {
12+
synthetic constructor •() → self::B*
13+
: super self::A::•()
14+
;
15+
method method(() →? dynamic x) → () →? dynamic
16+
return null;
17+
}
18+
static method foo() → void {}
19+
static method bar() → () → void
20+
return #C1;
21+
static method baz() → () → void
22+
return #C1;
23+
static method hest() → () → void
24+
return #C1;
25+
static method fisk() → () →? void
26+
return #C1;
27+
static method foobar(() →? dynamic x) → () →? dynamic
28+
return null;
29+
static method main() → dynamic {
30+
() → void g;
31+
() →? void f = g;
32+
() → void fBar = self::bar();
33+
() → void fBaz = self::baz();
34+
() → void fHest = self::hest();
35+
() →? void fFisk = self::fisk();
36+
}
37+
38+
constants {
39+
#C1 = tearoff self::foo
40+
}

0 commit comments

Comments
 (0)