From ae9715ac0311e1d65dc4fed957e067ee2654d8ea Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Thu, 1 Oct 2020 19:39:25 +0300 Subject: [PATCH 01/13] WinSDK: extract System submodule with winioctl.h Currently this header gets included into `WinSDK.WinSock2` via windows.h & winscard.h --- stdlib/public/Platform/winsdk.modulemap | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/stdlib/public/Platform/winsdk.modulemap b/stdlib/public/Platform/winsdk.modulemap index 8d7d464d27ffd..d11dd16400920 100644 --- a/stdlib/public/Platform/winsdk.modulemap +++ b/stdlib/public/Platform/winsdk.modulemap @@ -164,13 +164,6 @@ module WinSDK [system] { link "NetAPI32.Lib" } - module DbgHelp { - header "DbgHelp.h" - export * - - link "DbgHelp.Lib" - } - module DWM { header "dwmapi.h" export * @@ -244,6 +237,20 @@ module WinSDK [system] { link "shcore.lib" } + module System { + module DbgHelp { + header "DbgHelp.h" + export * + + link "DbgHelp.Lib" + } + + module IOCTL { + header "winioctl.h" + export * + } + } + module OLE32 { header "oaidl.h" export * From 04c21c18c935bc9a4101c2e5d49609c5d360e4b8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 22 Sep 2020 15:31:18 -0400 Subject: [PATCH 02/13] Parse: Disable circular definition check when parser lookup is off --- lib/Parse/ParseExpr.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 1c8019aaf9464..e05b08cd4ece8 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2208,20 +2208,23 @@ Expr *Parser::parseExprIdentifier() { // lookups, so disable this check when parsing for SwiftSyntax. if (!InPoundIfEnvironment && !Context.LangOpts.ParseForSyntaxTreeOnly) { D = lookupInScope(name); - // FIXME: We want this to work: "var x = { x() }", but for now it's better - // to disallow it than to crash. - if (D) { - for (auto activeVar : DisabledVars) { - if (activeVar == D) { - diagnose(loc.getBaseNameLoc(), DisabledVarReason); - return new (Context) ErrorExpr(loc.getSourceRange()); + + if (!Context.LangOpts.DisableParserLookup) { + // FIXME: We want this to work: "var x = { x() }", but for now it's better + // to disallow it than to crash. + if (D) { + for (auto activeVar : DisabledVars) { + if (activeVar == D) { + diagnose(loc.getBaseNameLoc(), DisabledVarReason); + return new (Context) ErrorExpr(loc.getSourceRange()); + } } - } - } else { - for (auto activeVar : DisabledVars) { - if (activeVar->getName() == name.getFullName()) { - diagnose(loc.getBaseNameLoc(), DisabledVarReason); - return new (Context) ErrorExpr(loc.getSourceRange()); + } else { + for (auto activeVar : DisabledVars) { + if (activeVar->getName() == name.getFullName()) { + diagnose(loc.getBaseNameLoc(), DisabledVarReason); + return new (Context) ErrorExpr(loc.getSourceRange()); + } } } } From 4648587326532a5e1ee672014cce4b1381607d3a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 1 Oct 2020 19:20:32 -0400 Subject: [PATCH 03/13] ASTScope: Move sortBySourceRange() and cull() calls out of addSiblingsToScopeTree() --- lib/AST/ASTScopeCreation.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index aa82c8014afc2..8d10d51974931 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -218,7 +218,7 @@ class ScopeCreator final { ASTScopeImpl *const organicInsertionPoint, ArrayRef nodesOrDeclsToAdd) { auto *ip = insertionPoint; - for (auto nd : sortBySourceRange(cull(nodesOrDeclsToAdd))) { + for (auto nd : nodesOrDeclsToAdd) { auto *const newIP = addToScopeTreeAndReturnInsertionPoint(nd, ip).getPtrOr(ip); ip = newIP; @@ -419,9 +419,6 @@ class ScopeCreator final { void addChildrenForKnownAttributes(ValueDecl *decl, ASTScopeImpl *parent); -public: - -private: /// Remove VarDecls because we'll find them when we expand the /// PatternBindingDecls. Remove EnunCases /// because they overlap EnumElements and AST includes the elements in the @@ -463,7 +460,6 @@ class ScopeCreator final { return -1 == signum; } -public: SWIFT_DEBUG_DUMP { print(llvm::errs()); } void print(raw_ostream &out) const { @@ -950,7 +946,9 @@ ASTSourceFileScope::expandAScopeThatCreatesANewInsertionPoint( // Assume that decls are only added at the end, in source order std::vector newNodes(decls.begin(), decls.end()); insertionPoint = - scopeCreator.addSiblingsToScopeTree(insertionPoint, this, newNodes); + scopeCreator.addSiblingsToScopeTree(insertionPoint, this, + scopeCreator.sortBySourceRange( + scopeCreator.cull(newNodes))); // Too slow to perform all the time: // ASTScopeAssert(scopeCreator->containsAllDeclContextsFromAST(), // "ASTScope tree missed some DeclContexts or made some up"); @@ -1068,7 +1066,10 @@ BraceStmtScope::expandAScopeThatCreatesANewInsertionPoint( // TODO: remove the sort after fixing parser to create brace statement // elements in source order auto *insertionPoint = - scopeCreator.addSiblingsToScopeTree(this, this, stmt->getElements()); + scopeCreator.addSiblingsToScopeTree(this, this, + scopeCreator.sortBySourceRange( + scopeCreator.cull( + stmt->getElements()))); if (auto *s = scopeCreator.getASTContext().Stats) ++s->getFrontendCounters().NumBraceStmtASTScopeExpansions; return { @@ -1414,6 +1415,7 @@ void GenericTypeOrExtensionScope::expandBody(ScopeCreator &) {} void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) { auto nodes = asNodeVector(getIterableDeclContext().get()->getMembers()); + nodes = scopeCreator.sortBySourceRange(scopeCreator.cull(nodes)); scopeCreator.addSiblingsToScopeTree(this, this, nodes); if (auto *s = scopeCreator.getASTContext().Stats) ++s->getFrontendCounters().NumIterableTypeBodyASTScopeExpansions; From 8b2cf55b705e5e6cf5d316ed8af75990017f8571 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 1 Oct 2020 20:24:56 -0400 Subject: [PATCH 04/13] ASTScope: Push isLocalBinding down from AbstractPatternEntryScope to PatternEntryDeclScope --- include/swift/AST/ASTScope.h | 16 ++++++++-------- lib/AST/ASTScopeCreation.cpp | 8 +++----- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index f4247df1468c3..aa373dcd6e750 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -1023,10 +1023,8 @@ class AbstractPatternEntryScope : public ASTScopeImpl { public: PatternBindingDecl *const decl; const unsigned patternEntryIndex; - const bool isLocalBinding; - AbstractPatternEntryScope(PatternBindingDecl *, unsigned entryIndex, - bool); + AbstractPatternEntryScope(PatternBindingDecl *, unsigned entryIndex); virtual ~AbstractPatternEntryScope() {} const PatternBindingEntry &getPatternEntry() const; @@ -1041,10 +1039,13 @@ class AbstractPatternEntryScope : public ASTScopeImpl { }; class PatternEntryDeclScope final : public AbstractPatternEntryScope { + const bool isLocalBinding; + public: PatternEntryDeclScope(PatternBindingDecl *pbDecl, unsigned entryIndex, - bool isLocalBinding) - : AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding) {} + bool isLocalBinding, Optional endLoc) + : AbstractPatternEntryScope(pbDecl, entryIndex), + isLocalBinding(isLocalBinding), endLoc(endLoc) {} virtual ~PatternEntryDeclScope() {} protected: @@ -1070,9 +1071,8 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope { Expr *initAsWrittenWhenCreated; public: - PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex, - bool isLocalBinding) - : AbstractPatternEntryScope(pbDecl, entryIndex, isLocalBinding), + PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex) + : AbstractPatternEntryScope(pbDecl, entryIndex), initAsWrittenWhenCreated(pbDecl->getOriginalInit(entryIndex)) {} virtual ~PatternEntryInitializerScope() {} diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index 8d10d51974931..a726c05ac5719 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -989,7 +989,7 @@ PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint( "Original inits are always after the '='"); scopeCreator .constructExpandAndInsertUncheckable( - this, decl, patternEntryIndex, isLocalBinding); + this, decl, patternEntryIndex); } // Add accessors for the variables in this pattern. @@ -1378,10 +1378,8 @@ ASTScopeImpl *LabeledConditionalStmtScope::createNestedConditionalClauseScopes( } AbstractPatternEntryScope::AbstractPatternEntryScope( - PatternBindingDecl *declBeingScoped, unsigned entryIndex, - bool isLocalBinding) - : decl(declBeingScoped), patternEntryIndex(entryIndex), - isLocalBinding(isLocalBinding) { + PatternBindingDecl *declBeingScoped, unsigned entryIndex) + : decl(declBeingScoped), patternEntryIndex(entryIndex) { ASTScopeAssert(entryIndex < declBeingScoped->getPatternList().size(), "out of bounds"); } From 4f1ab9d8e5d225d462dd5f4963777cc4df3442d2 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 1 Oct 2020 22:39:49 -0400 Subject: [PATCH 05/13] ASTScope: Directly calculate end location of GuardStmtScope and PatternEntryDeclScope Today, the reported source range of a GuardStmtScope is just that of the statement itself, ending after the 'else' block. Similarly, a PatternEntryDeclScope ends immediately after the initializer expression. Since these scopes introduce names until the end of the parent BraceStmt (meaning they change the insertion point), we were relying on the addition of child scopes to extend the source range. While we still need the hack for extending source ranges to deal with string interpolation, at least in the other cases we can get rid of it. Note that this fixes a bug where a GuardStmtScope would end before an inactive '#if' block if the inactive '#if' block was the last element of a BraceStmt. --- include/swift/AST/ASTScope.h | 12 +++- lib/AST/ASTScopeCreation.cpp | 122 ++++++++++++++++++++++---------- lib/AST/ASTScopeSourceRange.cpp | 15 +++- test/decl/var/usage.swift | 9 +++ 4 files changed, 114 insertions(+), 44 deletions(-) diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index aa373dcd6e750..c6f6c2a46cfdc 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -1040,6 +1040,7 @@ class AbstractPatternEntryScope : public ASTScopeImpl { class PatternEntryDeclScope final : public AbstractPatternEntryScope { const bool isLocalBinding; + Optional endLoc; public: PatternEntryDeclScope(PatternBindingDecl *pbDecl, unsigned entryIndex, @@ -1400,7 +1401,8 @@ class WhileStmtScope final : public LabeledConditionalStmtScope { class GuardStmtScope final : public LabeledConditionalStmtScope { public: GuardStmt *const stmt; - GuardStmtScope(GuardStmt *e) : stmt(e) {} + SourceLoc endLoc; + GuardStmtScope(GuardStmt *e, SourceLoc endLoc) : stmt(e), endLoc(endLoc) {} virtual ~GuardStmtScope() {} protected: @@ -1413,6 +1415,8 @@ class GuardStmtScope final : public LabeledConditionalStmtScope { public: std::string getClassName() const override; LabeledConditionalStmt *getLabeledConditionalStmt() const override; + SourceRange + getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; }; /// A scope after a guard statement that follows lookups into the conditions @@ -1427,9 +1431,11 @@ class LookupParentDiversionScope final : public ASTScopeImpl { public: ASTScopeImpl *const lookupParent; const SourceLoc startLoc; + const SourceLoc endLoc; - LookupParentDiversionScope(ASTScopeImpl *lookupParent, SourceLoc startLoc) - : lookupParent(lookupParent), startLoc(startLoc) {} + LookupParentDiversionScope(ASTScopeImpl *lookupParent, + SourceLoc startLoc, SourceLoc endLoc) + : lookupParent(lookupParent), startLoc(startLoc), endLoc(endLoc) {} SourceRange getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index a726c05ac5719..b7324c68013c7 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -213,14 +213,17 @@ class ScopeCreator final { /// Given an array of ASTNodes or Decl pointers, add them /// Return the resultant insertionPoint + /// + /// \param endLoc The end location for any "scopes until the end" that + /// we introduce here, such as PatternEntryDeclScope and GuardStmtScope ASTScopeImpl * addSiblingsToScopeTree(ASTScopeImpl *const insertionPoint, - ASTScopeImpl *const organicInsertionPoint, - ArrayRef nodesOrDeclsToAdd) { + ArrayRef nodesOrDeclsToAdd, + Optional endLoc) { auto *ip = insertionPoint; for (auto nd : nodesOrDeclsToAdd) { auto *const newIP = - addToScopeTreeAndReturnInsertionPoint(nd, ip).getPtrOr(ip); + addToScopeTreeAndReturnInsertionPoint(nd, ip, endLoc).getPtrOr(ip); ip = newIP; } return ip; @@ -229,12 +232,16 @@ class ScopeCreator final { public: /// For each of searching, call this unless the insertion point is needed void addToScopeTree(ASTNode n, ASTScopeImpl *parent) { - (void)addToScopeTreeAndReturnInsertionPoint(n, parent); + (void)addToScopeTreeAndReturnInsertionPoint(n, parent, None); } /// Return new insertion point if the scope was not a duplicate /// For ease of searching, don't call unless insertion point is needed + /// + /// \param endLoc The end location for any "scopes until the end" that + /// we introduce here, such as PatternEntryDeclScope and GuardStmtScope NullablePtr - addToScopeTreeAndReturnInsertionPoint(ASTNode, ASTScopeImpl *parent); + addToScopeTreeAndReturnInsertionPoint(ASTNode, ASTScopeImpl *parent, + Optional endLoc); bool isWorthTryingToCreateScopeFor(ASTNode n) const { if (!n) @@ -419,6 +426,18 @@ class ScopeCreator final { void addChildrenForKnownAttributes(ValueDecl *decl, ASTScopeImpl *parent); + /// Add PatternEntryDeclScopes for each pattern binding entry. + /// + /// Returns the new insertion point. + /// + /// \param endLoc Must be valid iff the pattern binding is in a local + /// scope, in which case this is the last source location where the + /// pattern bindings are going to be visible. + NullablePtr + addPatternBindingToScopeTree(PatternBindingDecl *patternBinding, + ASTScopeImpl *parent, + Optional endLoc); + /// Remove VarDecls because we'll find them when we expand the /// PatternBindingDecls. Remove EnunCases /// because they overlap EnumElements and AST includes the elements in the @@ -541,7 +560,10 @@ class NodeAdder : public ASTVisitor, NullablePtr, NullablePtr, void, void, void, ASTScopeImpl *, ScopeCreator &> { + Optional endLoc; + public: + explicit NodeAdder(Optional endLoc) : endLoc(endLoc) {} #pragma mark ASTNodes that do not create scopes @@ -633,7 +655,9 @@ class NodeAdder // the deferred nodes. NullablePtr visitGuardStmt(GuardStmt *e, ASTScopeImpl *p, ScopeCreator &scopeCreator) { - return scopeCreator.ifUniqueConstructExpandAndInsert(p, e); + ASTScopeAssert(endLoc.hasValue(), "GuardStmt outside of a BraceStmt?"); + return scopeCreator.ifUniqueConstructExpandAndInsert( + p, e, *endLoc); } NullablePtr visitTopLevelCodeDecl(TopLevelCodeDecl *d, ASTScopeImpl *p, @@ -694,28 +718,8 @@ class NodeAdder visitPatternBindingDecl(PatternBindingDecl *patternBinding, ASTScopeImpl *parentScope, ScopeCreator &scopeCreator) { - if (auto *var = patternBinding->getSingleVar()) - scopeCreator.addChildrenForKnownAttributes(var, parentScope); - - auto *insertionPoint = parentScope; - for (auto i : range(patternBinding->getNumPatternEntries())) { - bool isLocalBinding = false; - if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) { - isLocalBinding = varDecl->getDeclContext()->isLocalContext(); - } - - insertionPoint = - scopeCreator - .ifUniqueConstructExpandAndInsert( - insertionPoint, patternBinding, i, isLocalBinding) - .getPtrOr(insertionPoint); - - ASTScopeAssert(isLocalBinding || insertionPoint == parentScope, - "Bindings at the top-level or members of types should " - "not change the insertion point"); - } - - return insertionPoint; + return scopeCreator.addPatternBindingToScopeTree( + patternBinding, parentScope, endLoc); } NullablePtr visitEnumElementDecl(EnumElementDecl *eed, @@ -769,15 +773,18 @@ class NodeAdder // NodeAdder NullablePtr ScopeCreator::addToScopeTreeAndReturnInsertionPoint(ASTNode n, - ASTScopeImpl *parent) { + ASTScopeImpl *parent, + Optional endLoc) { if (!isWorthTryingToCreateScopeFor(n)) return parent; + + NodeAdder adder(endLoc); if (auto *p = n.dyn_cast()) - return NodeAdder().visit(p, parent, *this); + return adder.visit(p, parent, *this); if (auto *p = n.dyn_cast()) - return NodeAdder().visit(p, parent, *this); + return adder.visit(p, parent, *this); auto *p = n.get(); - return NodeAdder().visit(p, parent, *this); + return adder.visit(p, parent, *this); } void ScopeCreator::addChildrenForAllLocalizableAccessorsInSourceOrder( @@ -827,6 +834,41 @@ void ScopeCreator::addChildrenForKnownAttributes(ValueDecl *decl, } } +NullablePtr +ScopeCreator::addPatternBindingToScopeTree(PatternBindingDecl *patternBinding, + ASTScopeImpl *parentScope, + Optional endLoc) { + if (auto *var = patternBinding->getSingleVar()) + addChildrenForKnownAttributes(var, parentScope); + + auto *insertionPoint = parentScope; + for (auto i : range(patternBinding->getNumPatternEntries())) { + bool isLocalBinding = false; + if (auto *varDecl = patternBinding->getAnchoringVarDecl(i)) { + isLocalBinding = varDecl->getDeclContext()->isLocalContext(); + } + + Optional endLocForBinding = None; + if (isLocalBinding) { + endLocForBinding = endLoc; + ASTScopeAssert(endLoc.hasValue() && endLoc->isValid(), + "PatternBindingDecl in local context outside of BraceStmt?"); + } + + insertionPoint = + ifUniqueConstructExpandAndInsert( + insertionPoint, patternBinding, i, + isLocalBinding, endLocForBinding) + .getPtrOr(insertionPoint); + + ASTScopeAssert(isLocalBinding || insertionPoint == parentScope, + "Bindings at the top-level or members of types should " + "not change the insertion point"); + } + + return insertionPoint; +} + #pragma mark creation helpers void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) { @@ -946,9 +988,10 @@ ASTSourceFileScope::expandAScopeThatCreatesANewInsertionPoint( // Assume that decls are only added at the end, in source order std::vector newNodes(decls.begin(), decls.end()); insertionPoint = - scopeCreator.addSiblingsToScopeTree(insertionPoint, this, + scopeCreator.addSiblingsToScopeTree(insertionPoint, scopeCreator.sortBySourceRange( - scopeCreator.cull(newNodes))); + scopeCreator.cull(newNodes)), + None); // Too slow to perform all the time: // ASTScopeAssert(scopeCreator->containsAllDeclContextsFromAST(), // "ASTScope tree missed some DeclContexts or made some up"); @@ -1048,7 +1091,7 @@ GuardStmtScope::expandAScopeThatCreatesANewInsertionPoint(ScopeCreator & auto *const lookupParentDiversionScope = scopeCreator .constructExpandAndInsertUncheckable( - this, conditionLookupParent, stmt->getEndLoc()); + this, conditionLookupParent, stmt->getEndLoc(), endLoc); return {lookupParentDiversionScope, "Succeeding code must be in scope of guard variables"}; } @@ -1066,10 +1109,11 @@ BraceStmtScope::expandAScopeThatCreatesANewInsertionPoint( // TODO: remove the sort after fixing parser to create brace statement // elements in source order auto *insertionPoint = - scopeCreator.addSiblingsToScopeTree(this, this, + scopeCreator.addSiblingsToScopeTree(this, scopeCreator.sortBySourceRange( scopeCreator.cull( - stmt->getElements()))); + stmt->getElements())), + stmt->getEndLoc()); if (auto *s = scopeCreator.getASTContext().Stats) ++s->getFrontendCounters().NumBraceStmtASTScopeExpansions; return { @@ -1083,7 +1127,7 @@ TopLevelCodeScope::expandAScopeThatCreatesANewInsertionPoint(ScopeCreator & if (auto *body = scopeCreator - .addToScopeTreeAndReturnInsertionPoint(decl->getBody(), this) + .addToScopeTreeAndReturnInsertionPoint(decl->getBody(), this, None) .getPtrOrNull()) return {body, "So next top level code scope and put its decls in its body " "under a guard statement scope (etc) from the last top level " @@ -1414,7 +1458,7 @@ void GenericTypeOrExtensionScope::expandBody(ScopeCreator &) {} void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) { auto nodes = asNodeVector(getIterableDeclContext().get()->getMembers()); nodes = scopeCreator.sortBySourceRange(scopeCreator.cull(nodes)); - scopeCreator.addSiblingsToScopeTree(this, this, nodes); + scopeCreator.addSiblingsToScopeTree(this, nodes, None); if (auto *s = scopeCreator.getASTContext().Stats) ++s->getFrontendCounters().NumIterableTypeBodyASTScopeExpansions; } diff --git a/lib/AST/ASTScopeSourceRange.cpp b/lib/AST/ASTScopeSourceRange.cpp index 48a59b2f3ac59..1d93bdd762b84 100644 --- a/lib/AST/ASTScopeSourceRange.cpp +++ b/lib/AST/ASTScopeSourceRange.cpp @@ -248,7 +248,13 @@ SourceRange DefaultArgumentInitializerScope::getSourceRangeOfThisASTNode( SourceRange PatternEntryDeclScope::getSourceRangeOfThisASTNode( const bool omitAssertions) const { - return getPatternEntry().getSourceRange(); + SourceRange range = getPatternEntry().getSourceRange(); + if (endLoc.hasValue()) { + ASTScopeAssert(endLoc->isValid(), + "BraceStmt ends before pattern binding entry?"); + range.End = *endLoc; + } + return range; } SourceRange PatternEntryInitializerScope::getSourceRangeOfThisASTNode( @@ -445,9 +451,14 @@ SourceRange AttachedPropertyWrapperScope::getSourceRangeOfThisASTNode( return sourceRangeWhenCreated; } +SourceRange GuardStmtScope::getSourceRangeOfThisASTNode( + const bool omitAssertions) const { + return SourceRange(getStmt()->getStartLoc(), endLoc); +} + SourceRange LookupParentDiversionScope::getSourceRangeOfThisASTNode( const bool omitAssertions) const { - return SourceRange(startLoc); + return SourceRange(startLoc, endLoc); } #pragma mark source range caching diff --git a/test/decl/var/usage.swift b/test/decl/var/usage.swift index 76d145b314e56..9f89092728c4f 100644 --- a/test/decl/var/usage.swift +++ b/test/decl/var/usage.swift @@ -242,6 +242,15 @@ func testBuildConfigs() { #endif } +// same as above, but with a guard statement +func testGuardWithPoundIf(x: Int?) { + guard let x = x else { return } + +#if false + _ = x +#endif +} + // Bogus 'never mutated' warning when protocol variable is mutated only by mutating method protocol Fooable { mutating func mutFoo() From e1004499c4a223765710ffc960bcb93dd2fdb166 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 3 Oct 2020 02:24:10 -0400 Subject: [PATCH 06/13] [NFC] Split ProtocolDispatchStrategy out of MetadataValues.h. This allows us to avoid rebuilding most of the compiler whenever we add a new ABI constant. --- cmake/modules/AddSwift.cmake | 6 +++ include/swift/ABI/MetadataValues.h | 29 +---------- include/swift/ABI/ProtocolDispatchStrategy.h | 54 ++++++++++++++++++++ include/swift/SIL/TypeLowering.h | 5 +- lib/IRGen/IRGen.cpp | 1 + 5 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 include/swift/ABI/ProtocolDispatchStrategy.h diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index ec61d2abb836a..d1e2825f5f1af 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -630,3 +630,9 @@ macro(add_swift_tool_symlink name dest component) add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE) llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE COMPONENT ${component}) endmacro() + +# Declare that files in this library are built with LLVM's support +# libraries available. +macro(set_swift_llvm_is_available) + add_compile_options(-DSWIFT_LLVM_SUPPORT_IS_AVAILABLE) +endmacro() diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index e45629dce240a..bd044c5e36361 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -20,10 +20,10 @@ #define SWIFT_ABI_METADATAVALUES_H #include "swift/ABI/KeyPath.h" +#include "swift/ABI/ProtocolDispatchStrategy.h" #include "swift/AST/Ownership.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/FlagSet.h" -#include "swift/Runtime/Unreachable.h" #include #include @@ -410,20 +410,6 @@ enum class SpecialProtocol: uint8_t { Error = 1, }; -/// Identifiers for protocol method dispatch strategies. -enum class ProtocolDispatchStrategy: uint8_t { - /// Uses ObjC method dispatch. - /// - /// This must be 0 for ABI compatibility with Objective-C protocol_t records. - ObjC = 0, - - /// Uses Swift protocol witness table dispatch. - /// - /// To invoke methods of this protocol, a pointer to a protocol witness table - /// corresponding to the protocol conformance must be available. - Swift = 1, -}; - /// Flags for protocol descriptors. class ProtocolDescriptorFlags { typedef uint32_t int_type; @@ -486,18 +472,7 @@ class ProtocolDescriptorFlags { /// Does the protocol require a witness table for method dispatch? bool needsWitnessTable() const { - return needsWitnessTable(getDispatchStrategy()); - } - - static bool needsWitnessTable(ProtocolDispatchStrategy strategy) { - switch (strategy) { - case ProtocolDispatchStrategy::ObjC: - return false; - case ProtocolDispatchStrategy::Swift: - return true; - } - - swift_runtime_unreachable("Unhandled ProtocolDispatchStrategy in switch."); + return swift::protocolRequiresWitnessTable(getDispatchStrategy()); } /// Return the identifier if this is a special runtime-known protocol. diff --git a/include/swift/ABI/ProtocolDispatchStrategy.h b/include/swift/ABI/ProtocolDispatchStrategy.h new file mode 100644 index 0000000000000..c5276ee7b541e --- /dev/null +++ b/include/swift/ABI/ProtocolDispatchStrategy.h @@ -0,0 +1,54 @@ +//===--- ProtocolDispatchStrategy.h - ---------------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This header declares the ProtocolDispatchStrategy enum and some +// related operations. It's split out because we would otherwise need +// to include MetadataValues.h in some relatively central headers.s +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H +#define SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H + +#include "swift/Runtime/Unreachable.h" + +namespace swift { + +/// Identifiers for protocol method dispatch strategies. +enum class ProtocolDispatchStrategy: uint8_t { + /// Uses ObjC method dispatch. + /// + /// This must be 0 for ABI compatibility with Objective-C protocol_t records. + ObjC = 0, + + /// Uses Swift protocol witness table dispatch. + /// + /// To invoke methods of this protocol, a pointer to a protocol witness table + /// corresponding to the protocol conformance must be available. + Swift = 1, +}; + +/// Does a protocol using the given strategy require a witness table? +inline bool protocolRequiresWitnessTable(ProtocolDispatchStrategy strategy) { + switch (strategy) { + case ProtocolDispatchStrategy::ObjC: + return false; + case ProtocolDispatchStrategy::Swift: + return true; + } + + swift_runtime_unreachable("Unhandled ProtocolDispatchStrategy in switch."); +} + +} + +#endif diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index ed135eccf8e2f..98ff7ec7624df 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -13,7 +13,7 @@ #ifndef SWIFT_SIL_TYPELOWERING_H #define SWIFT_SIL_TYPELOWERING_H -#include "swift/ABI/MetadataValues.h" +#include "swift/ABI/ProtocolDispatchStrategy.h" #include "swift/AST/CaptureInfo.h" #include "swift/AST/Module.h" #include "swift/SIL/AbstractionPattern.h" @@ -792,8 +792,7 @@ class TypeConverter { /// True if a protocol uses witness tables for dynamic dispatch. static bool protocolRequiresWitnessTable(ProtocolDecl *P) { - return ProtocolDescriptorFlags::needsWitnessTable - (getProtocolDispatchStrategy(P)); + return swift::protocolRequiresWitnessTable(getProtocolDispatchStrategy(P)); } /// True if a type is passed indirectly at +0 when used as the "self" diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 7fe0c9ffffdcb..1c58d8206d624 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -16,6 +16,7 @@ #define DEBUG_TYPE "irgen" #include "IRGenModule.h" +#include "swift/ABI/MetadataValues.h" #include "swift/AST/DiagnosticsIRGen.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/IRGenRequests.h" From 66a42d8de74ceffdd6b4ee21b7d833828b7a76ff Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 3 Oct 2020 02:36:25 -0400 Subject: [PATCH 07/13] [NFC] Move some of the runtime's compiler abstraction into Compiler.h --- include/swift/Basic/Compiler.h | 49 ++++++++++++++++++++++++++++++ include/swift/Runtime/Config.h | 54 ++++------------------------------ 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/include/swift/Basic/Compiler.h b/include/swift/Basic/Compiler.h index b422175695ade..1958e762b2b83 100644 --- a/include/swift/Basic/Compiler.h +++ b/include/swift/Basic/Compiler.h @@ -34,10 +34,59 @@ #define SWIFT_ASSUME(x) #endif +/// Attributes. + #if __has_attribute(constructor) #define SWIFT_CONSTRUCTOR __attribute__((constructor)) #else #define SWIFT_CONSTRUCTOR #endif +/// \macro SWIFT_GNUC_PREREQ +/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't +/// available. +#ifndef SWIFT_GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define SWIFT_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ + ((maj) << 20) + ((min) << 10) + (patch)) +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SWIFT_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) +# else +# define SWIFT_GNUC_PREREQ(maj, min, patch) 0 +# endif +#endif + + +/// SWIFT_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +/// mark a method "not for inlining". +#if __has_attribute(noinline) || SWIFT_GNUC_PREREQ(3, 4, 0) +#define SWIFT_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define SWIFT_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define SWIFT_ATTRIBUTE_NOINLINE +#endif + +/// SWIFT_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +/// so, mark a method "always inline" because it is performance sensitive. GCC +/// 3.4 supported this but is buggy in various cases and produces unimplemented +/// errors, just use it in GCC 4.0 and later. +#if __has_attribute(always_inline) || SWIFT_GNUC_PREREQ(4, 0, 0) +#define SWIFT_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define SWIFT_ATTRIBUTE_ALWAYS_INLINE __forceinline +#else +#define SWIFT_ATTRIBUTE_ALWAYS_INLINE +#endif + +#ifdef __GNUC__ +#define SWIFT_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define SWIFT_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define SWIFT_ATTRIBUTE_NORETURN +#endif + #endif // SWIFT_BASIC_COMPILER_H diff --git a/include/swift/Runtime/Config.h b/include/swift/Runtime/Config.h index 372328a145d5d..da49b452f3b6e 100644 --- a/include/swift/Runtime/Config.h +++ b/include/swift/Runtime/Config.h @@ -17,71 +17,29 @@ #ifndef SWIFT_RUNTIME_CONFIG_H #define SWIFT_RUNTIME_CONFIG_H +#include "swift/Basic/Compiler.h" #include "swift/Runtime/CMakeConfig.h" -/// \macro SWIFT_RUNTIME_GNUC_PREREQ -/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't -/// available. -#ifndef SWIFT_RUNTIME_GNUC_PREREQ -# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define SWIFT_RUNTIME_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ - ((maj) << 20) + ((min) << 10) + (patch)) -# elif defined(__GNUC__) && defined(__GNUC_MINOR__) -# define SWIFT_RUNTIME_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) -# else -# define SWIFT_RUNTIME_GNUC_PREREQ(maj, min, patch) 0 -# endif -#endif - /// SWIFT_RUNTIME_LIBRARY_VISIBILITY - If a class marked with this attribute is /// linked into a shared library, then the class should be private to the /// library and not accessible from outside it. Can also be used to mark /// variables and functions, making them private to any shared library they are /// linked into. /// On PE/COFF targets, library visibility is the default, so this isn't needed. -#if (__has_attribute(visibility) || SWIFT_RUNTIME_GNUC_PREREQ(4, 0, 0)) && \ +#if (__has_attribute(visibility) || SWIFT_GNUC_PREREQ(4, 0, 0)) && \ !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32) #define SWIFT_RUNTIME_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) #else #define SWIFT_RUNTIME_LIBRARY_VISIBILITY #endif -/// Attributes. -/// SWIFT_RUNTIME_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, -/// mark a method "not for inlining". -#if __has_attribute(noinline) || SWIFT_RUNTIME_GNUC_PREREQ(3, 4, 0) -#define SWIFT_RUNTIME_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define SWIFT_RUNTIME_ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define SWIFT_RUNTIME_ATTRIBUTE_NOINLINE -#endif - -/// SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do -/// so, mark a method "always inline" because it is performance sensitive. GCC -/// 3.4 supported this but is buggy in various cases and produces unimplemented -/// errors, just use it in GCC 4.0 and later. -#if __has_attribute(always_inline) || SWIFT_RUNTIME_GNUC_PREREQ(4, 0, 0) -#define SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) -#elif defined(_MSC_VER) -#define SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE __forceinline -#else -#define SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE -#endif - -#ifdef __GNUC__ -#define SWIFT_RUNTIME_ATTRIBUTE_NORETURN __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define SWIFT_RUNTIME_ATTRIBUTE_NORETURN __declspec(noreturn) -#else -#define SWIFT_RUNTIME_ATTRIBUTE_NORETURN -#endif +#define SWIFT_RUNTIME_ATTRIBUTE_NOINLINE SWIFT_ATTRIBUTE_NOINLINE +#define SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE SWIFT_ATTRIBUTE_ALWAYS_INLINE +#define SWIFT_RUNTIME_ATTRIBUTE_NORETURN SWIFT_ATTRIBUTE_NORETURN /// SWIFT_RUNTIME_BUILTIN_TRAP - On compilers which support it, expands to an expression /// which causes the program to exit abnormally. -#if __has_builtin(__builtin_trap) || SWIFT_RUNTIME_GNUC_PREREQ(4, 3, 0) +#if __has_builtin(__builtin_trap) || SWIFT_GNUC_PREREQ(4, 3, 0) # define SWIFT_RUNTIME_BUILTIN_TRAP __builtin_trap() #elif defined(_MSC_VER) // The __debugbreak intrinsic is supported by MSVC, does not require forward From 0fb407943f40fc0b0ac078498fbb33d7763f08de Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 3 Oct 2020 02:39:21 -0400 Subject: [PATCH 08/13] [NFC] Rename swift_runtime_unreachable to swift_unreachable and make it use LLVM's support when available. --- include/swift/ABI/Metadata.h | 14 +++++----- include/swift/ABI/ProtocolDispatchStrategy.h | 4 +-- .../swift/{Runtime => Basic}/Unreachable.h | 28 ++++++++++++++----- include/swift/Demangling/TypeDecoder.h | 2 +- include/swift/Reflection/ReflectionContext.h | 4 +-- include/swift/Reflection/TypeRef.h | 4 +-- include/swift/Remote/MetadataReader.h | 6 ++-- include/swift/Runtime/Debug.h | 4 +-- lib/AST/CMakeLists.txt | 2 ++ lib/ASTSectionImporter/CMakeLists.txt | 2 ++ lib/ClangImporter/CMakeLists.txt | 2 ++ lib/Driver/CMakeLists.txt | 2 ++ lib/Frontend/CMakeLists.txt | 1 + lib/FrontendTool/CMakeLists.txt | 1 + lib/IDE/CMakeLists.txt | 1 + lib/IRGen/CMakeLists.txt | 1 + lib/LLVMPasses/CMakeLists.txt | 1 + lib/Migrator/CMakeLists.txt | 2 ++ lib/Parse/CMakeLists.txt | 2 ++ lib/PrintAsObjC/CMakeLists.txt | 1 + lib/SIL/CMakeLists.txt | 1 + lib/SILGen/CMakeLists.txt | 1 + lib/SILOptimizer/CMakeLists.txt | 1 + lib/Sema/CMakeLists.txt | 1 + lib/Serialization/CMakeLists.txt | 1 + lib/SyntaxParse/CMakeLists.txt | 1 + lib/TBDGen/CMakeLists.txt | 1 + stdlib/public/Reflection/TypeLowering.cpp | 12 ++++---- .../SwiftRemoteMirror/SwiftRemoteMirror.cpp | 4 +-- stdlib/public/runtime/Casting.cpp | 8 +++--- stdlib/public/runtime/DynamicCast.cpp | 6 ++-- stdlib/public/runtime/Exclusivity.cpp | 2 +- stdlib/public/runtime/Metadata.cpp | 26 ++++++++--------- stdlib/public/runtime/MetadataCache.h | 18 ++++++------ stdlib/public/runtime/MetadataLookup.cpp | 8 +++--- stdlib/public/runtime/ProtocolConformance.cpp | 6 ++-- stdlib/public/runtime/ReflectionMirror.cpp | 2 +- .../Compatibility51/ProtocolConformance.cpp | 2 +- 38 files changed, 112 insertions(+), 73 deletions(-) rename include/swift/{Runtime => Basic}/Unreachable.h (53%) diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 0ac4ab8943c42..9fbb260dc66ad 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -38,7 +38,7 @@ #include "swift/Basic/RelativePointer.h" #include "swift/Demangling/Demangle.h" #include "swift/Demangling/ManglingMacros.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include "../../../stdlib/public/SwiftShims/HeapObject.h" #if SWIFT_OBJC_INTEROP #include @@ -4664,7 +4664,7 @@ int32_t TargetTypeContextDescriptor::getGenericArgumentOffset() const { return llvm::cast>(this) ->getGenericArgumentOffset(); default: - swift_runtime_unreachable("Not a type context descriptor."); + swift_unreachable("Not a type context descriptor."); } } @@ -4682,7 +4682,7 @@ TargetTypeContextDescriptor::getFullGenericContextHeader() const { return llvm::cast>(this) ->getFullGenericContextHeader(); default: - swift_runtime_unreachable("Not a type context descriptor."); + swift_unreachable("Not a type context descriptor."); } } @@ -4699,7 +4699,7 @@ TargetTypeContextDescriptor::getGenericParams() const { case ContextDescriptorKind::OpaqueType: return llvm::cast>(this)->getGenericParams(); default: - swift_runtime_unreachable("Not a type context descriptor."); + swift_unreachable("Not a type context descriptor."); } } @@ -4717,7 +4717,7 @@ TargetTypeContextDescriptor::getForeignMetadataInitialization() const { return llvm::cast>(this) ->getForeignMetadataInitialization(); default: - swift_runtime_unreachable("Not a type context descriptor."); + swift_unreachable("Not a type context descriptor."); } } @@ -4735,7 +4735,7 @@ TargetTypeContextDescriptor::getSingletonMetadataInitialization() const return llvm::cast>(this) ->getSingletonMetadataInitialization(); default: - swift_runtime_unreachable("Not a enum, struct or class type descriptor."); + swift_unreachable("Not a enum, struct or class type descriptor."); } } @@ -4753,7 +4753,7 @@ TargetTypeContextDescriptor::getCanonicicalMetadataPrespecializations() return llvm::cast>(this) ->getCanonicicalMetadataPrespecializations(); default: - swift_runtime_unreachable("Not a type context descriptor."); + swift_unreachable("Not a type context descriptor."); } } diff --git a/include/swift/ABI/ProtocolDispatchStrategy.h b/include/swift/ABI/ProtocolDispatchStrategy.h index c5276ee7b541e..eb89c8f138f4a 100644 --- a/include/swift/ABI/ProtocolDispatchStrategy.h +++ b/include/swift/ABI/ProtocolDispatchStrategy.h @@ -19,7 +19,7 @@ #ifndef SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H #define SWIFT_ABI_PROTOCOLDISPATCHSTRATEGY_H -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" namespace swift { @@ -46,7 +46,7 @@ inline bool protocolRequiresWitnessTable(ProtocolDispatchStrategy strategy) { return true; } - swift_runtime_unreachable("Unhandled ProtocolDispatchStrategy in switch."); + swift_unreachable("Unhandled ProtocolDispatchStrategy in switch."); } } diff --git a/include/swift/Runtime/Unreachable.h b/include/swift/Basic/Unreachable.h similarity index 53% rename from include/swift/Runtime/Unreachable.h rename to include/swift/Basic/Unreachable.h index 4147d4ce80d23..8d0ed35b5a49d 100644 --- a/include/swift/Runtime/Unreachable.h +++ b/include/swift/Basic/Unreachable.h @@ -1,4 +1,4 @@ -//===--- Unreachable.h - Implements swift_runtime_unreachable ---*- C++ -*-===// +//===--- Unreachable.h - Implements swift_unreachable ---*- C++ -*-===// // // This source file is part of the Swift.org open source project // @@ -10,13 +10,25 @@ // //===----------------------------------------------------------------------===// // -// This file defines swift_runtime_unreachable, an LLVM-independent -// implementation of llvm_unreachable. +// This file defines swift_unreachable, which provides the +// functionality of llvm_unreachable without necessarily depending on +// the LLVM support libraries. // //===----------------------------------------------------------------------===// -#ifndef SWIFT_RUNTIME_UNREACHABLE_H -#define SWIFT_RUNTIME_UNREACHABLE_H +#ifndef SWIFT_BASIC_UNREACHABLE_H +#define SWIFT_BASIC_UNREACHABLE_H + +#ifdef SWIFT_LLVM_SUPPORT_IS_AVAILABLE + +// The implementation when LLVM is available. + +#include "llvm/Support/ErrorHandling.h" +#define swift_unreachable llvm_unreachable + +#else + +// The implementation when LLVM is not available. #include #include @@ -24,10 +36,12 @@ #include "swift/Runtime/Config.h" SWIFT_RUNTIME_ATTRIBUTE_NORETURN -inline static void swift_runtime_unreachable(const char *msg) { +inline static void swift_unreachable(const char *msg) { assert(false && msg); (void)msg; abort(); } -#endif // SWIFT_RUNTIME_UNREACHABLE_H +#endif + +#endif diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index fb33edf878252..296076adbf225 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -24,7 +24,7 @@ #include "swift/Demangling/Demangler.h" #include "swift/Demangling/NamespaceMacros.h" #include "swift/Runtime/Portability.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include "swift/Strings.h" #include "llvm/ADT/ArrayRef.h" #include diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h index 9e26669aa8f38..e52185c0b8ebe 100644 --- a/include/swift/Reflection/ReflectionContext.h +++ b/include/swift/Reflection/ReflectionContext.h @@ -33,7 +33,7 @@ #include "swift/Reflection/TypeLowering.h" #include "swift/Reflection/TypeRef.h" #include "swift/Reflection/TypeRefBuilder.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include #include @@ -1302,7 +1302,7 @@ class ReflectionContext return true; } - swift_runtime_unreachable("Unhandled MetadataSourceKind in switch."); + swift_unreachable("Unhandled MetadataSourceKind in switch."); } /// Read metadata for a captured generic type from a closure context. diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h index fb03cbc9e2e82..3d38e47128f85 100644 --- a/include/swift/Reflection/TypeRef.h +++ b/include/swift/Reflection/TypeRef.h @@ -22,7 +22,7 @@ #include "llvm/Support/Casting.h" #include "swift/ABI/MetadataValues.h" #include "swift/Remote/MetadataReader.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" namespace swift { namespace reflection { @@ -856,7 +856,7 @@ class TypeRefVisitor { #include "swift/Reflection/TypeRefs.def" } - swift_runtime_unreachable("Unhandled TypeRefKind in switch."); + swift_unreachable("Unhandled TypeRefKind in switch."); } }; diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 0090ae0746ed6..589bef52d8a68 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -28,7 +28,7 @@ #include "swift/ABI/TypeIdentity.h" #include "swift/Runtime/ExistentialContainer.h" #include "swift/Runtime/HeapObject.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include #include @@ -923,7 +923,7 @@ class MetadataReader { } } - swift_runtime_unreachable("Unhandled MetadataKind in switch"); + swift_unreachable("Unhandled MetadataKind in switch"); } TypeLookupErrorOr @@ -1295,7 +1295,7 @@ class MetadataReader { } } - swift_runtime_unreachable("Unhandled IsaEncodingKind in switch."); + swift_unreachable("Unhandled IsaEncodingKind in switch."); } /// Read the offset of the generic parameters of a class from the nominal diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h index f14e8d16f1554..f82fee34bc805 100644 --- a/include/swift/Runtime/Debug.h +++ b/include/swift/Runtime/Debug.h @@ -18,7 +18,7 @@ #define SWIFT_RUNTIME_DEBUG_HELPERS_H #include "swift/Runtime/Config.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include #include #include @@ -79,7 +79,7 @@ static inline void crash(const char *message) { CRSetCrashLogMessage(message); SWIFT_RUNTIME_BUILTIN_TRAP; - swift_runtime_unreachable("Expected compiler to crash."); + swift_unreachable("Expected compiler to crash."); } // swift::fatalError() halts with a crash log message, diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 6762297a9f098..e9e4ab76ccb30 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -9,6 +9,8 @@ else() ) endif() +set_swift_llvm_is_available() + add_swift_host_library(swiftAST STATIC AbstractSourceFileDepGraphFactory.cpp AccessRequests.cpp diff --git a/lib/ASTSectionImporter/CMakeLists.txt b/lib/ASTSectionImporter/CMakeLists.txt index 0bd9f991fc45e..1a8b262e2a2c0 100644 --- a/lib/ASTSectionImporter/CMakeLists.txt +++ b/lib/ASTSectionImporter/CMakeLists.txt @@ -1,3 +1,5 @@ +set_swift_llvm_is_available() + add_swift_host_library(swiftASTSectionImporter STATIC ASTSectionImporter.cpp LLVM_LINK_COMPONENTS core) diff --git a/lib/ClangImporter/CMakeLists.txt b/lib/ClangImporter/CMakeLists.txt index a9076c210e033..21294ee6da4ef 100644 --- a/lib/ClangImporter/CMakeLists.txt +++ b/lib/ClangImporter/CMakeLists.txt @@ -4,6 +4,8 @@ set(SWIFT_GYB_FLAGS add_gyb_target(generated_sorted_cf_database SortedCFDatabase.def.gyb) +set_swift_llvm_is_available() + add_swift_host_library(swiftClangImporter STATIC CFTypeInfo.cpp ClangAdapter.cpp diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index 380c3c6dc8a0c..d210da923bce6 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -1,3 +1,5 @@ +set_swift_llvm_is_available() + set(swiftDriver_sources Action.cpp Compilation.cpp diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 08988f9a078ee..2c8c24f9e4dd9 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftFrontend STATIC ArgsToFrontendInputsConverter.cpp ArgsToFrontendOptionsConverter.cpp diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt index 0e08c752eb30d..26b37f661b82b 100644 --- a/lib/FrontendTool/CMakeLists.txt +++ b/lib/FrontendTool/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftFrontendTool STATIC FrontendTool.cpp ImportedModules.cpp diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt index d028e874d39b7..48ebc21981d30 100644 --- a/lib/IDE/CMakeLists.txt +++ b/lib/IDE/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftIDE STATIC CodeCompletion.cpp CodeCompletionCache.cpp diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt index 7cfe61b987e86..777096b39e6e0 100644 --- a/lib/IRGen/CMakeLists.txt +++ b/lib/IRGen/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftIRGen STATIC AllocStackHoisting.cpp ClassLayout.cpp diff --git a/lib/LLVMPasses/CMakeLists.txt b/lib/LLVMPasses/CMakeLists.txt index 80edee61d1236..f5a3ee28b7562 100644 --- a/lib/LLVMPasses/CMakeLists.txt +++ b/lib/LLVMPasses/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftLLVMPasses STATIC LLVMSwiftAA.cpp LLVMSwiftRCIdentity.cpp diff --git a/lib/Migrator/CMakeLists.txt b/lib/Migrator/CMakeLists.txt index 3e37ff2ca48a9..473ad151f0640 100644 --- a/lib/Migrator/CMakeLists.txt +++ b/lib/Migrator/CMakeLists.txt @@ -47,6 +47,8 @@ swift_install_in_component(FILES ${datafiles} DESTINATION "lib/swift/migrator" COMPONENT compiler) +set_swift_llvm_is_available() + add_swift_host_library(swiftMigrator STATIC APIDiffMigratorPass.cpp EditorAdapter.cpp diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt index 7158bdce8b24e..550af6bf5954a 100644 --- a/lib/Parse/CMakeLists.txt +++ b/lib/Parse/CMakeLists.txt @@ -1,3 +1,5 @@ +set_swift_llvm_is_available() + if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) set(SWIFT_GYB_FLAGS --line-directive "^\"#line %(line)d \\\"%(file)s\\\"^\"") else() diff --git a/lib/PrintAsObjC/CMakeLists.txt b/lib/PrintAsObjC/CMakeLists.txt index ae667af64ac31..66044fa3fc7ff 100644 --- a/lib/PrintAsObjC/CMakeLists.txt +++ b/lib/PrintAsObjC/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftPrintAsObjC STATIC DeclAndTypePrinter.cpp ModuleContentsWriter.cpp diff --git a/lib/SIL/CMakeLists.txt b/lib/SIL/CMakeLists.txt index 74ca0507393d3..96a6b852ad8b0 100644 --- a/lib/SIL/CMakeLists.txt +++ b/lib/SIL/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSIL STATIC SIL.cpp) target_link_libraries(swiftSIL PUBLIC diff --git a/lib/SILGen/CMakeLists.txt b/lib/SILGen/CMakeLists.txt index c144b14bf69ee..c4daab77fd3e6 100644 --- a/lib/SILGen/CMakeLists.txt +++ b/lib/SILGen/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSILGen STATIC ArgumentSource.cpp Cleanup.cpp diff --git a/lib/SILOptimizer/CMakeLists.txt b/lib/SILOptimizer/CMakeLists.txt index ec1440d2b06a1..c9ddd901ab5dc 100644 --- a/lib/SILOptimizer/CMakeLists.txt +++ b/lib/SILOptimizer/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSILOptimizer STATIC SILOptimizer.cpp) target_link_libraries(swiftSILOptimizer PRIVATE diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 633a64b014896..e71cb7ff910bc 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSema STATIC BuilderTransform.cpp CSApply.cpp diff --git a/lib/Serialization/CMakeLists.txt b/lib/Serialization/CMakeLists.txt index 55a20aef848ea..1e7c14b1ce161 100644 --- a/lib/Serialization/CMakeLists.txt +++ b/lib/Serialization/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSerialization STATIC Deserialization.cpp DeserializeSIL.cpp diff --git a/lib/SyntaxParse/CMakeLists.txt b/lib/SyntaxParse/CMakeLists.txt index b1b1c562988aa..230f230ebd68f 100644 --- a/lib/SyntaxParse/CMakeLists.txt +++ b/lib/SyntaxParse/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftSyntaxParse STATIC RawSyntaxTokenCache.cpp SyntaxTreeCreator.cpp) diff --git a/lib/TBDGen/CMakeLists.txt b/lib/TBDGen/CMakeLists.txt index 06181211d4a67..60796eab5e73c 100644 --- a/lib/TBDGen/CMakeLists.txt +++ b/lib/TBDGen/CMakeLists.txt @@ -1,3 +1,4 @@ +set_swift_llvm_is_available() add_swift_host_library(swiftTBDGen STATIC TBDGen.cpp TBDGenRequests.cpp diff --git a/stdlib/public/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp index 729765edd1893..09bc0b6b258b4 100644 --- a/stdlib/public/Reflection/TypeLowering.cpp +++ b/stdlib/public/Reflection/TypeLowering.cpp @@ -23,7 +23,7 @@ #include "swift/Reflection/TypeLowering.h" #include "swift/Reflection/TypeRef.h" #include "swift/Reflection/TypeRefBuilder.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #ifdef DEBUG_TYPE_LOWERING #define DEBUG_LOG(expr) expr; @@ -212,7 +212,7 @@ class PrintTypeInfo { } } - swift_runtime_unreachable("Bad TypeInfo kind"); + swift_unreachable("Bad TypeInfo kind"); } }; @@ -2007,7 +2007,7 @@ class LowerType return nullptr; } - swift_runtime_unreachable("Unhandled FieldDescriptorKind in switch."); + swift_unreachable("Unhandled FieldDescriptorKind in switch."); } const TypeInfo *visitNominalTypeRef(const NominalTypeRef *N) { @@ -2039,7 +2039,7 @@ class LowerType return TC.getTypeInfo(TC.getThinFunctionTypeRef(), ExternalTypeInfo); } - swift_runtime_unreachable("Unhandled FunctionMetadataConvention in switch."); + swift_unreachable("Unhandled FunctionMetadataConvention in switch."); } const TypeInfo * @@ -2060,7 +2060,7 @@ class LowerType return TC.getTypeInfo(TC.getAnyMetatypeTypeRef(), ExternalTypeInfo); } - swift_runtime_unreachable("Unhandled MetatypeRepresentation in switch."); + swift_unreachable("Unhandled MetatypeRepresentation in switch."); } const TypeInfo * @@ -2256,7 +2256,7 @@ const TypeInfo *TypeConverter::getClassInstanceTypeInfo( return nullptr; } - swift_runtime_unreachable("Unhandled FieldDescriptorKind in switch."); + swift_unreachable("Unhandled FieldDescriptorKind in switch."); } } // namespace reflection diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index 9d5afad1cf41f..0af1e53b3f9d7 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -23,7 +23,7 @@ unsigned long long swift_reflection_classIsSwiftMask = 2; #include "swift/Reflection/ReflectionContext.h" #include "swift/Reflection/TypeLowering.h" #include "swift/Remote/CMemoryReader.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #if defined(__APPLE__) && defined(__MACH__) #include @@ -406,7 +406,7 @@ swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) { } } - swift_runtime_unreachable("Unhandled TypeInfoKind in switch"); + swift_unreachable("Unhandled TypeInfoKind in switch"); } static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) { diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp index 99e08243588bb..487bc05fb871a 100644 --- a/stdlib/public/runtime/Casting.cpp +++ b/stdlib/public/runtime/Casting.cpp @@ -35,7 +35,7 @@ # define SWIFT_CASTING_SUPPORTS_MUTEX 1 # include "swift/Runtime/Mutex.h" #endif -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #if SWIFT_OBJC_INTEROP @@ -1016,7 +1016,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest, } } - swift_runtime_unreachable("Unhandled ExistentialTypeRepresentation in switch."); + swift_unreachable("Unhandled ExistentialTypeRepresentation in switch."); } /******************************************************************************/ @@ -1214,7 +1214,7 @@ swift_dynamicCastMetatypeImpl(const Metadata *sourceType, return nullptr; } - swift_runtime_unreachable("Unhandled MetadataKind in switch."); + swift_unreachable("Unhandled MetadataKind in switch."); } static const Metadata * @@ -1424,7 +1424,7 @@ static bool _dynamicCastToUnknownClassFromExistential(OpaqueValue *dest, } } - swift_runtime_unreachable( + swift_unreachable( "Unhandled ExistentialTypeRepresentation in switch."); } diff --git a/stdlib/public/runtime/DynamicCast.cpp b/stdlib/public/runtime/DynamicCast.cpp index f19af13ab6311..e7f624ba8c555 100644 --- a/stdlib/public/runtime/DynamicCast.cpp +++ b/stdlib/public/runtime/DynamicCast.cpp @@ -1806,7 +1806,7 @@ static tryCastFunctionType *selectCasterForDest(const Metadata *destType) { case ExistentialTypeRepresentation::Error: // => Error existential return tryCastToErrorExistential; } - swift_runtime_unreachable( + swift_unreachable( "Unknown existential type representation in dynamic cast dispatch"); } case MetadataKind::Metatype: @@ -1821,14 +1821,14 @@ static tryCastFunctionType *selectCasterForDest(const Metadata *destType) { // These are internal details of runtime-only structures, // so will never appear in compiler-generated types. // As such, they don't need support here. - swift_runtime_unreachable( + swift_unreachable( "Unexpected MetadataKind in dynamic cast dispatch"); return nullptr; default: // If you see this message, then there is a new MetadataKind that I didn't // know about when I wrote this code. Please figure out what it is, how to // handle it, and add a case for it. - swift_runtime_unreachable( + swift_unreachable( "Unknown MetadataKind in dynamic cast dispatch"); } } diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp index 73628b7cdaae4..7750fbae41e8b 100644 --- a/stdlib/public/runtime/Exclusivity.cpp +++ b/stdlib/public/runtime/Exclusivity.cpp @@ -219,7 +219,7 @@ class AccessSet { } } - swift_runtime_unreachable("access not found in set"); + swift_unreachable("access not found in set"); } #ifndef NDEBUG diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 56fd8670c640f..5fc6dafd8baac 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -194,7 +194,7 @@ computeMetadataBoundsForSuperclass(const void *ref, #endif } } - swift_runtime_unreachable("unsupported superclass reference kind"); + swift_unreachable("unsupported superclass reference kind"); } static ClassMetadataBounds computeMetadataBoundsFromSuperclass( @@ -3716,7 +3716,7 @@ getExistentialValueWitnesses(ProtocolClassConstraint classConstraint, return getOpaqueExistentialValueWitnesses(numWitnessTables); } - swift_runtime_unreachable("Unhandled ProtocolClassConstraint in switch."); + swift_unreachable("Unhandled ProtocolClassConstraint in switch."); } template<> ExistentialTypeRepresentation @@ -3761,7 +3761,7 @@ ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const { } } - swift_runtime_unreachable( + swift_unreachable( "Unhandled ExistentialTypeRepresentation in switch."); } @@ -3810,7 +3810,7 @@ ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const { } } - swift_runtime_unreachable( + swift_unreachable( "Unhandled ExistentialTypeRepresentation in switch."); } @@ -3835,7 +3835,7 @@ ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const { } } - swift_runtime_unreachable( + swift_unreachable( "Unhandled ExistentialTypeRepresentation in switch."); } @@ -4030,7 +4030,7 @@ class ForeignMetadataCacheEntry return Value; } void setValue(ValueType value) { - swift_runtime_unreachable("should never be called"); + swift_unreachable("should never be called"); } public: @@ -4094,7 +4094,7 @@ class ForeignMetadataCacheEntry } AllocationResult allocate(Metadata *candidate) { - swift_runtime_unreachable( + swift_unreachable( "always flags allocation complete during construction"); } @@ -4555,7 +4555,7 @@ static void initProtocolWitness(void **slot, void *witness, reqt); return; } - swift_runtime_unreachable("bad witness kind"); + swift_unreachable("bad witness kind"); #else *slot = witness; #endif @@ -4588,7 +4588,7 @@ static void copyProtocolWitness(void **dest, void * const *src, swift_ptrauth_copy(dest, src, reqt.Flags.getExtraDiscriminator()); return; } - swift_runtime_unreachable("bad witness kind"); + swift_unreachable("bad witness kind"); #else *dest = *src; #endif @@ -5141,7 +5141,7 @@ static const WitnessTable *swift_getAssociatedConformanceWitnessSlowImpl( return assocWitnessTable; } - swift_runtime_unreachable("Invalid mangled associate conformance"); + swift_unreachable("Invalid mangled associate conformance"); } const WitnessTable *swift::swift_getAssociatedConformanceWitness( @@ -5234,7 +5234,7 @@ static Result performOnMetadataCache(const Metadata *metadata, case TypeContextDescriptorFlags::SingletonMetadataInitialization: return std::move(callbacks).forSingletonMetadata(description); } - swift_runtime_unreachable("bad metadata initialization kind"); + swift_unreachable("bad metadata initialization kind"); } auto &generics = description->getFullGenericContextHeader(); @@ -5280,7 +5280,7 @@ bool swift::addToMetadataQueue(MetadataCompletionQueueEntry *queueEntry, } bool forOtherMetadata(const Metadata *metadata) && { - swift_runtime_unreachable("metadata should always be complete"); + swift_unreachable("metadata should always be complete"); } } callbacks = { queueEntry, dependency }; @@ -5312,7 +5312,7 @@ void swift::resumeMetadataCompletion(MetadataCompletionQueueEntry *queueEntry) { } void forOtherMetadata(const Metadata *metadata) && { - swift_runtime_unreachable("metadata should always be complete"); + swift_unreachable("metadata should always be complete"); } } callbacks = { queueEntry }; diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h index d6f188f971e3c..0c9a186f8b574 100644 --- a/stdlib/public/runtime/MetadataCache.h +++ b/stdlib/public/runtime/MetadataCache.h @@ -366,7 +366,7 @@ class SimpleLockingCacheEntryBase { template Status beginInitialization(ConcurrencyControl &concurrency, ArgTys &&...args) { - swift_runtime_unreachable("beginAllocation always short-circuits"); + swift_unreachable("beginAllocation always short-circuits"); } }; @@ -592,7 +592,7 @@ inline bool satisfies(PrivateMetadataState state, MetadataState requirement) { case MetadataState::Complete: return state >= PrivateMetadataState::Complete; } - swift_runtime_unreachable("unsupported requirement kind"); + swift_unreachable("unsupported requirement kind"); } class PrivateMetadataTrackingInfo { @@ -642,7 +642,7 @@ class PrivateMetadataTrackingInfo { MetadataState getAccomplishedRequestState() const { switch (getState()) { case PrivateMetadataState::Allocating: - swift_runtime_unreachable("cannot call on allocating state"); + swift_unreachable("cannot call on allocating state"); case PrivateMetadataState::Abstract: return MetadataState::Abstract; case PrivateMetadataState::LayoutComplete: @@ -652,7 +652,7 @@ class PrivateMetadataTrackingInfo { case PrivateMetadataState::Complete: return MetadataState::Complete; } - swift_runtime_unreachable("bad state"); + swift_unreachable("bad state"); } bool satisfies(MetadataState requirement) { @@ -678,7 +678,7 @@ class PrivateMetadataTrackingInfo { // Otherwise, if it's a non-blocking request, we do not need to block. return (request.isBlocking() && !satisfies(request.getState())); } - swift_runtime_unreachable("bad state"); + swift_unreachable("bad state"); } constexpr RawType getRawValue() const { return Data; } @@ -1124,9 +1124,9 @@ class MetadataCacheEntryBase return; case LSK::Complete: - swift_runtime_unreachable("preparing to enqueue when already complete?"); + swift_unreachable("preparing to enqueue when already complete?"); } - swift_runtime_unreachable("bad kind"); + swift_unreachable("bad kind"); } /// Claim all the satisfied completion queue entries, given that @@ -1288,7 +1288,7 @@ class MetadataCacheEntryBase switch (LockedStorageKind) { case LSK::Complete: - swift_runtime_unreachable("enqueuing on complete cache entry?"); + swift_unreachable("enqueuing on complete cache entry?"); case LSK::AllocatingThread: LockedStorageKind = LSK::CompletionQueue; @@ -1340,7 +1340,7 @@ class MetadataCacheEntryBase // Check for an existing dependency. switch (LockedStorageKind) { case LSK::Complete: - swift_runtime_unreachable("dependency on complete cache entry?"); + swift_unreachable("dependency on complete cache entry?"); case LSK::AllocatingThread: case LSK::CompletionQueue: diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index fef3ff3f82e76..f271908ee1d50 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -88,10 +88,10 @@ static uintptr_t resolveSymbolicReferenceOffset(SymbolicReferenceKind kind, return (uintptr_t)contextPtr; } case SymbolicReferenceKind::AccessorFunctionReference: { - swift_runtime_unreachable("should not be indirectly referenced"); + swift_unreachable("should not be indirectly referenced"); } } - swift_runtime_unreachable("unknown symbolic reference kind"); + swift_unreachable("unknown symbolic reference kind"); } else { return ptr; } @@ -176,7 +176,7 @@ _buildDemanglingForSymbolicReference(SymbolicReferenceKind kind, (uintptr_t)resolvedReference); } - swift_runtime_unreachable("invalid symbolic reference kind"); + swift_unreachable("invalid symbolic reference kind"); } NodePointer @@ -1168,7 +1168,7 @@ findAssociatedTypeByName(const ProtocolDescriptor *protocol, StringRef name) { ++currentAssocTypeIdx; } - swift_runtime_unreachable("associated type names don't line up"); + swift_unreachable("associated type names don't line up"); } namespace { diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index c434011faea85..f3fa79c578a72 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -20,7 +20,7 @@ #include "swift/Runtime/Concurrent.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Metadata.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include "CompatibilityOverride.h" #include "ImageInspection.h" #include "Private.h" @@ -116,7 +116,7 @@ const ClassMetadata *TypeReference::getObjCClass(TypeReferenceKind kind) const { return nullptr; } - swift_runtime_unreachable("Unhandled TypeReferenceKind in switch."); + swift_unreachable("Unhandled TypeReferenceKind in switch."); } #endif @@ -155,7 +155,7 @@ ProtocolConformanceDescriptor::getCanonicalTypeMetadata() const { } } - swift_runtime_unreachable("Unhandled TypeReferenceKind in switch."); + swift_unreachable("Unhandled TypeReferenceKind in switch."); } template<> diff --git a/stdlib/public/runtime/ReflectionMirror.cpp b/stdlib/public/runtime/ReflectionMirror.cpp index 5fbad4fb3c136..ca7d6601c4cec 100644 --- a/stdlib/public/runtime/ReflectionMirror.cpp +++ b/stdlib/public/runtime/ReflectionMirror.cpp @@ -17,7 +17,7 @@ #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Metadata.h" #include "swift/Runtime/Enum.h" -#include "swift/Runtime/Unreachable.h" +#include "swift/Basic/Unreachable.h" #include "swift/Demangling/Demangle.h" #include "swift/Runtime/Debug.h" #include "swift/Runtime/Portability.h" diff --git a/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp b/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp index 4f22fd2bfda2d..09bd46ea02700 100644 --- a/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp +++ b/stdlib/toolchain/Compatibility51/ProtocolConformance.cpp @@ -231,7 +231,7 @@ override_getCanonicalTypeMetadata(const ProtocolConformanceDescriptor *conf) { } } - swift_runtime_unreachable("Unhandled TypeReferenceKind in switch."); + swift_unreachable("Unhandled TypeReferenceKind in switch."); } class ConformanceCandidate { From ffe21d46dd82d52ca5f780464886146c7d30cdfe Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 1 Oct 2020 23:21:05 -0400 Subject: [PATCH 09/13] Sema: Diagnose duplicate capture list entires when parser lookup is off Another spot where we have to check for redeclaration manually now. As before, we can use the existing mechanism though. --- lib/Sema/CSGen.cpp | 2 ++ lib/Sema/TypeCheckDeclPrimary.cpp | 8 ++++++++ lib/Sema/TypeChecker.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 751d893323e44..5d15df3ada4f4 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -3440,6 +3440,8 @@ namespace { // Generate constraints for each of the entries in the capture list. if (auto captureList = dyn_cast(expr)) { + TypeChecker::diagnoseDuplicateCaptureVars(captureList); + auto &CS = CG.getConstraintSystem(); for (const auto &capture : captureList->getCaptureList()) { SolutionApplicationTarget target(capture.Init); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 5092bf7c99b92..9e44995acd561 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1334,6 +1334,14 @@ void TypeChecker::diagnoseDuplicateBoundVars(Pattern *pattern) { diagnoseDuplicateDecls(boundVars); } +void TypeChecker::diagnoseDuplicateCaptureVars(CaptureListExpr *expr) { + SmallVector captureListVars; + for (auto &capture : expr->getCaptureList()) + captureListVars.push_back(capture.Var); + + diagnoseDuplicateDecls(captureListVars); +} + namespace { class DeclChecker : public DeclVisitor { public: diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index b30e9810a614f..6d21f393431d5 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -502,6 +502,8 @@ void checkParameterList(ParameterList *params); void diagnoseDuplicateBoundVars(Pattern *pattern); +void diagnoseDuplicateCaptureVars(CaptureListExpr *expr); + Type checkReferenceOwnershipAttr(VarDecl *D, Type interfaceType, ReferenceOwnershipAttr *attr); From 854e1e482f7544e0fa0a26101dac8eb7df3ebc85 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 23 Sep 2020 17:35:36 -0400 Subject: [PATCH 10/13] Frontend: Add -enable-parser-lookup flag This is for re-enabling it once it is turned off by default. --- include/swift/Option/Options.td | 6 +++++- lib/Driver/ToolChains.cpp | 1 + lib/Frontend/CompilerInvocation.cpp | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 7c80c7c03e68e..3c412e153c7dc 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1102,7 +1102,11 @@ def scan_clang_dependencies : Flag<["-"], "scan-clang-dependencies">, def disable_parser_lookup : Flag<["-"], "disable-parser-lookup">, Flags<[FrontendOption]>, - HelpText<"Disable parser lookup & use ast scope lookup only (experimental)">; + HelpText<"Disable parser lookup & use ASTScope lookup only (experimental)">; + +def enable_parser_lookup : Flag<["-"], "enable-parser-lookup">, + Flags<[FrontendOption]>, + HelpText<"Enable parser lookup">; def enable_request_based_incremental_dependencies : Flag<["-"], "enable-request-based-incremental-dependencies">, diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 2ff01dd73b4fa..b3dce353410b2 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -269,6 +269,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_print_educational_notes); inputArgs.AddLastArg(arguments, options::OPT_diagnostic_style); inputArgs.AddLastArg(arguments, options::OPT_disable_parser_lookup); + inputArgs.AddLastArg(arguments, options::OPT_enable_parser_lookup); inputArgs.AddLastArg(arguments, options::OPT_enable_experimental_concise_pound_file); inputArgs.AddLastArg( diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3d0f6a6180bb1..d02bc2222b758 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -425,7 +425,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, = A->getOption().matches(OPT_enable_target_os_checking); } - Opts.DisableParserLookup |= Args.hasArg(OPT_disable_parser_lookup); + Opts.DisableParserLookup |= Args.hasFlag(OPT_disable_parser_lookup, + OPT_enable_parser_lookup, + /*default*/ false); Opts.EnableNewOperatorLookup = Args.hasFlag(OPT_enable_new_operator_lookup, OPT_disable_new_operator_lookup, /*default*/ false); From bd36100cb3bb10e448991d7aac061e8984bc858b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 1 Oct 2020 23:43:33 -0400 Subject: [PATCH 11/13] Update tests in preparation for disabling parser lookup I created a second copy of each test where the output changes after disabling parser lookup. The primary copy now explicitly calls the frontend with -disable-parser-lookup and expects the new diagnostics; the *_parser_lookup.swift version calls the frontend with -enable-parser-lookup and has the old expectations. This allows us to turn parser lookup on and off by default without disturbing tests. Once parser lookup is completely removed we can remove the *_parser_lookup.swift variants. --- test/Constraints/tuple.swift | 4 +- test/Constraints/tuple_parser_lookup.swift | 337 +++++++ test/Parse/matching_patterns.swift | 4 +- .../matching_patterns_parser_lookup.swift | 332 ++++++ test/Parse/switch.swift | 4 +- test/Parse/switch_parser_lookup.swift | 647 ++++++++++++ test/Sema/diag_variable_used_in_initial.swift | 32 +- ...riable_used_in_initial_parser_lookup.swift | 56 ++ test/decl/circularity.swift | 5 +- test/decl/circularity_parser_lookup.swift | 114 +++ test/decl/typealias/generic.swift | 6 +- .../typealias/generic_parser_lookup.swift | 443 ++++++++ test/decl/var/variables.swift | 31 +- test/decl/var/variables_parser_lookup.swift | 121 +++ .../Localization/en_localization.swift | 7 +- .../en_localization_parser_lookup.swift | 9 + .../Localization/fr_localization.swift | 9 +- .../fr_localization_parser_lookup.swift | 13 + ...no_localization_files_and_wrong_path.swift | 7 +- ...n_files_and_wrong_path_parser_lookup.swift | 11 + test/expr/closure/closures.swift | 13 +- .../expr/closure/closures_parser_lookup.swift | 526 ++++++++++ test/expr/expressions.swift | 7 +- test/expr/expressions_parser_lookup.swift | 947 ++++++++++++++++++ test/stmt/statements.swift | 8 +- test/stmt/statements_parser_lookup.swift | 723 +++++++++++++ .../0180-rdar45557325-parser-lookup.swift | 11 + .../0180-rdar45557325.swift | 5 +- 28 files changed, 4381 insertions(+), 51 deletions(-) create mode 100644 test/Constraints/tuple_parser_lookup.swift create mode 100644 test/Parse/matching_patterns_parser_lookup.swift create mode 100644 test/Parse/switch_parser_lookup.swift create mode 100644 test/Sema/diag_variable_used_in_initial_parser_lookup.swift create mode 100644 test/decl/circularity_parser_lookup.swift create mode 100644 test/decl/typealias/generic_parser_lookup.swift create mode 100644 test/decl/var/variables_parser_lookup.swift create mode 100644 test/diagnostics/Localization/en_localization_parser_lookup.swift create mode 100644 test/diagnostics/Localization/fr_localization_parser_lookup.swift create mode 100644 test/diagnostics/Localization/no_localization_files_and_wrong_path_parser_lookup.swift create mode 100644 test/expr/closure/closures_parser_lookup.swift create mode 100644 test/expr/expressions_parser_lookup.swift create mode 100644 test/stmt/statements_parser_lookup.swift create mode 100644 validation-test/compiler_crashers_2_fixed/0180-rdar45557325-parser-lookup.swift diff --git a/test/Constraints/tuple.swift b/test/Constraints/tuple.swift index ec557012b835a..2d9a1d7d2742e 100644 --- a/test/Constraints/tuple.swift +++ b/test/Constraints/tuple.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup // Test various tuple constraints. @@ -305,6 +305,8 @@ if case (foo: let x, foo: let y) = zeroTuple { print(x+y) } // expected-error {{ // expected-warning@-1 {{'if' condition is always true}} enum BishBash { case bar(foo: Int, foo: String) } +// expected-error@-1 {{invalid redeclaration of 'foo'}} +// expected-note@-2 {{'foo' previously declared here}} let enumLabelDup: BishBash = .bar(foo: 0, foo: "") // expected-error {{cannot create a tuple with a duplicate element label}} func dupLabelClosure(_ fn: () -> Void) {} diff --git a/test/Constraints/tuple_parser_lookup.swift b/test/Constraints/tuple_parser_lookup.swift new file mode 100644 index 0000000000000..a3acaf4f356e4 --- /dev/null +++ b/test/Constraints/tuple_parser_lookup.swift @@ -0,0 +1,337 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +// Test various tuple constraints. + +func f0(x: Int, y: Float) {} + +var i : Int +var j : Int +var f : Float + +func f1(y: Float, rest: Int...) {} + +func f2(_: (_ x: Int, _ y: Int) -> Int) {} +func f2xy(x: Int, y: Int) -> Int {} +func f2ab(a: Int, b: Int) -> Int {} +func f2yx(y: Int, x: Int) -> Int {} + +func f3(_ x: (_ x: Int, _ y: Int) -> ()) {} +func f3a(_ x: Int, y: Int) {} +func f3b(_: Int) {} + +func f4(_ rest: Int...) {} +func f5(_ x: (Int, Int)) {} + +func f6(_: (i: Int, j: Int), k: Int = 15) {} + +//===----------------------------------------------------------------------===// +// Conversions and shuffles +//===----------------------------------------------------------------------===// + +func foo(a : [(some: Int, (key: Int, value: String))]) -> String { + for (i , (j, k)) in a { + if i == j { return k } + } +} + +func rdar28207648() -> [(Int, CustomStringConvertible)] { + let v : [(Int, Int)] = [] + return v as [(Int, CustomStringConvertible)] +} + +class rdar28207648Base {} +class rdar28207648Derived : rdar28207648Base {} + +func rdar28207648(x: (Int, rdar28207648Derived)) -> (Int, rdar28207648Base) { + return x as (Int, rdar28207648Base) +} + +public typealias Success = (response: T, data: V?) + +public enum Result { + case success(Success) + case error(Error) +} + + +let a = Success(response: 3, data: 3) +let success: Result = .success(a) + +// Variadic functions. +f4() +f4(1) +f4(1, 2, 3) + +f2(f2xy) +f2(f2ab) +f2(f2yx) + +f3(f3a) +f3(f3b) // expected-error{{cannot convert value of type '(Int) -> ()' to expected argument type '(Int, Int) -> ()'}} + +func getIntFloat() -> (int: Int, float: Float) {} +var values = getIntFloat() +func wantFloat(_: Float) {} +wantFloat(values.float) + +var e : (x: Int..., y: Int) // expected-error{{cannot create a variadic tuple}} + +typealias Interval = (a:Int, b:Int) +func takeInterval(_ x: Interval) {} +takeInterval(Interval(1, 2)) + +f5((1,1)) + +// Tuples with existentials +var any : Any = () +any = (1, 2) +any = (label: 4) // expected-error {{cannot create a single-element tuple with an element label}} + +// Scalars don't have .0/.1/etc +i = j.0 // expected-error{{value of type 'Int' has no member '0'}} +any.1 // expected-error{{value of type 'Any' has no member '1'}} +// expected-note@-1{{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}} +any = (5.0, 6.0) as (Float, Float) +_ = (any as! (Float, Float)).1 + +// Fun with tuples +protocol PosixErrorReturn { + static func errorReturnValue() -> Self +} + +extension Int : PosixErrorReturn { + static func errorReturnValue() -> Int { return -1 } +} + +func posixCantFail + (_ f: @escaping (A) -> T) -> (_ args:A) -> T +{ + return { args in + let result = f(args) + assert(result != T.errorReturnValue()) + return result + } +} + +func open(_ name: String, oflag: Int) -> Int { } + +var foo: Int = 0 + +var fd = posixCantFail(open)(("foo", 0)) + +// Tuples and lvalues +class C { + init() {} + func f(_: C) {} +} + +func testLValue(_ c: C) { + var c = c + c.f(c) + + let x = c + c = x +} + + +// Crash in TypeChecker::coercePatternToType +func invalidPatternCrash(_ k : Int) { + switch k { + case (k, cph_: k) as UInt8: // expected-error {{tuple pattern cannot match values of the non-tuple type 'UInt8'}} expected-warning {{cast from 'Int' to unrelated type 'UInt8' always fails}} + break + } +} + +// Tuple to tuple conversion with IdentityExpr / AnyTryExpr hang +class Paws { + init() throws {} +} + +func scruff() -> (AnyObject?, Error?) { + do { + return try (Paws(), nil) + } catch { + return (nil, error) + } +} + +// Test variadics with trailing closures. +func variadicWithTrailingClosure(_ x: Int..., y: Int = 2, fn: (Int, Int) -> Int) { +} + +variadicWithTrailingClosure(1, 2, 3) { $0 + $1 } +variadicWithTrailingClosure(1) { $0 + $1 } +variadicWithTrailingClosure() { $0 + $1 } +variadicWithTrailingClosure { $0 + $1 } + +variadicWithTrailingClosure(1, 2, 3, y: 0) { $0 + $1 } +variadicWithTrailingClosure(1, y: 0) { $0 + $1 } +variadicWithTrailingClosure(y: 0) { $0 + $1 } + +variadicWithTrailingClosure(1, 2, 3, y: 0, fn: +) +variadicWithTrailingClosure(1, y: 0, fn: +) +variadicWithTrailingClosure(y: 0, fn: +) + +variadicWithTrailingClosure(1, 2, 3, fn: +) +variadicWithTrailingClosure(1, fn: +) +variadicWithTrailingClosure(fn: +) + + +// QoI: Terrible diagnostic in tuple assignment +func gcd_23700031(_ a: T, b: T) { + var a = a + var b = b + (a, b) = (b, a % b) // expected-error {{binary operator '%' cannot be applied to two 'T' operands}} +} + +// +// Don't ignore tuple labels in same-type constraints or stronger. +protocol Kingdom { + associatedtype King +} +struct Victory { + init(_ king: K) where K.King == General {} // expected-note {{where 'General' = '(x: Int, y: Int)', 'K.King' = 'MagicKingdom<(Int, Int)>.King' (aka '(Int, Int)')}} +} +struct MagicKingdom : Kingdom { + typealias King = K +} +func magify(_ t: T) -> MagicKingdom { return MagicKingdom() } +func foo(_ pair: (Int, Int)) -> Victory<(x: Int, y: Int)> { + return Victory(magify(pair)) // expected-error {{initializer 'init(_:)' requires the types '(x: Int, y: Int)' and 'MagicKingdom<(Int, Int)>.King' (aka '(Int, Int)') be equivalent}} +} + + +// https://bugs.swift.org/browse/SR-596 +// Compiler crashes when accessing a non-existent property of a closure parameter +func call(_ f: (C) -> Void) {} +func makeRequest() { + call { obj in + print(obj.invalidProperty) // expected-error {{value of type 'C' has no member 'invalidProperty'}} + } +} + +// QoI: Misleading error message when expression result can't be inferred from closure +struct r25271859 { +} + +extension r25271859 { + func map(f: (T) -> U) -> r25271859 { + } + + func andThen(f: (T) -> r25271859) { // expected-note {{in call to function 'andThen(f:)'}} + } +} + +func f(a : r25271859<(Float, Int)>) { + a.map { $0.0 } // expected-error {{generic parameter 'U' could not be inferred}} (This is related to how solver is setup with multiple statements) + .andThen { _ in + print("hello") // comment this out and it runs, leave any form of print in and it doesn't + return r25271859() + } +} + +// LValue to rvalue conversions. + +func takesRValue(_: (Int, (Int, Int))) {} +func takesAny(_: Any) {} + +var x = 0 +var y = 0 + +let _ = (x, (y, 0)) +takesRValue((x, (y, 0))) +takesAny((x, (y, 0))) + +// SR-2600 - Closure cannot infer tuple parameter names +typealias Closure = ((a: A, b: B)) -> String + +func invoke(a: A, b: B, _ closure: Closure) { + print(closure((a, b))) +} + +invoke(a: 1, b: "B") { $0.b } + +invoke(a: 1, b: "B") { $0.1 } + +invoke(a: 1, b: "B") { (c: (a: Int, b: String)) in + return c.b +} + +invoke(a: 1, b: "B") { c in + return c.b +} + +// Crash with one-element tuple with labeled element +class Dinner {} + +func microwave() -> Dinner? { + let d: Dinner? = nil + return (n: d) // expected-error{{cannot convert return expression of type '(n: Dinner?)' to return type 'Dinner?'}} +} + +func microwave() -> Dinner { + let d: Dinner? = nil + return (n: d) // expected-error{{cannot convert return expression of type '(n: Dinner?)' to return type 'Dinner'}} +} + +// Tuple conversion with an optional +func f(b: Bool) -> (a: Int, b: String)? { + let x = 3 + let y = "" + return b ? (x, y) : nil +} + +// Single element tuple expressions +func singleElementTuple() { + let _ = (label: 123) // expected-error {{cannot create a single-element tuple with an element label}} {{12-19=}} + let _ = (label: 123).label // expected-error {{cannot create a single-element tuple with an element label}} {{12-19=}} + let _ = ((label: 123)) // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}} + let _ = ((label: 123)).label // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}} +} + +// Tuples with duplicate labels + +let dupLabel1: (foo: Int, foo: Int) = (foo: 1, foo: 2) // expected-error 2{{cannot create a tuple with a duplicate element label}} + +func dupLabel2(x a: Int, x b: Int) -> (y: Int, y: Int) { // expected-error {{cannot create a tuple with a duplicate element label}} + return (a, b) +} + +let _ = (bar: 0, bar: "") // expected-error {{cannot create a tuple with a duplicate element label}} + +let zeroTuple = (0,0) + +if case (foo: let x, foo: let y) = zeroTuple { print(x+y) } // expected-error {{cannot create a tuple with a duplicate element label}} +// expected-warning@-1 {{'if' condition is always true}} + +enum BishBash { case bar(foo: Int, foo: String) } +let enumLabelDup: BishBash = .bar(foo: 0, foo: "") // expected-error {{cannot create a tuple with a duplicate element label}} + +func dupLabelClosure(_ fn: () -> Void) {} +dupLabelClosure { print((bar: "", bar: 5).bar) } // expected-error {{cannot create a tuple with a duplicate element label}} + +struct DupLabelSubscript { + subscript(foo x: Int, foo y: Int) -> Int { + return 0 + } +} + +let dupLabelSubscriptStruct = DupLabelSubscript() +let _ = dupLabelSubscriptStruct[foo: 5, foo: 5] // ok + +// SR-12869 + +var dict: [String: (Int, Int)] = [:] +let bignum: Int64 = 1337 +dict["test"] = (bignum, 1) // expected-error {{cannot assign value of type '(Int64, Int)' to subscript of type '(Int, Int)'}} + +var tuple: (Int, Int) +tuple = (bignum, 1) // expected-error {{cannot assign value of type '(Int64, Int)' to type '(Int, Int)'}} + +var optionalTuple: (Int, Int)? +var optionalTuple2: (Int64, Int)? = (bignum, 1) +var optionalTuple3: (UInt64, Int)? = (bignum, 1) // expected-error {{cannot convert value of type '(Int64, Int)' to specified type '(UInt64, Int)?'}} + +optionalTuple = (bignum, 1) // expected-error {{cannot assign value of type '(Int64, Int)' to type '(Int, Int)'}} +// Optional to Optional +optionalTuple = optionalTuple2 // expected-error {{cannot assign value of type '(Int64, Int)?' to type '(Int, Int)?'}} diff --git a/test/Parse/matching_patterns.swift b/test/Parse/matching_patterns.swift index 1d32472a264bc..abaf38e7aa06d 100644 --- a/test/Parse/matching_patterns.swift +++ b/test/Parse/matching_patterns.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -swift-version 4 -I %S/Inputs -enable-source-import +// RUN: %target-typecheck-verify-swift -swift-version 4 -I %S/Inputs -enable-source-import -disable-parser-lookup import imported_enums @@ -47,7 +47,7 @@ case 1 + (_): // expected-error{{'_' can only appear in a pattern or on the left } switch (x,x) { -case (var a, var a): // expected-error {{definition conflicts with previous value}} expected-note {{previous definition of 'a' is here}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} +case (var a, var a): // expected-error {{invalid redeclaration of 'a'}} expected-note {{'a' previously declared here}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} fallthrough case _: // expected-warning {{case is already handled by previous patterns; consider removing it}} () diff --git a/test/Parse/matching_patterns_parser_lookup.swift b/test/Parse/matching_patterns_parser_lookup.swift new file mode 100644 index 0000000000000..172689808f50f --- /dev/null +++ b/test/Parse/matching_patterns_parser_lookup.swift @@ -0,0 +1,332 @@ +// RUN: %target-typecheck-verify-swift -swift-version 4 -I %S/Inputs -enable-source-import -enable-parser-lookup + +import imported_enums + +// TODO: Implement tuple equality in the library. +// BLOCKED: +func ~= (x: (Int,Int,Int), y: (Int,Int,Int)) -> Bool { + return true +} + +var x:Int + +func square(_ x: Int) -> Int { return x*x } + +struct A { + struct C { } +} + +switch x { +// Expressions as patterns. +case 0: + () +case 1 + 2: + () +case square(9): + () + +// 'var' and 'let' patterns. +case var a: + a = 1 +case let a: + a = 1 // expected-error {{cannot assign}} +case var var a: // expected-error {{'var' cannot appear nested inside another 'var' or 'let' pattern}} + a += 1 +case var let a: // expected-error {{'let' cannot appear nested inside another 'var' or 'let' pattern}} + print(a, terminator: "") +case var (var b): // expected-error {{'var' cannot appear nested inside another 'var'}} + b += 1 + +// 'Any' pattern. +case _: + () + +// patterns are resolved in expression-only positions are errors. +case 1 + (_): // expected-error{{'_' can only appear in a pattern or on the left side of an assignment}} + () +} + +switch (x,x) { +case (var a, var a): // expected-error {{definition conflicts with previous value}} expected-note {{previous definition of 'a' is here}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + fallthrough +case _: // expected-warning {{case is already handled by previous patterns; consider removing it}} + () +} + +var e : Any = 0 + +switch e { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +// 'is' pattern. +case is Int, + is A, + is A.C, + is (Int, Int), + is (a: Int, b: Int): + () +} + +// Enum patterns. +enum Foo { case A, B, C } + +func == (_: Voluntary, _: Voluntary) -> Bool { return true } + +enum Voluntary : Equatable { + case Naught + case Mere(T) + case Twain(T, T) + + + func enumMethod(_ other: Voluntary, foo: Foo) { + switch self { + case other: + () + + case .Naught, + .Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{17-19=}} + .Naught(_), // expected-error{{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{17-20=}} + .Naught(_, _): // expected-error{{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{17-23=}} + () + + case .Mere, + .Mere(), // expected-error{{tuple pattern cannot match values of the non-tuple type 'T'}} + .Mere(_), + .Mere(_, _): // expected-error{{tuple pattern cannot match values of the non-tuple type 'T'}} + () + + case .Twain(), // expected-error{{tuple pattern has the wrong length for tuple type '(T, T)'}} + .Twain(_), // expected-warning {{enum case 'Twain' has 2 associated values; matching them as a tuple is deprecated}} + // expected-note@-25 {{'Twain' declared here}} + .Twain(_, _), + .Twain(_, _, _): // expected-error{{tuple pattern has the wrong length for tuple type '(T, T)'}} + () + } + + switch foo { + case .Naught: // expected-error{{type 'Foo' has no member 'Naught'}} + () + case .A, .B, .C: + () + } + } +} + +var n : Voluntary = .Naught +if case let .Naught(value) = n {} // expected-error{{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{20-27=}} +if case let .Naught(value1, value2, value3) = n {} // expected-error{{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{20-44=}} + + + +switch n { +case Foo.A: // expected-error{{enum case 'A' is not a member of type 'Voluntary'}} + () +case Voluntary.Naught, + Voluntary.Naught(), // expected-error {{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{27-29=}} + Voluntary.Naught(_, _), // expected-error{{pattern with associated values does not match enum case 'Naught'}} + // expected-note@-1 {{remove associated values to make the pattern match}} {{27-33=}} + Voluntary.Naught, + .Naught: + () +case Voluntary.Mere, + Voluntary.Mere(_), + Voluntary.Mere(_, _), // expected-error{{tuple pattern cannot match values of the non-tuple type 'Int'}} + Voluntary.Mere, + Voluntary.Mere(_), + .Mere, + .Mere(_): + () +case .Twain, + .Twain(_), // expected-warning {{enum case 'Twain' has 2 associated values; matching them as a tuple is deprecated}} + // expected-note@-69 {{'Twain' declared here}} + .Twain(_, _), + .Twain(_, _, _): // expected-error{{tuple pattern has the wrong length for tuple type '(Int, Int)'}} + () +} + +var notAnEnum = 0 + +switch notAnEnum { +case .Foo: // expected-error{{type 'Int' has no member 'Foo'}} + () +} + +struct ContainsEnum { + enum Possible { + case Naught + case Mere(T) + case Twain(T, T) + } + + func member(_ n: Possible) { + switch n { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Mere(_)'}} + // expected-note@-2 {{missing case: '.Twain(_, _)'}} + case ContainsEnum.Possible.Naught, + ContainsEnum.Possible.Naught, // expected-warning {{case is already handled by previous patterns; consider removing it}} + Possible.Naught, // expected-warning {{case is already handled by previous patterns; consider removing it}} + Possible.Naught, // expected-warning {{case is already handled by previous patterns; consider removing it}} + .Naught: // expected-warning {{case is already handled by previous patterns; consider removing it}} + () + } + } +} + +func nonmemberAccessesMemberType(_ n: ContainsEnum.Possible) { + switch n { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Mere(_)'}} + // expected-note@-2 {{missing case: '.Twain(_, _)'}} + case ContainsEnum.Possible.Naught, + .Naught: // expected-warning {{case is already handled by previous patterns; consider removing it}} + () + } +} + +var m : ImportedEnum = .Simple + +switch m { +case imported_enums.ImportedEnum.Simple, + ImportedEnum.Simple, // expected-warning {{case is already handled by previous patterns; consider removing it}} + .Simple: // expected-warning {{case is already handled by previous patterns; consider removing it}} + () +case imported_enums.ImportedEnum.Compound, + imported_enums.ImportedEnum.Compound(_), // expected-warning {{case is already handled by previous patterns; consider removing it}} + ImportedEnum.Compound, // expected-warning {{case is already handled by previous patterns; consider removing it}} + ImportedEnum.Compound(_), // expected-warning {{case is already handled by previous patterns; consider removing it}} + .Compound, // expected-warning {{case is already handled by previous patterns; consider removing it}} + .Compound(_): // expected-warning {{case is already handled by previous patterns; consider removing it}} + () +} + +// Check that single-element tuple payloads work sensibly in patterns. + +enum LabeledScalarPayload { + case Payload(name: Int) +} + +var lsp: LabeledScalarPayload = .Payload(name: 0) +func acceptInt(_: Int) {} +func acceptString(_: String) {} + +switch lsp { +case .Payload(0): + () +case .Payload(name: 0): + () +case let .Payload(x): + acceptInt(x) + acceptString("\(x)") +case let .Payload(name: x): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +case let .Payload((name: x)): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +case .Payload(let (name: x)): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +case .Payload(let (name: x)): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +case .Payload(let x): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +case .Payload((let x)): // expected-warning {{case is already handled by previous patterns; consider removing it}} + acceptInt(x) + acceptString("\(x)") +} + +// Property patterns. + +struct S { + static var stat: Int = 0 + var x, y : Int + var comp : Int { + return x + y + } + + func nonProperty() {} +} + + + + + +// Tuple patterns. + +var t = (1, 2, 3) + +prefix operator +++ +infix operator +++ +prefix func +++(x: (Int,Int,Int)) -> (Int,Int,Int) { return x } +func +++(x: (Int,Int,Int), y: (Int,Int,Int)) -> (Int,Int,Int) { + return (x.0+y.0, x.1+y.1, x.2+y.2) +} + +switch t { +case (_, var a, 3): + a += 1 +case var (_, b, 3): + b += 1 +case var (_, var c, 3): // expected-error{{'var' cannot appear nested inside another 'var'}} + c += 1 +case (1, 2, 3): + () + +// patterns in expression-only positions are errors. +case +++(_, var d, 3): +// expected-error@-1{{'_' can only appear in a pattern or on the left side of an assignment}} + () +case (_, var e, 3) +++ (1, 2, 3): +// expected-error@-1{{'_' can only appear in a pattern or on the left side of an assignment}} + () +case (let (_, _, _)) + 1: +// expected-error@-1 {{'_' can only appear in a pattern or on the left side of an assignment}} + () +} + +// FIXME: We don't currently allow subpatterns for "isa" patterns that +// require interesting conditional downcasts. +class Base { } +class Derived : Base { } + + +switch [Derived(), Derived(), Base()] { +case let ds as [Derived]: // expected-error{{collection downcast in cast pattern is not implemented; use an explicit downcast to '[Derived]' instead}} + () +case is [Derived]: // expected-error{{collection downcast in cast pattern is not implemented; use an explicit downcast to '[Derived]' instead}} + () + +default: + () +} + + +// Optional patterns. +let op1 : Int? +let op2 : Int?? + +switch op1 { +case nil: break +case 1?: break +case _?: break +} + +switch op2 { +case nil: break +case _?: break +case (1?)?: break +case (_?)?: break // expected-warning {{case is already handled by previous patterns; consider removing it}} +} + + + +// Bogus diagnostic "refutable pattern match can fail" +let (responseObject: Int?) = op1 +// expected-error @-1 {{expected ',' separator}} {{25-25=,}} +// expected-error @-2 {{expected pattern}} +// expected-error @-3 {{type of expression is ambiguous without more context}} diff --git a/test/Parse/switch.swift b/test/Parse/switch.swift index d44fcacd457cb..7baf7e3ceb554 100644 --- a/test/Parse/switch.swift +++ b/test/Parse/switch.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup // TODO: Implement tuple equality in the library. // BLOCKED: @@ -246,7 +246,7 @@ case (1, _): func patternVarUsedInAnotherPattern(x: Int) { switch x { case let a, // expected-error {{'a' must be bound in every pattern}} - a: + a: // expected-error {{cannot find 'a' in scope}} break } } diff --git a/test/Parse/switch_parser_lookup.swift b/test/Parse/switch_parser_lookup.swift new file mode 100644 index 0000000000000..34a6398d7869b --- /dev/null +++ b/test/Parse/switch_parser_lookup.swift @@ -0,0 +1,647 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +// TODO: Implement tuple equality in the library. +// BLOCKED: +func ~= (x: (Int,Int), y: (Int,Int)) -> Bool { + return true +} + +func parseError1(x: Int) { + switch func {} // expected-error {{expected expression in 'switch' statement}} expected-error {{expected '{' after 'switch' subject expression}} expected-error {{expected identifier in function declaration}} expected-error {{closure expression is unused}} expected-note{{did you mean to use a 'do' statement?}} {{15-15=do }} +} + +func parseError2(x: Int) { + switch x // expected-error {{expected '{' after 'switch' subject expression}} +} + +func parseError3(x: Int) { + switch x { + case // expected-error {{expected pattern}} expected-error {{expected ':' after 'case'}} + } +} + +func parseError4(x: Int) { + switch x { + case var z where // expected-error {{expected expression for 'where' guard of 'case'}} expected-error {{expected ':' after 'case'}} + } +} + +func parseError5(x: Int) { + switch x { + case let z // expected-error {{expected ':' after 'case'}} expected-warning {{immutable value 'z' was never used}} {{8-13=_}} + } +} + +func parseError6(x: Int) { + switch x { + default // expected-error {{expected ':' after 'default'}} + } +} + +var x: Int + +switch x {} // expected-error {{'switch' statement body must have at least one 'case' or 'default' block}} + +switch x { +case 0: + x = 0 +// Multiple patterns per case +case 1, 2, 3: + x = 0 +// 'where' guard +case _ where x % 2 == 0: + x = 1 + x = 2 + x = 3 +case _ where x % 2 == 0, + _ where x % 3 == 0: + x = 1 +case 10, + _ where x % 3 == 0: + x = 1 +case _ where x % 2 == 0, + 20: + x = 1 +case var y where y % 2 == 0: + x = y + 1 +case _ where 0: // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + x = 0 +default: + x = 1 +} + +// Multiple cases per case block +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +case 1: + x = 0 +} + +switch x { +case 0: // expected-error{{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +default: + x = 0 +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: + x = 0 +case 1: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +} + +switch x { +case 0: + x = 0 +default: // expected-error {{'default' label in a 'switch' should have at least one executable statement}} {{9-9= break}} +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: + ; // expected-error {{';' statements are not allowed}} {{3-5=}} +case 1: + x = 0 +} + + + +switch x { + x = 1 // expected-error{{all statements inside a switch must be covered by a 'case' or 'default'}} +default: + x = 0 +case 0: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +case 1: + x = 0 +} + +switch x { +default: + x = 0 +default: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +} + +switch x { // expected-error{{'switch' statement body must have at least one 'case' or 'default' block}} + x = 1 // expected-error{{all statements inside a switch must be covered by a 'case' or 'default'}} +} + +switch x { // expected-error{{'switch' statement body must have at least one 'case' or 'default' block}} + x = 1 // expected-error{{all statements inside a switch must be covered by a 'case' or 'default'}} + x = 2 +} + +switch x { +default: // expected-error{{'default' label in a 'switch' should have at least one executable statement}} {{9-9= break}} +case 0: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +} + +switch x { +default: // expected-error{{'default' label in a 'switch' should have at least one executable statement}} {{9-9= break}} +default: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +default where x == 0: // expected-error{{'default' cannot be used with a 'where' guard expression}} + x = 0 +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: // expected-error{{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +case 1: + x = 0 +} + +switch x { // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} +case 0: + x = 0 +case 1: // expected-error{{'case' label in a 'switch' should have at least one executable statement}} {{8-8= break}} +} + + +case 0: // expected-error{{'case' label can only appear inside a 'switch' statement}} +var y = 0 +default: // expected-error{{'default' label can only appear inside a 'switch' statement}} +var z = 1 + +fallthrough // expected-error{{'fallthrough' is only allowed inside a switch}} + +switch x { +case 0: + fallthrough +case 1: + fallthrough +default: + fallthrough // expected-error{{'fallthrough' without a following 'case' or 'default' block}} +} + +// Fallthrough can transfer control anywhere within a case and can appear +// multiple times in the same case. +switch x { +case 0: + if true { fallthrough } + if false { fallthrough } + x += 1 +default: + x += 1 +} + +// Cases cannot contain 'var' bindings if there are multiple matching patterns +// attached to a block. They may however contain other non-binding patterns. + +var t = (1, 2) + +switch t { +case (var a, 2), (1, _): // expected-error {{'a' must be bound in every pattern}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + () + +case (_, 2), (var a, _): // expected-error {{'a' must be bound in every pattern}} + () + +case (var a, 2), (1, var b): // expected-error {{'a' must be bound in every pattern}} expected-error {{'b' must be bound in every pattern}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + () + +case (var a, 2): // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{17-17= break}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} +case (1, _): + () + +case (_, 2): // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{13-13= break}} +case (1, var a): // expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + () + +case (var a, 2): // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{17-17= break}} expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} +case (1, var b): // expected-warning {{variable 'b' was never used; consider replacing with '_' or removing it}} + () + +case (1, let b): // let bindings expected-warning {{immutable value 'b' was never used; consider replacing with '_' or removing it}} + () + +case (_, 2), (let a, _): // expected-error {{'a' must be bound in every pattern}} expected-warning {{case is already handled by previous patterns; consider removing it}} + () + +// OK +case (_, 2), (1, _): + () + +case (_, var a), (_, var a): // expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + // expected-warning@-2 {{case is already handled by previous patterns; consider removing it}} + () + +case (var a, var b), (var b, var a): // expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} expected-warning {{variable 'b' was never used; consider replacing with '_' or removing it}} + // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + // expected-warning@-2 {{case is already handled by previous patterns; consider removing it}} + () + +case (_, 2): // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{13-13= break}} +case (1, _): + () +} + +func patternVarUsedInAnotherPattern(x: Int) { + switch x { + case let a, // expected-error {{'a' must be bound in every pattern}} + a: + break + } +} + +// Fallthroughs can only transfer control into a case label with bindings if the previous case binds a superset of those vars. +switch t { +case (1, 2): + fallthrough // expected-error {{'fallthrough' from a case which doesn't bind variable 'a'}} expected-error {{'fallthrough' from a case which doesn't bind variable 'b'}} +case (var a, var b): // expected-warning {{variable 'a' was never mutated; consider changing to 'let' constant}} expected-warning {{variable 'b' was never mutated; consider changing to 'let' constant}} + t = (b, a) +} + +switch t { // specifically notice on next line that we shouldn't complain that a is unused - just never mutated +case (var a, let b): // expected-warning {{variable 'a' was never mutated; consider changing to 'let' constant}} + t = (b, b) + fallthrough // ok - notice that subset of bound variables falling through is fine +case (2, let a): + t = (a, a) +} + +func patternVarDiffType(x: Int, y: Double) { + switch (x, y) { + case (1, let a): // expected-error {{pattern variable bound to type 'Double', fallthrough case bound to type 'Int'}} + fallthrough + case (let a, _): + break + } +} + +func patternVarDiffMutability(x: Int, y: Double) { + switch x { + case let a where a < 5, var a where a > 10: // expected-error {{'var' pattern binding must match previous 'let' pattern binding}}{{27-30=let}} + break + default: + break + } + switch (x, y) { + // Would be nice to have a fixit in the following line if we detect that all bindings in the same pattern have the same problem. + case let (a, b) where a < 5, var (a, b) where a > 10: // expected-error 2{{'var' pattern binding must match previous 'let' pattern binding}}{{none}} + break + case (let a, var b) where a < 5, (let a, let b) where a > 10: // expected-error {{'let' pattern binding must match previous 'var' pattern binding}}{{44-47=var}} + break + case (let a, let b) where a < 5, (var a, let b) where a > 10, (let a, var b) where a == 8: + // expected-error@-1 {{'var' pattern binding must match previous 'let' pattern binding}}{{37-40=let}} + // expected-error@-2 {{'var' pattern binding must match previous 'let' pattern binding}}{{73-76=let}} + break + default: + break + } +} + +func test_label(x : Int) { +Gronk: // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} + switch x { + case 42: return + } +} + +func enumElementSyntaxOnTuple() { + switch (1, 1) { + case .Bar: // expected-error {{value of tuple type '(Int, Int)' has no member 'Bar'}} + break + default: + break + } +} + +// sr-176 +enum Whatever { case Thing } +func f0(values: [Whatever]) { // expected-note {{'values' declared here}} + switch value { // expected-error {{cannot find 'value' in scope; did you mean 'values'?}} + case .Thing: // Ok. Don't emit diagnostics about enum case not found in type <>. + break + } +} + +// sr-720 +enum Whichever { + case Thing + static let title = "title" + static let alias: Whichever = .Thing +} +func f1(x: String, y: Whichever) { + switch x { + case Whichever.title: // Ok. Don't emit diagnostics for static member of enum. + break + case Whichever.buzz: // expected-error {{type 'Whichever' has no member 'buzz'}} + break + case Whichever.alias: // expected-error {{expression pattern of type 'Whichever' cannot match values of type 'String'}} + // expected-note@-1 {{overloads for '~=' exist with these partially matching parameter lists: (Substring, String)}} + break + default: + break + } + switch y { + case Whichever.Thing: // Ok. + break + case Whichever.alias: // Ok. Don't emit diagnostics for static member of enum. + break + case Whichever.title: // expected-error {{expression pattern of type 'String' cannot match values of type 'Whichever'}} + break + } +} + + +switch Whatever.Thing { +case .Thing: // expected-error{{'case' label in a 'switch' should have at least one executable statement}} {{13-13= break}} +@unknown case _: + x = 0 +} + +switch Whatever.Thing { +case .Thing: // expected-error{{'case' label in a 'switch' should have at least one executable statement}} {{13-13= break}} +@unknown default: + x = 0 +} + +switch Whatever.Thing { +case .Thing: + x = 0 +@unknown case _: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{17-17= break}} +} + +switch Whatever.Thing { +case .Thing: + x = 0 +@unknown default: // expected-error {{'default' label in a 'switch' should have at least one executable statement}} {{18-18= break}} +} + + +switch Whatever.Thing { +@unknown default: + x = 0 +default: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +case .Thing: + x = 0 +} + +switch Whatever.Thing { +default: + x = 0 +@unknown case _: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} expected-error {{'@unknown' can only be applied to the last case in a switch}} + x = 0 +case .Thing: + x = 0 +} + +switch Whatever.Thing { +default: + x = 0 +@unknown default: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + x = 0 +case .Thing: + x = 0 +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown default where x == 0: // expected-error{{'default' cannot be used with a 'where' guard expression}} + x = 0 +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case _: + fallthrough // expected-error{{'fallthrough' without a following 'case' or 'default' block}} +} + +switch Whatever.Thing { +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + fallthrough +case .Thing: + break +} + +switch Whatever.Thing { +@unknown default: + fallthrough +case .Thing: // expected-error{{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + break +} + +switch Whatever.Thing { +@unknown case _, _: // expected-error {{'@unknown' cannot be applied to multiple patterns}} + break +} + +switch Whatever.Thing { +@unknown case _, _, _: // expected-error {{'@unknown' cannot be applied to multiple patterns}} + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case let value: // expected-error {{'@unknown' is only supported for catch-all cases ("case _")}} + _ = value +} + +switch (Whatever.Thing, Whatever.Thing) { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '(_, _)'}} +@unknown case (_, _): // expected-error {{'@unknown' is only supported for catch-all cases ("case _")}} + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case is Whatever: // expected-error {{'@unknown' is only supported for catch-all cases ("case _")}} + // expected-warning@-1 {{'is' test is always true}} + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case .Thing: // expected-error {{'@unknown' is only supported for catch-all cases ("case _")}} + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case (_): // okay + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown case _ where x == 0: // expected-error {{'where' cannot be used with '@unknown'}} + break +} + +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}} +@unknown default where x == 0: // expected-error {{'default' cannot be used with a 'where' guard expression}} + break +} + +switch Whatever.Thing { +case .Thing: + x = 0 +#if true +@unknown case _: + x = 0 +#endif +} + +switch x { +case 0: + break +@garbage case _: // expected-error {{unknown attribute 'garbage'}} + break +} + +switch x { +case 0: + break +@garbage @moreGarbage default: // expected-error {{unknown attribute 'garbage'}} expected-error {{unknown attribute 'moreGarbage'}} + break +} + +@unknown let _ = 1 // expected-error {{unknown attribute 'unknown'}} + +switch x { +case _: + @unknown let _ = 1 // expected-error {{unknown attribute 'unknown'}} +} + +switch Whatever.Thing { +case .Thing: + break +@unknown(garbage) case _: // expected-error {{unexpected '(' in attribute 'unknown'}} + break +} +switch Whatever.Thing { +case .Thing: + break +@unknown // expected-note {{attribute already specified here}} +@unknown // expected-error {{duplicate attribute}} +case _: + break +} +switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note {{add missing case: '.Thing'}} +@unknown @garbage(foobar) // expected-error {{unknown attribute 'garbage'}} +case _: + break +} + +switch x { // expected-error {{switch must be exhaustive}} +case 1: + break +@unknown case _: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}} + break +} + +switch x { // expected-error {{switch must be exhaustive}} +@unknown case _: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}} + break +} + +switch x { // expected-error {{switch must be exhaustive}} +@unknown default: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}} + break +} + +switch Whatever.Thing { +case .Thing: + break +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown case _: + break +} + +switch Whatever.Thing { +case .Thing: + break +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown default: + break +} + +switch Whatever.Thing { +case .Thing: + break +@unknown default: + break +@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + break +} + +switch Whatever.Thing { +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown case _: + break +} + +switch Whatever.Thing { +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown default: + break +} + +switch Whatever.Thing { +@unknown default: + break +@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + break +} + + +switch x { +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown case _: + break +} + +switch x { +@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}} + break +@unknown default: + break +} + +switch x { +@unknown default: + break +@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}} + break +} + +func testReturnBeforeUnknownDefault() { + switch x { // expected-error {{switch must be exhaustive}} + case 1: + return + @unknown default: // expected-note {{remove '@unknown' to handle remaining values}} + break + } +} + +func testReturnBeforeIncompleteUnknownDefault() { + switch x { // expected-error {{switch must be exhaustive}} + case 1: + return + @unknown default // expected-error {{expected ':' after 'default'}} + // expected-note@-1 {{remove '@unknown' to handle remaining values}} + } +} + +func testReturnBeforeIncompleteUnknownDefault2() { + switch x { // expected-error {{switch must be exhaustive}} expected-note {{do you want to add a default clause?}} + case 1: + return + @unknown // expected-error {{unknown attribute 'unknown'}} + } // expected-error {{expected declaration}} +} + +func testIncompleteArrayLiteral() { + switch x { // expected-error {{switch must be exhaustive}} + case 1: + _ = [1 // expected-error {{expected ']' in container literal expression}} expected-note {{to match this opening '['}} + @unknown default: // expected-note {{remove '@unknown' to handle remaining values}} + () + } +} diff --git a/test/Sema/diag_variable_used_in_initial.swift b/test/Sema/diag_variable_used_in_initial.swift index c84cdc9d0cdc6..c60dc5c0dc0fa 100644 --- a/test/Sema/diag_variable_used_in_initial.swift +++ b/test/Sema/diag_variable_used_in_initial.swift @@ -1,45 +1,49 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup class A1 { - func foo1() {} + func foo1() -> Int {} func foo2() { - var foo1 = foo1() // expected-error {{variable used within its own initial value}} + var foo1 = foo1() + // expected-warning@-1 {{initialization of variable 'foo1' was never used; consider replacing with assignment to '_' or removing it}} } } class A2 { var foo1 = 2 func foo2() { - // FIXME: "the var" doesn't sound right. - var foo1 = foo1 // expected-error {{variable used within its own initial value}} + var foo1 = foo1 + // expected-warning@-1 {{initialization of variable 'foo1' was never used; consider replacing with assignment to '_' or removing it}} } } class A3 { func foo2() { - // FIXME: this should also add fixit. - var foo1 = foo1() // expected-error {{variable used within its own initial value}}{{none}} + var foo1 = foo1() + // expected-warning@-1 {{initialization of variable 'foo1' was never used; consider replacing with assignment to '_' or removing it}} } - func foo1() {} + func foo1() -> Int {} } class A4 { func foo2() { - var foo1 = foo1 // expected-error {{variable used within its own initial value}}{{none}} + var foo1 = foo1 // expected-error {{use of local variable 'foo1' before its declaration}} + // expected-note@-1 {{'foo1' declared here}} } } func localContext() { class A5 { - func foo1() {} + func foo1() -> Int {} func foo2() { - var foo1 = foo1() // expected-error {{variable used within its own initial value}} + var foo1 = foo1() + // expected-warning@-1 {{initialization of variable 'foo1' was never used; consider replacing with assignment to '_' or removing it}} } class A6 { - func foo1() {} + func foo1() -> Int {} func foo2() { - var foo1 = foo1() // expected-error {{variable used within its own initial value}} + var foo1 = foo1() + // expected-warning@-1 {{initialization of variable 'foo1' was never used; consider replacing with assignment to '_' or removing it}} } } @@ -48,7 +52,7 @@ func localContext() { class A7 { func foo1() {} func foo2() { - var foo1 = foo1() // expected-error {{variable used within its own initial value}} + var foo1 = foo1() } } } diff --git a/test/Sema/diag_variable_used_in_initial_parser_lookup.swift b/test/Sema/diag_variable_used_in_initial_parser_lookup.swift new file mode 100644 index 0000000000000..6b2d7f900343e --- /dev/null +++ b/test/Sema/diag_variable_used_in_initial_parser_lookup.swift @@ -0,0 +1,56 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +class A1 { + func foo1() {} + func foo2() { + var foo1 = foo1() // expected-error {{variable used within its own initial value}} + } +} + +class A2 { + var foo1 = 2 + func foo2() { + // FIXME: "the var" doesn't sound right. + var foo1 = foo1 // expected-error {{variable used within its own initial value}} + } +} + +class A3 { + func foo2() { + // FIXME: this should also add fixit. + var foo1 = foo1() // expected-error {{variable used within its own initial value}}{{none}} + } + func foo1() {} +} + +class A4 { + func foo2() { + var foo1 = foo1 // expected-error {{variable used within its own initial value}}{{none}} + } +} + +func localContext() { + class A5 { + func foo1() {} + func foo2() { + var foo1 = foo1() // expected-error {{variable used within its own initial value}} + } + + class A6 { + func foo1() {} + func foo2() { + var foo1 = foo1() // expected-error {{variable used within its own initial value}} + } + } + + extension E { // expected-error {{declaration is only valid at file scope}} + // expected-error@-1{{cannot find type 'E' in scope}} + class A7 { + func foo1() {} + func foo2() { + var foo1 = foo1() // expected-error {{variable used within its own initial value}} + } + } + } + } +} diff --git a/test/decl/circularity.swift b/test/decl/circularity.swift index 1f2db505630a4..29af1f663a23c 100644 --- a/test/decl/circularity.swift +++ b/test/decl/circularity.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup // N.B. Validating the pattern binding initializer for `pickMe` used to cause // recursive validation of the VarDecl. Check that we don't regress now that @@ -40,7 +40,8 @@ class Base { class Sub: Base { var foo = { () -> Int in let x = 42 - return foo(1) // expected-error {{variable used within its own initial value}} + // FIXME: Bogus diagnostic + return foo(1) // expected-error {{cannot convert return expression of type '()' to return type 'Int'}} }() } diff --git a/test/decl/circularity_parser_lookup.swift b/test/decl/circularity_parser_lookup.swift new file mode 100644 index 0000000000000..be25472613ee6 --- /dev/null +++ b/test/decl/circularity_parser_lookup.swift @@ -0,0 +1,114 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +// N.B. Validating the pattern binding initializer for `pickMe` used to cause +// recursive validation of the VarDecl. Check that we don't regress now that +// this isn't the case. +public struct Cyclic { + static func pickMe(please: Bool) -> Int { return 42 } + public static let pickMe = Cyclic.pickMe(please: true) +} + +struct Node {} +struct Parameterized { + func please(_ transform: @escaping (_ otherValue: NewValue) -> Value) -> Parameterized { + fatalError() + } +} + +extension Parameterized where Value == [Node], Format == String { + static var pickMe: Parameterized { + fatalError() + } +} + +extension Parameterized where Value == Node, Format == String { + static let pickMe = Parameterized<[Node], String>.pickMe.please { [$0] } +} + +enum Loop: Circle { + struct DeLoop { } +} + +protocol Circle { + typealias DeLoop = Loop.DeLoop +} + +class Base { + static func foo(_ x: Int) {} +} + +class Sub: Base { + var foo = { () -> Int in + let x = 42 + return foo(1) // expected-error {{variable used within its own initial value}} + }() +} + +extension Float { + static let pickMe: Float = 1 +} + +extension SIMD3 { + init(_ scalar: Scalar) { self.init(repeating: scalar) } +} + +extension SIMD3 where SIMD3.Scalar == Float { + static let pickMe = SIMD3(.pickMe) +} + +// Test case with circular overrides +protocol P { + associatedtype A + // expected-note@-1 {{protocol requires nested type 'A'; do you want to add it?}} + // expected-note@-2 {{through reference here}} + func run(a: A) +} + +class C1 { + func run(a: Int) {} +} + +class C2: C1, P { + override func run(a: A) {} + // expected-error@-1 {{circular reference}} + // expected-note@-2 {{while resolving type 'A'}} + // expected-note@-3 2{{through reference here}} +} + +// Another crash to the above +open class G1 { + open func run(a: A) {} +} + +class C3: G1, P { + // expected-error@-1 {{type 'C3' does not conform to protocol 'P'}} + // expected-error@-2 {{cannot find type 'A' in scope}} + override func run(a: A) {} + // expected-error@-1 {{method does not override any method from its superclass}} +} + +// Another case that triggers circular override checking. +protocol P1 { + associatedtype X = Int // expected-note {{through reference here}} + init(x: X) +} + +class C4 { + required init(x: Int) {} +} + +class D4 : C4, P1 { // expected-note 2 {{through reference here}} + required init(x: X) { // expected-error {{circular reference}} + // expected-note@-1 {{while resolving type 'X'}} + // expected-note@-2 2{{through reference here}} + super.init(x: x) + } +} + +// SR-12236 +// N.B. This used to compile in 5.1. +protocol SR12236 { } +class SR12236_A { // expected-note {{through reference here}} + typealias Nest = SR12236 // expected-error {{circular reference}} expected-note {{through reference here}} +} +extension SR12236_A: SR12236_A.Nest { } diff --git a/test/decl/typealias/generic.swift b/test/decl/typealias/generic.swift index faf486048ec3a..732800f558492 100644 --- a/test/decl/typealias/generic.swift +++ b/test/decl/typealias/generic.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup struct MyType { // expected-note {{generic type 'MyType' declared here}} // expected-note @-1 {{arguments to generic parameter 'TyB' ('S' and 'Int') are expected to be equal}} @@ -35,8 +35,8 @@ typealias BadA = MyType // expected-error {{type 'T' constr typealias BadB = MyType // expected-error {{associated types must not have a generic parameter list}} // expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}} -typealias BadC = MyType // expected-error {{definition conflicts with previous value}} -// expected-note @-1 {{previous definition of 'T' is here}} +typealias BadC = MyType // expected-error {{invalid redeclaration of 'T'}} +// expected-note @-1 {{'T' previously declared here}} typealias Tuple2 = (T1, T2) diff --git a/test/decl/typealias/generic_parser_lookup.swift b/test/decl/typealias/generic_parser_lookup.swift new file mode 100644 index 0000000000000..63c0cb22af2f0 --- /dev/null +++ b/test/decl/typealias/generic_parser_lookup.swift @@ -0,0 +1,443 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +struct MyType { // expected-note {{generic type 'MyType' declared here}} + // expected-note @-1 {{arguments to generic parameter 'TyB' ('S' and 'Int') are expected to be equal}} + // expected-note @-2 4 {{arguments to generic parameter 'TyA' ('Float' and 'Int') are expected to be equal}} + var a : TyA, b : TyB +} + +// +// Type aliases that reference unbound generic types -- not really generic, +// but they behave as such, in the sense that you can apply generic +// arguments to them. +// + +typealias OurType = MyType + +typealias YourType = Swift.Optional + +struct Container { + typealias YourType = Swift.Optional +} + +let _: OurType +let _: YourType +let _: Container.YourType + +// +// Bona-fide generic type aliases +// + +typealias DS = MyType + +typealias BadA = MyType // expected-error {{type 'T' constrained to non-protocol, non-class type 'Int'}} + +typealias BadB = MyType // expected-error {{associated types must not have a generic parameter list}} +// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}} + +typealias BadC = MyType // expected-error {{definition conflicts with previous value}} +// expected-note @-1 {{previous definition of 'T' is here}} + +typealias Tuple2 = (T1, T2) + +typealias Tuple3 = (T1, T1) where T1 : Hashable + + +let _ : Tuple2 = (1, "foo") +let _ : Tuple2 = (1, "foo") +let _ : Tuple2 = ("bar", // expected-error {{cannot convert value of type '(String, String)' to specified type 'Tuple2' (aka '(Int, String)')}} + "foo") + +func f() { + typealias Tuple2b = (T1, T2) + let _ : Tuple2b = (1, "foo") + +} + + +typealias A = MyType // expected-note {{generic type 'A' declared here}} + +typealias B = MyType + +typealias C = MyType + +// Type aliases with unused generic params. +typealias D = MyType // expected-note 3 {{'T3' declared as parameter to type 'D'}} + +typealias E = Int // expected-note {{generic type 'E' declared here}} +// expected-note@-1 {{'T1' declared as parameter to type 'E'}} +// expected-note@-2 {{'T2' declared as parameter to type 'E'}} + +typealias F = (T1) -> T2 + +// Type alias of type alias. +typealias G = A + +let _ : E = 42 +let _ : E = 42 // expected-error {{generic type 'E' specialized with too few type parameters (got 1, but expected 2)}} +let _ : E = 42 +// expected-error@-1 {{generic parameter 'T1' could not be inferred}} +// expected-error@-2 {{generic parameter 'T2' could not be inferred}} +let _ : D = D(a: 1, b: 2) +// expected-error@-1 {{generic parameter 'T3' could not be inferred}} +// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{14-14=}} + +let _ : D = D(a: 1, b: 2) + +let _ : D = D(a: 1, b: 2) +// expected-error@-1 {{generic parameter 'T3' could not be inferred}} + + +// expected-error @+2 {{generic parameter 'T3' could not be inferred}} +// expected-note @+1 {{explicitly specify the generic arguments to fix this issue}} {{31-31=}} +let _ : D = D(a: 1, b: 2) + +let _ : F = { (a : Int) -> Int in a } // Infer the types of F + +let _ : F = { a in a } // expected-error {{unable to infer type of a closure parameter 'a' in the current context}} + +_ = MyType(a: "foo", b: 42) +_ = A(a: "foo", b: 42) +_ = A(a: "foo", b: 42) +_ = A(a: "foo", // expected-error {{cannot convert value of type 'String' to expected argument type 'Int'}} + b: 42) // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} +_ = B(a: 12, b: 42) +_ = B(a: 12, b: 42 as Float) +_ = B(a: "foo", b: 42) // expected-error {{conflicting arguments to generic parameter 'T1' ('Int' vs. 'String')}} +_ = C(a: "foo", b: 42) +_ = C(a: 42, // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} + b: 42) + +_ = G(a: "foo", b: 42) +_ = G(a: "foo", b: 42) + +// Generic typealias cannot have unbound generic type. +typealias VeryBad1 = MyType // expected-error {{reference to generic type 'MyType' requires arguments in <...>}} +typealias VeryBad2 = Swift.Array // expected-error {{reference to generic type 'Array' requires arguments in <...>}} + +struct MyTypeWithHashable { +} + +typealias MTWHInt = MyTypeWithHashable +typealias MTWHInt2 = MyTypeWithHashable // expected-error {{type 'HT' does not conform to protocol 'Hashable'}} + +func f(a : MyTypeWithHashable) { + f(a: MyTypeWithHashable()) + f(a: MTWHInt()) +} + + +// Unqualified lookup of generic typealiases nested inside generic contexts +class GenericClass { + typealias TA = MyType + typealias TAI = MyType + + func testCapture(s: S, t: T) -> TA { + return TA(a: t, b: s) + } + + func testCaptureUnbound(s: S, t: T) -> TA { + return TA(a: t, b: s) + } + + func testConcrete1(s: Int, t: T) -> TA { + return TA(a: t, b: s) + } + + func testConcreteUnbound1(s: Int, t: T) -> TA { + return TA(a: t, b: s) + } + + func testConcrete2(s: Float, t: Int) -> TAI { + return TAI(a: t, b: s) + } + + func testConcreteUnbound2(s: Float, t: Int) -> TAI { + return TAI(a: t, b: s) + } + + func testCaptureInvalid1(s: S, t: T) -> TA { + return TA(a: t, b: s) // expected-error {{cannot convert return expression of type 'GenericClass.TA' (aka 'MyType') to return type 'GenericClass.TA' (aka 'MyType')}} + } + + func testCaptureInvalid2(s: Int, t: T) -> TA { + return TA(a: t, b: s) // expected-error {{cannot convert value of type 'Int' to expected argument type 'S'}} + } + + struct NestedStruct { + typealias TA = MyType<(T, V), (U, V)> + + func testCapture(x: (T, S), y: (U, S)) -> TA { + return TA(a: x, b: y) + } + } + + // Stupid corner case -- underlying type is not dependent + typealias NotDependent = Int + + func misleadingCode(_: NotDependent) {} +} + +let gc = GenericClass() +let fn: MyType = gc.testCapture(s: 1, t: 1.0) + +func use(_ t: T) {} +use(fn) + +// Make sure we apply base substitutions to the interface type of the typealias +class ConcreteClass : GenericClass { + func testSubstitutedCapture1(s: S, t: String) -> TA { + return TA(a: t, b: s) + } + + func testSubstitutedCapture2(s: S, t: String) -> TA { + return TA(a: t, b: s) + } + + func testSubstitutedCapture3(s: Int, t: String) -> TA { + return TA(a: t, b: s) + } + + func testSubstitutedCapture4(s: Int, t: String) -> TA { + return TA(a: t, b: s) + } + + func testSubstitutedCapture5(s: Float, t: Int) -> TAI { + return TAI(a: t, b: s) + } + + func testSubstitutedCapture6(s: Float, t: Int) -> TAI { + return TAI(a: t, b: s) + } +} + +// Qualified lookup of generic typealiases nested inside concrete contexts +struct ConcreteStruct { + typealias O = Optional +} + +func takesUnsugaredType1(m: MyType) {} +func takesSugaredType1(m: ConcreteClass.TA) { + takesUnsugaredType1(m: m) +} + +let _ = ConcreteStruct.O(123) +let _ = ConcreteStruct.O(123) + +let _: ConcreteStruct.O = ConcreteStruct.O(123) +let _: ConcreteStruct.O = ConcreteStruct.O(123) + +let _: ConcreteStruct.O = ConcreteStruct.O(123) +let _: ConcreteStruct.O = ConcreteStruct.O(123) + +// Qualified lookup of generic typealiases nested inside generic contexts +// +// FIXME marks cases which still don't work correctly, and either produce a +// spurious diagnostic, or are actually invalid and do not diagnose. +// +// This occurs because the constraint solver does the wrong thing with an +// UnresolvedSpecializeExpr applied to a generic typealias. +// +// In the other cases, we manage to fold the UnresolvedSpecializeExpr in the +// precheckExpression() phase, which handles generic typealiases correctly. + +let _ = GenericClass.TA(a: 4.0, b: 1) // FIXME +let _ = GenericClass.TA(a: 1, b: 4.0) + +let _ = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _ = GenericClass.TA(a: 1, b: 4.0) + +let _ = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _ = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // FIXME +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType' to type 'MyType'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType' to type 'MyType'}} + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType' to type 'GenericClass.TA' (aka 'MyType')}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType' to type 'GenericClass.TA' (aka 'MyType')}} + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} +let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0) + +func takesUnsugaredType2(m: MyType) {} +func takesSugaredType2(m: GenericClass.TA) { + takesUnsugaredType2(m: m) +} + + +// +// Error paths +// + +// This works, but in the body of the extension we see the original type +// parameters of A<>'s underlying type MyType<>, rather than the type +// parameters of A<>. +extension A {} + +extension A {} // expected-error {{generic type 'A' specialized with too few type parameters (got 1, but expected 2)}} +extension A {} // expected-error {{constrained extension must be declared on the unspecialized generic type 'MyType' with constraints specified by a 'where' clause}} +extension C {} // expected-error {{cannot find type 'T' in scope}} +extension C {} // expected-error {{constrained extension must be declared on the unspecialized generic type 'MyType' with constraints specified by a 'where' clause}} + + +protocol ErrorQ { + associatedtype Y +} +protocol ErrorP { + associatedtype X: ErrorQ // expected-note {{protocol requires nested type 'X'; do you want to add it?}} +} + +typealias ErrorA = T.X.Y + +struct ErrorB : ErrorP { // expected-error {{type 'ErrorB' does not conform to protocol 'ErrorP'}} + typealias X = ErrorC // expected-note {{possibly intended match 'ErrorB.X' (aka 'ErrorC') does not conform to 'ErrorQ'}} +} + +struct ErrorC { + typealias Y = Int +} + +typealias Y = ErrorA + +typealias Id = T + +extension Id {} // expected-error {{non-nominal type 'Id' cannot be extended}} + +class OuterGeneric { + typealias Alias = AnotherGeneric + // expected-note@-1 {{generic type 'Alias' declared here}} + class InnerNonGeneric : Alias {} + // expected-error@-1 {{reference to generic type 'OuterGeneric.Alias' requires arguments in <...>}} +} + +class AnotherGeneric {} + +// +// Generic typealiases in protocols +// + +protocol P { + associatedtype A + typealias G1 = MyType + typealias G2 = MyType + typealias G3 = () -> () + typealias G4 = (T) -> () + + func firstRequirement(_: G1) + func secondRequirement(_: G2) + func thirdRequirement(_: G3) + func fourthRequirement(_: G4) + + func firstRequirementGeneric(_: G1) + func secondRequirementGeneric(_: G2) + func thirdRequirementGeneric(_: G3, _: T) + func fourthRequirementGeneric(_: G4) +} + +struct S : P { + typealias A = Float + + func shouldFail(fn: (Int) -> ()) { + thirdRequirement(fn) + // expected-error@-1 {{cannot convert value of type '(Int) -> ()' to expected argument type '() -> ()'}} + } + + func firstRequirement(_: G1) {} + func secondRequirement(_: G2) {} + func thirdRequirement(_: G3) {} + func fourthRequirement(_: G4) {} + + func firstRequirementGeneric(_: G1) { + _ = G1.self + } + + func secondRequirementGeneric(_: G2) { + _ = G2.self + } + + func thirdRequirementGeneric(_: G3, _: T) { + _ = G3.self + } + + func fourthRequirementGeneric(_: G4) { + _ = G4.self + } + + func expressionContext() { + let _: G1 = MyType(a: S(), b: 3) + let _: G1 = MyType(a: S(), b: 3) + + let _: S.G1 = MyType(a: S(), b: 3) + let _: S.G1 = MyType(a: S(), b: 3) + + let _: G2 = MyType(a: 3, b: 1.0) + let _: G2 = MyType(a: 3, b: 1.0) + + let _: S.G2 = MyType(a: 3, b: 1.0) + let _: S.G2 = MyType(a: 3, b: 1.0) + } +} + +func takesMyType(x: MyType) {} + +func takesMyType(y: MyType) {} + +func f(x: S.G1, y: S.G2) { + takesMyType(x: x) + takesMyType(y: y) +} + +// +// Generic typealiases with requirements +// + +typealias Element = S.Iterator.Element where S : Sequence + +func takesInt(_: Element<[Int]>) {} + +takesInt(10) + +func failsRequirementCheck(_: Element) {} +// expected-error@-1 {{type 'Int' does not conform to protocol 'Sequence'}} + +// +// Sugar in base types of a typealias. +// +struct X { + typealias GY = [V] +} + +typealias GX = X + +func testSugar(_ gx: GX, _ gy: GX.GY, gz: GX.GY.Element) { + let i: Int = gx // expected-error{{cannot convert value of type 'GX' (aka 'X') to specified type 'Int'}} + let i2: Int = gy // expected-error{{cannot convert value of type 'GX.GY' (aka 'Array') to specified type 'Int'}} + let i3: Int = gz // expected-error{{cannot convert value of type 'GX.GY.Element' (aka 'Double') to specified type 'Int'}} +} diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index f2b5d0190c4b1..b470686ca0819 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup var t1 : Int var t2 = 10 @@ -14,17 +14,30 @@ var bfx : Int, bfy : Int _ = 10 -var self1 = self1 // expected-error {{variable used within its own initial value}} -var self2 : Int = self2 // expected-error {{variable used within its own initial value}} -var (self3) : Int = self3 // expected-error {{variable used within its own initial value}} -var (self4) : Int = self4 // expected-error {{variable used within its own initial value}} -var self5 = self5 + self5 // expected-error 2 {{variable used within its own initial value}} -var self6 = !self6 // expected-error {{variable used within its own initial value}} -var (self7a, self7b) = (self7b, self7a) // expected-error 2 {{variable used within its own initial value}} +var self1 = self1 +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} + +var self2 : Int = self2 +var (self3) : Int = self3 +var (self4) : Int = self4 + +var self5 = self5 + self5 +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} + +var self6 = !self6 +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} + +var (self7a, self7b) = (self7b, self7a) +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} var self8 = 0 func testShadowing() { - var self8 = self8 // expected-error {{variable used within its own initial value}} + var self8 = self8 + // expected-warning@-1 {{initialization of variable 'self8' was never used; consider replacing with assignment to '_' or removing it}} } var (paren) = 0 diff --git a/test/decl/var/variables_parser_lookup.swift b/test/decl/var/variables_parser_lookup.swift new file mode 100644 index 0000000000000..8b2fa5c2aa080 --- /dev/null +++ b/test/decl/var/variables_parser_lookup.swift @@ -0,0 +1,121 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +var t1 : Int +var t2 = 10 +var t3 = 10, t4 = 20.0 +var (t5, t6) = (10, 20.0) +var t7, t8 : Int +var t9, t10 = 20 // expected-error {{type annotation missing in pattern}} +var t11, t12 : Int = 20 // expected-error {{type annotation missing in pattern}} +var t13 = 2.0, t14 : Int +var (x = 123, // expected-error {{expected ',' separator}} {{7-7=,}} expected-error {{expected pattern}} + y = 456) : (Int,Int) +var bfx : Int, bfy : Int + +_ = 10 + +var self1 = self1 // expected-error {{variable used within its own initial value}} +var self2 : Int = self2 // expected-error {{variable used within its own initial value}} +var (self3) : Int = self3 // expected-error {{variable used within its own initial value}} +var (self4) : Int = self4 // expected-error {{variable used within its own initial value}} +var self5 = self5 + self5 // expected-error 2 {{variable used within its own initial value}} +var self6 = !self6 // expected-error {{variable used within its own initial value}} +var (self7a, self7b) = (self7b, self7a) // expected-error 2 {{variable used within its own initial value}} + +var self8 = 0 +func testShadowing() { + var self8 = self8 // expected-error {{variable used within its own initial value}} +} + +var (paren) = 0 +var paren2: Int = paren + +struct Broken { + var b : Bool = True // expected-error{{cannot find 'True' in scope}} +} + +// rdar://16252090 - Warning when inferring empty tuple type for declarations +var emptyTuple = testShadowing() // expected-warning {{variable 'emptyTuple' inferred to have type '()'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: ()}} + +// rdar://15263687 - Diagnose variables inferenced to 'AnyObject' +var ao1 : AnyObject +var ao2 = ao1 + +var aot1 : AnyObject.Type +var aot2 = aot1 // expected-warning {{variable 'aot2' inferred to have type 'AnyObject.Type', which may be unexpected}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{9-9=: AnyObject.Type}} + + +for item in [AnyObject]() { // No warning in for-each loop. + _ = item +} + + +// Type inference of _Nil very coherent but kind of useless +var ptr = nil // expected-error {{'nil' requires a contextual type}} + +func testAnyObjectOptional() -> AnyObject? { + let x = testAnyObjectOptional() + return x +} + +// SR-11511 Warning for inferring an array of empty tuples +var arrayOfEmptyTuples = [""].map { print($0) } // expected-warning {{variable 'arrayOfEmptyTuples' inferred to have type '[()]'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{23-23=: [()]}} + +var maybeEmpty = Optional(arrayOfEmptyTuples) // expected-warning {{variable 'maybeEmpty' inferred to have type '[()]?'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: [()]?}} + +var shouldWarnWithoutSugar = (arrayOfEmptyTuples as Array<()>) // expected-warning {{variable 'shouldWarnWithoutSugar' inferred to have type 'Array<()>'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{27-27=: Array<()>}} + +class SomeClass {} + +// weak let's should be rejected +weak let V = SomeClass() // expected-error {{'weak' must be a mutable variable, because it may change at runtime}} + +let a = b ; let b = a +// expected-error@-1 {{circular reference}} +// expected-note@-2 {{through reference here}} +// expected-note@-3 {{through reference here}} +// expected-note@-4 {{through reference here}} +// expected-note@-5 {{through reference here}} +// expected-note@-6 {{through reference here}} + +// Swift should warn about immutable default initialized values +let uselessValue : String? + + +func tuplePatternDestructuring(_ x : Int, y : Int) { + let (b: _, a: h) = (b: x, a: y) + _ = h + + // Destructuring tuple with labels doesn't work + let (i, j) = (b: x, a: y) + _ = i+j + + // QoI: type variable reconstruction failing for tuple types + let (x: g1, a: h1) = (b: x, a: y) // expected-error {{cannot convert value of type '(b: Int, a: Int)' to specified type '(x: Int, a: Int)'}} +} + +// Crash while compiling attached test-app. +func test21057425() -> (Int, Int) { + let x: Int = "not an int!", y = 0 // expected-error{{cannot convert value of type 'String' to specified type 'Int'}} + return (x, y) +} + +// rdar://problem/21081340 +func test21081340() { + func foo() { } + let (x: a, y: b): () = foo() // expected-error{{tuple pattern has the wrong length for tuple type '()'}} +} + +// Swift let late initialization in top level control flow statements +if true { + let s : Int + s = 42 // should be valid. + _ = s +} + + diff --git a/test/diagnostics/Localization/en_localization.swift b/test/diagnostics/Localization/en_localization.swift index 6c9842f1d1df9..605c00dcaccf1 100644 --- a/test/diagnostics/Localization/en_localization.swift +++ b/test/diagnostics/Localization/en_localization.swift @@ -1,8 +1,11 @@ -// RUN: %target-typecheck-verify-swift -localization-path %S/Inputs -locale en +// RUN: %target-typecheck-verify-swift -localization-path %S/Inputs -locale en -disable-parser-lookup _ = "HI! // expected-error@-1{{unterminated string literal}} -var self1 = self1 // expected-error {{variable used within its own initial value}} +var self1 = self1 +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} + struct Broken { var b : Bool = True // expected-error{{cannot find 'True' in scope}} } diff --git a/test/diagnostics/Localization/en_localization_parser_lookup.swift b/test/diagnostics/Localization/en_localization_parser_lookup.swift new file mode 100644 index 0000000000000..dd5ed8f861127 --- /dev/null +++ b/test/diagnostics/Localization/en_localization_parser_lookup.swift @@ -0,0 +1,9 @@ +// RUN: %target-typecheck-verify-swift -localization-path %S/Inputs -locale en -enable-parser-lookup + +_ = "HI! +// expected-error@-1{{unterminated string literal}} +var self1 = self1 // expected-error {{variable used within its own initial value}} +struct Broken { + var b : Bool = True // expected-error{{cannot find 'True' in scope}} +} +var v1 : Int[1 // expected-error {{expected ']' in array type}} expected-note {{to match this opening '['}} diff --git a/test/diagnostics/Localization/fr_localization.swift b/test/diagnostics/Localization/fr_localization.swift index 9caf88a529e37..c2acde077a92a 100644 --- a/test/diagnostics/Localization/fr_localization.swift +++ b/test/diagnostics/Localization/fr_localization.swift @@ -1,12 +1,17 @@ // RUN: %empty-directory(%t) // RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/ // RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ 2>&1 | %FileCheck %s -// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr +// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr -disable-parser-lookup // CHECK: These diagnostic IDs are no longer availiable: 'not_available_in_def, not_available_in_def_2, not_available_in_def_3, not_available_in_def_4, not_available_in_def_5' _ = "HI! // expected-error@-1{{chaĂ®ne non terminĂ©e littĂ©rale}} -var self1 = self1 // expected-error {{variable utilisĂ©e dans sa propre valeur initiale}} + +// FIXME: This used to produce a localized diagnostic. + +var self1 = self1 // expected-note 2{{through reference here}} +// expected-error@-1 {{circular reference}} + struct Broken { var b : Bool = True // expected-error{{impossible de trouver 'True' portĂ©e}} } diff --git a/test/diagnostics/Localization/fr_localization_parser_lookup.swift b/test/diagnostics/Localization/fr_localization_parser_lookup.swift new file mode 100644 index 0000000000000..b46efe97f06c2 --- /dev/null +++ b/test/diagnostics/Localization/fr_localization_parser_lookup.swift @@ -0,0 +1,13 @@ +// RUN: %empty-directory(%t) +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/fr.yaml --output-directory=%t/ +// RUN: swift-serialize-diagnostics --input-file-path=%S/Inputs/en.yaml --output-directory=%t/ 2>&1 | %FileCheck %s +// RUN: %target-typecheck-verify-swift -localization-path %t -locale fr -enable-parser-lookup + +// CHECK: These diagnostic IDs are no longer availiable: 'not_available_in_def, not_available_in_def_2, not_available_in_def_3, not_available_in_def_4, not_available_in_def_5' +_ = "HI! +// expected-error@-1{{chaĂ®ne non terminĂ©e littĂ©rale}} +var self1 = self1 // expected-error {{variable utilisĂ©e dans sa propre valeur initiale}} +struct Broken { + var b : Bool = True // expected-error{{impossible de trouver 'True' portĂ©e}} +} +var v1 : Int[1 // expected-error {{expected ']' in array type}} expected-note {{to match this opening '['}} diff --git a/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift b/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift index f2a27dcf7b3f5..2184a5d762fc5 100644 --- a/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift +++ b/test/diagnostics/Localization/no_localization_files_and_wrong_path.swift @@ -1,11 +1,14 @@ -// RUN: %target-typecheck-verify-swift -localization-path /Not_exsisting_path -locale en +// RUN: %target-typecheck-verify-swift -localization-path /Not_exsisting_path -locale en -disable-parser-lookup // :0: warning: cannot find translations for 'en' at '/Not_exsisting_path/en.yaml': no such file // :0: warning: specified localization directory '/Not_exsisting_path' does not exist, translation is disabled _ = "HI! // expected-error@-1{{unterminated string literal}} -var self1 = self1 // expected-error {{variable used within its own initial value}} +var self1 = self1 +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} + struct Broken { var b : Bool = True // expected-error{{cannot find 'True' in scope}} } diff --git a/test/diagnostics/Localization/no_localization_files_and_wrong_path_parser_lookup.swift b/test/diagnostics/Localization/no_localization_files_and_wrong_path_parser_lookup.swift new file mode 100644 index 0000000000000..88633ab4f03b3 --- /dev/null +++ b/test/diagnostics/Localization/no_localization_files_and_wrong_path_parser_lookup.swift @@ -0,0 +1,11 @@ +// RUN: %target-typecheck-verify-swift -localization-path /Not_exsisting_path -locale en -enable-parser-lookup + +// :0: warning: cannot find translations for 'en' at '/Not_exsisting_path/en.yaml': no such file +// :0: warning: specified localization directory '/Not_exsisting_path' does not exist, translation is disabled + +_ = "HI! +// expected-error@-1{{unterminated string literal}} +var self1 = self1 // expected-error {{variable used within its own initial value}} +struct Broken { + var b : Bool = True // expected-error{{cannot find 'True' in scope}} +} diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 90514b405d185..ad884058d150f 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup var func6 : (_ fn : (Int,Int) -> Int) -> () var func6a : ((Int, Int) -> Int) -> () @@ -116,9 +116,14 @@ func f0(_ a: Any) -> Int { return 1 } assert(f0(1) == 1) -var selfRef = { selfRef() } // expected-error {{variable used within its own initial value}} +var selfRef = { selfRef() } +// expected-note@-1 2{{through reference here}} +// expected-error@-2 {{circular reference}} +// expected-error@-3 {{unable to infer closure type in the current context}} + var nestedSelfRef = { - var recursive = { nestedSelfRef() } // expected-error {{variable used within its own initial value}} + var recursive = { nestedSelfRef() } + // expected-warning@-1 {{variable 'recursive' was never mutated; consider changing to 'let' constant}} recursive() } @@ -319,7 +324,7 @@ func testCaptureBehavior(_ ptr : SomeClass) { doStuff { [weak v1] in v1!.foo() } // expected-warning @+2 {{variable 'v1' was written to, but never read}} doStuff { [weak v1, // expected-note {{previous}} - weak v1] in v1!.foo() } // expected-error {{definition conflicts with previous value}} + weak v1] in v1!.foo() } // expected-error {{invalid redeclaration of 'v1'}} doStuff { [unowned v2] in v2.foo() } doStuff { [unowned(unsafe) v2] in v2.foo() } doStuff { [unowned(safe) v2] in v2.foo() } diff --git a/test/expr/closure/closures_parser_lookup.swift b/test/expr/closure/closures_parser_lookup.swift new file mode 100644 index 0000000000000..1ec9182c62d59 --- /dev/null +++ b/test/expr/closure/closures_parser_lookup.swift @@ -0,0 +1,526 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +var func6 : (_ fn : (Int,Int) -> Int) -> () +var func6a : ((Int, Int) -> Int) -> () +var func6b : (Int, (Int, Int) -> Int) -> () +func func6c(_ f: (Int, Int) -> Int, _ n: Int = 0) {} + + +// Expressions can be auto-closurified, so that they can be evaluated separately +// from their definition. +var closure1 : () -> Int = {4} // Function producing 4 whenever it is called. +var closure2 : (Int,Int) -> Int = { 4 } // expected-error{{contextual type for closure argument list expects 2 arguments, which cannot be implicitly ignored}} {{36-36= _,_ in}} +var closure3a : () -> () -> (Int,Int) = {{ (4, 2) }} // multi-level closing. +var closure3b : (Int,Int) -> (Int) -> (Int,Int) = {{ (4, 2) }} // expected-error{{contextual type for closure argument list expects 2 arguments, which cannot be implicitly ignored}} {{52-52=_,_ in }} +// expected-error@-1 {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{53-53= _ in}} +var closure4 : (Int,Int) -> Int = { $0 + $1 } +var closure5 : (Double) -> Int = { + $0 + 1.0 + // expected-error@-1 {{cannot convert value of type 'Double' to closure result type 'Int'}} +} + +var closure6 = $0 // expected-error {{anonymous closure argument not contained in a closure}} + +var closure7 : Int = { 4 } // expected-error {{function produces expected type 'Int'; did you mean to call it with '()'?}} {{27-27=()}} // expected-note {{Remove '=' to make 'closure7' a computed property}}{{20-22=}} + +var capturedVariable = 1 +var closure8 = { [capturedVariable] in + capturedVariable += 1 // expected-error {{left side of mutating operator isn't mutable: 'capturedVariable' is an immutable capture}} +} + +func funcdecl1(_ a: Int, _ y: Int) {} +func funcdecl3() -> Int {} +func funcdecl4(_ a: ((Int) -> Int), _ b: Int) {} + +func funcdecl5(_ a: Int, _ y: Int) { + // Pass in a closure containing the call to funcdecl3. + funcdecl4({ funcdecl3() }, 12) // expected-error {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{14-14= _ in}} + + + func6({$0 + $1}) // Closure with two named anonymous arguments + func6({($0) + $1}) // Closure with sequence expr inferred type + func6({($0) + $0}) // // expected-error {{contextual closure type '(Int, Int) -> Int' expects 2 arguments, but 1 was used in closure body}} + + + var testfunc : ((), Int) -> Int // expected-note {{'testfunc' declared here}} + testfunc({$0+1}) // expected-error {{missing argument for parameter #2 in call}} + // expected-error@-1 {{cannot convert value of type '(Int) -> Int' to expected argument type '()'}} + + funcdecl5(1, 2) // recursion. + + // Element access from a tuple. + var a : (Int, f : Int, Int) + var b = a.1+a.f + + // Tuple expressions with named elements. + var i : (y : Int, x : Int) = (x : 42, y : 11) // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} + funcdecl1(123, 444) + + // Calls. + 4() // expected-error {{cannot call value of non-function type 'Int'}}{{4-6=}} + + + // rdar://12017658 - Infer some argument types from func6. + func6({ a, b -> Int in a+b}) + // Return type inference. + func6({ a,b in a+b }) + + // Infer incompatible type. + func6({a,b -> Float in 4.0 }) // expected-error {{declared closure result 'Float' is incompatible with contextual type 'Int'}} {{17-22=Int}} // Pattern doesn't need to name arguments. + func6({ _,_ in 4 }) + + func6({a,b in 4.0 }) // expected-error {{cannot convert value of type 'Double' to closure result type 'Int'}} + + // TODO: This diagnostic can be improved: rdar://22128205 + func6({(a : Float, b) in 4 }) // expected-error {{cannot convert value of type '(Float, Int) -> Int' to expected argument type '(Int, Int) -> Int'}} + + + + var fn = {} + var fn2 = { 4 } + + + var c : Int = { a,b -> Int in a+b} // expected-error{{cannot convert value of type '(Int, Int) -> Int' to specified type 'Int'}} + + +} + +func unlabeledClosureArgument() { + + func add(_ x: Int, y: Int) -> Int { return x + y } + func6a({$0 + $1}) // single closure argument + func6a(add) + func6b(1, {$0 + $1}) // second arg is closure + func6b(1, add) + func6c({$0 + $1}) // second arg is default int + func6c(add) +} + +// rdar://11935352 - closure with no body. +func closure_no_body(_ p: () -> ()) { + return closure_no_body({}) +} + + +// rdar://12019415 +func t() { + let u8 : UInt8 = 1 + let x : Bool = true + + if 0xA0..<0xBF ~= Int(u8) && x { + } +} + +// +func f0(_ a: Any) -> Int { return 1 } +assert(f0(1) == 1) + + +var selfRef = { selfRef() } // expected-error {{variable used within its own initial value}} +var nestedSelfRef = { + var recursive = { nestedSelfRef() } // expected-error {{variable used within its own initial value}} + recursive() +} + +var shadowed = { (shadowed: Int) -> Int in + let x = shadowed + return x +} // no-warning +var shadowedShort = { (shadowedShort: Int) -> Int in shadowedShort+1 } // no-warning + + +func anonymousClosureArgsInClosureWithArgs() { + func f(_: String) {} + var a1 = { () in $0 } // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments}} + var a2 = { () -> Int in $0 } // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments}} + var a3 = { (z: Int) in $0 } // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'z'?}} {{26-28=z}} + var a4 = { (z: [Int], w: [Int]) in + f($0.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'z'?}} {{7-9=z}} expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} + f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}} + } + var a5 = { (_: [Int], w: [Int]) in + f($0.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments}} + f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}} + } +} + +func doStuff(_ fn : @escaping () -> Int) {} +func doVoidStuff(_ fn : @escaping () -> ()) {} + +// Require specifying self for locations in code where strong reference cycles are likely +class ExplicitSelfRequiredTest { + var x = 42 + func method() -> Int { + // explicit closure requires an explicit "self." base or an explicit capture. + doVoidStuff({ self.x += 1 }) + doVoidStuff({ [self] in x += 1 }) + doVoidStuff({ [self = self] in x += 1 }) + doVoidStuff({ [unowned self] in x += 1 }) + doVoidStuff({ [unowned(unsafe) self] in x += 1 }) + doVoidStuff({ [unowned self = self] in x += 1 }) + + doStuff({ [self] in x+1 }) + doStuff({ [self = self] in x+1 }) + doStuff({ self.x+1 }) + doStuff({ [unowned self] in x+1 }) + doStuff({ [unowned(unsafe) self] in x+1 }) + doStuff({ [unowned self = self] in x+1 }) + doStuff({ x+1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} expected-note{{reference 'self.' explicitly}} {{15-15=self.}} + doVoidStuff({ doStuff({ x+1 })}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{28-28= [self] in}} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} + doVoidStuff({ x += 1 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{19-19=self.}} + doVoidStuff({ _ = "\(x)"}) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}} + doVoidStuff({ [y = self] in x += 1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{33-33=self.}} + doStuff({ [y = self] in x+1 }) // expected-warning {{capture 'y' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} + doVoidStuff({ [weak self] in x += 1 }) // expected-note {{weak capture of 'self' here does not enable implicit 'self'}} expected-warning {{variable 'self' was written to, but never read}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doStuff({ [weak self] in x+1 }) // expected-note {{weak capture of 'self' here does not enable implicit 'self'}} expected-warning {{variable 'self' was written to, but never read}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff({ [self = self.x] in x += 1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + doStuff({ [self = self.x] in x+1 }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} + + // Methods follow the same rules as properties, uses of 'self' without capturing must be marked with "self." + doStuff { method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} expected-note{{reference 'self.' explicitly}} {{15-15=self.}} + doVoidStuff { _ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{23-23=self.}} + doVoidStuff { _ = "\(method())" } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}} + doVoidStuff { () -> () in _ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self]}} expected-note{{reference 'self.' explicitly}} {{35-35=self.}} + doVoidStuff { [y = self] in _ = method() } // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{20-20=self, }} expected-note{{reference 'self.' explicitly}} {{37-37=self.}} + doStuff({ [y = self] in method() }) // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{29-29=self.}} + doVoidStuff({ [weak self] in _ = method() }) // expected-note {{weak capture of 'self' here does not enable implicit 'self'}} expected-warning {{variable 'self' was written to, but never read}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doStuff({ [weak self] in method() }) // expected-note {{weak capture of 'self' here does not enable implicit 'self'}} expected-warning {{variable 'self' was written to, but never read}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff({ [self = self.x] in _ = method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doStuff({ [self = self.x] in method() }) // expected-note {{variable other than 'self' captured here under the name 'self' does not enable implicit 'self'}} expected-warning {{capture 'self' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} + doVoidStuff { _ = self.method() } + doVoidStuff { [self] in _ = method() } + doVoidStuff { [self = self] in _ = method() } + doVoidStuff({ [unowned self] in _ = method() }) + doVoidStuff({ [unowned(unsafe) self] in _ = method() }) + doVoidStuff({ [unowned self = self] in _ = method() }) + + doStuff { self.method() } + doStuff { [self] in method() } + doStuff({ [self = self] in method() }) + doStuff({ [unowned self] in method() }) + doStuff({ [unowned(unsafe) self] in method() }) + doStuff({ [unowned self = self] in method() }) + + // When there's no space between the opening brace and the first expression, insert it + doStuff {method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in }} expected-note{{reference 'self.' explicitly}} {{14-14=self.}} + doVoidStuff {_ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in }} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} + doVoidStuff {() -> () in _ = method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self]}} expected-note{{reference 'self.' explicitly}} {{34-34=self.}} + // With an empty capture list, insertion should should be suggested without a comma + doStuff { [] in method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self}} expected-note{{reference 'self.' explicitly}} {{21-21=self.}} + doStuff { [ ] in method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self}} expected-note{{reference 'self.' explicitly}} {{23-23=self.}} + doStuff { [ /* This space intentionally left blank. */ ] in method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self}} expected-note{{reference 'self.' explicitly}} {{65-65=self.}} + // expected-note@+1 {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self}} + doStuff { [ // Nothing in this capture list! + ] + in + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{9-9=self.}} + } + // An inserted capture list should be on the same line as the opening brace, immediately following it. + // expected-note@+1 {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} + doStuff { + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{7-7=self.}} + } + // expected-note@+2 {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} + // Note: Trailing whitespace on the following line is intentional and should not be removed! + doStuff { + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{7-7=self.}} + } + // expected-note@+1 {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} + doStuff { // We have stuff to do. + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{7-7=self.}} + } + // expected-note@+1 {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{14-14= [self] in}} + doStuff {// We have stuff to do. + method() // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{7-7=self.}} + } + + // String interpolation should offer the diagnosis and fix-its at the expected locations + doVoidStuff { _ = "\(method())" } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}} expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} + doVoidStuff { _ = "\(x+1)" } // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{26-26=self.}} expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{18-18= [self] in}} + + // If we already have a capture list, self should be added to the list + let y = 1 + doStuff { [y] in method() } // expected-warning {{capture 'y' was never used}} expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} expected-note{{reference 'self.' explicitly}} {{22-22=self.}} + doStuff { [ // expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} + y // expected-warning {{capture 'y' was never used}} + ] in method() } // expected-error {{call to method 'method' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{reference 'self.' explicitly}} {{14-14=self.}} + + // "self." shouldn't be required in the initializer expression in a capture list + // This should not produce an error, "x" isn't being captured by the closure. + doStuff({ [myX = x] in myX }) + + // This should produce an error, since x is used within the inner closure. + doStuff({ [myX = {x}] in 4 }) // expected-error {{reference to property 'x' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note{{capture 'self' explicitly to enable implicit 'self' in this closure}} {{23-23= [self] in }} expected-note{{reference 'self.' explicitly}} {{23-23=self.}} + // expected-warning @-1 {{capture 'myX' was never used}} + + return 42 + } +} + +// If the implicit self is of value type, no diagnostic should be produced. +struct ImplicitSelfAllowedInStruct { + var x = 42 + mutating func method() -> Int { + doStuff({ x+1 }) + doVoidStuff({ x += 1 }) + doStuff({ method() }) + doVoidStuff({ _ = method() }) + } + + func method2() -> Int { + doStuff({ x+1 }) + doVoidStuff({ _ = x+1 }) + doStuff({ method2() }) + doVoidStuff({ _ = method2() }) + } +} + +enum ImplicitSelfAllowedInEnum { + case foo + var x: Int { 42 } + mutating func method() -> Int { + doStuff({ x+1 }) + doVoidStuff({ _ = x+1 }) + doStuff({ method() }) + doVoidStuff({ _ = method() }) + } + + func method2() -> Int { + doStuff({ x+1 }) + doVoidStuff({ _ = x+1 }) + doStuff({ method2() }) + doVoidStuff({ _ = method2() }) + } +} + + +class SomeClass { + var field : SomeClass? + func foo() -> Int {} +} + +func testCaptureBehavior(_ ptr : SomeClass) { + // Test normal captures. + weak var wv : SomeClass? = ptr + unowned let uv : SomeClass = ptr + unowned(unsafe) let uv1 : SomeClass = ptr + unowned(safe) let uv2 : SomeClass = ptr + doStuff { wv!.foo() } + doStuff { uv.foo() } + doStuff { uv1.foo() } + doStuff { uv2.foo() } + + + // Capture list tests + let v1 : SomeClass? = ptr + let v2 : SomeClass = ptr + + doStuff { [weak v1] in v1!.foo() } + // expected-warning @+2 {{variable 'v1' was written to, but never read}} + doStuff { [weak v1, // expected-note {{previous}} + weak v1] in v1!.foo() } // expected-error {{definition conflicts with previous value}} + doStuff { [unowned v2] in v2.foo() } + doStuff { [unowned(unsafe) v2] in v2.foo() } + doStuff { [unowned(safe) v2] in v2.foo() } + doStuff { [weak v1, weak v2] in v1!.foo() + v2!.foo() } + + let i = 42 + // expected-warning @+1 {{variable 'i' was never mutated}} + doStuff { [weak i] in i! } // expected-error {{'weak' may only be applied to class and class-bound protocol types, not 'Int'}} +} + +extension SomeClass { + func bar() { + doStuff { [unowned self] in self.foo() } + doStuff { [unowned xyz = self.field!] in xyz.foo() } + doStuff { [weak xyz = self.field] in xyz!.foo() } + + // rdar://16889886 - Assert when trying to weak capture a property of self in a lazy closure + // FIXME: We should probably offer a fix-it to the field capture error and suppress the 'implicit self' error. https://bugs.swift.org/browse/SR-11634 + doStuff { [weak self.field] in field!.foo() } // expected-error {{fields may only be captured by assigning to a specific name}} expected-error {{reference to property 'field' in closure requires explicit use of 'self' to make capture semantics explicit}} expected-note {{reference 'self.' explicitly}} {{36-36=self.}} expected-note {{capture 'self' explicitly to enable implicit 'self' in this closure}} {{16-16=self, }} + // expected-warning @+1 {{variable 'self' was written to, but never read}} + doStuff { [weak self&field] in 42 } // expected-error {{expected ']' at end of capture list}} + + } + + func strong_in_capture_list() { + // QOI: "[strong self]" in capture list generates unhelpful error message + _ = {[strong self] () -> () in return } // expected-error {{expected 'weak', 'unowned', or no specifier in capture list}} + } +} + + +// Observed variable in a closure triggers an assertion +var closureWithObservedProperty: () -> () = { + var a: Int = 42 { // expected-warning {{variable 'a' was never used; consider replacing with '_' or removing it}} + willSet { + _ = "Will set a to \(newValue)" + } + didSet { + _ = "Did set a with old value of \(oldValue)" + } + } +} + +; + +{}() // expected-error{{top-level statement cannot begin with a closure expression}} + + + +// rdar://19179412 - Crash on valid code. +func rdar19179412() -> (Int) -> Int { + return { x in + class A { + let d : Int = 0 + } + return 0 + } +} + +// Test coercion of single-expression closure return types to void. +func takesVoidFunc(_ f: () -> ()) {} +var i: Int = 1 + +// expected-warning @+1 {{expression of type 'Int' is unused}} +takesVoidFunc({i}) +// expected-warning @+1 {{expression of type 'Int' is unused}} +var f1: () -> () = {i} +var x = {return $0}(1) + +func returnsInt() -> Int { return 0 } +takesVoidFunc(returnsInt) // expected-error {{cannot convert value of type '() -> Int' to expected argument type '() -> ()'}} +takesVoidFunc({() -> Int in 0}) // expected-error {{declared closure result 'Int' is incompatible with contextual type '()'}} {{22-25=()}} + +// These used to crash the compiler, but were fixed to support the implementation of rdar://problem/17228969 +Void(0) // expected-error{{argument passed to call that takes no arguments}} +_ = {0} + +// "multi-statement closures require an explicit return type" should be an error not a note +let samples = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }} + if (i > 10) { return true } + else { return false } + }() + +// Swift error: cannot capture '$0' before it is declared +func f(_ fp : (Bool, Bool) -> Bool) {} +f { $0 && !$1 } + + +// unexpected error on self. capture inside class method +func TakesIntReturnsVoid(_ fp : ((Int) -> ())) {} + +struct TestStructWithStaticMethod { + static func myClassMethod(_ count: Int) { + // Shouldn't require "self." + TakesIntReturnsVoid { _ in myClassMethod(0) } + } +} + +class TestClassWithStaticMethod { + class func myClassMethod(_ count: Int) { + // Shouldn't require "self." + TakesIntReturnsVoid { _ in myClassMethod(0) } + } +} + +// Test that we can infer () as the result type of these closures. +func genericOne(_ a: () -> T) {} +func genericTwo(_ a: () -> T, _ b: () -> T) {} +genericOne {} +genericTwo({}, {}) + + +// QoI: Warning for unused capture list variable should be customized +class r22344208 { + func f() { + let q = 42 + let _: () -> Int = { + [unowned self, // expected-warning {{capture 'self' was never used}} + q] in // expected-warning {{capture 'q' was never used}} + 1 } + } +} + +var f = { (s: Undeclared) -> Int in 0 } // expected-error {{cannot find type 'Undeclared' in scope}} + +// Swift compiler crashes when using closure, declared to return illegal type. +func r21375863() { + var width = 0 // expected-warning {{variable 'width' was never mutated}} + var height = 0 // expected-warning {{variable 'height' was never mutated}} + var bufs: [[UInt8]] = (0..<4).map { _ -> [asdf] in // expected-error {{cannot find type 'asdf' in scope}} expected-warning {{variable 'bufs' was never used}} + [UInt8](repeating: 0, count: width*height) + } +} + +// +// Don't crash if we infer a closure argument to have a tuple type containing inouts. +func r25993258_helper(_ fn: (inout Int, Int) -> ()) {} +func r25993258a() { + r25993258_helper { x in () } // expected-error {{contextual closure type '(inout Int, Int) -> ()' expects 2 arguments, but 1 was used in closure body}} +} +func r25993258b() { + r25993258_helper { _ in () } // expected-error {{contextual closure type '(inout Int, Int) -> ()' expects 2 arguments, but 1 was used in closure body}} +} + +// We have to map the captured var type into the right generic environment. +class GenericClass {} + +func lvalueCapture(c: GenericClass) { + var cc = c + weak var wc = c + + func innerGeneric(_: U) { + _ = cc + _ = wc + + cc = wc! + } +} + +// Don't expose @lvalue-ness in diagnostics. +let closure = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }} + var helper = true + return helper +} + +// SR-9839 +func SR9839(_ x: @escaping @convention(block) () -> Void) {} + +func id(_ x: T) -> T { + return x +} + +var qux: () -> Void = {} + +SR9839(qux) +SR9839(id(qux)) // expected-error {{conflicting arguments to generic parameter 'T' ('() -> Void' vs. '@convention(block) () -> Void')}} + +func forceUnwrap(_ x: T?) -> T { + return x! +} + +var qux1: (() -> Void)? = {} + +SR9839(qux1!) +SR9839(forceUnwrap(qux1)) + +// rdar://problem/65155671 - crash referencing parameter of outer closure +func rdar65155671(x: Int) { + { a in + _ = { [a] in a } + }(x) +} + +func sr3186(_ f: (@escaping (@escaping (T) -> U) -> ((T) -> U))) -> ((T) -> U) { + return { x in return f(sr3186(f))(x) } +} + +class SR3186 { + init() { + // expected-warning@+1{{capture 'self' was never used}} + let v = sr3186 { f in { [unowned self, f] x in x != 1000 ? f(x + 1) : "success" } }(0) + print("\(v)") + } +} diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 4479f9a74fc15..d4dcbe24a27d1 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup //===----------------------------------------------------------------------===// // Tests and samples. @@ -246,15 +246,16 @@ func test_as_2() { func test_lambda() { // A simple closure. var a = { (value: Int) -> () in markUsed(value+1) } + // expected-warning@-1 {{initialization of variable 'a' was never used; consider replacing with assignment to '_' or removing it}} // A recursive lambda. - // FIXME: This should definitely be accepted. var fib = { (n: Int) -> Int in + // expected-warning@-1 {{variable 'fib' was never mutated; consider changing to 'let' constant}} if (n < 2) { return n } - return fib(n-1)+fib(n-2) // expected-error 2 {{variable used within its own initial value}} + return fib(n-1)+fib(n-2) } } diff --git a/test/expr/expressions_parser_lookup.swift b/test/expr/expressions_parser_lookup.swift new file mode 100644 index 0000000000000..582d59d7d5d12 --- /dev/null +++ b/test/expr/expressions_parser_lookup.swift @@ -0,0 +1,947 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +//===----------------------------------------------------------------------===// +// Tests and samples. +//===----------------------------------------------------------------------===// + +// Comment. With unicode characters: Â¡Ă§Â®Ă¥zÂ¥! + +func markUsed(_: T) {} + +// Various function types. +var func1 : () -> () // No input, no output. +var func2 : (Int) -> Int +var func3 : () -> () -> () // Takes nothing, returns a fn. +var func3a : () -> (() -> ()) // same as func3 +var func6 : (_ fn : (Int,Int) -> Int) -> () // Takes a fn, returns nothing. +var func7 : () -> (Int,Int,Int) // Takes nothing, returns tuple. + +// Top-Level expressions. These are 'main' content. +func1() +_ = 4+7 + +var bind_test1 : () -> () = func1 +var bind_test2 : Int = 4; func1 // expected-error {{expression resolves to an unused variable}} + +(func1, func2) // expected-error {{expression resolves to an unused variable}} + +func basictest() { + // Simple integer variables. + var x : Int + var x2 = 4 // Simple Type inference. + var x3 = 4+x*(4+x2)/97 // Basic Expressions. + + // Declaring a variable Void, aka (), is fine too. + var v : Void + + var x4 : Bool = true + var x5 : Bool = + 4 // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + + //var x6 : Float = 4+5 + + var x7 = 4; 5 // expected-warning {{integer literal is unused}} + + // Test implicit conversion of integer literal to non-Int64 type. + var x8 : Int8 = 4 + x8 = x8 + 1 + _ = x8 + 1 + _ = 0 + x8 + 1.0 + x8 // expected-error{{binary operator '+' cannot be applied to operands of type 'Double' and 'Int8'}} + // expected-note @-1 {{overloads for '+' exist with these partially matching parameter lists:}} + + + var x9 : Int16 = x8 + 1 // expected-error {{cannot convert value of type 'Int8' to specified type 'Int16'}} + + // Various tuple types. + var tuple1 : () + var tuple2 : (Int) + var tuple3 : (Int, Int, ()) + var tuple2a : (a : Int) // expected-error{{cannot create a single-element tuple with an element label}}{{18-22=}} + var tuple3a : (a : Int, b : Int, c : ()) + + var tuple4 = (1, 2) // Tuple literal. + var tuple5 = (1, 2, 3, 4) // Tuple literal. + var tuple6 = (1 2) // expected-error {{expected ',' separator}} {{18-18=,}} + + // Brace expressions. + var brace3 = { + var brace2 = 42 // variable shadowing. + _ = brace2+7 + } + + // Function calls. + var call1 : () = func1() + var call2 = func2(1) + var call3 : () = func3()() + + // Cannot call an integer. + bind_test2() // expected-error {{cannot call value of non-function type 'Int'}}{{13-15=}} +} + +// +func testUnusedLiterals_SR3522() { + 42 // expected-warning {{integer literal is unused}} + 2.71828 // expected-warning {{floating-point literal is unused}} + true // expected-warning {{boolean literal is unused}} + false // expected-warning {{boolean literal is unused}} + "Hello" // expected-warning {{string literal is unused}} + "Hello \(42)" // expected-warning {{string literal is unused}} + #file // expected-warning {{#file literal is unused}} + (#line) // expected-warning {{#line literal is unused}} + #column // expected-warning {{#column literal is unused}} + #function // expected-warning {{#function literal is unused}} + #dsohandle // expected-warning {{#dsohandle literal is unused}} + __FILE__ // expected-error {{__FILE__ has been replaced with #file in Swift 3}} expected-warning {{#file literal is unused}} + __LINE__ // expected-error {{__LINE__ has been replaced with #line in Swift 3}} expected-warning {{#line literal is unused}} + __COLUMN__ // expected-error {{__COLUMN__ has been replaced with #column in Swift 3}} expected-warning {{#column literal is unused}} + __FUNCTION__ // expected-error {{__FUNCTION__ has been replaced with #function in Swift 3}} expected-warning {{#function literal is unused}} + __DSO_HANDLE__ // expected-error {{__DSO_HANDLE__ has been replaced with #dsohandle in Swift 3}} expected-warning {{#dsohandle literal is unused}} + + nil // expected-error {{'nil' requires a contextual type}} + #fileLiteral(resourceName: "what.txt") // expected-error {{could not infer type of file reference literal}} expected-note * {{}} + #imageLiteral(resourceName: "hello.png") // expected-error {{could not infer type of image literal}} expected-note * {{}} + #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1) // expected-error {{could not infer type of color literal}} expected-note * {{}} +} + +// Infix operators and attribute lists. +infix operator %% : MinPrecedence +precedencegroup MinPrecedence { + associativity: left + lowerThan: AssignmentPrecedence +} + +func %%(a: Int, b: Int) -> () {} +var infixtest : () = 4 % 2 + 27 %% 123 + + + +// The 'func' keyword gives a nice simplification for function definitions. +func funcdecl1(_ a: Int, _ y: Int) {} +func funcdecl2() { + return funcdecl1(4, 2) +} +func funcdecl3() -> Int { + return 12 +} +func funcdecl4(_ a: ((Int) -> Int), b: Int) {} +func signal(_ sig: Int, f: (Int) -> Void) -> (Int) -> Void {} + +// Doing fun things with named arguments. Basic stuff first. +func funcdecl6(_ a: Int, b: Int) -> Int { return a+b } + +// Can dive into tuples, 'b' is a reference to a whole tuple, c and d are +// fields in one. Cannot dive into functions or through aliases. +func funcdecl7(_ a: Int, b: (c: Int, d: Int), third: (c: Int, d: Int)) -> Int { + _ = a + b.0 + b.c + third.0 + third.1 + b.foo // expected-error {{value of tuple type '(c: Int, d: Int)' has no member 'foo'}} +} + +// Error recovery. +func testfunc2 (_: ((), Int) -> Int) -> Int {} +func makeTuple() -> (String, Int) { return ("foo", 42) } +func errorRecovery() { + testfunc2({ $0 + 1 }) // expected-error {{contextual closure type '((), Int) -> Int' expects 2 arguments, but 1 was used in closure body}} + // expected-error@-1 {{cannot convert value of type '()' to expected argument type 'Int'}} + + enum union1 { + case bar + case baz + } + var a: Int = .hello // expected-error {{type 'Int' has no member 'hello'}} + var b: union1 = .bar // ok + var c: union1 = .xyz // expected-error {{type 'union1' has no member 'xyz'}} + var d: (Int,Int,Int) = (1,2) // expected-error {{'(Int, Int)' is not convertible to '(Int, Int, Int)', tuples have a different number of elements}} + var e: (Int,Int) = (1, 2, 3) // expected-error {{'(Int, Int, Int)' is not convertible to '(Int, Int)', tuples have a different number of elements}} + var f: (Int,Int) = (1, 2, f : 3) // expected-error {{'(Int, Int, f: Int)' is not convertible to '(Int, Int)', tuples have a different number of elements}} + + // CrashTracer: [USER] swift at …mous_namespace::ConstraintGenerator::getTypeForPattern + 698 + var (g1, g2, g3) = (1, 2) // expected-error {{'(Int, Int)' is not convertible to '(Int, Int, _)', tuples have a different number of elements}} + var (h1, h2) = (1, 2, 3) // expected-error {{'(Int, Int, Int)' is not convertible to '(Int, Int)', tuples have a different number of elements}} + var i: (Bool, Bool) = makeTuple() // expected-error {{cannot convert value of type '(String, Int)' to specified type '(Bool, Bool)'}} +} + +func acceptsInt(_ x: Int) {} +acceptsInt(unknown_var) // expected-error {{cannot find 'unknown_var' in scope}} + + + +var test1a: (Int) -> (Int) -> Int = { { $0 } } // expected-error{{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{38-38= _ in}} +var test1b = { 42 } +var test1c = { { 42 } } +var test1d = { { { 42 } } } + +func test2(_ a: Int, b: Int) -> (c: Int) { // expected-error{{cannot create a single-element tuple with an element label}} {{34-37=}} expected-note {{did you mean 'a'?}} expected-note {{did you mean 'b'?}} + _ = a+b + a+b+c // expected-error{{cannot find 'c' in scope}} + return a+b +} + + +func test3(_ arg1: Int, arg2: Int) -> Int { + return 4 +} + +func test4() -> ((_ arg1: Int, _ arg2: Int) -> Int) { + return test3 +} + +func test5() { + let a: (Int, Int) = (1,2) + var + _: ((Int) -> Int, Int) = a // expected-error {{cannot convert value of type '(Int, Int)' to specified type '((Int) -> Int, Int)'}} + + + let c: (a: Int, b: Int) = (1,2) + let _: (b: Int, a: Int) = c // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} +} + + +// Functions can obviously take and return values. +func w3(_ a: Int) -> Int { return a } +func w4(_: Int) -> Int { return 4 } + + + +func b1() {} + +func foo1(_ a: Int, b: Int) -> Int {} +func foo2(_ a: Int) -> (_ b: Int) -> Int {} +func foo3(_ a: Int = 2, b: Int = 3) {} + +prefix operator ^^ + +prefix func ^^(a: Int) -> Int { + return a + 1 +} + +func test_unary1() { + var x: Int + + x = ^^(^^x) + x = *x // expected-error {{'*' is not a prefix unary operator}} + x = x* // expected-error {{'*' is not a postfix unary operator}} + x = +(-x) + x = + -x // expected-error {{unary operator cannot be separated from its operand}} {{8-9=}} +} +func test_unary2() { + var x: Int + // FIXME: second diagnostic is redundant. + x = &; // expected-error {{expected expression after unary operator}} expected-error {{expected expression in assignment}} +} +func test_unary3() { + var x: Int + // FIXME: second diagnostic is redundant. + x = &, // expected-error {{expected expression after unary operator}} expected-error {{expected expression in assignment}} +} + +func test_as_1() { + var _: Int +} +func test_as_2() { + let x: Int = 1 + x as [] // expected-error {{expected element type}} {{9-9= <#type#>}} +} + +func test_lambda() { + // A simple closure. + var a = { (value: Int) -> () in markUsed(value+1) } + + // A recursive lambda. + // FIXME: This should definitely be accepted. + var fib = { (n: Int) -> Int in + if (n < 2) { + return n + } + + return fib(n-1)+fib(n-2) // expected-error 2 {{variable used within its own initial value}} + } +} + +func test_lambda2() { + { () -> protocol in + // expected-error @-1 {{'protocol<...>' composition syntax has been removed and is not needed here}} {{11-24=Int}} + // expected-error @-2 {{non-protocol, non-class type 'Int' cannot be used within a protocol-constrained type}} + // expected-warning @-3 {{result of call to closure returning 'Any' is unused}} + return 1 + }() +} + +func test_floating_point() { + _ = 0.0 + _ = 100.1 + var _: Float = 0.0 + var _: Double = 0.0 +} + +func test_nonassoc(_ x: Int, y: Int) -> Bool { + // FIXME: the second error and note here should arguably disappear + return x == y == x // expected-error {{adjacent operators are in non-associative precedence group 'ComparisonPrecedence'}} expected-error {{binary operator '==' cannot be applied to operands of type 'Bool' and 'Int'}} + // expected-note@-1 {{overloads for '==' exist with these partially matching parameter lists: (Bool, Bool), (Int, Int)}} +} + +// More realistic examples. + +func fib(_ n: Int) -> Int { + if (n < 2) { + return n + } + + return fib(n-2) + fib(n-1) +} + +//===----------------------------------------------------------------------===// +// Integer Literals +//===----------------------------------------------------------------------===// + +// FIXME: Should warn about integer constants being too large +var + il_a: Bool = 4 // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} +var il_b: Int8 + = 123123 +var il_c: Int8 = 4 // ok + +struct int_test4 : ExpressibleByIntegerLiteral { + typealias IntegerLiteralType = Int + init(integerLiteral value: Int) {} // user type. +} + +var il_g: int_test4 = 4 + + + +// This just barely fits in Int64. +var il_i: Int64 = 18446744073709551615 + +// This constant is too large to fit in an Int64, but it is fine for Int128. +// FIXME: Should warn about the first. +var il_j: Int64 = 18446744073709551616 +// var il_k: Int128 = 18446744073709551616 + +var bin_literal: Int64 = 0b100101 +var hex_literal: Int64 = 0x100101 +var oct_literal: Int64 = 0o100101 + +// verify that we're not using C rules +var oct_literal_test: Int64 = 0123 +assert(oct_literal_test == 123) + +// ensure that we swallow random invalid chars after the first invalid char +var invalid_num_literal: Int64 = 0QWERTY // expected-error{{'Q' is not a valid digit in integer literal}} +var invalid_bin_literal: Int64 = 0bQWERTY // expected-error{{'Q' is not a valid binary digit (0 or 1) in integer literal}} +var invalid_hex_literal: Int64 = 0xQWERTY // expected-error{{'Q' is not a valid hexadecimal digit (0-9, A-F) in integer literal}} +var invalid_oct_literal: Int64 = 0oQWERTY // expected-error{{'Q' is not a valid octal digit (0-7) in integer literal}} +var invalid_exp_literal: Double = 1.0e+QWERTY // expected-error{{'Q' is not a valid digit in floating point exponent}} +var invalid_fp_exp_literal: Double = 0x1p+QWERTY // expected-error{{'Q' is not a valid digit in floating point exponent}} + +// don't emit a partial integer literal if the invalid char is valid for identifiers. +var invalid_num_literal_prefix: Int64 = 0a1234567 // expected-error{{'a' is not a valid digit in integer literal}} +var invalid_num_literal_middle: Int64 = 0123A5678 // expected-error{{'A' is not a valid digit in integer literal}} +var invalid_bin_literal_middle: Int64 = 0b1020101 // expected-error{{'2' is not a valid binary digit (0 or 1) in integer literal}} +var invalid_oct_literal_middle: Int64 = 0o1357864 // expected-error{{'8' is not a valid octal digit (0-7) in integer literal}} +var invalid_hex_literal_middle: Int64 = 0x147ADG0 // expected-error{{'G' is not a valid hexadecimal digit (0-9, A-F) in integer literal}} + +var invalid_hex_literal_exponent_ = 0xffp+12abc // expected-error{{'a' is not a valid digit in floating point exponent}} +var invalid_float_literal_exponent = 12e1abc // expected-error{{'a' is not a valid digit in floating point exponent}} + +// rdar://11088443 +var negative_int32: Int32 = -1 + +// +var tupleelemvar = 1 +markUsed((tupleelemvar, tupleelemvar).1) + +func int_literals() { + // Fits exactly in 64-bits - rdar://11297273 + _ = 1239123123123123 + // Overly large integer. + // FIXME: Should warn about it. + _ = 123912312312312312312 + +} + +// +func tuple_of_rvalues(_ a:Int, b:Int) -> Int { + return (a, b).1 +} + +extension Int { + func testLexingMethodAfterIntLiteral() {} + func _0() {} + // Hex letters + func ffa() {} + // Hex letters + non hex. + func describe() {} + // Hex letters + 'p'. + func eap() {} + // Hex letters + 'p' + non hex. + func fpValue() {} +} + +123.testLexingMethodAfterIntLiteral() +0b101.testLexingMethodAfterIntLiteral() +0o123.testLexingMethodAfterIntLiteral() +0x1FFF.testLexingMethodAfterIntLiteral() + +123._0() +0b101._0() +0o123._0() +0x1FFF._0() + +0x1fff.ffa() +0x1FFF.describe() +0x1FFF.eap() +0x1FFF.fpValue() + +var separator1: Int = 1_ +var separator2: Int = 1_000 +var separator4: Int = 0b1111_0000_ +var separator5: Int = 0b1111_0000 +var separator6: Int = 0o127_777_ +var separator7: Int = 0o127_777 +var separator8: Int = 0x12FF_FFFF +var separator9: Int = 0x12FF_FFFF_ + +//===----------------------------------------------------------------------===// +// Float Literals +//===----------------------------------------------------------------------===// + +var fl_a = 0.0 +var fl_b: Double = 1.0 +var fl_c: Float = 2.0 +// FIXME: crummy diagnostic +var fl_d: Float = 2.0.0 // expected-error {{expected named member of numeric literal}} +var fl_e: Float = 1.0e42 +var fl_f: Float = 1.0e+ // expected-error {{expected a digit in floating point exponent}} +var fl_g: Float = 1.0E+42 +var fl_h: Float = 2e-42 +var vl_i: Float = -.45 // expected-error {{'.45' is not a valid floating point literal; it must be written '0.45'}} {{20-20=0}} +var fl_j: Float = 0x1p0 +var fl_k: Float = 0x1.0p0 +var fl_l: Float = 0x1.0 // expected-error {{hexadecimal floating point literal must end with an exponent}} +var fl_m: Float = 0x1.FFFFFEP-2 +var fl_n: Float = 0x1.fffffep+2 +var fl_o: Float = 0x1.fffffep+ // expected-error {{expected a digit in floating point exponent}} +var fl_p: Float = 0x1p // expected-error {{expected a digit in floating point exponent}} +var fl_q: Float = 0x1p+ // expected-error {{expected a digit in floating point exponent}} +var fl_r: Float = 0x1.0fp // expected-error {{expected a digit in floating point exponent}} +var fl_s: Float = 0x1.0fp+ // expected-error {{expected a digit in floating point exponent}} +var fl_t: Float = 0x1.p // expected-error {{value of type 'Int' has no member 'p'}} +var fl_u: Float = 0x1.p2 // expected-error {{value of type 'Int' has no member 'p2'}} +var fl_v: Float = 0x1.p+ // expected-error {{'+' is not a postfix unary operator}} +var fl_w: Float = 0x1.p+2 // expected-error {{value of type 'Int' has no member 'p'}} + +var if1: Double = 1.0 + 4 // integer literal ok as double. +var if2: Float = 1.0 + 4 // integer literal ok as float. + +var fl_separator1: Double = 1_.2_ +var fl_separator2: Double = 1_000.2_ +var fl_separator3: Double = 1_000.200_001 +var fl_separator4: Double = 1_000.200_001e1_ +var fl_separator5: Double = 1_000.200_001e1_000 +var fl_separator6: Double = 1_000.200_001e1_000 +var fl_separator7: Double = 0x1_.0FFF_p1_ +var fl_separator8: Double = 0x1_0000.0FFF_ABCDp10_001 + +var fl_bad_separator1: Double = 1e_ // expected-error {{'_' is not a valid first character in floating point exponent}} +var fl_bad_separator2: Double = 0x1p_ // expected-error {{'_' is not a valid first character in floating point exponent}} + +//===----------------------------------------------------------------------===// +// String Literals +//===----------------------------------------------------------------------===// + +var st_a = "" +var st_b: String = "" +var st_c = "asdfasd // expected-error {{unterminated string literal}} + +var st_d = " \t\n\r\"\'\\ " // Valid simple escapes +var st_e = " \u{12}\u{0012}\u{00000078} " // Valid unicode escapes +var st_u1 = " \u{1} " +var st_u2 = " \u{123} " +var st_u3 = " \u{1234567} " // expected-error {{invalid unicode scalar}} +var st_u4 = " \q " // expected-error {{invalid escape sequence in literal}} + +var st_u5 = " \u{FFFFFFFF} " // expected-error {{invalid unicode scalar}} +var st_u6 = " \u{D7FF} \u{E000} " // Fencepost UTF-16 surrogate pairs. +var st_u7 = " \u{D800} " // expected-error {{invalid unicode scalar}} +var st_u8 = " \u{DFFF} " // expected-error {{invalid unicode scalar}} +var st_u10 = " \u{0010FFFD} " // Last valid codepoint, 0xFFFE and 0xFFFF are reserved in each plane +var st_u11 = " \u{00110000} " // expected-error {{invalid unicode scalar}} + +func stringliterals(_ d: [String: Int]) { + + // rdar://11385385 + let x = 4 + "Hello \(x+1) world" // expected-warning {{string literal is unused}} + + "Error: \(x+1"; // expected-error {{unterminated string literal}} + + "Error: \(x+1 // expected-error {{unterminated string literal}} + ; // expected-error {{';' statements are not allowed}} + + // rdar://14050788 [DF] String Interpolations can't contain quotes + "test \("nested")" + "test \("\("doubly nested")")" + "test \(d["hi"])" + "test \("quoted-paren )")" + "test \("quoted-paren (")" + "test \("\\")" + "test \("\n")" + "test \("\")" // expected-error {{unterminated string literal}} + + "test \ + // expected-error @-1 {{unterminated string literal}} expected-error @-1 {{invalid escape sequence in literal}} + "test \("\ + // expected-error @-1 {{unterminated string literal}} + "test newline \("something" + + "something else")" + // expected-error @-2 {{unterminated string literal}} expected-error @-1 {{unterminated string literal}} + + // expected-warning @+2 {{variable 'x2' was never used; consider replacing with '_' or removing it}} + // expected-error @+1 {{unterminated string literal}} + var x2 : () = ("hello" + " + ; +} + +func testSingleQuoteStringLiterals() { + _ = 'abc' // expected-error{{single-quoted string literal found, use '"'}}{{7-12="abc"}} + _ = 'abc' + "def" // expected-error{{single-quoted string literal found, use '"'}}{{7-12="abc"}} + + _ = 'ab\nc' // expected-error{{single-quoted string literal found, use '"'}}{{7-14="ab\\nc"}} + + _ = "abc\('def')" // expected-error{{single-quoted string literal found, use '"'}}{{13-18="def"}} + _ = 'ab\("c")' // expected-error{{single-quoted string literal found, use '"'}}{{7-17="ab\\("c")"}} + _ = 'a\('b')c' // expected-error{{single-quoted string literal found, use '"'}}{{7-17="a\\('b')c"}} + // expected-error@-1{{single-quoted string literal found, use '"'}}{{11-14="b"}} + + _ = "abc' // expected-error{{unterminated string literal}} + _ = 'abc" // expected-error{{unterminated string literal}} + _ = "a'c" + + _ = 'ab\'c' // expected-error{{single-quoted string literal found, use '"'}}{{7-14="ab'c"}} + + _ = 'ab"c' // expected-error{{single-quoted string literal found, use '"'}}{{7-13="ab\\"c"}} + _ = 'ab\"c' // expected-error{{single-quoted string literal found, use '"'}}{{7-14="ab\\"c"}} + _ = 'ab\\"c' // expected-error{{single-quoted string literal found, use '"'}}{{7-15="ab\\\\\\"c"}} +} + +// +var s = "" // expected-note {{did you mean 's'?}} +s.append(contentsOf: ["x"]) + +//===----------------------------------------------------------------------===// +// InOut arguments +//===----------------------------------------------------------------------===// + +func takesInt(_ x: Int) {} +func takesExplicitInt(_ x: inout Int) { } + +func testInOut(_ arg: inout Int) { + var x: Int + takesExplicitInt(x) // expected-error{{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{20-20=&}} + takesExplicitInt(&x) + takesInt(&x) // expected-error{{'&' used with non-inout argument of type 'Int'}} + var y = &x //expected-error {{use of extraneous '&'}} + var z = &arg //expected-error {{use of extraneous '&'}} + + takesExplicitInt(5) // expected-error {{cannot pass immutable value as inout argument: literals are not mutable}} +} + +//===----------------------------------------------------------------------===// +// Conversions +//===----------------------------------------------------------------------===// + +var pi_f: Float +var pi_d: Double + +struct SpecialPi {} // Type with no implicit construction. + +var pi_s: SpecialPi + +func getPi() -> Float {} +func getPi() -> Double {} +func getPi() -> SpecialPi {} + +enum Empty { } + +extension Empty { + init(_ f: Float) { } +} + +func conversionTest(_ a: inout Double, b: inout Int) { + var f: Float + var d: Double + a = Double(b) + a = Double(f) + a = Double(d) // no-warning + b = Int(a) + f = Float(b) + + var pi_f1 = Float(pi_f) + var pi_d1 = Double(pi_d) + var pi_s1 = SpecialPi(pi_s) // expected-error {{argument passed to call that takes no arguments}} + + var pi_f2 = Float(getPi()) // expected-error {{ambiguous use of 'init(_:)'}} + var pi_d2 = Double(getPi()) // expected-error {{ambiguous use of 'init(_:)'}} + var pi_s2: SpecialPi = getPi() // no-warning + + var float = Float.self + var pi_f3 = float.init(getPi()) // expected-error {{ambiguous use of 'init(_:)'}} + var pi_f4 = float.init(pi_f) + + var e = Empty(f) // expected-warning {{variable 'e' inferred to have type 'Empty', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{8-8=: Empty}} + var e2 = Empty(d) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Float'}} + var e3 = Empty(Float(d)) // expected-warning {{variable 'e3' inferred to have type 'Empty', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}} {{9-9=: Empty}} +} + +// FIXME(diagnostics): This note is pointing to a synthesized init +struct Rule { // expected-note {{'init(target:dependencies:)' declared here}} + var target: String + var dependencies: String +} + +var ruleVar: Rule +// FIXME(diagnostics): To be able to suggest different candidates here we need to teach the solver how to figure out to which parameter +// does argument belong to in this case. If the `target` was of a different type, we currently suggest to add an argument for `dependencies:` +// which is incorrect. +ruleVar = Rule("a") // expected-error {{missing argument label 'target:' in call}} +// expected-error@-1 {{missing argument for parameter 'dependencies' in call}} + +class C { // expected-note {{did you mean 'C'?}} + var x: C? + init(other: C?) { x = other } + + func method() {} +} + +_ = C(3) // expected-error {{missing argument label 'other:' in call}} +// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'C?'}} +_ = C(other: 3) // expected-error {{cannot convert value of type 'Int' to expected argument type 'C?'}} + +//===----------------------------------------------------------------------===// +// Unary Operators +//===----------------------------------------------------------------------===// + +func unaryOps(_ i8: inout Int8, i64: inout Int64) { + i8 = ~i8 + i64 += 1 + i8 -= 1 + + Int64(5) += 1 // expected-error{{left side of mutating operator has immutable type 'Int64'}} + + // attempt to modify a 'let' variable with ++ results in typecheck error not being able to apply ++ to Float + let a = i8 // expected-note {{change 'let' to 'var' to make it mutable}} {{3-6=var}} + a += 1 // expected-error {{left side of mutating operator isn't mutable: 'a' is a 'let' constant}} + + var b : Int { get { }} + b += 1 // expected-error {{left side of mutating operator isn't mutable: 'b' is a get-only property}} +} + +//===----------------------------------------------------------------------===// +// Iteration +//===----------------------------------------------------------------------===// + +func..<(x: Double, y: Double) -> Double { + return x + y +} + +func iterators() { + _ = 0..<42 + _ = 0.0..<42.0 +} + +//===----------------------------------------------------------------------===// +// Magic literal expressions +//===----------------------------------------------------------------------===// + +func magic_literals() { + _ = __FILE__ // expected-error {{__FILE__ has been replaced with #file in Swift 3}} + _ = __LINE__ // expected-error {{__LINE__ has been replaced with #line in Swift 3}} + _ = __COLUMN__ // expected-error {{__COLUMN__ has been replaced with #column in Swift 3}} + _ = __DSO_HANDLE__ // expected-error {{__DSO_HANDLE__ has been replaced with #dsohandle in Swift 3}} + + _ = #file + _ = #line + #column + var _: UInt8 = #line + #column +} + +//===----------------------------------------------------------------------===// +// lvalue processing +//===----------------------------------------------------------------------===// + + +infix operator +-+= +@discardableResult +func +-+= (x: inout Int, y: Int) -> Int { return 0} + +func lvalue_processing() { + var i = 0 + i += 1 // obviously ok + + var fn = (+-+=) + + var n = 42 + fn(n, 12) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{6-6=&}} + fn(&n, 12) // expected-warning {{result of call to function returning 'Int' is unused}} + + n +-+= 12 + + (+-+=)(&n, 12) // ok. + (+-+=)(n, 12) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{10-10=&}} +} + +struct Foo { + func method() {} + mutating func mutatingMethod() {} +} + +func test() { + var x = Foo() + let y = Foo() + + // rdar://15708430 + (&x).method() // expected-error {{use of extraneous '&'}} + (&x).mutatingMethod() // expected-error {{use of extraneous '&'}} +} + + +// Unused results. +func unusedExpressionResults() { + // Unused l-value + _ // expected-error{{'_' can only appear in a pattern or on the left side of an assignment}} + + // Conditional Optional binding hides compiler error + let optionalc:C? = nil + optionalc?.method() // ok + optionalc?.method // expected-error {{expression resolves to an unused function}} +} + + + + +//===----------------------------------------------------------------------===// +// Collection Literals +//===----------------------------------------------------------------------===// + +func arrayLiterals() { + let _ = [1,2,3] + let _ : [Int] = [] + let _ = [] // expected-error {{empty collection literal requires an explicit type}} +} + +func dictionaryLiterals() { + let _ = [1 : "foo",2 : "bar",3 : "baz"] + let _: Dictionary = [:] + let _ = [:] // expected-error {{empty collection literal requires an explicit type}} +} + +func invalidDictionaryLiteral() { + // FIXME: lots of unnecessary diagnostics. + + var a = [1: ; // expected-error {{expected value in dictionary literal}} + var b = [1: ;] // expected-error {{expected value in dictionary literal}} + var c = [1: "one" ;] // expected-error {{expected key expression in dictionary literal}} expected-error {{expected ',' separator}} {{20-20=,}} + var d = [1: "one", ;] // expected-error {{expected key expression in dictionary literal}} + var e = [1: "one", 2] // expected-error {{expected ':' in dictionary literal}} + var f = [1: "one", 2 ;] // expected-error {{expected ':' in dictionary literal}} + var g = [1: "one", 2: ;] // expected-error {{expected value in dictionary literal}} +} + + +[4].joined(separator: [1]) +// expected-error@-1 {{cannot convert value of type 'Int' to expected element type 'String'}} +// expected-error@-2 {{cannot convert value of type '[Int]' to expected argument type 'String'}} + +[4].joined(separator: [[[1]]]) +// expected-error@-1 {{cannot convert value of type 'Int' to expected element type 'String'}} +// expected-error@-2 {{cannot convert value of type '[[[Int]]]' to expected argument type 'String'}} + +//===----------------------------------------------------------------------===// +// nil/metatype comparisons +//===----------------------------------------------------------------------===// +_ = Int.self == nil // expected-warning {{comparing non-optional value of type 'Any.Type' to 'nil' always returns false}} +_ = nil == Int.self // expected-warning {{comparing non-optional value of type 'Any.Type' to 'nil' always returns false}} +_ = Int.self != nil // expected-warning {{comparing non-optional value of type 'Any.Type' to 'nil' always returns true}} +_ = nil != Int.self // expected-warning {{comparing non-optional value of type 'Any.Type' to 'nil' always returns true}} + +// Disallow postfix ? when not chaining +func testOptionalChaining(_ a : Int?, b : Int!, c : Int??) { + _ = a? // expected-error {{optional chain has no effect, expression already produces 'Int?'}} {{8-9=}} + _ = a?.customMirror + + _ = b? // expected-error {{optional chain has no effect, expression already produces 'Int?'}} + _ = b?.customMirror + + var _: Int? = c? // expected-error {{'?' must be followed by a call, member lookup, or subscript}} +} + + +// Nil Coalescing operator (??) should have a higher precedence +func testNilCoalescePrecedence(cond: Bool, a: Int?, r: ClosedRange?) { + // ?? should have higher precedence than logical operators like || and comparisons. + if cond || (a ?? 42 > 0) {} // Ok. + if (cond || a) ?? 42 > 0 {} // expected-error {{cannot be used as a boolean}} {{15-15=(}} {{16-16= != nil)}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + // expected-error@-2 {{cannot convert value of type 'Bool' to expected argument type 'Int'}} + if (cond || a) ?? (42 > 0) {} // expected-error {{cannot be used as a boolean}} {{15-15=(}} {{16-16= != nil)}} + + if cond || a ?? 42 > 0 {} // Parses as the first one, not the others. + + + // ?? should have lower precedence than range and arithmetic operators. + let r1 = r ?? (0...42) // ok + let r2 = (r ?? 0)...42 // not ok: expected-error {{binary operator '??' cannot be applied to operands of type 'ClosedRange?' and 'Int'}} + let r3 = r ?? 0...42 // parses as the first one, not the second. + + + // [Type checker] Diagnose unsavory optional injections + // Accidental optional injection for ??. + let i = 42 + _ = i ?? 17 // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'Int', so the right side is never used}} {{9-15=}} +} + +// Parsing of as and ?? regressed +func testOptionalTypeParsing(_ a : AnyObject) -> String { + return a as? String ?? "default name string here" +} + +func testParenExprInTheWay() { + let x = 42 + + if x & 4.0 {} // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + if (x & 4.0) {} // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + if !(x & 4.0) {} // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + + if x & x {} // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} +} + +// Mixed method/property overload groups can cause a crash during constraint optimization +public struct TestPropMethodOverloadGroup { + public typealias Hello = String + public let apply:(Hello) -> Int + public func apply(_ input:Hello) -> Int { + return apply(input) + } +} + + +// Passing ternary operator expression as inout crashes Swift compiler +func inoutTests(_ arr: inout Int) { + var x = 1, y = 2 + (true ? &x : &y) // expected-error {{use of extraneous '&'}} + let a = (true ? &x : &y) // expected-error {{use of extraneous '&'}} + + inoutTests(true ? &x : &y) // expected-error {{use of extraneous '&'}} + + &_ // expected-error {{use of extraneous '&'}} + + inoutTests((&x, 24).0) // expected-error {{use of extraneous '&'}} + + inoutTests((&x)) // expected-error {{use of extraneous '&'}} + inoutTests(&x) + + // inout not rejected as operand to assignment operator + &x += y // expected-error {{use of extraneous '&'}} + + // + func takeAny(_ x: Any) {} + takeAny(&x) // expected-error{{'&' used with non-inout argument of type 'Any'}} + func takeManyAny(_ x: Any...) {} + takeManyAny(&x) // expected-error{{'&' used with non-inout argument of type 'Any'}} + takeManyAny(1, &x) // expected-error{{'&' used with non-inout argument of type 'Any'}} + func takeIntAndAny(_ x: Int, _ y: Any) {} + takeIntAndAny(1, &x) // expected-error{{'&' used with non-inout argument of type 'Any'}} +} + + +// Compiler crash in default argument & inout expr +var g20802757 = 2 +func r20802757(_ z: inout Int = &g20802757) { // expected-error {{cannot provide default value to inout parameter 'z'}} + // expected-error@-1 {{use of extraneous '&'}} + print(z) +} + +_ = _.foo // expected-error {{'_' can only appear in a pattern or on the left side of an assignment}} + +// wrong arg list crashing sourcekit +func r22211854() { + func f(_ x: Bool, _ y: Int, _ z: String = "") {} // expected-note 2 {{'f' declared here}} + func g(_ x: T, _ y: T, _ z: String = "") {} // expected-note 2 {{'g' declared here}} + + f(false) // expected-error{{missing argument for parameter #2 in call}} + g(1) // expected-error{{missing argument for parameter #2 in call}} + func h() -> Int { return 1 } + f(h() == 1) // expected-error{{missing argument for parameter #2 in call}} + g(h() == 1) // expected-error{{missing argument for parameter #2 in call}} +} + +// Compiler crash on invoking function with labeled defaulted param with non-labeled argument +func r22348394() { + func f(x: Int = 0) { } + f(Int(3)) // expected-error{{missing argument label 'x:' in call}} +} + +// Compiler crashes in Assertion failed: ((AllowOverwrite || !E->hasLValueAccessKind()) && "l-value access kind has already been set"), function visit +protocol Proto { var y: String? { get } } +func r23185177(_ x: Proto?) -> [String] { + return x?.y // expected-error{{cannot convert return expression of type 'String?' to return type '[String]'}} +} + +// Miscompile: wrong argument parsing when calling a function in swift2.0 +func r22913570() { + func f(_ from: Int = 0, to: Int) {} // expected-note {{'f(_:to:)' declared here}} + f(1 + 1) // expected-error{{missing argument for parameter 'to' in call}} +} + +// SR-628 mixing lvalues and rvalues in tuple expression +do { + var x = 0 + var y = 1 + let _ = (x, x + 1).0 + let _ = (x, 3).1 + (x,y) = (2,3) + (x,4) = (1,2) // expected-error {{cannot assign to value: literals are not mutable}} + (x,y).1 = 7 // expected-error {{cannot assign to immutable expression of type 'Int'}} + x = (x,(3,y)).1.1 +} + +// SR-3439 subscript with pound exprssions. +Sr3439: do { + class B { + init() {} + subscript(x: Int) -> Int { return x } + subscript(x: String) -> String { return x } + + func foo() { + _ = self[#line] // Ok. + } + } + class C : B { + func bar() { + _ = super[#file] // Ok. + } + } + + let obj = C(); + _ = obj[#column] // Ok. +} + +// rdar://problem/23672697 - No way to express literal integers larger than Int without using type ascription +let _: Int64 = 0xFFF_FFFF_FFFF_FFFF +let _: Int64 = Int64(0xFFF_FFFF_FFFF_FFFF) +let _: Int64 = 0xFFF_FFFF_FFFF_FFFF as Int64 +let _ = Int64(0xFFF_FFFF_FFFF_FFFF) +let _ = 0xFFF_FFFF_FFFF_FFFF as Int64 + +// rdar://problem/20289969 - string interpolation with comment containing ')' or '"' +let _ = "foo \(42 /* ) " ) */)" +let _ = "foo \(foo // ) " // expected-error {{unterminated string literal}} +let _ = "foo \(42 /* + * multiline comment + */)end" +// expected-error @-3 {{unterminated string literal}} +// expected-error @-2 {{expected expression}} +// expected-error @-3 {{unterminated string literal}} diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift index 93de7f6efabc8..2c1e4e5085bdd 100644 --- a/test/stmt/statements.swift +++ b/test/stmt/statements.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -disable-parser-lookup /* block comments */ /* /* nested too */ */ @@ -501,8 +501,9 @@ func test_guard(_ x : Int, y : Int??, cond : Bool) { guard let e, cond else {} // expected-error {{variable binding in a condition requires an initializer}} guard case let f? : Int?, cond else {} // expected-error {{variable binding in a condition requires an initializer}} + // FIXME: Bring back the tailored diagnostic guard let g = y else { - markUsed(g) // expected-error {{variable declared in 'guard' condition is not usable in its body}} + markUsed(g) // expected-error {{cannot find 'g' in scope}} } guard let h = y, cond {} // expected-error {{expected 'else' after 'guard' condition}} {{25-25=else }} @@ -512,8 +513,9 @@ func test_guard(_ x : Int, y : Int??, cond : Bool) { // SR-7567 guard let outer = y else { + // FIXME: Bring back the tailored diagnostic guard true else { - print(outer) // expected-error {{variable declared in 'guard' condition is not usable in its body}} + print(outer) // expected-error {{cannot find 'outer' in scope}} } } } diff --git a/test/stmt/statements_parser_lookup.swift b/test/stmt/statements_parser_lookup.swift new file mode 100644 index 0000000000000..caeb47ef5097a --- /dev/null +++ b/test/stmt/statements_parser_lookup.swift @@ -0,0 +1,723 @@ +// RUN: %target-typecheck-verify-swift -enable-parser-lookup + +/* block comments */ +/* /* nested too */ */ + +func markUsed(_ t: T) {} + +func f1(_ a: Int, _ y: Int) {} +func f2() {} +func f3() -> Int {} + +func invalid_semi() { + ; // expected-error {{';' statements are not allowed}} {{3-5=}} +} + +func nested1(_ x: Int) { + var y : Int + // expected-warning@-1 {{variable 'y' was never mutated; consider changing to 'let' constant}} + + func nested2(_ z: Int) -> Int { + return x+y+z + } + + _ = nested2(1) +} + +func funcdecl5(_ a: Int, y: Int) { + var x : Int + + // a few statements + if (x != 0) { + if (x != 0 || f3() != 0) { + // while with and without a space after it. + while(true) { 4; 2; 1 } // expected-warning 3 {{integer literal is unused}} + while (true) { 4; 2; 1 } // expected-warning 3 {{integer literal is unused}} + } + } + + // Assignment statement. + x = y + (x) = y + + 1 = x // expected-error {{cannot assign to value: literals are not mutable}} + (1) = x // expected-error {{cannot assign to value: literals are not mutable}} + "string" = "other" // expected-error {{cannot assign to value: literals are not mutable}} + [1, 1, 1, 1] = [1, 1] // expected-error {{cannot assign to immutable expression of type '[Int]}} + 1.0 = x // expected-error {{cannot assign to value: literals are not mutable}} + nil = 1 // expected-error {{cannot assign to value: literals are not mutable}} + + (x:1).x = 1 // expected-error {{cannot assign to immutable expression of type 'Int'}} + var tup : (x:Int, y:Int) + tup.x = 1 + _ = tup + + let B : Bool + + // if/then/else. + if (B) { + } else if (y == 2) { + } + + // This diagnostic is terrible - rdar://12939553 + if x {} // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + + if true { + if (B) { + } else { + } + } + + if (B) { + f1(1,2) + } else { + f2() + } + + if (B) { + if (B) { + f1(1,2) + } else { + f2() + } + } else { + f2() + } + + // while statement. + while (B) { + } + + // It's okay to leave out the spaces in these. + while(B) {} + if(B) {} +} + +struct infloopbool { + var boolValue: infloopbool { + return self + } +} + +func infloopbooltest() { + if (infloopbool()) {} // expected-error {{cannot convert value of type 'infloopbool' to expected condition type 'Bool'}} +} + +// test "builder" API style +extension Int { + static func builder() -> Int { } + var builderProp: Int { return 0 } + func builder2() {} +} +Int + .builder() + .builderProp + .builder2() + +struct SomeGeneric { + static func builder() -> SomeGeneric { } + var builderProp: SomeGeneric { return .builder() } + func builder2() {} +} +SomeGeneric + .builder() + .builderProp + .builder2() + + +break // expected-error {{'break' is only allowed inside a loop, if, do, or switch}} +continue // expected-error {{'continue' is only allowed inside a loop}} +while true { + func f() { + break // expected-error {{'break' is only allowed inside a loop}} + continue // expected-error {{'continue' is only allowed inside a loop}} + } + + // Labeled if + MyIf: if 1 != 2 { + break MyIf + continue MyIf // expected-error {{'continue' cannot be used with if statements}} + break // break the while + continue // continue the while. + } +} + +// Labeled if +MyOtherIf: if 1 != 2 { + break MyOtherIf + continue MyOtherIf // expected-error {{'continue' cannot be used with if statements}} + break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if}} + continue // expected-error {{'continue' is only allowed inside a loop}} +} + +do { + break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} +} + +func tuple_assign() { + var a,b,c,d : Int + (a,b) = (1,2) + func f() -> (Int,Int) { return (1,2) } + ((a,b), (c,d)) = (f(), f()) + _ = (a,b,c,d) +} + +func missing_semicolons() { + var w = 321 + func g() {} + g() w += 1 // expected-error{{consecutive statements}} {{6-6=;}} + var z = w"hello" // expected-error{{consecutive statements}} {{12-12=;}} expected-warning {{string literal is unused}} + // expected-warning@-1 {{initialization of variable 'z' was never used; consider replacing with assignment to '_' or removing it}} + class C {}class C2 {} // expected-error{{consecutive statements}} {{14-14=;}} + struct S {}struct S2 {} // expected-error{{consecutive statements}} {{14-14=;}} + func j() {}func k() {} // expected-error{{consecutive statements}} {{14-14=;}} +} + +//===--- Return statement. + +return 42 // expected-error {{return invalid outside of a func}} + +return // expected-error {{return invalid outside of a func}} + +func NonVoidReturn1() -> Int { + _ = 0 + return // expected-error {{non-void function should return a value}} +} + +func NonVoidReturn2() -> Int { + return + // expected-error {{unary operator cannot be separated from its operand}} {{11-1=}} expected-error {{expected expression in 'return' statement}} +} + +func VoidReturn1() { + if true { return } + // Semicolon should be accepted -- rdar://11344875 + return; // no-error +} + +func VoidReturn2() { + return () // no-error +} + +func VoidReturn3() { + return VoidReturn2() // no-error +} + +//===--- If statement. + +func IfStmt1() { + if 1 > 0 // expected-error {{expected '{' after 'if' condition}} + _ = 42 +} + +func IfStmt2() { + if 1 > 0 { + } else // expected-error {{expected '{' or 'if' after 'else'}} + _ = 42 +} +func IfStmt3() { + if 1 > 0 { + } else 1 < 0 { // expected-error {{expected '{' or 'if' after 'else'; did you mean to write 'if'?}} {{9-9= if}} + _ = 42 + } else { + } +} + +//===--- While statement. + +func WhileStmt1() { + while 1 > 0 // expected-error {{expected '{' after 'while' condition}} + _ = 42 +} + +//===-- Do statement. +func DoStmt() { + // This is just a 'do' statement now. + do { + } +} + + +func DoWhileStmt1() { + do { // expected-error {{'do-while' statement is not allowed}} + // expected-note@-1 {{did you mean 'repeat-while' statement?}} {{3-5=repeat}} + // expected-note@-2 {{did you mean separate 'do' and 'while' statements?}} {{5-5=\n}} + } while true +} + +func DoWhileStmt2() { + do { + + } + while true { + + } +} + +func LabeledDoStmt() { + LABEL: { // expected-error {{labeled block needs 'do'}} {{10-10=do }} + } +} + +//===--- Repeat-while statement. + +func RepeatWhileStmt1() { + repeat {} while true + + repeat {} while false + + repeat { break } while true + repeat { continue } while true +} + +func RepeatWhileStmt2() { + repeat // expected-error {{expected '{' after 'repeat'}} expected-error {{expected 'while' after body of 'repeat' statement}} +} + +func RepeatWhileStmt4() { + repeat { + } while + // expected-error {{unary operator cannot be separated from its operand}} {{12-1=}} expected-error {{expected expression in 'repeat-while' condition}} +} + +func brokenSwitch(_ x: Int) -> Int { + switch x { + case .Blah(var rep): // expected-error{{type 'Int' has no member 'Blah'}} + return rep + } +} + +func switchWithVarsNotMatchingTypes(_ x: Int, y: Int, z: String) -> Int { + switch (x,y,z) { + case (let a, 0, _), (0, let a, _): // OK + return a + case (let a, _, _), (_, _, let a): // expected-error {{pattern variable bound to type 'String', expected type 'Int'}} + // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + return a + } +} + +func breakContinue(_ x : Int) -> Int { + +Outer: + for _ in 0...1000 { + + Switch: // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} + switch x { + case 42: break Outer + case 97: continue Outer + case 102: break Switch + case 13: continue + case 139: break // 'break' should be able to break out of switch statements + } + } + + // shadowing loop labels should be an error +Loop: // expected-note {{previously declared here}} + for _ in 0...2 { + Loop: // expected-error {{label 'Loop' cannot be reused on an inner statement}} + for _ in 0...2 { + } + } + + + // Following a 'break' statement by another statement on a new line result in an error/fit-it + switch 5 { + case 5: + markUsed("before the break") + break + markUsed("after the break") // 'markUsed' is not a label for the break. + default: + markUsed("") + } + + let x : Int? = 42 + + // Should be able to pattern match 'nil' against optionals + switch x { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.some(_)'}} + case .some(42): break + case nil: break + + } + +} + + +enum MyEnumWithCaseLabels { + case Case(one: String, two: Int) +} + +func testMyEnumWithCaseLabels(_ a : MyEnumWithCaseLabels) { + // Enum case labels are ignored in "case let" statements + switch a { + case let .Case(one: _, two: x): break // ok + case let .Case(xxx: _, two: x): break // expected-error {{tuple pattern element label 'xxx' must be 'one'}} + // TODO: In principle, reordering like this could be supported. + case let .Case(two: _, one: x): break // expected-error {{tuple pattern element label}} + } +} + + + +// "defer" + +func test_defer(_ a : Int) { + + defer { VoidReturn1() } + defer { breakContinue(1)+42 } // expected-warning {{result of operator '+' is unused}} + + // Ok: + defer { while false { break } } + + // Not ok. + while false { defer { break } } // expected-error {{'break' cannot transfer control out of a defer statement}} + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{17-22=do}} + defer { return } // expected-error {{'return' cannot transfer control out of a defer statement}} + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} +} + +class SomeTestClass { + var x = 42 + + func method() { + defer { x = 97 } // self. not required here! + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{5-10=do}} + } +} + +enum DeferThrowError: Error { + case someError +} + +func throwInDefer() { + defer { throw DeferThrowError.someError } // expected-error {{errors cannot be thrown out of a defer body}} + print("Foo") +} + +func throwInDeferOK1() { + defer { + do { + throw DeferThrowError.someError + } catch {} + } + print("Bar") +} + +func throwInDeferOK2() throws { + defer { + do { + throw DeferThrowError.someError + } catch {} + } + print("Bar") +} + +func throwingFuncInDefer1() throws { + defer { try throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}} + print("Bar") +} + +func throwingFuncInDefer1a() throws { + defer { + do { + try throwingFunctionCalledInDefer() + } catch {} + } + print("Bar") +} + +func throwingFuncInDefer2() throws { + defer { throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}} + print("Bar") +} + +func throwingFuncInDefer2a() throws { + defer { + do { + throwingFunctionCalledInDefer() + // expected-error@-1 {{call can throw but is not marked with 'try'}} + // expected-note@-2 {{did you mean to use 'try'?}} + // expected-note@-3 {{did you mean to handle error as optional value?}} + // expected-note@-4 {{did you mean to disable error propagation?}} + } catch {} + } + print("Bar") +} + +func throwingFuncInDefer3() { + defer { try throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}} + print("Bar") +} + +func throwingFuncInDefer3a() { + defer { + do { + try throwingFunctionCalledInDefer() + } catch {} + } + print("Bar") +} + +func throwingFuncInDefer4() { + defer { throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}} + print("Bar") +} + +func throwingFuncInDefer4a() { + defer { + do { + throwingFunctionCalledInDefer() + // expected-error@-1 {{call can throw but is not marked with 'try'}} + // expected-note@-2 {{did you mean to use 'try'?}} + // expected-note@-3 {{did you mean to handle error as optional value?}} + // expected-note@-4 {{did you mean to disable error propagation?}} + } catch {} + } + print("Bar") +} + +func throwingFunctionCalledInDefer() throws { + throw DeferThrowError.someError +} + +class SomeDerivedClass: SomeTestClass { + override init() { + defer { + super.init() // expected-error {{initializer chaining ('super.init') cannot be nested in another expression}} + } + } +} + +func test_guard(_ x : Int, y : Int??, cond : Bool) { + + // These are all ok. + guard let a = y else {} + markUsed(a) + guard let b = y, cond else {} + guard case let c = x, cond else {} + guard case let Optional.some(d) = y else {} + guard x != 4, case _ = x else { } + + + guard let e, cond else {} // expected-error {{variable binding in a condition requires an initializer}} + guard case let f? : Int?, cond else {} // expected-error {{variable binding in a condition requires an initializer}} + + guard let g = y else { + markUsed(g) // expected-error {{variable declared in 'guard' condition is not usable in its body}} + } + + guard let h = y, cond {} // expected-error {{expected 'else' after 'guard' condition}} {{25-25=else }} + + + guard case _ = x else {} // expected-warning {{'guard' condition is always true, body is unreachable}} + + // SR-7567 + guard let outer = y else { + guard true else { + print(outer) // expected-error {{variable declared in 'guard' condition is not usable in its body}} + } + } +} + +func test_is_as_patterns() { + switch 4 { + case is Int: break // expected-warning {{'is' test is always true}} + case _ as Int: break // expected-warning {{'as' test is always true}} + // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + case _: break // expected-warning {{case is already handled by previous patterns; consider removing it}} + } +} + +// Fuzzing SourceKit: crash in Parser::parseStmtForEach(...) +func matching_pattern_recursion() { + switch 42 { + case { // expected-error {{expression pattern of type '() -> ()' cannot match values of type 'Int'}} + for i in zs { + } + }: break + } +} + +// Swift's break operator in switch should be indicated in errors +func r18776073(_ a : Int?) { + switch a { + case nil: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{14-14= break}} + case _?: break + } +} + +// unhelpful error message from "throw nil" +func testThrowNil() throws { + throw nil // expected-error {{cannot infer concrete Error for thrown 'nil' value}} +} + + +// rdar://problem/23684220 +// Even if the condition fails to typecheck, save it in the AST anyway; the old +// condition may have contained a SequenceExpr. +func r23684220(_ b: Any) { + if let _ = b ?? b {} // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'Any', so the right side is never used}} + // expected-error@-1 {{initializer for conditional binding must have Optional type, not 'Any'}} +} + + +// QoI: try/catch (instead of do/catch) creates silly diagnostics +func f21080671() { + try { // expected-error {{the 'do' keyword is used to specify a 'catch' region}} {{3-6=do}} + } catch { } + + + try { // expected-error {{the 'do' keyword is used to specify a 'catch' region}} {{3-6=do}} + f21080671() + } catch let x as Int { + } catch { + } +} + +// QoI: Using "&& #available" should fixit to comma +// https://twitter.com/radexp/status/694561060230184960 +func f(_ x : Int, y : Int) { + if x == y && #available(iOS 52, *) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-15=,}} + if #available(iOS 52, *) && x == y {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{27-30=,}} + + // https://twitter.com/radexp/status/694790631881883648 + if x == y && let _ = Optional(y) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-15=,}} + if x == y&&let _ = Optional(y) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-14=,}} +} + + + +// QoI: Warn about cases where switch statement "ignores" where clause +enum Type { + case Foo + case Bar +} +func r25178926(_ a : Type) { + switch a { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Bar'}} + case .Foo, .Bar where 1 != 100: + // expected-warning @-1 {{'where' only applies to the second pattern match in this case}} + // expected-note @-2 {{disambiguate by adding a line break between them if this is desired}} {{14-14=\n }} + // expected-note @-3 {{duplicate the 'where' on both patterns to check both patterns}} {{12-12= where 1 != 100}} + break + } + + switch a { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Bar'}} + case .Foo: break + case .Bar where 1 != 100: break + } + + switch a { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Bar'}} + case .Foo, // no warn + .Bar where 1 != 100: + break + } + + switch a { // expected-error {{switch must be exhaustive}} + // expected-note@-1 {{missing case: '.Foo'}} + // expected-note@-2 {{missing case: '.Bar'}} + case .Foo where 1 != 100, .Bar where 1 != 100: + break + } +} + +do { + guard 1 == 2 else { + break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} + } +} + +func fn(a: Int) { + guard a < 1 else { + break // expected-error {{'break' is only allowed inside a loop, if, do, or switch}} + } +} + +func fn(x: Int) { + if x >= 0 { + guard x < 1 else { + guard x < 2 else { + break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} + } + return + } + } +} + +func bad_if() { + if 1 {} // expected-error {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + if (x: false) {} // expected-error {{cannot convert value of type '(x: Bool)' to expected condition type 'Bool'}} + if (x: 1) {} // expected-error {{cannot convert value of type '(x: Int)' to expected condition type 'Bool'}} + if nil {} // expected-error {{'nil' is not compatible with expected condition type 'Bool'}} +} + +// Typo correction for loop labels +for _ in [1] { + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} +} +while true { + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} +} +repeat { + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} +} while true + +outerLoop: for _ in [1] { // expected-note {{'outerLoop' declared here}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{9-18=outerLoop}} +} +outerLoop: for _ in [1] { // expected-note {{'outerLoop' declared here}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{12-21=outerLoop}} +} +outerLoop: while true { // expected-note {{'outerLoop' declared here}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{9-18=outerLoop}} +} +outerLoop: while true { // expected-note {{'outerLoop' declared here}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{12-21=outerLoop}} +} +outerLoop: repeat { // expected-note {{'outerLoop' declared here}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{9-18=outerLoop}} +} while true +outerLoop: repeat { // expected-note {{'outerLoop' declared here}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope; did you mean 'outerLoop'?}} {{12-21=outerLoop}} +} while true + +outerLoop1: for _ in [1] { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}} + outerLoop2: for _ in [1] { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } +} +outerLoop1: for _ in [1] { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}} + outerLoop2: for _ in [1] { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } +} +outerLoop1: while true { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}} + outerLoop2: while true { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } +} +outerLoop1: while true { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}} + outerLoop2: while true { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } +} +outerLoop1: repeat { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}} + outerLoop2: repeat { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}} + break outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } while true +} while true +outerLoop1: repeat { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}} + outerLoop2: repeat { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}} + continue outerloop // expected-error {{cannot find label 'outerloop' in scope}} + } while true +} while true + +// Errors in case syntax +class +case, // expected-error {{expected identifier in enum 'case' declaration}} expected-error {{expected identifier after comma in enum 'case' declaration}} expected-error {{enum 'case' is not allowed outside of an enum}} +case // expected-error {{expected identifier in enum 'case' declaration}} expected-error {{enum 'case' is not allowed outside of an enum}} +// NOTE: EOF is important here to properly test a code path that used to crash the parser diff --git a/validation-test/compiler_crashers_2_fixed/0180-rdar45557325-parser-lookup.swift b/validation-test/compiler_crashers_2_fixed/0180-rdar45557325-parser-lookup.swift new file mode 100644 index 0000000000000..93e2285cf083c --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/0180-rdar45557325-parser-lookup.swift @@ -0,0 +1,11 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -typecheck -verify -enable-parser-lookup + +// REQUIRES: objc_interop + +import Foundation + +class MyClass: NSObject { + func f() { + let url = URL(url) // expected-error{{variable used within its own initial value}} + } +} diff --git a/validation-test/compiler_crashers_2_fixed/0180-rdar45557325.swift b/validation-test/compiler_crashers_2_fixed/0180-rdar45557325.swift index 0276ac8627fb5..af0f3b45e45d2 100644 --- a/validation-test/compiler_crashers_2_fixed/0180-rdar45557325.swift +++ b/validation-test/compiler_crashers_2_fixed/0180-rdar45557325.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -typecheck -verify +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -typecheck -verify -disable-parser-lookup // REQUIRES: objc_interop @@ -6,6 +6,7 @@ import Foundation class MyClass: NSObject { func f() { - let url = URL(url) // expected-error{{variable used within its own initial value}} + let url = URL(url) // expected-error{{use of local variable 'url' before its declaration}} + // expected-note@-1 {{'url' declared here}} } } From 9294c0768731b1f8e56313814ea6ccdae8cab561 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 2 Oct 2020 21:42:06 -0700 Subject: [PATCH 12/13] CI: add concurrency to the Windows CI set Enable the concurrency support for Windows CI to mirror the other platforms. --- utils/build-windows.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index 90462413e1ad1..39360fbc09a2f 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -201,6 +201,7 @@ cmake^ -DCMAKE_CXX_FLAGS:STRING="/GS- /Oy"^ -DCMAKE_EXE_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ -DCMAKE_SHARED_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DSWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY=YES^ -S "%source_root%\llvm-project\llvm" %exitOnError% cmake --build "%build_root%\llvm" %exitOnError% From 573886d5d60f84abc881b74b631288d94839b16f Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 2 Oct 2020 13:54:17 -0700 Subject: [PATCH 13/13] [build] Remove forced tracing of lldb dotest --- utils/build-script-impl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build-script-impl b/utils/build-script-impl index 2bb99c886a669..49e339d9715b6 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -2012,7 +2012,7 @@ for host in "${ALL_HOSTS[@]}"; do fi # Construct dotest arguments. We use semicolons so CMake interprets this as a list. - DOTEST_ARGS="--build-dir;${lldb_build_dir}/lldb-test-build.noindex;${LLDB_TEST_CATEGORIES};-t" + DOTEST_ARGS="--build-dir;${lldb_build_dir}/lldb-test-build.noindex;${LLDB_TEST_CATEGORIES}" # Only set the extra arguments if they're not empty. if [[ -n "${DOTEST_EXTRA}" ]]; then