From 67661ccf9361890c5a4e3e8d40da8ba2bb31f34d Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Sun, 4 Feb 2024 08:12:25 -0800 Subject: [PATCH] Frontend: Ignore lazy typechecking flags when emitting non-resilient modules. The `-experimental-lazy-typecheck` and `-experimental-skip-non-exportable-decls` flags are not safe to use when emitting a non-resilient module because the clients of non-resilient modules expect to have access to all the members of a type in order to e.g. compute the size the type. The `-experimental-skip-non-exportable-decls` flag skips serialization of non-public members and would therefore cause mis-compilation. The `-experimental-lazy-typecheck` is theoretically safe for non-resilient modules but more requestification work is needed before it can be used successfully. Resolves rdar://122272758 --- include/swift/AST/DiagnosticsFrontend.def | 3 ++ .../ArgsToFrontendOptionsConverter.cpp | 20 +++++++--- lib/Frontend/CompilerInvocation.cpp | 23 +++++++++-- test/Macros/skip_non_exportable_decls.swift | 2 +- test/SILGen/lazy_typecheck_var_init.swift | 19 ++++----- test/SILGen/skip_non_exportable_decls.swift | 40 +++++++++---------- .../skip_non_exportable_decls_top_level.swift | 4 +- test/Sema/lazy-typecheck.swift | 2 +- 8 files changed, 71 insertions(+), 42 deletions(-) diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 59d50542b9d..6e9e296fe9d 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -166,6 +166,9 @@ ERROR(cannot_emit_ir_skipping_function_bodies,none, WARNING(emit_reference_dependencies_without_primary_file,none, "ignoring -emit-reference-dependencies (requires -primary-file)", ()) +WARNING(ignoring_option_requires_option,none, + "ignoring %0 (requires %1)", (StringRef, StringRef)) + WARNING(warn_implicit_concurrency_import_failed,none, "unable to perform implicit import of \"_Concurrency\" module: no such module found", ()) REMARK(warn_implicit_string_processing_import_failed,none, diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 6790d13f8d9..9a8a60ca3cc 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -318,11 +318,21 @@ bool ArgsToFrontendOptionsConverter::convert( A->getOption().matches(OPT_serialize_debugging_options); } - Opts.SkipNonExportableDecls |= - Args.hasArg(OPT_experimental_skip_non_exportable_decls); - Opts.SkipNonExportableDecls |= - Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) && - Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies_is_lazy); + if (Args.hasArg(OPT_enable_library_evolution)) { + Opts.SkipNonExportableDecls |= + Args.hasArg(OPT_experimental_skip_non_exportable_decls); + + Opts.SkipNonExportableDecls |= + Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) && + Args.hasArg( + OPT_experimental_skip_non_inlinable_function_bodies_is_lazy); + } else { + if (Args.hasArg(OPT_experimental_skip_non_exportable_decls)) + Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option, + "-experimental-skip-non-exportable-decls", + "-enable-library-evolution"); + } + // HACK: The driver currently erroneously passes all flags to module interface // verification jobs. -experimental-skip-non-exportable-decls is not // appropriate for verification tasks and should be ignored, though. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 6ba548b009a..b5ccf423297 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1523,10 +1523,25 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args, Opts.DebugGenericSignatures |= Args.hasArg(OPT_debug_generic_signatures); Opts.DebugInverseRequirements |= Args.hasArg(OPT_debug_inverse_requirements); - Opts.EnableLazyTypecheck |= Args.hasArg(OPT_experimental_lazy_typecheck); - Opts.EnableLazyTypecheck |= - Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) && - Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies_is_lazy); + if (Args.hasArg(OPT_enable_library_evolution)) { + Opts.EnableLazyTypecheck |= Args.hasArg(OPT_experimental_lazy_typecheck); + Opts.EnableLazyTypecheck |= + Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) && + Args.hasArg( + OPT_experimental_skip_non_inlinable_function_bodies_is_lazy); + } else { + if (Args.hasArg(OPT_experimental_lazy_typecheck)) + Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option, + "-experimental-lazy-typecheck", + "-enable-library-evolution"); + + if (Args.hasArg( + OPT_experimental_skip_non_inlinable_function_bodies_is_lazy)) + Diags.diagnose(SourceLoc(), diag::ignoring_option_requires_option, + "-experimental-skip-non-inlinable-function-bodies-is-lazy", + "-enable-library-evolution"); + } + // HACK: The driver currently erroneously passes all flags to module interface // verification jobs. -experimental-skip-non-exportable-decls is not // appropriate for verification tasks and should be ignored, though. diff --git a/test/Macros/skip_non_exportable_decls.swift b/test/Macros/skip_non_exportable_decls.swift index 69700ae62da..e2e38f81c2f 100644 --- a/test/Macros/skip_non_exportable_decls.swift +++ b/test/Macros/skip_non_exportable_decls.swift @@ -5,7 +5,7 @@ // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library.swiftmodule %S/Inputs/freestanding_macro_library.swift -module-name freestanding_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) -// RUN: %target-swift-frontend -parse-as-library -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -experimental-skip-non-exportable-decls | %FileCheck %s +// RUN: %target-swift-frontend -parse-as-library -enable-library-evolution -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -experimental-skip-non-exportable-decls | %FileCheck %s @freestanding(declaration) macro anonymousTypes(public: Bool = false, causeErrors: Bool = false, _: () -> String) = #externalMacro(module: "MacroDefinition", type: "DefineAnonymousTypesMacro") diff --git a/test/SILGen/lazy_typecheck_var_init.swift b/test/SILGen/lazy_typecheck_var_init.swift index f93ee934a58..79a41198c26 100644 --- a/test/SILGen/lazy_typecheck_var_init.swift +++ b/test/SILGen/lazy_typecheck_var_init.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NON-LAZY -// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -module-name Test -experimental-lazy-typecheck | %FileCheck %s --check-prefixes=CHECK,CHECK-LAZY +// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NON-LAZY +// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test -experimental-lazy-typecheck | %FileCheck %s --check-prefixes=CHECK,CHECK-LAZY enum E { case a, b @@ -16,25 +16,25 @@ func internalFunc(_ e: E = .a) -> Int { public var globalVar = internalFunc() public struct S { - // CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV11instanceVarSivpfi : $@convention(thin) () -> Int { + // CHECK-LABEL: sil hidden [transparent]{{.*}} @$s4Test1SV11instanceVarSivpfi : $@convention(thin) () -> Int { public var instanceVar = internalFunc() - // CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV12instanceVar2Sivpfi : $@convention(thin) () -> Int { + // CHECK-LABEL: sil hidden [transparent]{{.*}} @$s4Test1SV12instanceVar2Sivpfi : $@convention(thin) () -> Int { public var instanceVar2 = internalFunc(.b) // CHECK-NOT: s4Test1SV15lazyInstanceVarSivpfi - // CHECK-LABEL: sil [transparent]{{.*}} @$s4Test1SV018$__lazy_storage_$_B11InstanceVar33_0E4F053AA3AB7D4CDE3A37DBA8EF0430LLSiSgvpfi : $@convention(thin) () -> Optional { + // CHECK-LABEL: sil hidden [transparent]{{.*}} @$s4Test1SV018$__lazy_storage_$_B11InstanceVar33_0E4F053AA3AB7D4CDE3A37DBA8EF0430LLSiSgvpfi : $@convention(thin) () -> Optional { public lazy var lazyInstanceVar = internalFunc() // CHECK-LABEL: sil private [global_init_once_fn]{{.*}} @$s4Test1SV9staticVar_WZ : $@convention(c) (Builtin.RawPointer) -> () { public static var staticVar = internalFunc() // FIXME: This initializer should be subsumed. - // CHECK-LAZY: sil [transparent] [ossa] @$s4Test1SV15subsumedInitVarSivpfi : $@convention(thin) () -> Int { - // CHECK-NON-LAZY-NOT: sil [transparent] [ossa] @$s4Test1SV15subsumedInitVarSivpfi : $@convention(thin) () -> Int { + // CHECK-LAZY: sil hidden [transparent]{{.*}} @$s4Test1SV15subsumedInitVarSivpfi : $@convention(thin) () -> Int { + // CHECK-NON-LAZY-NOT: sil hidden [transparent]{{.*}} @$s4Test1SV15subsumedInitVarSivpfi : $@convention(thin) () -> Int { public var subsumedInitVar = internalFunc() - // CHECK-LABEL: sil [transparent] [ossa] @$s4Test1SV19varWithInitAccessorSivpfi : $@convention(thin) () -> Int { + // CHECK-LABEL: sil hidden [transparent] [ossa] @$s4Test1SV19varWithInitAccessorSivpfi : $@convention(thin) () -> Int { public var varWithInitAccessor: Int = internalFunc() { @storageRestrictions(initializes: subsumedInitVar) init { @@ -51,8 +51,9 @@ extension S { public static var staticVarInExtension = internalFunc() } +// CHECK-LABEL: sil{{.*}} @$s4Test8returnsSAA1SVyF : $@convention(thin) () -> @out S public func returnsS() -> S { // Force the synthesized initializer for S to be emitted. - // CHECK: function_ref @$s4Test1SVACycfC : $@convention(method) (@thin S.Type) -> S + // CHECK: function_ref @$s4Test1SVACycfC : $@convention(method) (@thin S.Type) -> @out S return S() } diff --git a/test/SILGen/skip_non_exportable_decls.swift b/test/SILGen/skip_non_exportable_decls.swift index d6e13235e1a..7822e98e98a 100644 --- a/test/SILGen/skip_non_exportable_decls.swift +++ b/test/SILGen/skip_non_exportable_decls.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-SKIP -// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -module-name Test -experimental-skip-non-exportable-decls | %FileCheck %s --check-prefixes=CHECK,CHECK-SKIP +// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-SKIP +// RUN: %target-swift-frontend -emit-silgen %s -parse-as-library -enable-library-evolution -module-name Test -experimental-skip-non-exportable-decls | %FileCheck %s --check-prefixes=CHECK,CHECK-SKIP import Swift @@ -15,7 +15,7 @@ import Swift // CHECK-NO-SKIP: sil_global private @$s4Test15publicGlobalVar_Wz : $Builtin.Word // CHECK-SKIP-NOT: s4Test15publicGlobalVar_Wz -// CHECK: sil_global @$s4Test15publicGlobalVarSivp : $Int +// CHECK: sil_global private @$s4Test15publicGlobalVarSivp : $Int // CHECK-NO-SKIP: sil private{{.*}} @$s4Test11privateFunc33_CFB3F9DC47F5EF9E1D08B58758351A08LLyyF : $@convention(thin) () -> () { // CHECK-SKIP-NOT: s4Test11privateFunc33_CFB3F9DC47F5EF9E1D08B58758351A08LLyyF @@ -46,7 +46,7 @@ internal func internalFuncWithNestedFunc() { // CHECK-SKIP-NOT: s4Test022internalFuncWithNestedC0yyFyycyXEfU_ // CHECK-NO-SKIP: sil private{{.*}} @$s4Test022internalFuncWithNestedC0yyFyycyXEfU_6$deferL_yyF : $@convention(thin) () -> () { -// CHECK-SKIP-NOT: @$s4Test022internalFuncWithNestedC0yyFyycyXEfU_6$deferL_yyF +// CHECK-SKIP-NOT: sil{{.*}} @$s4Test022internalFuncWithNestedC0yyFyycyXEfU_6$deferL_yyF // CHECK: sil{{.*}} @$s4Test10publicFuncyyF : $@convention(thin) () -> () { public func publicFunc() {} @@ -73,8 +73,8 @@ internal var internalGlobalVar = 1 // CHECK-NO-SKIP: sil private [global_init_once_fn]{{.*}} @$s4Test15publicGlobalVar_WZ : $@convention(c) (Builtin.RawPointer) -> () { // CHECK-SKIP-NOT: s4Test15publicGlobalVar_WZ -// CHECK-NO-SKIP: sil [global_init]{{.*}} @$s4Test15publicGlobalVarSivau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK-SKIP-NOT: s4Test15publicGlobalVarSivau +// CHECK-NO-SKIP: sil hidden [global_init]{{.*}} @$s4Test15publicGlobalVarSivau : $@convention(thin) () -> Builtin.RawPointer { +// CHECK-SKIP-NOT: sil{{.*}} s4Test15publicGlobalVarSivau public var publicGlobalVar = 1 // CHECK: sil [serialized]{{.*}} @$s4Test023inlinableFuncWithNestedC0yyF : $@convention(thin) () -> () { @@ -94,9 +94,9 @@ public var publicGlobalVar = 1 @propertyWrapper public struct PublicWrapper { - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvg : $@convention(method) (@in_guaranteed PublicWrapper) -> @out T { - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvs : $@convention(method) (@in T, @inout PublicWrapper) -> () { - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvM : $@yield_once @convention(method) (@inout PublicWrapper) -> @yields @inout T { + // CHECK: sil{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvg : $@convention(method) (@in_guaranteed PublicWrapper) -> @out T { + // CHECK: sil{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvs : $@convention(method) (@in T, @inout PublicWrapper) -> () { + // CHECK: sil{{.*}} @$s4Test13PublicWrapperV12wrappedValuexvM : $@yield_once @convention(method) (@inout PublicWrapper) -> @yields @inout T { public var wrappedValue: T // CHECK: sil{{.*}} @$s4Test13PublicWrapperV12wrappedValueACyxGx_tcfC : $@convention(method) (@in T, @thin PublicWrapper.Type) -> @out PublicWrapper { @@ -118,24 +118,24 @@ private class PrivateClass { } public class PublicClass { - // CHECK-NO-SKIP: sil [transparent]{{.*}} @$s4Test11PublicClassC11internalVarSivpfi : $@convention(thin) () -> Int { + // CHECK-NO-SKIP: sil{{.*}} @$s4Test11PublicClassC11internalVarSivpfi : $@convention(thin) () -> Int { // CHECK-SKIP-NOT: s4Test11PublicClassC11internalVarSivpfi - // CHECK-NO-SKIP: sil hidden [transparent]{{.*}} @$s4Test11PublicClassC11internalVarSivg : $@convention(method) (@guaranteed PublicClass) -> Int { + // CHECK-NO-SKIP: sil hidden{{.*}} @$s4Test11PublicClassC11internalVarSivg : $@convention(method) (@guaranteed PublicClass) -> Int { // CHECK-SKIP-NOT: s4Test11PublicClassC11internalVarSivg - // CHECK-NO-SKIP: sil hidden [transparent]{{.*}} @$s4Test11PublicClassC11internalVarSivs : $@convention(method) (Int, @guaranteed PublicClass) -> () { + // CHECK-NO-SKIP: sil hidden{{.*}} @$s4Test11PublicClassC11internalVarSivs : $@convention(method) (Int, @guaranteed PublicClass) -> () { // CHECK-SKIP-NOT: s4Test11PublicClassC11internalVarSivs - // CHECK-NO-SKIP: sil hidden [transparent]{{.*}} @$s4Test11PublicClassC11internalVarSivM : $@yield_once @convention(method) (@guaranteed PublicClass) -> @yields @inout Int { + // CHECK-NO-SKIP: sil hidden{{.*}} @$s4Test11PublicClassC11internalVarSivM : $@yield_once @convention(method) (@guaranteed PublicClass) -> @yields @inout Int { // CHECK-SKIP-NOT: s4Test11PublicClassC11internalVarSivM var internalVar = 1 - // CHECK-NO-SKIP: sil [transparent]{{.*}} @$s4Test11PublicClassC9publicVarSivpfi : $@convention(thin) () -> Int { + // CHECK-NO-SKIP: sil{{.*}} @$s4Test11PublicClassC9publicVarSivpfi : $@convention(thin) () -> Int { // CHECK-SKIP-NOT: s4Test11PublicClassC9publicVarSivpfi - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test11PublicClassC9publicVarSivg : $@convention(method) (@guaranteed PublicClass) -> Int { - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test11PublicClassC9publicVarSivs : $@convention(method) (Int, @guaranteed PublicClass) -> () { - // CHECK: sil [transparent] [serialized]{{.*}} @$s4Test11PublicClassC9publicVarSivM : $@yield_once @convention(method) (@guaranteed PublicClass) -> @yields @inout Int { + // CHECK: sil{{.*}} @$s4Test11PublicClassC9publicVarSivg : $@convention(method) (@guaranteed PublicClass) -> Int { + // CHECK: sil{{.*}} @$s4Test11PublicClassC9publicVarSivs : $@convention(method) (Int, @guaranteed PublicClass) -> () { + // CHECK: sil{{.*}} @$s4Test11PublicClassC9publicVarSivM : $@yield_once @convention(method) (@guaranteed PublicClass) -> @yields @inout Int { public var publicVar = 1 - // CHECK-NO-SKIP: sil{{.*}} @$s4Test11PublicClassC16publicWrappedVarSivpfP : $@convention(thin) (Int) -> PublicWrapper { + // CHECK-NO-SKIP: sil{{.*}} @$s4Test11PublicClassC16publicWrappedVarSivpfP : $@convention(thin) (Int) -> @out PublicWrapper { // CHECK-SKIP-NOT: s4Test11PublicClassC16publicWrappedVarSivpfP // CHECK: sil{{.*}} @$s4Test11PublicClassC16publicWrappedVarSivg : $@convention(method) (@guaranteed PublicClass) -> Int { // CHECK: sil{{.*}} @$s4Test11PublicClassC16publicWrappedVarSivs : $@convention(method) (Int, @guaranteed PublicClass) -> () { @@ -174,7 +174,7 @@ extension PublicClass { // CHECK-NO-SKIP-NEXT: } // CHECK-SKIP-NOT: sil_vtable PrivateClass -// CHECK-LABEL: sil_vtable [serialized] PublicClass { +// CHECK-LABEL: sil_vtable PublicClass { // CHECK-NO-SKIP-NEXT: #PublicClass.internalVar!getter // CHECK-SKIP-NOT: #PublicClass.internalVar!getter // CHECK-NO-SKIP-NEXT: #PublicClass.internalVar!setter @@ -194,4 +194,4 @@ extension PublicClass { // CHECK-NEXT: #PublicClass.deinit!deallocator // CHECK-NEXT: } -// CHECK: sil_property #PublicClass.publicVar () +// CHECK: sil_property #PublicClass.publicVar diff --git a/test/SILGen/skip_non_exportable_decls_top_level.swift b/test/SILGen/skip_non_exportable_decls_top_level.swift index 38e19d00783..f82b76adea6 100644 --- a/test/SILGen/skip_non_exportable_decls_top_level.swift +++ b/test/SILGen/skip_non_exportable_decls_top_level.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-silgen %s -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-SKIP -// RUN: %target-swift-frontend -emit-silgen %s -module-name Test -experimental-skip-non-exportable-decls | %FileCheck %s --check-prefixes=CHECK,CHECK-SKIP +// RUN: %target-swift-frontend -enable-library-evolution -emit-silgen %s -module-name Test | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-SKIP +// RUN: %target-swift-frontend -enable-library-evolution -emit-silgen %s -module-name Test -experimental-skip-non-exportable-decls | %FileCheck %s --check-prefixes=CHECK,CHECK-SKIP // CHECK-NO-SKIP: sil_global hidden @$s4Test1xSivp : $Int // CHECK-SKIP: sil_global hidden_external @$s4Test1xSivp : $Int diff --git a/test/Sema/lazy-typecheck.swift b/test/Sema/lazy-typecheck.swift index 30e554ecfcc..12e9b88a6fc 100644 --- a/test/Sema/lazy-typecheck.swift +++ b/test/Sema/lazy-typecheck.swift @@ -1,5 +1,5 @@ // RUN: not %target-typecheck-verify-swift -// RUN: %target-typecheck-verify-swift -experimental-lazy-typecheck +// RUN: %target-typecheck-verify-swift -enable-library-evolution -experimental-lazy-typecheck // With lazy typechecking enabled and no compiler outputs specified, no errors // should be emitted for this semantically invalid code.