From 81984c34324584e2cfa278811a9b421730414357 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Thu, 4 Jun 2020 14:25:18 -0700 Subject: [PATCH 1/5] [Parse] Avoid delayed member parsing for type decl with missing brace Cache empty member list so that 'IterableDeclContext::loadAllMembers()' doesn't perform delayed member parsing. Fixes: rdar://problem/63921896 (cherry picked from commit bdfe1b1b08b117eb98626551a5fba72049e99813) --- include/swift/Parse/Parser.h | 5 +- lib/Parse/ParseDecl.cpp | 66 ++++++++----------- .../complete_sequence_innertype.swift | 10 +++ 3 files changed, 39 insertions(+), 42 deletions(-) create mode 100644 test/SourceKit/CodeComplete/complete_sequence_innertype.swift diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index c96c773f6fab8..bbc39e23ed5fc 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -929,9 +929,8 @@ class Parser { std::pair, Optional> parseDeclListDelayed(IterableDeclContext *IDC); - bool parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, - SourceLoc PosBeforeLB, - Diag<> ErrorDiag, + bool parseMemberDeclList(SourceLoc &LBLoc, SourceLoc &RBLoc, + Diag<> LBraceDiag, Diag<> RBraceDiag, IterableDeclContext *IDC); bool canDelayMemberDeclParsing(bool &HasOperatorDeclarations, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b4fd7a1e6ce3e..57d75efd4f17f 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4425,10 +4425,18 @@ ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi, return Result; } -bool Parser::parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, - SourceLoc PosBeforeLB, - Diag<> ErrorDiag, +bool Parser::parseMemberDeclList(SourceLoc &LBLoc, SourceLoc &RBLoc, + Diag<> LBraceDiag, Diag<> RBraceDiag, IterableDeclContext *IDC) { + if (parseToken(tok::l_brace, LBLoc, LBraceDiag)) { + LBLoc = RBLoc = PreviousLoc; + + // Cache the empty result to prevent delayed parsing. + Context.evaluator.cacheOutput( + ParseMembersRequest{IDC}, FingerprintAndMembers{None, {}}); + return true; + } + bool HasOperatorDeclarations; bool HasNestedClassDeclarations; @@ -4447,7 +4455,7 @@ bool Parser::parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, bool hadError = false; ParseDeclOptions Options = getMemberParseDeclOptions(IDC); auto membersAndHash = - parseDeclList(LBLoc, RBLoc, ErrorDiag, Options, IDC, hadError); + parseDeclList(LBLoc, RBLoc, RBraceDiag, Options, IDC, hadError); IDC->setMaybeHasOperatorDeclarations(); IDC->setMaybeHasNestedClassDeclarations(); Context.evaluator.cacheOutput( @@ -4617,16 +4625,12 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) { SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - auto PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_extension)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - status.setIsParseError(); - } else { + { ContextChange CC(*this, ext); Scope S(this, ScopeKind::Extension); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_extension, diag::expected_rbrace_extension, ext)) status.setIsParseError(); @@ -6578,15 +6582,11 @@ ParserResult Parser::parseDeclEnum(ParseDeclOptions Flags, SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { Scope S(this, ScopeKind::EnumBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_enum, diag::expected_rbrace_enum, ED)) Status.setIsParseError(); @@ -6864,16 +6864,12 @@ ParserResult Parser::parseDeclStruct(ParseDeclOptions Flags, // Make the entities of the struct as a code block. SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { // Parse the body. Scope S(this, ScopeKind::StructBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_struct, diag::expected_rbrace_struct, SD)) Status.setIsParseError(); @@ -6980,16 +6976,12 @@ ParserResult Parser::parseDeclClass(ParseDeclOptions Flags, SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBLoc, RBLoc; - auto PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) { - LBLoc = PreviousLoc; - RBLoc = LBLoc; - Status.setIsParseError(); - } else { + { // Parse the body. Scope S(this, ScopeKind::ClassBody); - if (parseMemberDeclList(LBLoc, RBLoc, PosBeforeLB, + if (parseMemberDeclList(LBLoc, RBLoc, + diag::expected_lbrace_class, diag::expected_rbrace_class, CD)) Status.setIsParseError(); @@ -7081,14 +7073,10 @@ parseDeclProtocol(ParseDeclOptions Flags, DeclAttributes &Attributes) { SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock); SourceLoc LBraceLoc; SourceLoc RBraceLoc; - SourceLoc PosBeforeLB = Tok.getLoc(); - if (parseToken(tok::l_brace, LBraceLoc, diag::expected_lbrace_protocol)) { - LBraceLoc = PreviousLoc; - RBraceLoc = LBraceLoc; - Status.setIsParseError(); - } else { + { // Parse the members. - if (parseMemberDeclList(LBraceLoc, RBraceLoc, PosBeforeLB, + if (parseMemberDeclList(LBraceLoc, RBraceLoc, + diag::expected_lbrace_protocol, diag::expected_rbrace_protocol, Proto)) Status.setIsParseError(); diff --git a/test/SourceKit/CodeComplete/complete_sequence_innertype.swift b/test/SourceKit/CodeComplete/complete_sequence_innertype.swift new file mode 100644 index 0000000000000..e6d114e5654b5 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_sequence_innertype.swift @@ -0,0 +1,10 @@ +func test() { + class C: +} + +// RUN: %sourcekitd-test \ +// RUN: -req=complete -pos=2:11 -repeat-request=2 %s -- %s -parse-as-library \ +// RUN: | %FileCheck %s + +// CHECK: key.results: [ +// CHECK: description: "Int", From a73611e22eb5402ab351e75e991b47c7e3393ee4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 3 Jun 2020 10:26:59 -0700 Subject: [PATCH 2/5] [CSGen] Allow `is` patterns to infer type from enclosing context Instead of assuming type of its sub-pattern `is` should be able to infer type from context and then propagate that to the sub-pattern via conversion. This enables support for patterns like `.foo(_ as Foo)` where `is` would have a type different from `_` which gets inferred from associated value of `foo` and converted to `Foo` that becomes a type of `_` pattern. Resolves: rdar://problem/63510989 (cherry picked from commit b14d9655ca4e1c32cf3a055bd9d4be2f5bf3471f) --- lib/Sema/CSGen.cpp | 14 +++++++++++++- test/Constraints/patterns.swift | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 882d5c6e79379..ab03b13fbc402 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2535,7 +2535,19 @@ namespace { ConstraintKind::CheckedCast, subPatternType, castType, locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); - return setType(subPatternType); + // Allow `is` pattern to infer type from context which is then going + // to be propaged down to its sub-pattern via conversion. This enables + // correct handling of patterns like `_ as Foo` where `_` would + // get a type of `Foo` but `is` pattern enclosing it could still be + // inferred from enclosing context. + auto isType = CS.createTypeVariable( + CS.getConstraintLocator( + locator.withPathElement(LocatorPathElt::PatternMatch(pattern))), + TVO_CanBindToNoEscape); + CS.addConstraint( + ConstraintKind::Conversion, subPatternType, isType, + locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); + return setType(isType); } case PatternKind::Bool: diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index f184629fa37f4..a3a2de3f5ee24 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -478,3 +478,20 @@ func rdar_60048356() { } } } + +// rdar://problem/63510989 - valid pattern doesn't type-check +func rdar63510989() { + enum Value : P { + func p() {} + } + + enum E { + case foo(P?) + } + + func test(e: E) { + if case .foo(_ as Value) = e {} // Ok + if case .foo(let v as Value) = e {} // Ok + // expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}} + } +} From 6bf67bd957755e6f6ebb8032ec5e4f07d37ba3d9 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 5 Jun 2020 06:21:57 -0700 Subject: [PATCH 3/5] [5.3] The test framepointer_arm64.sil requires ios --- test/IRGen/framepointer_arm64.sil | 1 + 1 file changed, 1 insertion(+) diff --git a/test/IRGen/framepointer_arm64.sil b/test/IRGen/framepointer_arm64.sil index e82a1dabf4ef4..c0b4dcef142df 100644 --- a/test/IRGen/framepointer_arm64.sil +++ b/test/IRGen/framepointer_arm64.sil @@ -4,6 +4,7 @@ // RUN: %target-swift-frontend -target arm64-apple-ios8.0 -primary-file %s -S -no-omit-leaf-frame-pointer | %FileCheck %s --check-prefix=CHECKASM-ALL // REQUIRES: CODEGENERATOR=AArch64 +// REQUIRES: OS=ios // UNSUPPORTED: OS=linux-gnu // UNSUPPORTED: OS=windows From daf858efca1f9bc17bf1f3c61ef69c031bd2cc96 Mon Sep 17 00:00:00 2001 From: David Ungar Date: Sat, 6 Jun 2020 14:17:29 -0700 Subject: [PATCH 4/5] Merge pull request #32219 from davidungar/quick-dependency-bug-fix Simplest fix to a dependency bug. --- lib/AST/AbstractSourceFileDepGraphFactory.cpp | 22 ++++++++++++++++--- .../Fingerprints/class-fingerprint.swift | 7 +----- .../Fingerprints/enum-fingerprint.swift | 7 +----- .../Fingerprints/protocol-fingerprint.swift | 6 +---- .../Fingerprints/struct-fingerprint.swift | 7 +----- ...peBodyFingerprintsDependencyGraphTests.cpp | 4 ++-- 6 files changed, 25 insertions(+), 28 deletions(-) diff --git a/lib/AST/AbstractSourceFileDepGraphFactory.cpp b/lib/AST/AbstractSourceFileDepGraphFactory.cpp index 390fe06dbfcbc..6a4ccfdf78ab6 100644 --- a/lib/AST/AbstractSourceFileDepGraphFactory.cpp +++ b/lib/AST/AbstractSourceFileDepGraphFactory.cpp @@ -79,14 +79,30 @@ void AbstractSourceFileDepGraphFactory::addAUsedDecl( const DependencyKey &defKey, const DependencyKey &useKey) { auto *defNode = g.findExistingNodeOrCreateIfNew(defKey, None, false /* = !isProvides */); + // If the depended-upon node is defined in this file, then don't // create an arc to the user, when the user is the whole file. // Otherwise, if the defNode's type-body fingerprint changes, // the whole file will be marked as dirty, losing the benefit of the // fingerprint. - if (defNode->getIsProvides() && - useKey.getKind() == NodeKind::sourceFileProvide) - return; + + // if (defNode->getIsProvides() && + // useKey.getKind() == NodeKind::sourceFileProvide) + // return; + + // Turns out the above three lines cause miscompiles, so comment them out + // for now. We might want them back if we can change the inputs to this + // function to be more precise. + + // Example of a miscompile: + // In main.swift + // func foo(_: Any) { print("Hello Any") } + // foo(123) + // Then add the following line to another file: + // func foo(_: Int) { print("Hello Int") } + // Although main.swift needs to get recompiled, the commented-out code below + // prevents that. + auto nullableUse = g.findExistingNode(useKey); assert(nullableUse.isNonNull() && "Use must be an already-added provides"); auto *useNode = nullableUse.get(); diff --git a/test/Frontend/Fingerprints/class-fingerprint.swift b/test/Frontend/Fingerprints/class-fingerprint.swift index 99c8bbeebbd30..3cab8d6e990c5 100644 --- a/test/Frontend/Fingerprints/class-fingerprint.swift +++ b/test/Frontend/Fingerprints/class-fingerprint.swift @@ -71,9 +71,4 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps -// RUN: %FileCheck -check-prefix=CHECK-MAINB-RECOMPILED %s < %t/output4 - -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} -// CHECK-MAINB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} - +// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 diff --git a/test/Frontend/Fingerprints/enum-fingerprint.swift b/test/Frontend/Fingerprints/enum-fingerprint.swift index 87564d0461242..05083f4f7ec9b 100644 --- a/test/Frontend/Fingerprints/enum-fingerprint.swift +++ b/test/Frontend/Fingerprints/enum-fingerprint.swift @@ -71,9 +71,4 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps -// RUN: %FileCheck -check-prefix=CHECK-MAINB-RECOMPILED %s < %t/output4 - -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} -// CHECK-MAINB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} - +// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 diff --git a/test/Frontend/Fingerprints/protocol-fingerprint.swift b/test/Frontend/Fingerprints/protocol-fingerprint.swift index 4bf913339d776..62a9ddd000878 100644 --- a/test/Frontend/Fingerprints/protocol-fingerprint.swift +++ b/test/Frontend/Fingerprints/protocol-fingerprint.swift @@ -71,9 +71,5 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps -// RUN: %FileCheck -check-prefix=CHECK-MAINB-RECOMPILED %s < %t/output4 - -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} -// CHECK-MAINB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} +// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 diff --git a/test/Frontend/Fingerprints/struct-fingerprint.swift b/test/Frontend/Fingerprints/struct-fingerprint.swift index cc6cfb28547a4..a0c9012a7c422 100644 --- a/test/Frontend/Fingerprints/struct-fingerprint.swift +++ b/test/Frontend/Fingerprints/struct-fingerprint.swift @@ -71,9 +71,4 @@ // only-run-for-debugging: cp %t/usesB.swiftdeps %t/usesB4.swiftdeps -// RUN: %FileCheck -check-prefix=CHECK-MAINB-RECOMPILED %s < %t/output4 - -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} -// CHECK-MAINB-RECOMPILED: Queuing because of dependencies discovered later: {compile: usesA.o <= usesA.swift} -// CHECK-MAINB-RECOMPILED-NOT: Queuing because of dependencies discovered later: {compile: usesB.o <= usesB.swift} - +// RUN: %FileCheck -check-prefix=CHECK-MAINAB-RECOMPILED %s < %t/output4 diff --git a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp index 8eaa7a8dbd240..3666d78a4e92d 100644 --- a/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp +++ b/unittests/Driver/TypeBodyFingerprintsDependencyGraphTests.cpp @@ -808,10 +808,10 @@ TEST(ModuleDepGraph, UseFingerprints) { { const auto jobs = simulateReload(graph, &job0, {{NodeKind::nominal, {"A1@11", "A2@2"}}}); - EXPECT_EQ(2u, jobs.size()); + EXPECT_EQ(3u, jobs.size()); EXPECT_TRUE(contains(jobs, &job0)); EXPECT_TRUE(contains(jobs, &job1)); - EXPECT_FALSE(contains(jobs, &job2)); + EXPECT_TRUE(contains(jobs, &job2)); EXPECT_FALSE(contains(jobs, &job3)); } } From 217b33e40f34bfc827f45a97e9c6f90732c9a9d0 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 8 Jun 2020 19:37:07 -0700 Subject: [PATCH 5/5] [czar][test] Disable multifile/batch-mode-llvmIRHash-consistency This was previously disabled on master, but not on the release branch. rdar://62338337 --- test/multifile/batch-mode-llvmIRHash-consistency.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/multifile/batch-mode-llvmIRHash-consistency.swift b/test/multifile/batch-mode-llvmIRHash-consistency.swift index d4add2e0eaf55..a35928b44103a 100644 --- a/test/multifile/batch-mode-llvmIRHash-consistency.swift +++ b/test/multifile/batch-mode-llvmIRHash-consistency.swift @@ -1,6 +1,9 @@ // Ensure that the LLVMIR hash of the 2nd compilation in batch mode // is consistent no matter if the first one generates code or not. +// This test fails in some configurations. +// REQUIRES: rdar_62338337 + // RUN: %empty-directory(%t) // RUN: echo 'public enum E: Error {}' >%t/main.swift // RUN: echo >%t/other.swift