diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart index 3659c695701..e5681d6b9f4 100644 --- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart @@ -36,6 +36,7 @@ import 'package:kernel/ast.dart' Member, Name, NeverType, + NonNullableByDefaultCompiledMode, Nullability, Procedure, ProcedureKind, @@ -310,6 +311,11 @@ class SourceLibraryBuilder extends LibraryBuilderImpl { super( fileUri, libraryDeclaration.toScope(importScope), new Scope.top()) { library.isNonNullableByDefault = isNonNullableByDefault; + library.nonNullableByDefaultCompiledMode = loader.target.enableNonNullable + ? (loader.nnbdStrongMode + ? NonNullableByDefaultCompiledMode.Strong + : NonNullableByDefaultCompiledMode.Weak) + : NonNullableByDefaultCompiledMode.Disabled; } SourceLibraryBuilder( @@ -958,6 +964,12 @@ class SourceLibraryBuilder extends LibraryBuilderImpl { } library.isNonNullableByDefault = isNonNullableByDefault; + // TODO(CFE Team): Is this really needed in two places? + library.nonNullableByDefaultCompiledMode = loader.target.enableNonNullable + ? (loader.nnbdStrongMode + ? NonNullableByDefaultCompiledMode.Strong + : NonNullableByDefaultCompiledMode.Weak) + : NonNullableByDefaultCompiledMode.Disabled; return library; } diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt index 196b8de9be4..cc5c7df1934 100644 --- a/pkg/front_end/test/spell_checking_list_code.txt +++ b/pkg/front_end/test/spell_checking_list_code.txt @@ -22,6 +22,7 @@ acov across affecting afterwards +agnostic agree ahe ai @@ -97,6 +98,8 @@ bin binder binders binds +bit1 +bit2 bj blob blocking diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md index b6ff1da754c..ce59c925798 100644 --- a/pkg/kernel/binary.md +++ b/pkg/kernel/binary.md @@ -143,7 +143,7 @@ type CanonicalName { type ComponentFile { UInt32 magic = 0x90ABCDEF; - UInt32 formatVersion = 39; + UInt32 formatVersion = 40; List problemsAsJson; // Described in problems.md. Library[] libraries; UriSource sourceMap; @@ -228,7 +228,8 @@ type Name { } type Library { - Byte flags (_unused_, isSynthetic, isNonNullableByDefault); + Byte flags (_unused_, isSynthetic, isNonNullableByDefault, + nnbdModeBit1, nnbdModeBit2); UInt languageVersionMajor; UInt languageVersionMinor; CanonicalNameReference canonicalName; diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart index 141595f9fbf..072b58ccf86 100644 --- a/pkg/kernel/lib/ast.dart +++ b/pkg/kernel/lib/ast.dart @@ -315,6 +315,8 @@ class Reference { // LIBRARIES and CLASSES // ------------------------------------------------------------------------ +enum NonNullableByDefaultCompiledMode { Disabled, Weak, Strong, Agnostic } + class Library extends NamedNode implements Annotatable, Comparable, FileUriNode { /// An import path to this library. @@ -347,6 +349,8 @@ class Library extends NamedNode static const int SyntheticFlag = 1 << 1; static const int NonNullableByDefaultFlag = 1 << 2; + static const int NonNullableByDefaultModeBit1Weak = 1 << 3; + static const int NonNullableByDefaultModeBit2Strong = 1 << 4; int flags = 0; @@ -364,6 +368,38 @@ class Library extends NamedNode : (flags & ~NonNullableByDefaultFlag); } + NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode { + bool weak = (flags & NonNullableByDefaultModeBit1Weak) != 0; + bool strong = (flags & NonNullableByDefaultModeBit2Strong) != 0; + + if (weak && strong) return NonNullableByDefaultCompiledMode.Agnostic; + if (strong) return NonNullableByDefaultCompiledMode.Strong; + if (weak) return NonNullableByDefaultCompiledMode.Weak; + return NonNullableByDefaultCompiledMode.Disabled; + } + + void set nonNullableByDefaultCompiledMode( + NonNullableByDefaultCompiledMode mode) { + switch (mode) { + case NonNullableByDefaultCompiledMode.Disabled: + flags = (flags & ~NonNullableByDefaultModeBit1Weak) & + ~NonNullableByDefaultModeBit2Strong; + break; + case NonNullableByDefaultCompiledMode.Weak: + flags = (flags | NonNullableByDefaultModeBit1Weak) & + ~NonNullableByDefaultModeBit2Strong; + break; + case NonNullableByDefaultCompiledMode.Strong: + flags = (flags & ~NonNullableByDefaultModeBit1Weak) | + NonNullableByDefaultModeBit2Strong; + break; + case NonNullableByDefaultCompiledMode.Agnostic: + flags = (flags | NonNullableByDefaultModeBit1Weak) | + NonNullableByDefaultModeBit2Strong; + break; + } + } + String name; /// Problems in this [Library] encoded as json objects. diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart index dec7c711ce1..a18adf33f51 100644 --- a/pkg/kernel/lib/binary/tag.dart +++ b/pkg/kernel/lib/binary/tag.dart @@ -149,7 +149,7 @@ class Tag { /// Internal version of kernel binary format. /// Bump it when making incompatible changes in kernel binaries. /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md. - static const int BinaryFormatVersion = 39; + static const int BinaryFormatVersion = 40; } abstract class ConstantTag { diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart index 658f532481e..d6d8ecf80ed 100644 --- a/pkg/kernel/test/binary/library_flags_test.dart +++ b/pkg/kernel/test/binary/library_flags_test.dart @@ -4,18 +4,72 @@ import 'utils.dart'; -/// Test that library flags (external, synthetic) -/// are serialized and read correctly. +/// Test that library flags are serialized and read correctly. main() { - Library lib = new Library(Uri.parse("foo://bar.dart")); - lib.isSynthetic = false; - Library lib2 = libRoundTrip(lib); - if (lib2.isSynthetic != false) - throw "Serialized and re-read library had change in synthetic flag."; + setSynthetic(Library lib, bool isSynthetic) { + lib.isSynthetic = isSynthetic; + } - lib = new Library(Uri.parse("foo://bar.dart")); - lib.isSynthetic = true; - lib2 = libRoundTrip(lib); - if (lib2.isSynthetic != true) - throw "Serialized and re-read library had change in synthetic flag."; + verifySynthetic(Library lib, bool isSynthetic) { + if (lib.isSynthetic != isSynthetic) { + throw "Serialized and re-read library had change in synthetic flag."; + } + } + + setNonNullableByDefault(Library lib, bool isNonNullableByDefault) { + lib.isNonNullableByDefault = isNonNullableByDefault; + } + + verifyNonNullableByDefault(Library lib, bool isNonNullableByDefault) { + if (lib.isNonNullableByDefault != isNonNullableByDefault) { + throw "Serialized and re-read library had change in " + "isNonNullableByDefault flag."; + } + } + + setNonNullableByDefaultCompiledMode(Library lib, + NonNullableByDefaultCompiledMode nonNullableByDefaultCompiledMode) { + lib.nonNullableByDefaultCompiledMode = nonNullableByDefaultCompiledMode; + } + + verifyNonNullableByDefaultCompiledMode(Library lib, + NonNullableByDefaultCompiledMode nonNullableByDefaultCompiledMode) { + if (lib.nonNullableByDefaultCompiledMode != + nonNullableByDefaultCompiledMode) { + throw "Serialized and re-read library had change in " + "nonNullableByDefaultCompiledMode flag."; + } + } + + int combination = 0; + for (bool isSynthetic in [true, false]) { + for (bool isNonNullableByDefault in [true, false]) { + for (NonNullableByDefaultCompiledMode nonNullableByDefaultCompiledMode + in [ + NonNullableByDefaultCompiledMode.Disabled, + NonNullableByDefaultCompiledMode.Weak, + NonNullableByDefaultCompiledMode.Strong, + NonNullableByDefaultCompiledMode.Agnostic, + ]) { + combination++; + print("Checking combination #$combination (" + "isSynthetic: $isSynthetic; " + "isNonNullableByDefault: $isNonNullableByDefault; " + "nonNullableByDefaultCompiledMode:" + " $nonNullableByDefaultCompiledMode"); + Library lib = new Library(Uri.parse("foo://bar.dart")); + setSynthetic(lib, isSynthetic); + setNonNullableByDefault(lib, isNonNullableByDefault); + setNonNullableByDefaultCompiledMode( + lib, nonNullableByDefaultCompiledMode); + Library lib2 = libRoundTrip(lib); + verifySynthetic(lib2, isSynthetic); + verifyNonNullableByDefault(lib2, isNonNullableByDefault); + verifyNonNullableByDefaultCompiledMode( + lib2, nonNullableByDefaultCompiledMode); + } + } + } + + print("Done: Everything looks good."); } diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h index e87c35682ea..3779497b26a 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.h +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h @@ -763,6 +763,15 @@ class LibraryHelper { kExternal = 1 << 0, kSynthetic = 1 << 1, kIsNonNullableByDefault = 1 << 2, + kNonNullableByDefaultCompiledModeBit1Weak = 1 << 3, + kNonNullableByDefaultCompiledModeBit2Strong = 1 << 4, + }; + + enum NonNullableByDefaultCompiledMode { + kDisabled, + kWeak, + kStrong, + kAgnostic }; explicit LibraryHelper(KernelReaderHelper* helper, uint32_t binary_version) @@ -782,6 +791,14 @@ class LibraryHelper { bool IsNonNullableByDefault() const { return (flags_ & kIsNonNullableByDefault) != 0; } + NonNullableByDefaultCompiledMode GetNonNullableByDefaultCompiledMode() const { + bool weak = (flags_ & kNonNullableByDefaultCompiledModeBit1Weak) != 0; + bool strong = (flags_ & kNonNullableByDefaultCompiledModeBit2Strong) != 0; + if (weak && strong) return kAgnostic; + if (strong) return kStrong; + if (weak) return kWeak; + return kDisabled; + } uint8_t flags_ = 0; NameIndex canonical_name_; diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index d89e50a92b4..2004067fd6d 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -20,7 +20,7 @@ static const uint32_t kMagicProgramFile = 0x90ABCDEFu; // Both version numbers are inclusive. static const uint32_t kMinSupportedKernelFormatVersion = 29; -static const uint32_t kMaxSupportedKernelFormatVersion = 39; +static const uint32_t kMaxSupportedKernelFormatVersion = 40; // Keep in sync with package:kernel/lib/binary/tag.dart #define KERNEL_TAG_LIST(V) \