From 42345dabd342fe793e4eb3bf338ba9560fac0725 Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Tue, 28 Jan 2020 12:56:59 -0800 Subject: [PATCH 01/31] SymbolGraph: Move pathComponents up and include interfaceLanguage `pathComponents` doesn't help with disambiguation, so it shouldn't be a part of the identifier, but can be moved up one level. Include an interface language in the identifier instead. rdar://problem/58853310 --- lib/SymbolGraphGen/Edge.cpp | 10 +++-- lib/SymbolGraphGen/Symbol.cpp | 24 ++++++++++-- lib/SymbolGraphGen/Symbol.h | 43 ++------------------- lib/SymbolGraphGen/SymbolGraphASTWalker.cpp | 29 +++----------- lib/SymbolGraphGen/SymbolGraphASTWalker.h | 8 +--- 5 files changed, 37 insertions(+), 77 deletions(-) diff --git a/lib/SymbolGraphGen/Edge.cpp b/lib/SymbolGraphGen/Edge.cpp index 296cc0960fee2..22f43eacc5402 100644 --- a/lib/SymbolGraphGen/Edge.cpp +++ b/lib/SymbolGraphGen/Edge.cpp @@ -25,12 +25,14 @@ void Edge::serialize(llvm::json::OStream &OS) const { // In case a dependent module isn't available, serialize a fallback name. auto TargetModuleName = Target->getModuleContext()->getName().str(); + if (TargetModuleName != Walker->M.getName().str()) { - auto TargetSymbolIdentifier = Walker->getSymbolIdentifier(Target); - auto TargetComponents = TargetSymbolIdentifier.SimpleComponents; + SmallVector, 8> TargetPathComponents; + Walker->getPathComponents(Target, TargetPathComponents); + SmallString<128> Scratch(TargetModuleName); - for (auto it = TargetComponents.begin(); - it != TargetComponents.end(); ++it) { + for (auto it = TargetPathComponents.begin(); + it != TargetPathComponents.end(); ++it) { Scratch.push_back('.'); Scratch.append(*it); } diff --git a/lib/SymbolGraphGen/Symbol.cpp b/lib/SymbolGraphGen/Symbol.cpp index c30210d75a1e1..425b98217b921 100644 --- a/lib/SymbolGraphGen/Symbol.cpp +++ b/lib/SymbolGraphGen/Symbol.cpp @@ -76,15 +76,30 @@ void Symbol::serializeKind(llvm::json::OStream &OS) const { void Symbol::serializeIdentifier(SymbolGraphASTWalker &Walker, llvm::json::OStream &OS) const { - AttributeRAII A("identifier", OS); - Walker.getSymbolIdentifier(VD).serialize(OS); + OS.attributeObject("identifier", [&](){ + OS.attribute("precise", Walker.getUSR(VD)); + OS.attribute("interfaceLanguage", "swift"); + }); +} + +void Symbol::serializePathComponents(SymbolGraphASTWalker &Walker, + llvm::json::OStream &OS) const { + OS.attributeArray("pathComponents", [&](){ + SmallVector, 8> PathComponents; + Walker.getPathComponents(VD, PathComponents); + for (auto Component : PathComponents) { + OS.value(Component); + } + }); } void Symbol::serializeNames(SymbolGraphASTWalker &Walker, llvm::json::OStream &OS) const { OS.attributeObject("names", [&](){ - auto Identifier = Walker.getSymbolIdentifier(VD); - OS.attribute("title", Identifier.SimpleComponents.back()); + SmallVector, 8> PathComponents; + Walker.getPathComponents(VD, PathComponents); + + OS.attribute("title", PathComponents.back()); // "navigator": null Walker.serializeSubheadingDeclarationFragments("subheading", VD, OS); // "prose": null @@ -370,6 +385,7 @@ void Symbol::serialize(SymbolGraphASTWalker &Walker, OS.object([&](){ serializeKind(OS); serializeIdentifier(Walker, OS); + serializePathComponents(Walker, OS); serializeNames(Walker, OS); serializeDocComment(Walker, OS); diff --git a/lib/SymbolGraphGen/Symbol.h b/lib/SymbolGraphGen/Symbol.h index 9cdbca5757164..6e22255596b50 100644 --- a/lib/SymbolGraphGen/Symbol.h +++ b/lib/SymbolGraphGen/Symbol.h @@ -24,46 +24,6 @@ namespace symbolgraphgen { struct AvailabilityDomain; struct SymbolGraphASTWalker; -/** - An identifier for a symbol that provides a globally unique identifier suitable for - internal lookups and a locally unique path for human use, such as a URL. - */ -struct SymbolIdentifier { - /** - A string that uniquely identifies a symbol within a module in the event of - ambiguities. A precise identifier need not be human readable. - */ - StringRef PreciseIdentifier; - - /** - The components for a "fully qualified" identifier. - */ - ArrayRef SimpleComponents; - - SymbolIdentifier(llvm::StringRef PreciseIdentifier, - ArrayRef SimpleComponents) - : PreciseIdentifier(PreciseIdentifier), - SimpleComponents(SimpleComponents) { - assert(!PreciseIdentifier.empty()); - } - - void serialize(llvm::json::OStream &OS) const { - OS.object([&](){ - OS.attribute("precise", PreciseIdentifier); - OS.attributeArray("simpleComponents", [&](){ - for (auto Component : SimpleComponents) { - OS.value(Component); - } - }); - }); - } - - bool operator==(const SymbolIdentifier &Other) const { - return PreciseIdentifier == Other.PreciseIdentifier && - SimpleComponents == Other.SimpleComponents; - } -}; - /// A symbol from a module: a node in a graph. struct Symbol { const ValueDecl *VD; @@ -76,6 +36,9 @@ struct Symbol { void serializeIdentifier(SymbolGraphASTWalker &Walker, llvm::json::OStream &OS) const; + void serializePathComponents(SymbolGraphASTWalker &Walker, + llvm::json::OStream &OS) const; + void serializeNames(SymbolGraphASTWalker &Walker, llvm::json::OStream &OS) const; diff --git a/lib/SymbolGraphGen/SymbolGraphASTWalker.cpp b/lib/SymbolGraphGen/SymbolGraphASTWalker.cpp index 2ce1337d65468..cc370438be29b 100644 --- a/lib/SymbolGraphGen/SymbolGraphASTWalker.cpp +++ b/lib/SymbolGraphGen/SymbolGraphASTWalker.cpp @@ -149,24 +149,15 @@ StringRef SymbolGraphASTWalker::getUSR(const ValueDecl *VD) { return USR; } -SymbolIdentifier -SymbolGraphASTWalker::getSymbolIdentifier(const ValueDecl *VD) { - // Look in the symbol identifier cache for this declartion. - auto Found = SymbolIdentifierCache.find(VD); - if (Found != SymbolIdentifierCache.end()) { - return Found->getSecond(); - } - - // Not found; need to build a symbol identifier and add it to the cache. - auto PreciseIdentifier = getUSR(VD); - llvm::SmallVector SimpleIdentifierChain; - +void +SymbolGraphASTWalker::getPathComponents(const ValueDecl *VD, + SmallVectorImpl> &Components) { // Collect the spellings of the fully qualified identifier components. auto Decl = VD; while (Decl && !isa(Decl)) { SmallString<32> Scratch; Decl->getFullName().getString(Scratch); - SimpleIdentifierChain.push_back(Ctx.allocateCopy(Scratch.str())); + Components.push_back(Scratch); if (const auto *DC = Decl->getDeclContext()) { if (const auto *Proto = DC->getExtendedProtocolDecl()) { Decl = Proto; @@ -179,17 +170,9 @@ SymbolGraphASTWalker::getSymbolIdentifier(const ValueDecl *VD) { Decl = nullptr; } } - - // The list is leaf-to-root, but our list is root-to-leaf, so reverse it. - std::reverse(SimpleIdentifierChain.begin(), SimpleIdentifierChain.end()); - SymbolIdentifier Identifier { - PreciseIdentifier, - Ctx.allocateCopy(llvm::makeArrayRef(SimpleIdentifierChain)) - }; - - SymbolIdentifierCache.insert({VD, Identifier}); - return Identifier; + // The list is leaf-to-root, but our list is root-to-leaf, so reverse it. + std::reverse(Components.begin(), Components.end()); } PrintOptions SymbolGraphASTWalker::getDeclarationFragmentsPrintOptions() const { diff --git a/lib/SymbolGraphGen/SymbolGraphASTWalker.h b/lib/SymbolGraphGen/SymbolGraphASTWalker.h index fb3e3dc9b6d0d..adf15ec5d46ca 100644 --- a/lib/SymbolGraphGen/SymbolGraphASTWalker.h +++ b/lib/SymbolGraphGen/SymbolGraphASTWalker.h @@ -27,7 +27,6 @@ class ValueDecl; namespace symbolgraphgen { -struct SymbolIdentifier; struct SymbolGraph; struct SymbolGraphOptions; @@ -49,9 +48,6 @@ struct SymbolGraphASTWalker : public SourceEntityWalker { /// A context for allocations. markup::MarkupContext Ctx; - /// A cache of identifiers for declarations that may be seen more than once. - llvm::DenseMap SymbolIdentifierCache; - /// A cache of USRs for declarations. llvm::DenseMap USRCache; @@ -72,8 +68,8 @@ struct SymbolGraphASTWalker : public SourceEntityWalker { /// Get the USR of a declaration and add it to the local allocator. StringRef getUSR(const ValueDecl *VD); - /// Returns a `SymbolIdentifier` for a given declaration. - SymbolIdentifier getSymbolIdentifier(const ValueDecl *VD); + /// Returns an array of path components for a declaration. + void getPathComponents(const ValueDecl *VD, SmallVectorImpl> &Components); // MARK: - Declaration Fragments From 37e403db78c78a39e046b810cd3bd702ec1f598d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 28 Jan 2020 16:16:04 -0800 Subject: [PATCH 02/31] Compile libraries in testcases with -parse-as-library (NFC) This is in preparation to a change in serialization of global variables where this detail will matter. --- test/DebugInfo/inlinescopes.swift | 2 +- test/SILGen/expressions.swift | 2 +- test/SILGen/global_init_attribute.swift | 2 +- test/SILGen/global_resilience.swift | 2 +- test/Serialization/Recovery/typedefs.swift | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/DebugInfo/inlinescopes.swift b/test/DebugInfo/inlinescopes.swift index 769b8a38ce8f0..6c4a3a4fefc3d 100644 --- a/test/DebugInfo/inlinescopes.swift +++ b/test/DebugInfo/inlinescopes.swift @@ -6,7 +6,7 @@ // RUN: %FileCheck %s -check-prefix=TRANSPARENT-CHECK < %t.ll // CHECK: define{{( dllexport)?}}{{( protected)?( signext)?}} i32 @main{{.*}} -// CHECK: call swiftcc i64 @"$s4main8noinlineys5Int64VADF"(i64 %4), !dbg ![[CALL:.*]] +// CHECK: call swiftcc i64 @"$s4main8noinlineys5Int64VADF"(i64 %{{.*}}), !dbg ![[CALL:.*]] // CHECK-DAG: ![[TOPLEVEL:.*]] = !DIFile(filename: "{{.*}}inlinescopes.swift" import FooBar diff --git a/test/SILGen/expressions.swift b/test/SILGen/expressions.swift index f642702602900..54654a6ee7b29 100644 --- a/test/SILGen/expressions.swift +++ b/test/SILGen/expressions.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: echo "public var x = Int()" | %target-swift-frontend -module-name FooBar -emit-module -o %t - +// RUN: echo "public var x = Int()" | %target-swift-frontend -parse-as-library -module-name FooBar -emit-module -o %t - // RUN: %target-swift-emit-silgen -parse-stdlib -module-name expressions %s -I%t -disable-access-control | %FileCheck %s import Swift diff --git a/test/SILGen/global_init_attribute.swift b/test/SILGen/global_init_attribute.swift index f47bde0192a73..95167c7127078 100644 --- a/test/SILGen/global_init_attribute.swift +++ b/test/SILGen/global_init_attribute.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-module -o %t %S/Inputs/def_global.swift +// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-module -o %t %S/Inputs/def_global.swift // RUN: %target-swift-emit-silgen -Xllvm -sil-full-demangle -parse-as-library -I %t %s | %FileCheck %s // // Test that SILGen uses the "global_init" attribute for all global diff --git a/test/SILGen/global_resilience.swift b/test/SILGen/global_resilience.swift index c05720d0713eb..78b425a9ed684 100644 --- a/test/SILGen/global_resilience.swift +++ b/test/SILGen/global_resilience.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_global.swiftmodule -module-name=resilient_global %S/../Inputs/resilient_global.swift +// RUN: %target-swift-frontend -emit-module -parse-as-library -enable-library-evolution -emit-module-path=%t/resilient_global.swiftmodule -module-name=resilient_global %S/../Inputs/resilient_global.swift // RUN: %target-swift-emit-silgen -I %t -enable-library-evolution -parse-as-library %s | %FileCheck %s // RUN: %target-swift-emit-sil -I %t -O -enable-library-evolution -parse-as-library %s | %FileCheck --check-prefix=CHECK-OPT %s diff --git a/test/Serialization/Recovery/typedefs.swift b/test/Serialization/Recovery/typedefs.swift index a9fab839e045b..4b33701fd00e8 100644 --- a/test/Serialization/Recovery/typedefs.swift +++ b/test/Serialization/Recovery/typedefs.swift @@ -1,4 +1,7 @@ // RUN: %empty-directory(%t) + +// Cannot use -parse-as-library here because that would compile also the +// #if VERIFY path, which contains top-level code. // RUN: %target-swift-frontend -emit-sil -o - -emit-module-path %t/Lib.swiftmodule -module-name Lib -I %S/Inputs/custom-modules -disable-objc-attr-requires-foundation-module -enable-objc-interop %s | %FileCheck -check-prefix CHECK-VTABLE %s // RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s From f2c61d8ec58fd10535fc3eb2cab192a47de7e222 Mon Sep 17 00:00:00 2001 From: David Ungar Date: Mon, 27 Jan 2020 21:48:19 -0800 Subject: [PATCH 03/31] Bug fixes for type fingerprints --- ...endenciesSourceFileDepGraphConstructor.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp index 41df94b5fab71..a2cb94342861f 100644 --- a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp +++ b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp @@ -680,12 +680,10 @@ class SourceFileDepGraphConstructor { for (const auto &contextNameFingerprint : contextNameFingerprints) { auto p = g.findExistingNodePairOrCreateAndAddIfNew( kind, contextNameFingerprint); - // When we don't have a fingerprint yet, must rebuild every provider when - // interfaceHash changes. So when interface (i.e. interface hash) of - // sourceFile changes, every provides is dirty. And since we don't know - // what happened, dirtyness might affect the interface. - if (!p.getInterface()->getFingerprint().hasValue()) - g.addArc(g.getSourceFileNodePair().getInterface(), p.getInterface()); + // Since the current type fingerprints only include tokens in the body, + // when the interface hash changes, it is possible that the type in the + // file has changed. + g.addArc(g.getSourceFileNodePair().getInterface(), p.getInterface()); } } @@ -809,8 +807,15 @@ bool swift::fine_grained_dependencies::emitReferenceDependencies( // that may have been there. No error handling -- this is just a nicety, it // doesn't matter if it fails. llvm::sys::fs::rename(outputPath, outputPath + "~"); + // Since, when fingerprints are enabled, + // the parser diverts token hashing into per-body fingerprints + // before it can know if a difference is in a private type, + // in order to be able to test the changed fingerprints + // we force the inclusion of private declarations when fingerprints + // are enabled. const bool includeIntrafileDeps = - SF->getASTContext().LangOpts.FineGrainedDependenciesIncludeIntrafileOnes; + SF->getASTContext().LangOpts.FineGrainedDependenciesIncludeIntrafileOnes || + SF->getASTContext().LangOpts.EnableTypeFingerprints; const bool hadCompilationError = SF->getASTContext().hadError(); auto gc = SourceFileDepGraphConstructor::forSourceFile( SF, depTracker, outputPath, includeIntrafileDeps, hadCompilationError); From bbffc0959b714a0300d92a2f8549309f841b1fae Mon Sep 17 00:00:00 2001 From: David Ungar Date: Mon, 27 Jan 2020 21:48:51 -0800 Subject: [PATCH 04/31] Tests for type fingerprints are enabled. --- ...ine_grained_swiftdeps_with_fingerprints.sh | 7 ++ .../added_method-type-fingerprints.swift | 55 ++++++++++++ ...s_private_property-type-fingerprints.swift | 53 +++++++++++ ...ate_class_property-type-fingerprints.swift | 53 +++++++++++ ...m_private_property-type-fingerprints.swift | 56 ++++++++++++ ...vate_enum_property-type-fingerprints.swift | 55 ++++++++++++ ...ded_private_method-type-fingerprints.swift | 55 ++++++++++++ ...method_value_types-type-fingerprints.swift | 88 +++++++++++++++++++ ...te_protocol_method-type-fingerprints.swift | 50 +++++++++++ ..._protocol_property-type-fingerprints.swift | 50 +++++++++++ ...t_private_property-type-fingerprints.swift | 56 ++++++++++++ ...te_struct_property-type-fingerprints.swift | 56 ++++++++++++ ...edited_method_body-type-fingerprints.swift | 31 +++++++ test/InterfaceHash/edited_method_body.swift | 4 +- ...ed_property_getter-type-fingerprints.swift | 33 +++++++ .../edited_property_getter.swift | 4 +- .../rdar23148987-type-fingerprints.swift | 61 +++++++++++++ .../Serialization/rdar40839486.swift | 4 +- 18 files changed, 765 insertions(+), 6 deletions(-) create mode 100755 test/Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh create mode 100644 test/InterfaceHash/added_method-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_class_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_enum_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_method-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/added_private_struct_property-type-fingerprints.swift create mode 100644 test/InterfaceHash/edited_method_body-type-fingerprints.swift create mode 100644 test/InterfaceHash/edited_property_getter-type-fingerprints.swift create mode 100644 validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift diff --git a/test/Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh b/test/Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh new file mode 100755 index 0000000000000..80bb392c22cfb --- /dev/null +++ b/test/Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +# Fine-grained swiftdeps files use multiple lines for each graph node. +# Compress such a file so that each entry is one line of the form: +# +# Also sort for consistency, since the node order can vary. + +awk '/kind:/ {k = $2; f = ""}; /aspect:/ {a = $2}; /context:/ {c = $2}; /name/ {n = $2}; /sequenceNumber/ {s = $2}; /fingerprint:/ {f = $2 }; /isProvides:/ {isP = $2; print k, a, c, n, isP, f}' | sort diff --git a/test/InterfaceHash/added_method-type-fingerprints.swift b/test/InterfaceHash/added_method-type-fingerprints.swift new file mode 100644 index 0000000000000..7b51e1f67b758 --- /dev/null +++ b/test/InterfaceHash/added_method-type-fingerprints.swift @@ -0,0 +1,55 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +class C { + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +class C { + func f2() -> Int { + return 0 + } + + func f3() -> Int { + return 1 + } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift new file mode 100644 index 0000000000000..cf3a104cc71b1 --- /dev/null +++ b/test/InterfaceHash/added_private_class_private_property-type-fingerprints.swift @@ -0,0 +1,53 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +private class C { + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +private class C { + func f2() -> Int { + return 0 + } + + private var x: Int = 0 +} + +// Since C is a type or extension, the interface hash ought to not get the +// changed token hash. + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_class_property-type-fingerprints.swift b/test/InterfaceHash/added_private_class_property-type-fingerprints.swift new file mode 100644 index 0000000000000..f4e01619c1b76 --- /dev/null +++ b/test/InterfaceHash/added_private_class_property-type-fingerprints.swift @@ -0,0 +1,53 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +class C { + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +class C { + func f2() -> Int { + return 0 + } + + private var x: Int = 0 +} + +// Since C is a type or extension, the interface hash ought to not get the +// changed token hash. + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift new file mode 100644 index 0000000000000..9ad0b28d56449 --- /dev/null +++ b/test/InterfaceHash/added_private_enum_private_property-type-fingerprints.swift @@ -0,0 +1,56 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + + +// BEGIN a.swift +private enum A { + case x, y + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +private enum A { + case x, y + func f2() -> Int { + return 0 + } + + var foo: Int { return 0 } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift b/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift new file mode 100644 index 0000000000000..c8220f6f9a54b --- /dev/null +++ b/test/InterfaceHash/added_private_enum_property-type-fingerprints.swift @@ -0,0 +1,55 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +enum A { + case x, y + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +enum A { + case x, y + func f2() -> Int { + return 0 + } + + private var foo: Int { return 0 } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method-type-fingerprints.swift b/test/InterfaceHash/added_private_method-type-fingerprints.swift new file mode 100644 index 0000000000000..c0c60206d9c92 --- /dev/null +++ b/test/InterfaceHash/added_private_method-type-fingerprints.swift @@ -0,0 +1,55 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +class C { + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +class C { + func f2() -> Int { + return 0 + } + + private func f3() -> Int { + return 1 + } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' C true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' C true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1C{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1C{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1C{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift b/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift new file mode 100644 index 0000000000000..42fee00e31bf0 --- /dev/null +++ b/test/InterfaceHash/added_private_method_value_types-type-fingerprints.swift @@ -0,0 +1,88 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +struct A { + func f2() -> Int { + return 0 + } +} + +enum B { + case x, y + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +struct A { + func f2() -> Int { + return 0 + } + + private func f3() -> Int { + return 1 + } +} + +enum B { + case x, y + func f2() -> Int { + return 0 + } + + private func f3() -> Int { + return 1 + } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' A true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' A true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1A{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1A{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' B true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' B true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1B{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1B{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1B{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift new file mode 100644 index 0000000000000..c0ccd54a11771 --- /dev/null +++ b/test/InterfaceHash/added_private_protocol_method-type-fingerprints.swift @@ -0,0 +1,50 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +private protocol P { + func f2() -> Int + var y: Int { get set } +} + +// BEGIN b.swift +private protocol P { + func f2() -> Int + func f3() -> Int + var y: Int { get set } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift b/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift new file mode 100644 index 0000000000000..c27cee3752b83 --- /dev/null +++ b/test/InterfaceHash/added_private_protocol_property-type-fingerprints.swift @@ -0,0 +1,50 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +private protocol P { + func f2() -> Int + var y: Int { get set } +} + +// BEGIN b.swift +private protocol P { + func f2() -> Int + var x: Int { get set } + var y: Int { get set } +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' P true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' P true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1P{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1P{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1P{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift new file mode 100644 index 0000000000000..47e371aff0901 --- /dev/null +++ b/test/InterfaceHash/added_private_struct_private_property-type-fingerprints.swift @@ -0,0 +1,56 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +struct S { + func f2() -> Int { + return 0 + } + + var y: Int = 0 +} + +// BEGIN b.swift +struct S { + func f2() -> Int { + return 0 + } + + private var x: Int = 0 + var y: Int = 0 +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift b/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift new file mode 100644 index 0000000000000..bd92b5dfbe37f --- /dev/null +++ b/test/InterfaceHash/added_private_struct_property-type-fingerprints.swift @@ -0,0 +1,56 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: not diff %t/{a,b}-processed.swiftdeps >%t/diffs + +// BEGIN a.swift +private struct S { + func f2() -> Int { + return 0 + } + + var y: Int = 0 +} + +// BEGIN b.swift +private struct S { + func f2() -> Int { + return 0 + } + + var x: Int = 0 + var y: Int = 0 +} + +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-SAME-INTERFACE-HASH +// RUN: %FileCheck %s <%t/diffs -check-prefix=CHECK-DIFFERENT-TYPE-FINGERPRINT + +// CHECK-SAME-INTERFACE-HASH-NOT: sourceFileProvides + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < topLevel interface '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel implementation '' S true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > topLevel interface '' S true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < nominal interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > nominal interface 4main1S{{[^ ]+}} '' true + +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: < potentialMember interface 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember implementation 4main1S{{[^ ]+}} '' true +// CHECK-DIFFERENT-TYPE-FINGERPRINT-DAG: > potentialMember interface 4main1S{{[^ ]+}} '' true diff --git a/test/InterfaceHash/edited_method_body-type-fingerprints.swift b/test/InterfaceHash/edited_method_body-type-fingerprints.swift new file mode 100644 index 0000000000000..10ae3e000c09f --- /dev/null +++ b/test/InterfaceHash/edited_method_body-type-fingerprints.swift @@ -0,0 +1,31 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: cmp %t/{a,b}-processed.swiftdeps + +// BEGIN a.swift +class C { + func f2() -> Int { + return 0 + } +} + +// BEGIN b.swift +class C { + func f2() -> Int { + return 1 + } +} diff --git a/test/InterfaceHash/edited_method_body.swift b/test/InterfaceHash/edited_method_body.swift index 2f87dd9f02fef..b0aebce44e500 100644 --- a/test/InterfaceHash/edited_method_body.swift +++ b/test/InterfaceHash/edited_method_body.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash +// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash +// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash // RUN: cmp %t/a.hash %t/b.hash // BEGIN a.swift diff --git a/test/InterfaceHash/edited_property_getter-type-fingerprints.swift b/test/InterfaceHash/edited_property_getter-type-fingerprints.swift new file mode 100644 index 0000000000000..0a0b5fdaaff54 --- /dev/null +++ b/test/InterfaceHash/edited_property_getter-type-fingerprints.swift @@ -0,0 +1,33 @@ +// REQUIRES: shell +// Also uses awk: +// XFAIL OS=windows + +// When adding a private protocol method, the interface hash should stay the same +// The per-type fingerprint should change + +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: cp %t/{a,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/a-processed.swiftdeps +// RUN: cp %t/{b,x}.swift +// RUN: %target-swift-frontend -typecheck -enable-type-fingerprints -primary-file %t/x.swift -emit-reference-dependencies-path %t/x.swiftdeps -module-name main +// RUN: %S/../Inputs/process_fine_grained_swiftdeps_with_fingerprints.sh <%t/x.swiftdeps >%t/b-processed.swiftdeps + +// RUN: cmp %t/{a,b}-processed.swiftdeps + +// BEGIN a.swift +class C { + var p: Int { + return 0 + } +} + +// BEGIN b.swift +class C { + var p: Int { + let x = 1 + return x + } +} + diff --git a/test/InterfaceHash/edited_property_getter.swift b/test/InterfaceHash/edited_property_getter.swift index 42584e33f6467..deaeb8ccc08dc 100644 --- a/test/InterfaceHash/edited_property_getter.swift +++ b/test/InterfaceHash/edited_property_getter.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %{python} %utils/split_file.py -o %t %s -// RUN: %target-swift-frontend -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash -// RUN: %target-swift-frontend -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash +// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/a.swift 2> %t/a.hash +// RUN: %target-swift-frontend -disable-type-fingerprints -dump-interface-hash -primary-file %t/b.swift 2> %t/b.hash // RUN: cmp %t/a.hash %t/b.hash // BEGIN a.swift diff --git a/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift b/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift new file mode 100644 index 0000000000000..3eefcdd073ba8 --- /dev/null +++ b/validation-test/Driver/Dependencies/rdar23148987-type-fingerprints.swift @@ -0,0 +1,61 @@ +// RUN: %empty-directory(%t) + +// RUN: cp %s %t/main.swift +// RUN: cp %S/Inputs/rdar23148987/helper-1.swift %t/helper.swift +// RUN: touch -t 201401240005 %t/*.swift + +// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1 %s + +// CHECK-1-NOT: warning +// CHECK-1: {{^{$}} +// CHECK-1: "kind": "began" +// CHECK-1: "name": "compile" +// CHECK-1: ".\/main.swift" +// CHECK-1: {{^}$}} + +// CHECK-1: {{^{$}} +// CHECK-1: "kind": "began" +// CHECK-1: "name": "compile" +// CHECK-1: ".\/helper.swift" +// CHECK-1: {{^}$}} + +// RUN: ls %t/ | %FileCheck -check-prefix=CHECK-LS %s + +// CHECK-LS-DAG: main.o +// CHECK-LS-DAG: helper.o + +// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1-SKIPPED %s + +// CHECK-1-SKIPPED-NOT: warning +// CHECK-1-SKIPPED: {{^{$}} +// CHECK-1-SKIPPED: "kind": "skipped" +// CHECK-1-SKIPPED: "name": "compile" +// CHECK-1-SKIPPED: ".\/main.swift" +// CHECK-1-SKIPPED: {{^}$}} + +// CHECK-1-SKIPPED: {{^{$}} +// CHECK-1-SKIPPED: "kind": "skipped" +// CHECK-1-SKIPPED: "name": "compile" +// CHECK-1-SKIPPED: ".\/helper.swift" +// CHECK-1-SKIPPED: {{^}$}} + +// RUN: cp %S/Inputs/rdar23148987/helper-2.swift %t/helper.swift +// RUN: touch -t 201401240006 %t/helper.swift +// RUN: cd %t && %target-build-swift -enable-type-fingerprints -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 -driver-show-incremental -driver-show-job-lifecycle | %FileCheck -check-prefix=CHECK-2 %s + +// CHECK-2-NOT: warning +// CHECK-2: {{^{$}} +// CHECK-2: "kind": "began" +// CHECK-2: "name": "compile" +// CHECK-2: ".\/helper.swift" +// CHECK-2: {{^}$}} + +// CHECK-2: {{^{$}} +// CHECK-2: "kind": "began" +// CHECK-2: "name": "compile" +// CHECK-2: ".\/main.swift" +// CHECK-2: {{^}$}} + +func test(obj: Test) { + obj.foo() +} diff --git a/validation-test/Serialization/rdar40839486.swift b/validation-test/Serialization/rdar40839486.swift index 3704eec44bf09..8c4e1531b0db1 100644 --- a/validation-test/Serialization/rdar40839486.swift +++ b/validation-test/Serialization/rdar40839486.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift -disable-type-fingerprints -emit-module-path %t/main4.swiftmodule -swift-version 4 -Fsystem %sdk/System/Library/PrivateFrameworks/ %s -// RUN: %target-build-swift -disable-type-fingerprints -emit-module-path %t/main4_2.swiftmodule -swift-version 4.2 -Fsystem %sdk/System/Library/PrivateFrameworks/ %s +// RUN: %target-build-swift -emit-module-path %t/main4.swiftmodule -swift-version 4 -Fsystem %sdk/System/Library/PrivateFrameworks/ %s +// RUN: %target-build-swift -emit-module-path %t/main4_2.swiftmodule -swift-version 4.2 -Fsystem %sdk/System/Library/PrivateFrameworks/ %s // REQUIRES: OS=macosx || OS=ios From b0786e7e06230a3d1f59271389b56222ea74aca3 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jan 2020 21:13:22 -0800 Subject: [PATCH 05/31] Fix propagation of guaranteed phi args during DiagnoseUnreachable. Fixes assertion failure - UNREACHABLE executed at swift/include/swift/SIL/OwnershipUtils.h:127! --- .../Mandatory/DiagnoseUnreachable.cpp | 7 ++--- test/SILOptimizer/diagnose_unreachable.sil | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp index 6923725dc55b6..107829132d2a8 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp @@ -185,12 +185,9 @@ static void propagateBasicBlockArgs(SILBasicBlock &BB) { // this to CCP and trigger another round of copy propagation. SILArgument *Arg = *AI; - // If this argument is guaranteed and Args[Idx] is a SILFunctionArgument, - // delete the end_borrow. - if (Arg->getOwnershipKind() == ValueOwnershipKind::Guaranteed && - isa(Args[Idx])) { + // If this argument is guaranteed and Args[Idx], delete the end_borrow. + if (Arg->getOwnershipKind() == ValueOwnershipKind::Guaranteed) deleteEndBorrows(Arg); - } // We were able to fold, so all users should use the new folded value. Arg->replaceAllUsesWith(Args[Idx]); diff --git a/test/SILOptimizer/diagnose_unreachable.sil b/test/SILOptimizer/diagnose_unreachable.sil index bbf443dc223ec..7045ca9e368ab 100644 --- a/test/SILOptimizer/diagnose_unreachable.sil +++ b/test/SILOptimizer/diagnose_unreachable.sil @@ -782,3 +782,33 @@ bb1(%2 : @owned $Builtin.NativeObject): bb2: unreachable } + +// Test propagation of guaranteed phi arguments. The nested end_borrow +// must be removed, even with the outer borrow is *not* a function +// argument. + +enum EnumWithB { + case A(B) + func testit() -> Int +} + +// CHECK-LABEL: sil hidden [ossa] @testPropagateGuaranteedPhi : $@convention(method) (@guaranteed EnumWithB) -> () { +// CHECK: bb1([[PHI:%.*]] : @guaranteed $B): +// CHECK: br bb2 +// CHECK: bb2: +// CHECK: end_borrow [[PHI]] : $B +// CHECK-NOT: end_borrow +// CHECK-LABEL: } // end sil function 'testPropagateGuaranteedPhi' +sil hidden [ossa] @testPropagateGuaranteedPhi : $@convention(method) (@guaranteed EnumWithB) -> () { +bb0(%0 : @guaranteed $EnumWithB): + switch_enum %0 : $EnumWithB, case #EnumWithB.A!enumelt.1: bb1 + +bb1(%2 : @guaranteed $B): + br bb3(%2 : $B) + +bb3(%4 : @guaranteed $B): + end_borrow %4 : $B + end_borrow %2 : $B + %99 = tuple () + return %99 : $() +} From 1af49ecb996e66aa0b7de7395ee073973a13ed7c Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 28 Jan 2020 22:54:08 -0800 Subject: [PATCH 06/31] Fix an EscapeAnalysis assert to handle recent changes. setPointsToEdge should assert that its target isn't already merged, but now that we batch up multiple merge requests, it's fine to allow the target to be scheduled-for-merge. Many assertions have been recently added and tightened in order to "discover" unexpected cases. There's nothing incorrect about how these cases were handled, but they lack unit tests. In this case I still haven't been able to reduce a test case. I'm continuing to work on it, but don't want to further delay the fix. --- include/swift/SILOptimizer/Analysis/EscapeAnalysis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h index c1d405c4d7f42..2d56b97d85695 100644 --- a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h @@ -449,7 +449,7 @@ class EscapeAnalysis : public BottomUpIPAnalysis { /// Sets the outgoing points-to edge. The \p To node must be a Content node. void setPointsToEdge(CGNode *To) { - assert(!To->mergeTo); + assert(!To->isMerged); assert(To->Type == NodeType::Content && "Wrong node type for points-to edge"); pointsToIsEdge = true; From b2083db45d88696eec1c34e5e79ce1f9849e290b Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 29 Jan 2020 00:06:57 -0800 Subject: [PATCH 07/31] [ConstraintSystem] Add a fix to allow conversion between non-class type and AnyObject --- lib/Sema/CSFix.cpp | 37 +++++++++++++++++++++++++++++++++++++ lib/Sema/CSFix.h | 22 ++++++++++++++++++++-- lib/Sema/CSSimplify.cpp | 13 +++++++++++-- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index ffc4e502509a5..95e78c3a454be 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1180,3 +1180,40 @@ SpecifyObjectLiteralTypeImport::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) SpecifyObjectLiteralTypeImport(cs, locator); } + +AllowNonClassTypeToConvertToAnyObject::AllowNonClassTypeToConvertToAnyObject( + ConstraintSystem &cs, Type type, ConstraintLocator *locator) + : ContextualMismatch(cs, FixKind::AllowNonClassTypeToConvertToAnyObject, + type, cs.getASTContext().getAnyObjectType(), locator) { +} + +bool AllowNonClassTypeToConvertToAnyObject::diagnose(bool asNote) const { + auto &cs = getConstraintSystem(); + + auto *locator = getLocator(); + if (locator->getPath().empty()) + return false; + + const auto &last = locator->getPath().back(); + switch (last.getKind()) { + case ConstraintLocator::ContextualType: { + ContextualFailure failure(cs, getFromType(), getToType(), locator); + return failure.diagnose(asNote); + } + + case ConstraintLocator::ApplyArgToParam: { + ArgumentMismatchFailure failure(cs, getFromType(), getToType(), locator); + return failure.diagnose(asNote); + } + + default: + return false; + } +} + +AllowNonClassTypeToConvertToAnyObject * +AllowNonClassTypeToConvertToAnyObject::create(ConstraintSystem &cs, Type type, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + AllowNonClassTypeToConvertToAnyObject(cs, type, locator); +} diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 05959c8ddbaf4..086f9d5e3de89 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -235,12 +235,15 @@ enum class FixKind : uint8_t { /// Closure return type has to be explicitly specified because it can't be /// inferred in current context e.g. because it's a multi-statement closure. SpecifyClosureReturnType, - - /// Object literal type coudn't be infered because the module where + + /// Object literal type coudn't be inferred because the module where /// the default type that implements the associated literal protocol /// is declared was not imported. SpecifyObjectLiteralTypeImport, + /// Allow any type (and not just class or class-constrained type) to + /// be convertible to AnyObject. + AllowNonClassTypeToConvertToAnyObject, }; class ConstraintFix { @@ -1655,6 +1658,21 @@ class SpecifyObjectLiteralTypeImport final : public ConstraintFix { }; +class AllowNonClassTypeToConvertToAnyObject final : public ContextualMismatch { + AllowNonClassTypeToConvertToAnyObject(ConstraintSystem &cs, Type type, + ConstraintLocator *locator); + +public: + std::string getName() const { + return "allow non-class type to convert to 'AnyObject'"; + } + + bool diagnose(bool asNote = false) const; + + static AllowNonClassTypeToConvertToAnyObject * + create(ConstraintSystem &cs, Type type, ConstraintLocator *locator); +}; + } // end namespace constraints } // end namespace swift diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 43a00626b0e8d..46b71306844d5 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2095,9 +2095,17 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, // Subtype relation to AnyObject also allows class-bound // existentials that are not @objc and therefore carry // witness tables. - if (!type1->isClassExistentialType() && - !type1->mayHaveSuperclass()) + if (!type1->isClassExistentialType() && !type1->mayHaveSuperclass()) { + if (shouldAttemptFixes()) { + auto *fix = AllowNonClassTypeToConvertToAnyObject::create( + *this, type1, getConstraintLocator(locator)); + + return recordFix(fix) ? getTypeMatchFailure(locator) + : getTypeMatchSuccess(); + } + return getTypeMatchFailure(locator); + } } // Keep going. @@ -8837,6 +8845,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::AllowMutatingMemberOnRValueBase: case FixKind::AllowTupleSplatForSingleParameter: case FixKind::AllowInvalidUseOfTrailingClosure: + case FixKind::AllowNonClassTypeToConvertToAnyObject: case FixKind::SpecifyClosureReturnType: llvm_unreachable("handled elsewhere"); } From ec3b783380a984c2ee1531108e08170a85ace793 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 29 Jan 2020 00:37:39 -0800 Subject: [PATCH 08/31] [Diagnostics] Improve diagnostic for invalid conversion to AnyObject --- include/swift/AST/DiagnosticsSema.def | 17 +++++- lib/Sema/CSDiagnostics.cpp | 56 +++++++++++++------ lib/Sema/CSDiagnostics.h | 2 +- test/ClangImporter/attr-swift_private.swift | 2 +- test/Constraints/bridging.swift | 10 ++-- test/Generics/existential_restrictions.swift | 2 +- test/Interpreter/SDK/misc_osx.swift | 2 +- test/Parse/metatype_object_conversion.swift | 7 +-- ...g_metatype_cast_to_reference_no_objc.swift | 4 +- 9 files changed, 68 insertions(+), 34 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index fef7af3b04473..02438f31c3bd5 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -338,6 +338,10 @@ ERROR(cannot_convert_initializer_value,none, "cannot convert value of type %0 to specified type %1", (Type,Type)) ERROR(cannot_convert_initializer_value_protocol,none, "value of type %0 does not conform to specified type %1", (Type,Type)) +ERROR(cannot_convert_initializer_value_anyobject,none, + "value of type %0 expected to be instance of class or " + "class-constrained type", + (Type, Type)) ERROR(cannot_convert_initializer_value_nil,none, "'nil' cannot initialize specified type %0", (Type)) @@ -346,6 +350,10 @@ ERROR(cannot_convert_to_return_type,none, (Type,Type)) ERROR(cannot_convert_to_return_type_protocol,none, "return expression of type %0 does not conform to %1", (Type,Type)) +ERROR(cannot_convert_return_type_to_anyobject,none, + "return expression of type %0 expected to be an instance of " + "a class or class-constrained type", + (Type, Type)) ERROR(cannot_convert_to_return_type_nil,none, "'nil' is incompatible with return type %0", (Type)) @@ -440,7 +448,10 @@ NOTE(candidate_performs_illegal_ephemeral_conv,none, ERROR(cannot_convert_argument_value_protocol,none, "argument type %0 does not conform to expected type %1", (Type, Type)) - +ERROR(cannot_convert_argument_value_anyobject,none, + "argument type %0 expected to be an instance of " + "a class or class-constrained type", + (Type, Type)) ERROR(cannot_convert_argument_value_nil,none, "'nil' is not compatible with expected argument type %0", (Type)) @@ -536,6 +547,10 @@ NOTE(assign_protocol_conformance_fix_it,none, ERROR(cannot_convert_assign_protocol,none, "value of type %0 does not conform to %1 in assignment", (Type, Type)) +ERROR(cannot_convert_assign_anyobject,none, + "value of type %0 expected to be an instance of " + "a class or class-constrained type in assignment", + (Type, Type)) ERROR(cannot_convert_assign_nil,none, "'nil' cannot be assigned to type %0", (Type)) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index b8cf4a95a75bb..b85e37691bb76 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -1977,7 +1977,7 @@ bool ContextualFailure::diagnoseAsError() { CTP = CTP_ClosureResult; } - if (auto msg = getDiagnosticFor(CTP, toType->isExistentialType())) { + if (auto msg = getDiagnosticFor(CTP, toType)) { diagnostic = *msg; break; } @@ -2276,11 +2276,9 @@ bool ContextualFailure::diagnoseCoercionToUnrelatedType() const { if (auto *coerceExpr = dyn_cast(anchor)) { auto fromType = getType(coerceExpr->getSubExpr()); auto toType = getType(coerceExpr->getCastTypeLoc()); - - auto diagnostic = - getDiagnosticFor(CTP_CoerceOperand, - /*forProtocol=*/toType->isExistentialType()); - + + auto diagnostic = getDiagnosticFor(CTP_CoerceOperand, toType); + auto diag = emitDiagnostic(anchor->getLoc(), *diagnostic, fromType, toType); diag.highlight(anchor->getSourceRange()); @@ -2844,15 +2842,24 @@ bool ContextualFailure::isIntegerToStringIndexConversion() const { Optional> ContextualFailure::getDiagnosticFor(ContextualTypePurpose context, - bool forProtocol) { + Type contextualType) { + auto forProtocol = contextualType->isExistentialType(); switch (context) { - case CTP_Initialization: + case CTP_Initialization: { + if (contextualType->isAnyObject()) + return diag::cannot_convert_initializer_value_anyobject; + return forProtocol ? diag::cannot_convert_initializer_value_protocol : diag::cannot_convert_initializer_value; + } case CTP_ReturnStmt: - case CTP_ReturnSingleExpr: + case CTP_ReturnSingleExpr: { + if (contextualType->isAnyObject()) + return diag::cannot_convert_return_type_to_anyobject; + return forProtocol ? diag::cannot_convert_to_return_type_protocol : diag::cannot_convert_to_return_type; + } case CTP_EnumCaseRawValue: return diag::cannot_convert_raw_initializer_value; case CTP_DefaultParameter: @@ -2861,9 +2868,13 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context, case CTP_YieldByValue: return forProtocol ? diag::cannot_convert_yield_value_protocol : diag::cannot_convert_yield_value; - case CTP_CallArgument: + case CTP_CallArgument: { + if (contextualType->isAnyObject()) + return diag::cannot_convert_argument_value_anyobject; + return forProtocol ? diag::cannot_convert_argument_value_protocol : diag::cannot_convert_argument_value; + } case CTP_ClosureResult: return forProtocol ? diag::cannot_convert_closure_result_protocol : diag::cannot_convert_closure_result; @@ -2879,9 +2890,13 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context, case CTP_CoerceOperand: return forProtocol ? diag::cannot_convert_coerce_protocol : diag::cannot_convert_coerce; - case CTP_AssignSource: + case CTP_AssignSource: { + if (contextualType->isAnyObject()) + return diag::cannot_convert_assign_anyobject; + return forProtocol ? diag::cannot_convert_assign_protocol : diag::cannot_convert_assign; + } case CTP_SubscriptAssignSource: return forProtocol ? diag::cannot_convert_subscript_assign_protocol : diag::cannot_convert_subscript_assign; @@ -2908,7 +2923,7 @@ bool TupleContextualFailure::diagnoseAsError() { else if ((purpose == CTP_Initialization) && !cs.getContextualType(getAnchor())) diagnostic = diag::tuple_types_not_convertible; - else if (auto diag = getDiagnosticFor(purpose, /*forProtocol=*/false)) + else if (auto diag = getDiagnosticFor(purpose, getToType())) diagnostic = *diag; else return false; @@ -2919,7 +2934,7 @@ bool TupleContextualFailure::diagnoseAsError() { bool FunctionTypeMismatch::diagnoseAsError() { auto purpose = getContextualTypePurpose(); - auto diagnostic = getDiagnosticFor(purpose, /*forProtocol=*/false); + auto diagnostic = getDiagnosticFor(purpose, getToType()); if (!diagnostic) return false; @@ -4839,17 +4854,16 @@ bool MissingContextualConformanceFailure::diagnoseAsError() { if (path.empty()) { assert(isa(anchor)); if (isa(cast(anchor)->getDest())) { - diagnostic = - getDiagnosticFor(CTP_SubscriptAssignSource, /*forProtocol=*/true); + diagnostic = getDiagnosticFor(CTP_SubscriptAssignSource, getToType()); } else { - diagnostic = getDiagnosticFor(CTP_AssignSource, /*forProtocol=*/true); + diagnostic = getDiagnosticFor(CTP_AssignSource, getToType()); } } else { const auto &last = path.back(); switch (last.getKind()) { case ConstraintLocator::ContextualType: assert(Context != CTP_Unused); - diagnostic = getDiagnosticFor(Context, /*forProtocol=*/true); + diagnostic = getDiagnosticFor(Context, getToType()); break; case ConstraintLocator::SequenceElementType: { @@ -5277,7 +5291,7 @@ bool InOutConversionFailure::diagnoseAsError() { assert(locator->findLast()); auto contextualType = cs.getContextualType(anchor); auto purpose = getContextualTypePurpose(); - auto diagnostic = getDiagnosticFor(purpose, /*forProtocol=*/false); + auto diagnostic = getDiagnosticFor(purpose, contextualType); if (!diagnostic) return false; @@ -5385,6 +5399,12 @@ bool ArgumentMismatchFailure::diagnoseAsError() { auto argType = getFromType(); auto paramType = getToType(); + if (paramType->isAnyObject()) { + emitDiagnostic(getLoc(), diag::cannot_convert_argument_value_anyobject, + argType, paramType); + return true; + } + Diag diagnostic = diag::cannot_convert_argument_value; // If parameter type is a protocol value, let's says that diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 90f64c5175acf..386ea94c8831a 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -653,7 +653,7 @@ class ContextualFailure : public FailureDiagnostic { ContextualTypePurpose getContextualTypePurpose() const { return CTP; } static Optional> - getDiagnosticFor(ContextualTypePurpose context, bool forProtocol); + getDiagnosticFor(ContextualTypePurpose context, Type contextualType); }; /// Diagnose errors related to converting function type which diff --git a/test/ClangImporter/attr-swift_private.swift b/test/ClangImporter/attr-swift_private.swift index 05ddc81835f30..f249454b15d96 100644 --- a/test/ClangImporter/attr-swift_private.swift +++ b/test/ClangImporter/attr-swift_private.swift @@ -121,7 +121,7 @@ func testCF(_ a: __PrivCFType, b: __PrivCFSub, c: __PrivInt) { makeSureAnyObject(a) makeSureAnyObject(b) #if !IRGEN - makeSureAnyObject(c) // expected-error {{argument type '__PrivInt' (aka 'Int32') does not conform to expected type 'AnyObject'}} + makeSureAnyObject(c) // expected-error {{argument type '__PrivInt' (aka 'Int32') expected to be an instance of a class or class-constrained type}} #endif } diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift index 4cdc52e3e2626..c40fb0bdf181d 100644 --- a/test/Constraints/bridging.swift +++ b/test/Constraints/bridging.swift @@ -89,7 +89,7 @@ func bridgeToObjC(_ s: BridgedStruct) -> BridgedClass { } func bridgeToAnyObject(_ s: BridgedStruct) -> AnyObject { - return s // expected-error{{return expression of type 'BridgedStruct' does not conform to 'AnyObject'}} + return s // expected-error{{return expression of type 'BridgedStruct' expected to be an instance of a class or class-constrained type}} return s as AnyObject } @@ -344,14 +344,14 @@ func forceUniversalBridgeToAnyObject(a: T, b: U, c: An z = g as AnyObject z = h as AnyObject - z = a // expected-error{{does not conform to 'AnyObject'}} + z = a // expected-error{{value of type 'T' expected to be an instance of a class or class-constrained type in assignment}} z = b - z = c // expected-error{{does not conform to 'AnyObject'}} expected-note {{cast 'Any' to 'AnyObject'}} {{8-8= as AnyObject}} - z = d // expected-error{{does not conform to 'AnyObject'}} + z = c // expected-error{{value of type 'Any' expected to be an instance of a class or class-constrained type in assignment}} expected-note {{cast 'Any' to 'AnyObject'}} {{8-8= as AnyObject}} + z = d // expected-error{{value of type 'KnownUnbridged' expected to be an instance of a class or class-constrained type in assignment}} z = e z = f z = g - z = h // expected-error{{does not conform to 'AnyObject'}} + z = h // expected-error{{value of type 'String' expected to be an instance of a class or class-constrained type in assignment}} _ = z } diff --git a/test/Generics/existential_restrictions.swift b/test/Generics/existential_restrictions.swift index ae652220daa2b..fbf2f29375fc5 100644 --- a/test/Generics/existential_restrictions.swift +++ b/test/Generics/existential_restrictions.swift @@ -25,7 +25,7 @@ func fT(_ t: T) { } func testPassExistential(_ p: P, op: OP, opp: OP & P, cp: CP, sp: SP, any: Any, ao: AnyObject) { fP(p) // expected-error{{value of protocol type 'P' cannot conform to 'P'; only struct/enum/class types can conform to protocols}} fAO(p) // expected-error{{global function 'fAO' requires that 'P' be a class type}} - fAOE(p) // expected-error{{argument type 'P' does not conform to expected type 'AnyObject'}} + fAOE(p) // expected-error{{argument type 'P' expected to be an instance of a class or class-constrained type}} fT(p) fOP(op) diff --git a/test/Interpreter/SDK/misc_osx.swift b/test/Interpreter/SDK/misc_osx.swift index fabd2413023c3..15383cf784077 100644 --- a/test/Interpreter/SDK/misc_osx.swift +++ b/test/Interpreter/SDK/misc_osx.swift @@ -13,5 +13,5 @@ func testFSEventStreamRef(stream: FSEventStreamRef) { FSEventStreamRetain(stream) // no-warning FSEventStreamRelease(stream) - let _: AnyObject = stream // expected-error {{value of type 'FSEventStreamRef' (aka 'OpaquePointer') does not conform to specified type 'AnyObject'}} + let _: AnyObject = stream // expected-error {{value of type 'FSEventStreamRef' (aka 'OpaquePointer') expected to be instance of class or class-constrained type}} } diff --git a/test/Parse/metatype_object_conversion.swift b/test/Parse/metatype_object_conversion.swift index 96f27402dc86f..2dc87ff1e87bb 100644 --- a/test/Parse/metatype_object_conversion.swift +++ b/test/Parse/metatype_object_conversion.swift @@ -12,15 +12,14 @@ func takesAnyObject(_ x: AnyObject) {} func concreteTypes() { takesAnyObject(C.self) - // TODO: Better error messages - takesAnyObject(S.self) // expected-error{{argument type 'S.Type' does not conform to expected type 'AnyObject'}} - takesAnyObject(ClassConstrainedProto.self) // expected-error{{argument type 'ClassConstrainedProto.Protocol' does not conform to expected type 'AnyObject'}} + takesAnyObject(S.self) // expected-error{{argument type 'S.Type' expected to be an instance of a class or class-constrained type}} + takesAnyObject(ClassConstrainedProto.self) // expected-error{{argument type 'ClassConstrainedProto.Protocol' expected to be an instance of a class or class-constrained type}} } func existentialMetatypes(nonClass: NonClassProto.Type, classConstrained: ClassConstrainedProto.Type, compo: (NonClassProto & ClassConstrainedProto).Type) { - takesAnyObject(nonClass) // expected-error{{argument type 'NonClassProto.Type' does not conform to expected type 'AnyObject'}} + takesAnyObject(nonClass) // expected-error{{argument type 'NonClassProto.Type' expected to be an instance of a class or class-constrained type}} takesAnyObject(classConstrained) takesAnyObject(compo) } diff --git a/test/Sema/diag_metatype_cast_to_reference_no_objc.swift b/test/Sema/diag_metatype_cast_to_reference_no_objc.swift index 28566417e0fbf..abca5b92aa279 100644 --- a/test/Sema/diag_metatype_cast_to_reference_no_objc.swift +++ b/test/Sema/diag_metatype_cast_to_reference_no_objc.swift @@ -3,6 +3,6 @@ class C {} func test(c: AnyClass) { - let _: AnyObject = c // expected-error {{value of type 'AnyClass' (aka 'AnyObject.Type') does not conform to specified type 'AnyObject'}} - let _: AnyObject = C.self // expected-error {{value of type 'C.Type' does not conform to specified type 'AnyObject'}} + let _: AnyObject = c // expected-error {{value of type 'AnyClass' (aka 'AnyObject.Type') expected to be instance of class or class-constrained type}} + let _: AnyObject = C.self // expected-error {{value of type 'C.Type' expected to be instance of class or class-constrained type}} } From ffa6bf47294960fb6aaf26da47c213bbb5a10c9d Mon Sep 17 00:00:00 2001 From: Chris Amanse <12277586+chrisamanse@users.noreply.github.com> Date: Wed, 29 Jan 2020 08:21:52 -0800 Subject: [PATCH 09/31] Fix memory leaks in ThreadBarriers.swift (#12212) * Fix memory leaks in ThreadBarriers.swift * Fatal error on pthread cond/mutex destroy failure * Rename pthread to thread * Fix pthread init function calls * Fix guard statement --- .../SwiftPrivateThreadExtras.swift | 5 +-- .../ThreadBarriers.swift | 36 +++++++++++-------- .../stdlib/StringSlicesConcurrentAppend.swift | 3 +- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift b/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift index 002aef8e74145..bc849536a9429 100644 --- a/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift +++ b/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift @@ -162,10 +162,7 @@ public class _stdlib_Barrier { } deinit { - let ret = _stdlib_thread_barrier_destroy(_threadBarrierPtr) - if ret != 0 { - fatalError("_stdlib_thread_barrier_destroy() failed") - } + _stdlib_thread_barrier_destroy(_threadBarrierPtr) } public func wait() { diff --git a/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift b/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift index 9f5e183447021..6d79bd124e976 100644 --- a/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift +++ b/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift @@ -69,13 +69,12 @@ public func _stdlib_thread_barrier_init( InitializeConditionVariable(barrier.pointee.cond!) #else barrier.pointee.mutex = UnsafeMutablePointer.allocate(capacity: 1) - if pthread_mutex_init(barrier.pointee.mutex!, nil) != 0 { - // FIXME: leaking memory. - return -1 - } barrier.pointee.cond = UnsafeMutablePointer.allocate(capacity: 1) - if pthread_cond_init(barrier.pointee.cond!, nil) != 0 { - // FIXME: leaking memory, leaking a mutex. + guard _stdlib_thread_barrier_mutex_and_cond_init(barrier) == 0 else { + barrier.pointee.mutex!.deinitialize(count: 1) + barrier.pointee.mutex!.deallocate() + barrier.pointee.cond!.deinitialize(count: 1) + barrier.pointee.cond!.deallocate() return -1 } #endif @@ -83,20 +82,27 @@ public func _stdlib_thread_barrier_init( return 0 } +private func _stdlib_thread_barrier_mutex_and_cond_init(_ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t>) -> CInt { + guard pthread_mutex_init(barrier.pointee.mutex!, nil) == 0 else { + return -1 + } + guard pthread_cond_init(barrier.pointee.cond!, nil) == 0 else { + pthread_mutex_destroy(barrier.pointee.mutex!) + return -1 + } + return 0 +} + public func _stdlib_thread_barrier_destroy( _ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t> -) -> CInt { +) { #if os(Windows) // Condition Variables do not need to be explicitly destroyed // Mutexes do not need to be explicitly destroyed #else - if pthread_cond_destroy(barrier.pointee.cond!) != 0 { - // FIXME: leaking memory, leaking a mutex. - return -1 - } - if pthread_mutex_destroy(barrier.pointee.mutex!) != 0 { - // FIXME: leaking memory. - return -1 + guard pthread_cond_destroy(barrier.pointee.cond!) == 0 && + pthread_mutex_destroy(barrier.pointee.mutex!) == 0 else { + fatalError("_stdlib_thread_barrier_destroy() failed") } #endif barrier.pointee.cond!.deinitialize(count: 1) @@ -105,7 +111,7 @@ public func _stdlib_thread_barrier_destroy( barrier.pointee.mutex!.deinitialize(count: 1) barrier.pointee.mutex!.deallocate() - return 0 + return } public func _stdlib_thread_barrier_wait( diff --git a/validation-test/stdlib/StringSlicesConcurrentAppend.swift b/validation-test/stdlib/StringSlicesConcurrentAppend.swift index 64441e7a184ea..942449e9dfdc8 100644 --- a/validation-test/stdlib/StringSlicesConcurrentAppend.swift +++ b/validation-test/stdlib/StringSlicesConcurrentAppend.swift @@ -111,8 +111,7 @@ StringTestSuite.test("SliceConcurrentAppend") { expectEqual(0, joinRet1) expectEqual(0, joinRet2) - ret = _stdlib_thread_barrier_destroy(barrierVar!) - expectEqual(0, ret) + _stdlib_thread_barrier_destroy(barrierVar!) barrierVar!.deinitialize(count: 1) barrierVar!.deallocate() From 3fff5dd064fd99eb905cbbec37cc8e6e9c19762c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 29 Jan 2020 09:40:38 -0800 Subject: [PATCH 10/31] [ConstraintSystem] Extend metatype instance type mismatch coverage Originally type mismatches associated with metatypes were only covered for coercions but fix coverage grew since then and now it makes sense to remove special case and let `repairFailures` take care of it. --- lib/Sema/CSSimplify.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 870eae283b2f5..2a24f5f95d981 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4068,16 +4068,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, auto result = matchTypes(instanceType1, instanceType2, subKind, subflags, locator.withPathElement(ConstraintLocator::InstanceType)); - if (shouldAttemptFixes() && result.isFailure()) { - auto *anchor = locator.getAnchor(); - if (anchor && isa(anchor)) { - auto *fix = - ContextualMismatch::create(*this, instanceType1, instanceType2, - getConstraintLocator(locator)); - conversionsOrFixes.push_back(fix); - break; - } - } + + // If matching of the instance types resulted in the failure make sure + // to give `repairFailure` a chance to run to attempt to fix the issue. + if (shouldAttemptFixes() && result.isFailure()) + break; + return result; } From 0bd1e61a20652577b00017c5cd087c2dbe73d2f9 Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Wed, 29 Jan 2020 10:09:32 -0800 Subject: [PATCH 11/31] [build][gardening] adjust one more framework path (#29529) This is a follow to #29507 addressing one more place in which we need to collate -F with the framework path Addresses rdar://problem/58934566 --- cmake/modules/AddSwift.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 931d751a03459..a89442f485d85 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -2133,7 +2133,10 @@ function(add_swift_target_library name) list(APPEND swiftlib_swift_compile_flags_all "-Fsystem" "${ios_support_frameworks_path}") list(APPEND swiftlib_c_compile_flags_all "-iframework" "${ios_support_frameworks_path}") - list(APPEND swiftlib_link_flags_all "-F" "${ios_support_frameworks_path}") + # We collate -F with the framework path to avoid unwanted deduplication + # of options by target_compile_options -- this way no undesired + # side effects are introduced should a new search path be added. + list(APPEND swiftlib_link_flags_all "-F${ios_support_frameworks_path}") endif() if(sdk IN_LIST SWIFT_APPLE_PLATFORMS AND SWIFTLIB_IS_SDK_OVERLAY) From 17d9d20275aac858104e92b3d33e0b5bdcfe0344 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jan 2020 10:23:18 -0800 Subject: [PATCH 12/31] Improve one of the comments in COWArrayOpts. --- lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp index c48c161cb28ed..b4265a2690aa3 100644 --- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp @@ -849,11 +849,16 @@ bool COWArrayOpt::hoistMakeMutable(ArraySemanticsCall MakeMutable, // Check whether we can hoist make_mutable based on the operations that are // in the loop. - // Note that in this case we don't verify that the array buffer is not aliased - // and therefore we must be conservative if the make_mutable is executed - // conditionally (i.e. doesn't dominate all exit blocks). - // The test SILOptimizer/cowarray_opt.sil: dont_hoist_if_executed_conditionally - // shows the problem. + // + // Hoisting make_mutable releases the original array storage. If an alias of + // that storage is accessed on any path reachable from the loop header that + // doesn't already pass through the make_mutable, then hoisting is + // illegal. hasLoopOnlyDestructorSafeArrayOperations checks that the array + // storage is not accessed within the loop. However, this does not include + // paths exiting the loop. Rather than analyzing code outside the loop, simply + // check that the original make_mutable dominates all exits. The test + // SILOptimizer/cowarray_opt.sil: dont_hoist_if_executed_conditionally shows + // the problem. if (hasLoopOnlyDestructorSafeArrayOperations() && dominatesExits) { // Done. We can hoist the make_mutable. // We still need the array uses later to check if we can add loads to From 0440e914519f1212e00e30e22192ced00a21cdef Mon Sep 17 00:00:00 2001 From: David Ungar Date: Wed, 29 Jan 2020 10:54:18 -0800 Subject: [PATCH 13/31] Try setting mod times explicitly to fix unreproducible ci failure. --- test/Frontend/type-fingerprint.swift | 29 ++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/test/Frontend/type-fingerprint.swift b/test/Frontend/type-fingerprint.swift index 8d9188e8362c4..aa08da31bedf2 100644 --- a/test/Frontend/type-fingerprint.swift +++ b/test/Frontend/type-fingerprint.swift @@ -12,16 +12,27 @@ // RUN: cp %S/Inputs/type-fingerprint/{main,a}.swift %t // RUN: cp %S/Inputs/type-fingerprint/ofm.json %t // RUN: cp %S/Inputs/type-fingerprint/b0.swift %t/b.swift + +// Seeing weird failure on CI, so set the mod times +// RUN: touch -t 200101010101 %t/*.swift + // RUN: cd %t && %swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental ./main.swift ./a.swift ./b.swift -module-name main -output-file-map ofm.json >&output1 -// RUN: cp %t/b.swiftdeps %t/b1.swiftdeps +// only-run-for-debugging: cp %t/b.swiftdeps %t/b1.swiftdeps // Change one type, but uses of all types get recompiled // RUN: cp %S/Inputs/type-fingerprint/b1.swift %t/b.swift + +// Seeing weird failure on CI, so ensure that b.swift is newer +// RUN: touch -t 200201010101 %t/* +// RUN: touch -t 200101010101 %t/*.swift +// RUN: touch -t 200301010101 %t/b.swift + // RUN: cd %t && %swiftc_driver -disable-type-fingerprints -enable-batch-mode -j2 -incremental -driver-show-incremental ./main.swift ./a.swift ./b.swift -module-name main -output-file-map ofm.json >&output2 -// RUN: cp %t/b.swiftdeps %t/b2.swiftdeps +// Save for debugging: +// only-run-for-debugging: cp %t/b.swiftdeps %t/b2.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output2 @@ -40,16 +51,26 @@ // RUN: cp %S/Inputs/type-fingerprint/{main,a}.swift %t // RUN: cp %S/Inputs/type-fingerprint/ofm.json %t // RUN: cp %S/Inputs/type-fingerprint/b0.swift %t/b.swift + +// Seeing weird failure on CI, so set the mod times +// RUN: touch -t 200101010101 %t/*.swift + // RUN: cd %t && %swiftc_driver -enable-batch-mode -j2 -incremental -driver-show-incremental ./main.swift ./a.swift ./b.swift -module-name main -output-file-map ofm.json >&output3 -// RUN: cp %t/b.swiftdeps %t/b3.swiftdeps +// only-run-for-debugging: cp %t/b.swiftdeps %t/b3.swiftdeps // Change one type, only uses of that type get recompiled // RUN: cp %S/Inputs/type-fingerprint/b1.swift %t/b.swift + +// Seeing weird failure on CI, so ensure that b.swift is newer +// RUN: touch -t 200201010101 %t/* +// RUN: touch -t 200101010101 %t/*.swift +// RUN: touch -t 200301010101 %t/b.swift + // RUN: cd %t && %swiftc_driver -enable-batch-mode -j2 -incremental -driver-show-incremental ./main.swift ./a.swift ./b.swift -module-name main -output-file-map ofm.json >&output4 -// RUN: cp %t/b.swiftdeps %t/b4.swiftdeps +// only-run-for-debugging: cp %t/b.swiftdeps %t/b4.swiftdeps // RUN: %FileCheck -check-prefix=CHECK-MAINB-RECOMPILED %s < %t/output4 From 4028ac245a8556353b5ba27ffe1c8f3d8f17fe03 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Wed, 29 Jan 2020 11:15:53 -0800 Subject: [PATCH 14/31] EscapeAnalysis: add support for access markers. This will be critical when OSSA relies on access markers everywhere and more passes are converted to OSSA. --- lib/SILOptimizer/Analysis/EscapeAnalysis.cpp | 1 + test/SILOptimizer/escape_analysis.sil | 22 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index 62e0059646990..e5b1eec09a578 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -122,6 +122,7 @@ SILValue EscapeAnalysis::getPointerBase(SILValue value) { case ValueKind::StructElementAddrInst: case ValueKind::StructExtractInst: case ValueKind::TupleElementAddrInst: + case ValueKind::BeginAccessInst: case ValueKind::UncheckedTakeEnumDataAddrInst: case ValueKind::UncheckedEnumDataInst: case ValueKind::MarkDependenceInst: diff --git a/test/SILOptimizer/escape_analysis.sil b/test/SILOptimizer/escape_analysis.sil index eddfac11b7f09..e510fbadcda74 100644 --- a/test/SILOptimizer/escape_analysis.sil +++ b/test/SILOptimizer/escape_analysis.sil @@ -1888,3 +1888,25 @@ bb0(%0 : @guaranteed $@sil_unowned Builtin.NativeObject): %1 = strong_copy_unowned_value %0 : $@sil_unowned Builtin.NativeObject return %1 : $Builtin.NativeObject } + +// Test begin_access. It should look like a derived pointer. +// CHECK-LABEL: CG of testAccessMarkerHelper +sil hidden @testAccessMarkerHelper : $@convention(thin) (@inout SomeData) -> () { +bb0(%0 : $*SomeData): + %1 = tuple () + return %1 : $() +} + +// CHECK-LABEL: CG of testAccessMarker +// CHECK-NEXT: Arg %0 Esc: A, Succ: (%0.1) +// CHECK-NEXT: Con [ref] %0.1 Esc: G, Succ: +// CHECK-LABEL: End +sil hidden @testAccessMarker : $@convention(thin) (@inout SomeData) -> () { +bb0(%0 : $*SomeData): + %1 = begin_access [modify] [static] %0 : $*SomeData + %2 = function_ref @testAccessMarkerHelper : $@convention(thin) (@inout SomeData) -> () + %3 = apply %2(%1) : $@convention(thin) (@inout SomeData) -> () + end_access %1 : $*SomeData + %5 = tuple () + return %5 : $() +} From b8960133ff57cade7f1d1254585c79502b820b8b Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 29 Jan 2020 11:45:58 -0800 Subject: [PATCH 15/31] Add source annotation to SILPrinter under flag -sil-print-sourceinfo (#29444) * Add source annotation to SILPrinter under flag -sil-print-sourceinfo rdar://58365252 --- include/swift/Basic/SourceManager.h | 3 +++ lib/Basic/SourceLoc.cpp | 15 ++++++++++++++- lib/SIL/SILPrinter.cpp | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index ed4f5dc34126e..7cf754731c1ab 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -243,6 +243,9 @@ class SourceManager { llvm::Optional resolveOffsetForEndOfLine(unsigned BufferId, unsigned Line) const; + /// Get the length of the line + llvm::Optional getLineLength(unsigned BufferId, unsigned Line) const; + SourceLoc getLocForLineCol(unsigned BufferId, unsigned Line, unsigned Col) const { auto Offset = resolveFromLineCol(BufferId, Line, Col); return Offset.hasValue() ? getLocForOffset(BufferId, Offset.getValue()) : diff --git a/lib/Basic/SourceLoc.cpp b/lib/Basic/SourceLoc.cpp index 7c66731e41fe1..76547ff2e91f6 100644 --- a/lib/Basic/SourceLoc.cpp +++ b/lib/Basic/SourceLoc.cpp @@ -331,10 +331,20 @@ SourceManager::resolveOffsetForEndOfLine(unsigned BufferId, return resolveFromLineCol(BufferId, Line, ~0u); } +llvm::Optional +SourceManager::getLineLength(unsigned BufferId, unsigned Line) const { + auto BegOffset = resolveFromLineCol(BufferId, Line, 0); + auto EndOffset = resolveFromLineCol(BufferId, Line, ~0u); + if (BegOffset && EndOffset) { + return EndOffset.getValue() - BegOffset.getValue(); + } + return None; +} + llvm::Optional SourceManager::resolveFromLineCol(unsigned BufferId, unsigned Line, unsigned Col) const { - if (Line == 0 || Col == 0) { + if (Line == 0) { return None; } const bool LineEnd = Col == ~0u; @@ -353,6 +363,9 @@ llvm::Optional SourceManager::resolveFromLineCol(unsigned BufferId, return None; } Ptr = LineStart; + if (Col == 0) { + return Ptr - InputBuf->getBufferStart(); + } // The <= here is to allow for non-inclusive range end positions at EOF for (; ; ++Ptr) { --Col; diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index 4900797283f88..976b9c790185c 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -64,6 +64,10 @@ llvm::cl::opt SILPrintDebugInfo("sil-print-debuginfo", llvm::cl::init(false), llvm::cl::desc("Include debug info in SIL output")); +llvm::cl::opt +SILPrintSourceInfo("sil-print-sourceinfo", llvm::cl::init(false), + llvm::cl::desc("Include source annotation in SIL output")); + llvm::cl::opt SILPrintGenericSpecializationInfo( "sil-print-generic-specialization-info", llvm::cl::init(false), llvm::cl::desc("Include generic specialization" @@ -618,7 +622,22 @@ class SILPrinter : public SILInstructionVisitor { } *this << '\n'; + const auto &SM = BB->getModule().getASTContext().SourceMgr; + Optional PrevLoc; for (const SILInstruction &I : *BB) { + if (SILPrintSourceInfo) { + auto CurSourceLoc = I.getLoc().getSourceLoc(); + if (CurSourceLoc.isValid()) { + if (!PrevLoc || SM.getLineNumber(CurSourceLoc) > SM.getLineNumber(PrevLoc->getSourceLoc())) { + auto Buffer = SM.findBufferContainingLoc(CurSourceLoc); + auto Line = SM.getLineNumber(CurSourceLoc); + auto LineLength = SM.getLineLength(Buffer, Line); + PrintState.OS << " // " << SM.extractText({SM.getLocForLineCol(Buffer, Line, 0), LineLength.getValueOr(0)}) << + "\tSourceLoc: " << SM.getDisplayNameForLoc(CurSourceLoc) << ":" << Line << "\n"; + PrevLoc = I.getLoc(); + } + } + } Ctx.printInstructionCallBack(&I); if (SILPrintGenericSpecializationInfo) { if (auto AI = ApplySite::isa(const_cast(&I))) From 3c86061de8a2a6474860ae209b3e70ce6dc17866 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 28 Jan 2020 17:11:15 -0800 Subject: [PATCH 16/31] Sema: Fix module interface printing of inherited generic initializers Make sure we use the sugared form of GenericTypeParamType and not the canonical type. Fixes . --- lib/Sema/CodeSynthesis.cpp | 6 ++---- test/ModuleInterface/inherited-generic-parameters.swift | 5 +++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index a087a878ba1d5..85e8249f4c9bd 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -411,10 +411,8 @@ configureGenericDesignatedInitOverride(ASTContext &ctx, auto *gp = cast(type); if (gp->getDepth() < superclassDepth) return Type(gp).subst(subMap); - return CanGenericTypeParamType::get( - gp->getDepth() - superclassDepth + depth, - gp->getIndex(), - ctx); + return genericParams->getParams()[gp->getIndex()] + ->getDeclaredInterfaceType(); }; auto lookupConformanceFn = diff --git a/test/ModuleInterface/inherited-generic-parameters.swift b/test/ModuleInterface/inherited-generic-parameters.swift index 4a538a33942b7..1be75a69d7311 100644 --- a/test/ModuleInterface/inherited-generic-parameters.swift +++ b/test/ModuleInterface/inherited-generic-parameters.swift @@ -15,6 +15,10 @@ public class Base { // CHECK-NEXT: public init(x: @escaping (In) -> Out) public init(x: @escaping (In) -> Out) {} + +// CHECK-NEXT: public init(_: A, _: A) + public init(_: A, _: A) {} + // CHECK: } } @@ -22,6 +26,7 @@ public class Base { public class Derived : Base { // CHECK-NEXT: {{(@objc )?}}deinit // CHECK-NEXT: override public init(x: @escaping (T) -> T) +// CHECK-NEXT: override public init(_ argument: A, _ argument: A) // CHECK-NEXT: } } From 2e1e4284ac3ebc64a0cedee59aa88b1c7ec5b3be Mon Sep 17 00:00:00 2001 From: David Ungar Date: Wed, 29 Jan 2020 13:31:50 -0800 Subject: [PATCH 17/31] Added ability to add fingerprint via # --- include/swift/AST/FineGrainedDependencies.h | 1 + ...endenciesSourceFileDepGraphConstructor.cpp | 37 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/FineGrainedDependencies.h b/include/swift/AST/FineGrainedDependencies.h index 50cba234d0e46..49f0b755f9e39 100644 --- a/include/swift/AST/FineGrainedDependencies.h +++ b/include/swift/AST/FineGrainedDependencies.h @@ -799,6 +799,7 @@ class SourceFileDepGraph { compoundNamesByRDK); static constexpr char noncascadingOrPrivatePrefix = '#'; + static constexpr char nameFingerprintSeparator = ','; static std::string noncascading(std::string name); diff --git a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp index a2cb94342861f..eba5fe33192bb 100644 --- a/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp +++ b/lib/AST/FineGrainedDependenciesSourceFileDepGraphConstructor.cpp @@ -848,12 +848,29 @@ bool swift::fine_grained_dependencies::emitReferenceDependencies( static StringRef stripPrefix(const StringRef name) { return name.ltrim(SourceFileDepGraph::noncascadingOrPrivatePrefix); } +static StringRef stripFingerprint(const StringRef nameAndFingerprint) { + return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) + .first; +} +static StringRef stripName(const StringRef nameAndFingerprint) { + return nameAndFingerprint.split(SourceFileDepGraph::nameFingerprintSeparator) + .second; +} +static std::string extractName(const StringRef prefixNameFingerprint) { + return stripFingerprint(stripPrefix(prefixNameFingerprint)).str(); +} +static Optional extractFingerprint( + const StringRef prefixNameFingerprint) { + const auto fp = stripName(stripPrefix(prefixNameFingerprint)); + return fp.empty() ? None : Optional(fp.str()); +} static std::vector getBaseNameProvides(ArrayRef simpleNames) { std::vector result; for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint("", stripPrefix(n).str(), None)); + result.push_back(ContextNameFingerprint("", extractName(n), + extractFingerprint(n))); return result; } @@ -861,7 +878,8 @@ static std::vector getMangledHolderProvides(ArrayRef simpleNames) { std::vector result; for (StringRef n : simpleNames) - result.push_back(ContextNameFingerprint(stripPrefix(n).str(), "", None)); + result.push_back(ContextNameFingerprint(extractName(n), "", + extractFingerprint(n))); return result; } @@ -869,12 +887,15 @@ static std::vector getCompoundProvides( ArrayRef> compoundNames) { std::vector result; for (const auto &p : compoundNames) - result.push_back(ContextNameFingerprint(stripPrefix(p.first), - stripPrefix(p.second), None)); + result.push_back(ContextNameFingerprint(extractName(p.first), + extractName(p.second), + extractFingerprint(p.second))); return result; } -static bool cascades(const std::string &s) { return s.empty() || s[0] != SourceFileDepGraph::noncascadingOrPrivatePrefix; } +static bool cascades(const std::string &s) { + return s.empty() || s[0] != SourceFileDepGraph::noncascadingOrPrivatePrefix; +} // Use '_' as a prefix for a file-private member static bool isPrivate(const std::string &s) { @@ -904,7 +925,8 @@ getCompoundDepends( // (On Linux, the compiler needs more verbosity than: // result.push_back({{n, "", false}, cascades(n)}); result.push_back( - std::make_pair(std::make_tuple(stripPrefix(n), std::string(), false), cascades(n))); + std::make_pair(std::make_tuple(stripPrefix(n), std::string(), false), + cascades(n))); } for (auto &p : compoundNames) { // Likewise, for Linux expand the following out: @@ -932,7 +954,8 @@ SourceFileDepGraph SourceFileDepGraph::simulateLoad( SourceFileDepGraphConstructor c( swiftDepsFilename, includePrivateDeps, hadCompilationError, interfaceHash, getSimpleDepends(simpleNamesByRDK[dependsTopLevel]), - getCompoundDepends(simpleNamesByRDK[dependsNominal], compoundNamesByRDK[dependsMember]), + getCompoundDepends(simpleNamesByRDK[dependsNominal], + compoundNamesByRDK[dependsMember]), getSimpleDepends(simpleNamesByRDK[dependsDynamicLookup]), getExternalDepends(simpleNamesByRDK[dependsExternal]), {}, // precedence groups From e13ea48dcdbee74a5641d98b463737411a1473a7 Mon Sep 17 00:00:00 2001 From: Chris Amanse Date: Wed, 29 Jan 2020 14:14:12 -0800 Subject: [PATCH 18/31] Private method should be for non-Windows only --- stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift b/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift index 6d79bd124e976..54517a901b117 100644 --- a/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift +++ b/stdlib/private/SwiftPrivateThreadExtras/ThreadBarriers.swift @@ -82,6 +82,7 @@ public func _stdlib_thread_barrier_init( return 0 } +#if !os(Windows) private func _stdlib_thread_barrier_mutex_and_cond_init(_ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t>) -> CInt { guard pthread_mutex_init(barrier.pointee.mutex!, nil) == 0 else { return -1 @@ -92,6 +93,7 @@ private func _stdlib_thread_barrier_mutex_and_cond_init(_ barrier: UnsafeMutable } return 0 } +#endif public func _stdlib_thread_barrier_destroy( _ barrier: UnsafeMutablePointer<_stdlib_thread_barrier_t> From d2ad3dc3259c9a8d3eadcf58a4ac7977d040ca8b Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 29 Jan 2020 15:29:13 -0800 Subject: [PATCH 19/31] [NFC] Commit a regression test for rdar://58960414 --- .../Headers/CategoryOverrides.h | 13 ++++++++ .../PrivateHeaders/Private.h | 4 +++ ...bjc_redeclared_properties_categories.swift | 30 +++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/Headers/CategoryOverrides.h b/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/Headers/CategoryOverrides.h index 03c13252ac497..4c66878d60f8a 100644 --- a/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/Headers/CategoryOverrides.h +++ b/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/Headers/CategoryOverrides.h @@ -19,3 +19,16 @@ typedef struct SomeStruct_s { @interface MyDerivedClass : MyBaseClass @property (nonatomic, strong, nullable) Base *derivedMember; @end + +typedef enum { + Caster, + Grantulated, + Confectioners, + Cane, + Demerara, + Turbinado, +} RefinedSugar /*NS_REFINED_FOR_SWIFT*/ __attribute__((swift_private)); + +@interface Refinery : Base +@property (nonatomic, readonly) RefinedSugar sugar /*NS_REFINED_FOR_SWIFT*/ __attribute__((swift_private)); +@end diff --git a/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/PrivateHeaders/Private.h b/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/PrivateHeaders/Private.h index d52dd6c550ec9..0c4ed45702bca 100644 --- a/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/PrivateHeaders/Private.h +++ b/test/ClangImporter/Inputs/frameworks/CategoryOverrides.framework/PrivateHeaders/Private.h @@ -14,3 +14,7 @@ @interface MyBaseClass () @end + +@interface Refinery () +@property (nonatomic, readwrite) RefinedSugar sugar; +@end diff --git a/test/ClangImporter/objc_redeclared_properties_categories.swift b/test/ClangImporter/objc_redeclared_properties_categories.swift index 0281251b87a75..7cf1ae534e37b 100644 --- a/test/ClangImporter/objc_redeclared_properties_categories.swift +++ b/test/ClangImporter/objc_redeclared_properties_categories.swift @@ -1,11 +1,11 @@ // RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -typecheck -F %S/Inputs/frameworks %s 2>&1 | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-PUBLIC %s // RUN: echo '#import ' > %t.h -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.h %s 2>&1 | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s --allow-empty +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.h %s 2>&1 | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s --allow-empty // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-pch -F %S/Inputs/frameworks -o %t.pch %t.h -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.pch %s 2>&1 | %FileCheck --allow-empty -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck --allow-empty -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.pch %s 2>&1 | %FileCheck --allow-empty -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/frameworks -enable-objc-interop -import-objc-header %t.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck --allow-empty -check-prefix=CHECK -check-prefix=CHECK-PRIVATE %s import CategoryOverrides @@ -54,3 +54,27 @@ func takesABaseClass(_ x: MyBaseClass) { // CHECK-PRIVATE-NOT: has no member 'derivedMember' x.derivedMember = Base() } + +// A category declared in a (private) header can introduce overrides of a +// property that has mismatched Swift naming conventions. If we see a +// non-__attribute__((swift_private)) decl, sometimes it comes in too. + +extension Refinery { + public enum RefinedSugar { + case caster + case grantulated + case confectioners + case cane + case demerara + case turbinado + } + + public var sugar: Refinery.RefinedSugar { + return .caster // RefinedSugar(self.__sugar) + } +} + +func takesARefinery(_ x: Refinery) { + // CHECK: cannot assign to property: 'sugar' is a get-only property + x.sugar = .caster +} From 286781fc3e8325456278755ebc334cd2e9b7ab49 Mon Sep 17 00:00:00 2001 From: David Ungar Date: Wed, 29 Jan 2020 16:48:42 -0800 Subject: [PATCH 20/31] Add a unit test for an individual node change, & add ability to set fingerprints in unit tests. --- .../Driver/FineGrainedDependencyDriverGraph.h | 2 +- .../FineGrainedDependencyDriverGraph.cpp | 7 ++++++- .../FineGrainedDependencyGraphTests.cpp | 16 ++++++++++++++ ...peBodyFingerprintsDependencyGraphTests.cpp | 21 +++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/swift/Driver/FineGrainedDependencyDriverGraph.h b/include/swift/Driver/FineGrainedDependencyDriverGraph.h index af7b2f5116c06..9d1e9954d2c15 100644 --- a/include/swift/Driver/FineGrainedDependencyDriverGraph.h +++ b/include/swift/Driver/FineGrainedDependencyDriverGraph.h @@ -437,7 +437,7 @@ class ModuleDepGraph { /// Call \p fn for each node whose key matches \p key. void forEachMatchingNode(const DependencyKey &key, - function_ref) const; + function_ref) const; void forEachNodeInJob(StringRef swiftDeps, function_ref) const; diff --git a/lib/Driver/FineGrainedDependencyDriverGraph.cpp b/lib/Driver/FineGrainedDependencyDriverGraph.cpp index dd997a283f1ca..5bda1956f9b4c 100644 --- a/lib/Driver/FineGrainedDependencyDriverGraph.cpp +++ b/lib/Driver/FineGrainedDependencyDriverGraph.cpp @@ -171,6 +171,11 @@ ModuleDepGraph::findJobsToRecompileWhenNodesChange< std::unordered_set>( const std::unordered_set &); +template std::vector +ModuleDepGraph::findJobsToRecompileWhenNodesChange< + std::vector>( + const std::vector &); + std::vector ModuleDepGraph::computeSwiftDepsFromNodes( ArrayRef nodes) const { llvm::StringSet<> swiftDepsOfNodes; @@ -441,7 +446,7 @@ void ModuleDepGraph::forEachNode( void ModuleDepGraph::forEachMatchingNode( const DependencyKey &key, - function_ref fn) const { + function_ref fn) const { nodeMap.forEachValueMatching( key, [&](const std::string &, ModuleDepGraphNode *n) { fn(n); }); } diff --git a/unittests/Driver/FineGrainedDependencyGraphTests.cpp b/unittests/Driver/FineGrainedDependencyGraphTests.cpp index b8af2dddc03a7..28e8286866d9e 100644 --- a/unittests/Driver/FineGrainedDependencyGraphTests.cpp +++ b/unittests/Driver/FineGrainedDependencyGraphTests.cpp @@ -808,3 +808,19 @@ TEST(ModuleDepGraph, MutualInterfaceHash) { const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } + +TEST(ModuleDepGraph, DisabledTypeBodyFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/ false); + + graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); + graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); + graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); + + { + const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job1); + EXPECT_EQ(3u, jobs.size()); + EXPECT_TRUE(contains(jobs, &job0)); + EXPECT_TRUE(contains(jobs, &job1)); + EXPECT_TRUE(contains(jobs, &job2)); + } +} diff --git a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp index ff06b0344c252..041cc9c2ee416 100644 --- a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp +++ b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp @@ -808,3 +808,24 @@ TEST(ModuleDepGraphWithTypeBodyFingerprints, MutualInterfaceHash) { const auto jobs = graph.findJobsToRecompileWhenWholeJobChanges(&job0); EXPECT_TRUE(contains(jobs, &job1)); } + +TEST(ModuleDepGraph, EnabledTypeBodyFingerprints) { + ModuleDepGraph graph(/*EnableTypeFingerprints=*/ true); + + graph.simulateLoad(&job0, {{dependsNominal, {"B2"}}}); + graph.simulateLoad(&job1, {{providesNominal, {"B1", "B2"}}}); + graph.simulateLoad(&job2, {{dependsNominal, {"B1"}}}); + + + const DependencyKey k = DependencyKey(NodeKind::nominal, + DeclAspect::interface, "B1", ""); + std::vector changedNodes; + graph.forEachMatchingNode( + k, + [&](ModuleDepGraphNode* n) {changedNodes.push_back(n);}); + { + const auto jobs = graph.findJobsToRecompileWhenNodesChange(changedNodes); + EXPECT_TRUE(contains(jobs, &job2)); + EXPECT_FALSE(contains(jobs, &job0)); + } +} From 9bd638579de91b68c77219623ae987008fa4e6dd Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 29 Jan 2020 14:51:28 -0800 Subject: [PATCH 21/31] Sema: Fix duplicate diagnostic spam with 'Self' in properties Fixes / . --- lib/Sema/TypeCheckDeclPrimary.cpp | 11 +++++++---- test/type/self.swift | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index cb4f75303721a..5659c6f8912aa 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1336,13 +1336,13 @@ class DeclChecker : public DeclVisitor { } if (VD->getDeclContext()->getSelfClassDecl()) { - checkDynamicSelfType(VD, VD->getValueInterfaceType()); - if (VD->getValueInterfaceType()->hasDynamicSelfType()) { if (VD->hasStorage()) VD->diagnose(diag::dynamic_self_in_stored_property); else if (VD->isSettable(nullptr)) VD->diagnose(diag::dynamic_self_in_mutable_property); + else + checkDynamicSelfType(VD, VD->getValueInterfaceType()); } } @@ -2153,8 +2153,11 @@ class DeclChecker : public DeclVisitor { checkExplicitAvailability(FD); - if (FD->getDeclContext()->getSelfClassDecl()) - checkDynamicSelfType(FD, FD->getResultInterfaceType()); + // Skip this for accessors, since we should have diagnosed the + // storage itself. + if (!isa(FD)) + if (FD->getDeclContext()->getSelfClassDecl()) + checkDynamicSelfType(FD, FD->getResultInterfaceType()); checkDefaultArguments(FD->getParameters()); diff --git a/test/type/self.swift b/test/type/self.swift index bc2fa859cb96b..10e27b93a4e6e 100644 --- a/test/type/self.swift +++ b/test/type/self.swift @@ -270,3 +270,20 @@ class Foo { Self.value * 2 }() } + +// https://bugs.swift.org/browse/SR-11681 - duplicate diagnostics +struct Box { + let boxed: T +} + +class Boxer { + lazy var s = Box(boxed: self as! Self) + // expected-error@-1 {{stored property cannot have covariant 'Self' type}} + // expected-error@-2 {{mutable property cannot have covariant 'Self' type}} + + var t = Box(boxed: Self()) + // expected-error@-1 {{stored property cannot have covariant 'Self' type}} + // expected-error@-2 {{covariant 'Self' type cannot be referenced from a stored property initializer}} + + required init() {} +} From f4a5301bfd6c71e4673442f7314d74a1d4ed3db8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 29 Jan 2020 22:36:06 -0800 Subject: [PATCH 22/31] Sema: Fix crash when property type references type alias with unsatisfied requirements The fix for did not handle properties because those types are resolved using the archetype resolver. We would bail out early because of a bogus early return that can just be removed. Fixes . --- lib/Sema/TypeCheckType.cpp | 4 ---- test/Constraints/conditionally_defined_types.swift | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index ad3ab2f99e947..483c9db23cb4d 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1463,10 +1463,6 @@ static Type resolveNestedIdentTypeComponent( inferredAssocType); } - // At this point, we need to have resolved the type of the member. - if (memberType->hasError()) - return memberType; - // If there are generic arguments, apply them now. return applyGenericArguments(memberType, resolution, comp, options); }; diff --git a/test/Constraints/conditionally_defined_types.swift b/test/Constraints/conditionally_defined_types.swift index 2107fa6e6faca..193d40a7f766d 100644 --- a/test/Constraints/conditionally_defined_types.swift +++ b/test/Constraints/conditionally_defined_types.swift @@ -222,3 +222,15 @@ let _ = Conforms.Decl4.Decl2.self // expected-error {{type 'Z2.T' (aka 'Y let _ = Conforms.Decl4.Decl3.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}} let _ = Conforms.Decl4.Decl4.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}} let _ = Conforms.Decl4.Decl5.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}} + +// rdar://problem/45271663 +protocol PP { associatedtype V } +struct SS {} +enum EE {} +extension EE : PP where A : PP, B : PP { typealias V = EE } + +protocol P2 { associatedtype U } +func f(s: SS) -> SS> where PI.U : PP, PI.V : P2 { + let t: EE.V + // expected-error@-1 {{type 'PI.V.U' does not conform to protocol 'PP'}} +} From be37141b0fc5ad82dafbaaed2936a5a62c4de1e0 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Wed, 29 Jan 2020 23:56:09 -0800 Subject: [PATCH 23/31] Revert "build: simplify version tracking logic" --- lib/Basic/CMakeLists.txt | 58 ++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt index fd60da8ff5379..6cd7577ce3f93 100644 --- a/lib/Basic/CMakeLists.txt +++ b/lib/Basic/CMakeLists.txt @@ -11,32 +11,59 @@ else() set(UUID_INCLUDE "${UUID_INCLUDE_DIRS}") endif() -function(generate_revision_inc revision_inc_var name dir) - find_first_existing_vc_file("${dir}" ${name}_vc) +# Figure out if we can track VC revisions. +# FIXME: Copied from Clang. +function(find_first_existing_file out_var) + foreach(file ${ARGN}) + if(EXISTS "${file}") + set(${out_var} "${file}" PARENT_SCOPE) + return() + endif() + endforeach() +endfunction() - # Create custom target to generate the VC revision include. - set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/${name}Revision.inc") +macro(find_first_existing_vc_file out_var path) + find_first_existing_file(${out_var} + "${path}/.git/logs/HEAD" # Git + "${path}/.svn/wc.db" # SVN 1.7 + "${path}/.svn/entries" # SVN 1.6 + ) +endmacro() - set(generate_vcs_version_script "${LLVM_MAIN_SRC_DIR}/cmake/modules/GenerateVersionFromVCS.cmake") +set(generate_vcs_version_script "${LLVM_MAIN_SRC_DIR}/cmake/modules/GenerateVersionFromVCS.cmake") - add_custom_command(OUTPUT "${version_inc}" - DEPENDS "${${name}_vc}" "${generate_vcs_version_script}" - COMMAND ${CMAKE_COMMAND} "-DNAMES=$" - "-D$_SOURCE_DIR=${dir}" - "-DHEADER_FILE=${version_inc}" - -P "${generate_vcs_version_script}") +function(generate_revision_inc revision_inc_var name dir) + find_first_existing_vc_file(dep_file "${dir}") + # Create custom target to generate the VC revision include. + set(revision_inc "${CMAKE_CURRENT_BINARY_DIR}/${name}Revision.inc") + string(TOUPPER ${name} upper_name) + if(DEFINED dep_file) + add_custom_command(OUTPUT "${revision_inc}" + DEPENDS "${dep_file}" "${generate_vcs_version_script}" + COMMAND + ${CMAKE_COMMAND} "-DNAMES=${upper_name}" + "-D${upper_name}_SOURCE_DIR=${dir}" + "-DHEADER_FILE=${revision_inc}" + -P "${generate_vcs_version_script}") + else() + # Generate an empty Revision.inc file if we are not using git or SVN. + file(WRITE "${revision_inc}" "") + endif() # Mark the generated header as being generated. - set_source_files_properties("${version_inc}" + set_source_files_properties("${revision_inc}" PROPERTIES GENERATED TRUE HEADER_FILE_ONLY TRUE) - set(${revision_inc_var} ${version_inc} PARENT_SCOPE) + set(${revision_inc_var} ${revision_inc} PARENT_SCOPE) endfunction() generate_revision_inc(llvm_revision_inc LLVM "${LLVM_MAIN_SRC_DIR}") generate_revision_inc(clang_revision_inc Clang "${CLANG_MAIN_SRC_DIR}") generate_revision_inc(swift_revision_inc Swift "${SWIFT_SOURCE_DIR}") +set(version_inc_files + ${llvm_revision_inc} ${clang_revision_inc} ${swift_revision_inc}) + add_swift_host_library(swiftBasic STATIC AnyValue.cpp Cache.cpp @@ -68,10 +95,7 @@ add_swift_host_library(swiftBasic STATIC Unicode.cpp UUID.cpp Version.cpp - - ${llvm_revision_inc} - ${clang_revision_inc} - ${swift_revision_inc} + ${version_inc_files} # Platform-specific TaskQueue implementations Unix/TaskQueue.inc From dcaa950f7b42893bec920f73223cc3d3bdabf7f9 Mon Sep 17 00:00:00 2001 From: Luciano Almeida Date: Thu, 30 Jan 2020 12:28:32 -0300 Subject: [PATCH 24/31] [CSDiag] Removing unused FailureDiagnosis::visitTryExpr --- lib/Sema/CSDiag.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 1910e242ce091..ddb0d6d86c42d 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -221,7 +221,6 @@ class FailureDiagnosis :public ASTVisitor{ validateContextualType(Type contextualType, ContextualTypePurpose CTP); bool visitExpr(Expr *E); - bool visitTryExpr(TryExpr *E); bool visitApplyExpr(ApplyExpr *AE); bool visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E); @@ -1425,12 +1424,6 @@ visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E) { return false; } -/// A TryExpr doesn't change it's argument, nor does it change the contextual -/// type. -bool FailureDiagnosis::visitTryExpr(TryExpr *E) { - return visit(E->getSubExpr()); -} - bool FailureDiagnosis::visitExpr(Expr *E) { // Check each of our immediate children to see if any of them are // independently invalid. From 2d10a8a9a0c5ac7f0de5cf8bda980dbad0b5e4e2 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 30 Jan 2020 09:45:29 -0800 Subject: [PATCH 25/31] [ConstraintSystem] Extend function type conversion mismatch coverage Originally type mismatches associated with conversions between function types were only covered for coercions and assignments but fix coverage grew since then and now it makes sense to remove special case and let `repairFailures` take care of it. --- lib/Sema/CSSimplify.cpp | 17 ++--------------- test/Constraints/enum_cases.swift | 8 ++++---- test/Constraints/tuple_arguments.swift | 3 ++- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 2a24f5f95d981..fabf1338b2a97 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4083,21 +4083,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, auto result = matchFunctionTypes(func1, func2, kind, flags, locator); - if (shouldAttemptFixes() && result.isFailure()) { - // If this is a contextual type mismatch failure - // let's give the solver a chance to "fix" it. - if (auto last = locator.last()) { - if (last->is()) - break; - } - - // If this is a type mismatch in assignment, we don't really care - // (yet) was it argument or result type mismatch, let's produce a - // diagnostic which mentions both function types. - auto *anchor = locator.getAnchor(); - if (anchor && isa(anchor)) - break; - } + if (shouldAttemptFixes() && result.isFailure()) + break; return result; } diff --git a/test/Constraints/enum_cases.swift b/test/Constraints/enum_cases.swift index 5a918dacd6fa1..dbfe34ec5ca59 100644 --- a/test/Constraints/enum_cases.swift +++ b/test/Constraints/enum_cases.swift @@ -22,14 +22,14 @@ let _ = arr.map(E.bar) // Ok let _ = arr.map(E.two) // expected-error {{cannot invoke 'map' with an argument list of type '(@escaping (Int, Int) -> E)'}} // expected-note@-1{{expected an argument list of type '((Self.Element) throws -> T)'}} -let _ = arr.map(E.tuple) // expected-error {{cannot invoke 'map' with an argument list of type '(@escaping ((x: Int, y: Int)) -> E)'}} -// expected-note@-1{{expected an argument list of type '((Self.Element) throws -> T)'}} +let _ = arr.map(E.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> E' to expected argument type '(String) throws -> T'}} +// expected-error@-1 {{generic parameter 'T' could not be inferred}} let _ = arr.map(G_E.foo) // Ok let _ = arr.map(G_E.bar) // Ok let _ = arr.map(G_E.two) // expected-error {{cannot convert value of type '(String, String) -> G_E' to expected argument type '(String) throws -> G_E'}} -let _ = arr.map(G_E.tuple) // expected-error {{cannot invoke 'map' with an argument list of type '(@escaping ((x: Int, y: Int)) -> G_E)'}} -// expected-note@-1{{expected an argument list of type '((Self.Element) throws -> T)'}} +let _ = arr.map(G_E.tuple) // expected-error {{cannot convert value of type '((x: Int, y: Int)) -> G_E' to expected argument type '(String) throws -> T'}} +// expected-error@-1 {{generic parameter 'T' could not be inferred}} let _ = E.foo("hello") // expected-error {{missing argument label 'bar:' in call}} let _ = E.bar("hello") // Ok diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift index 3011132d48d78..0b1852ea221ed 100644 --- a/test/Constraints/tuple_arguments.swift +++ b/test/Constraints/tuple_arguments.swift @@ -1702,7 +1702,8 @@ _ = x.map { (_: ()) in () } // https://bugs.swift.org/browse/SR-9470 do { func f(_: Int...) {} - let _ = [(1, 2, 3)].map(f) // expected-error {{cannot invoke 'map' with an argument list of type '(@escaping (Int...) -> ())'}} + let _ = [(1, 2, 3)].map(f) // expected-error {{cannot convert value of type '(Int...) -> ()' to expected argument type '((Int, Int, Int)) throws -> T'}} + // expected-error@-1 {{generic parameter 'T' could not be inferred}} } // rdar://problem/48443263 - cannot convert value of type '() -> Void' to expected argument type '(_) -> Void' From d171b30d097752bf72958f1f28496961e70e5fe6 Mon Sep 17 00:00:00 2001 From: David Ungar Date: Thu, 30 Jan 2020 09:48:49 -0800 Subject: [PATCH 26/31] Allow fine-grained-dependency-include-intrafile in tests for compatibility with enabled type fingerprints. --- include/swift/Option/Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index dd2d0c0d026f4..dbadf83aa6318 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -191,7 +191,7 @@ HelpText<"Emit dot files every time driver imports an fine-grained swiftdeps fil def fine_grained_dependency_include_intrafile : Flag<["-"], "fine-grained-dependency-include-intrafile">, -InternalDebugOpt, +Flags<[FrontendOption, HelpHidden]>, HelpText<"Include within-file dependencies.">; def emit_fine_grained_dependency_sourcefile_dot_files : From 458ae7b6f94dbc47c2412508df7128b79cb7f901 Mon Sep 17 00:00:00 2001 From: David Ungar Date: Thu, 30 Jan 2020 09:49:18 -0800 Subject: [PATCH 27/31] Use -fine-grained-dependency-include-intrafile for compatibility with type fingerprints. --- .../NameBinding/reference-dependencies-fine.swift | 11 +++++++---- .../reference-dependencies-members-fine.swift | 15 +++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/test/NameBinding/reference-dependencies-fine.swift b/test/NameBinding/reference-dependencies-fine.swift index f9e4b38ab5f65..e15fbcf24e500 100644 --- a/test/NameBinding/reference-dependencies-fine.swift +++ b/test/NameBinding/reference-dependencies-fine.swift @@ -4,10 +4,11 @@ // RUN: %empty-directory(%t) // RUN: cp %s %t/main.swift -// RUN: %target-swift-frontend -enable-fine-grained-dependencies -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps +// Need -fine-grained-dependency-include-intrafile to be invarient wrt type-body-fingerprints enabled/disabled +// RUN: %target-swift-frontend -enable-fine-grained-dependencies -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps // Check that the output is deterministic. -// RUN: %target-swift-frontend -enable-fine-grained-dependencies -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps +// RUN: %target-swift-frontend -enable-fine-grained-dependencies -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps // Merge each entry onto one line and sort to overcome order differences // RUN: %S/../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps @@ -339,7 +340,8 @@ struct Outer { } } -// CHECK-TOPLEVEL-DAG: topLevel interface '' privateFunc false +// CHECK-TOPLEVEL-DAG: topLevel interface '' privateFunc true +// CHECK-TOPLEVEL-DAG: topLevel implementation '' privateFunc true private func privateFunc() {} // CHECK-TOPLEVEL-DAG: topLevel interface '' topLevel1 false @@ -498,7 +500,8 @@ struct Sentinel2 {} // CHECK-POTENTIALMEMBER-DAG: potentialMember interface 4main13PrivateProto3P '' false // CHECK-NOMINAL-2-DAG: nominal interface Sa '' false -// CHECK-NOMINAL-2-DAG: nominal interface Sb '' false +// CHECK-NOMINAL-2-DAG: nominal interface Sb '' true +// CHECK-NOMINAL-2-DAG: nominal implementation Sb '' true // CHECK-NOMINAL-2-DAG: nominal interface 4main18ClassFromOtherFileC '' false // CHECK-NOMINAL-2-DAG: nominal interface SL '' false // CHECK-NOMINAL-2-DAG: nominal interface s25ExpressibleByFloatLiteralP '' false diff --git a/test/NameBinding/reference-dependencies-members-fine.swift b/test/NameBinding/reference-dependencies-members-fine.swift index c1c9ba58dff74..bbb99fbfb3e98 100644 --- a/test/NameBinding/reference-dependencies-members-fine.swift +++ b/test/NameBinding/reference-dependencies-members-fine.swift @@ -4,9 +4,11 @@ // RUN: %empty-directory(%t) // RUN: cp %s %t/main.swift -// RUN: %target-swift-frontend -enable-fine-grained-dependencies -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps -// RUN: %target-swift-frontend -enable-fine-grained-dependencies -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps +// Need -fine-grained-dependency-include-intrafile to be invarient wrt type-body-fingerprints enabled/disabled +// RUN: %target-swift-frontend -enable-fine-grained-dependencies -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t.swiftdeps + +// RUN: %target-swift-frontend -enable-fine-grained-dependencies -fine-grained-dependency-include-intrafile -typecheck -primary-file %t/main.swift %S/Inputs/reference-dependencies-members-helper.swift -emit-reference-dependencies-path - > %t-2.swiftdeps // RUN: %S/../Inputs/process_fine_grained_swiftdeps.sh <%t.swiftdeps >%t-processed.swiftdeps // RUN: %S/../Inputs/process_fine_grained_swiftdeps.sh <%t-2.swiftdeps >%t-2-processed.swiftdeps @@ -14,7 +16,6 @@ // RUN: %FileCheck -check-prefix=PROVIDES-NOMINAL %s < %t-processed.swiftdeps // RUN: %FileCheck -check-prefix=PROVIDES-NOMINAL-2 %s < %t-processed.swiftdeps -// RUN: %FileCheck -check-prefix=PROVIDES-NOMINAL-NEGATIVE %s < %t-processed.swiftdeps // RUN: %FileCheck -check-prefix=PROVIDES-MEMBER %s < %t-processed.swiftdeps // RUN: %FileCheck -check-prefix=PROVIDES-MEMBER-NEGATIVE %s < %t-processed.swiftdeps // RUN: %FileCheck -check-prefix=DEPENDS-NOMINAL %s < %t-processed.swiftdeps @@ -54,15 +55,13 @@ protocol SomeProto {} // DEPENDS-MEMBER-DAG: member interface 4main10OtherClassC deinit false extension OtherClass : SomeProto {} -// PROVIDES-NOMINAL-NEGATIVE-NOT: nominal implementation 4main11OtherStructV '' true -// PROVIDES-NOMINAL-NEGATIVE-NOT: nominal interface 4main11OtherStructV '' true -// DEPENDS-NOMINAL-DAG: nominal interface 4main11OtherStructV '' false +// PROVIDES-NOMINAL-DAG: nominal implementation 4main11OtherStructV '' true +// PROVIDES-NOMINAL-DAG: nominal interface 4main11OtherStructV '' true extension OtherStruct { // PROVIDES-MEMBER-DAG: potentialMember interface 4main11OtherStructV '' true // PROVIDES-MEMBER-DAG: member interface 4main11OtherStructV foo true // PROVIDES-MEMBER-DAG: member interface 4main11OtherStructV bar true - // PROVIDES-MEMBER-NEGATIVE-NOT: member interface 4main11OtherStructV baz true - // DEPENDS-MEMBER-DAG: member interface 4main11OtherStructV baz false + // PROVIDES-MEMBER-DAG: member interface 4main11OtherStructV baz true // DEPENDS-MEMBER-NEGATIVE-NOT:: potentialMember interface 4main11OtherStructV baz false func foo() {} var bar: () { return () } From 6debe3d3b500420b474e9d86a5e5ec25bc63ed23 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 30 Jan 2020 09:54:24 -0800 Subject: [PATCH 28/31] [ConstraintSystem] Don't produce conformance fixes for mismatches associated with function result type If there are any requirement failures associated with result types which are part of a function type conversion, let's record general conversion mismatch in order for it to capture and display complete function types. --- lib/Sema/CSSimplify.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index fabf1338b2a97..09a1c7eda4973 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2160,6 +2160,17 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, break; } + + // TODO(diagnostics): If there are any requirement failures associated + // with result types which are part of a function type conversion, + // let's record general conversion mismatch in order for it to capture + // and display complete function types. + // + // Once either reacher locators or better diagnostic presentation for + // nested type failures is available this check could be removed. + if (last->is()) + return getTypeMatchFailure(locator); + } else { // There are no elements in the path auto *anchor = locator.getAnchor(); if (!(anchor && From 3375b362ebe6b4677deef859ee7a272f44317fc6 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Thu, 30 Jan 2020 14:15:38 -0800 Subject: [PATCH 29/31] Search nested types tables in parent modules Add another cross-cutting module configuration to the nested types table search path. A module can have no overlay but also contain a nested types table suitable for finding a given member name. UIKit is the sharpest example of this state of affairs. UIKit currently defines an overlay in Swift where we find some nested types. But it also defines an inner module that has some other nested types tables. Resolves rdar://58940989 --- lib/Serialization/Deserialization.cpp | 4 ++++ test/Serialization/multi-file-nested-type-extension.swift | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 4c62bb3728b1a..8e9d098532b23 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1468,6 +1468,10 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { if (auto overlayModule = LF->getOverlayModule()) { nestedType = findNestedTypeDeclInModule(getFile(), overlayModule, memberName, baseType); + } else if (LF->getParentModule() != extensionModule) { + nestedType = findNestedTypeDeclInModule(getFile(), + LF->getParentModule(), + memberName, baseType); } } } diff --git a/test/Serialization/multi-file-nested-type-extension.swift b/test/Serialization/multi-file-nested-type-extension.swift index fd2d139a25009..181fc38b72c52 100644 --- a/test/Serialization/multi-file-nested-type-extension.swift +++ b/test/Serialization/multi-file-nested-type-extension.swift @@ -10,7 +10,7 @@ // REQUIRES: asserts // CHECK: Statistics -// CHECK: 1 Serialization - # of nested types resolved without full lookup +// CHECK: 2 Serialization - # of nested types resolved without full lookup // Note the Optional here and below; this was once necessary to produce a crash. // Without it, the type of the parameter is initialized "early" enough to not @@ -21,3 +21,9 @@ extension Outer { public func useTypes(_: Outer.Callback?) {} } + +extension OuterClass.Inner { + public static var instance: OuterClass.Inner { + return OuterClass.Inner() + } +} From e121cb09cdab86c1479cc0ebf8ac063f2823e0a8 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 30 Jan 2020 15:04:07 -0800 Subject: [PATCH 30/31] Revert "[SourceKit] Disable module system headers validation" This reverts commit 951b85359a8b4781bae9e0735a893aee07b3dd1e. --- lib/IDE/CompletionInstance.cpp | 5 +++++ tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp | 5 ----- tools/swift-ide-test/swift-ide-test.cpp | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 446d80601a9c3..7d326b96bf116 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -362,6 +362,11 @@ bool swift::ide::CompletionInstance::performOperation( // source text. That breaks an invariant of syntax tree building. Invocation.getLangOptions().BuildSyntaxTree = false; + // This validation may call stat(2) many times. Disable it to prevent + // performance regression. + Invocation.getSearchPathOptions().DisableModulesValidateSystemDependencies = + true; + // Since caching uses the interface hash, and since per type fingerprints // weaken that hash, disable them here: Invocation.getLangOptions().EnableTypeFingerprints = false; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 1ebbcfeb25441..1e2b1fd10a211 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -539,11 +539,6 @@ bool SwiftASTManager::initCompilerInvocation( // We don't care about LLVMArgs FrontendOpts.LLVMArgs.clear(); - // This validation may call stat(2) many times. Disable it to prevent - // performance issues. - Invocation.getSearchPathOptions().DisableModulesValidateSystemDependencies = - true; - // SwiftSourceInfo files provide source location information for decls coming // from loaded modules. For most IDE use cases it either has an undesirable // impact on performance with no benefit (code completion), results in stale diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index fb2b67b7225fb..995eaaaab5eef 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -3436,8 +3436,6 @@ int main(int argc, char *argv[]) { options::DebugForbidTypecheckPrefix; InitInvok.getTypeCheckerOptions().DebugConstraintSolver = options::DebugConstraintSolver; - InitInvok.getSearchPathOptions().DisableModulesValidateSystemDependencies = - true; for (auto ConfigName : options::BuildConfigs) InitInvok.getLangOptions().addCustomConditionalCompilationFlag(ConfigName); From cb20d0ebfa9623a61f581edaba7e805cd0c357fd Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 30 Jan 2020 15:04:56 -0800 Subject: [PATCH 31/31] Revert "[CodeCompletion] Disable module system headers validation" This reverts commit ec70a40205396a9bd9e0310b3b81b4b41838976a. --- lib/IDE/CompletionInstance.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 7d326b96bf116..446d80601a9c3 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -362,11 +362,6 @@ bool swift::ide::CompletionInstance::performOperation( // source text. That breaks an invariant of syntax tree building. Invocation.getLangOptions().BuildSyntaxTree = false; - // This validation may call stat(2) many times. Disable it to prevent - // performance regression. - Invocation.getSearchPathOptions().DisableModulesValidateSystemDependencies = - true; - // Since caching uses the interface hash, and since per type fingerprints // weaken that hash, disable them here: Invocation.getLangOptions().EnableTypeFingerprints = false;