From 41d099bc914fd3a651ef939c4c93be6072625938 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 21 Oct 2019 15:55:55 -0700 Subject: [PATCH 1/6] Remove the argument to setInvalid() --- include/swift/AST/Decl.h | 2 +- lib/Parse/ParseDecl.cpp | 4 ++-- lib/Sema/CSDiag.cpp | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 414f9707ebb44..56f1c196fc306 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -810,7 +810,7 @@ class alignas(1 << DeclAlignInBits) Decl { bool isInvalid() const { return Bits.Decl.Invalid; } /// Mark this declaration invalid. - void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; } + void setInvalid() { Bits.Decl.Invalid = true; } /// Determine whether this declaration was implicitly generated by the /// compiler (rather than explicitly written in source code). diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b68231c6226d6..2ba3bd8ffc459 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4840,7 +4840,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags, VarLoc, Identifier(), CurDeclContext); storage->setImplicit(true); - storage->setInvalid(true); + storage->setInvalid(); Pattern *pattern = TypedPattern::createImplicit(Context, new (Context) NamedPattern(storage), @@ -4850,7 +4850,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags, auto binding = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling, VarLoc, entry, CurDeclContext); - binding->setInvalid(true); + binding->setInvalid(); storage->setParentPatternBinding(binding); Decls.push_back(binding); diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 287480e689e9c..03866a4df80af 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -910,9 +910,6 @@ namespace { P->setInterfaceType(Type()); } TS->PossiblyInvalidDecls.insert(P); - - if (P->isInvalid()) - P->setInvalid(false); } expr->setType(nullptr); From 4996858c4d95202f93486db7e092a8c96830b4bd Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 21 Oct 2019 17:43:04 -0700 Subject: [PATCH 2/6] Re-implement isInvalid for ValueDecls --- include/swift/AST/Decl.h | 4 +- lib/AST/ASTMangler.cpp | 2 +- lib/AST/ASTPrinter.cpp | 4 +- lib/AST/Decl.cpp | 71 +++++++++++++++++++ lib/AST/Module.cpp | 11 +-- lib/AST/TypeCheckRequests.cpp | 3 - lib/AST/USRGeneration.cpp | 3 - lib/IDE/CodeCompletion.cpp | 3 +- lib/Sema/CSApply.cpp | 1 - lib/Sema/CSGen.cpp | 4 -- lib/Sema/CSSimplify.cpp | 6 -- .../DerivedConformanceRawRepresentable.cpp | 2 - lib/Sema/LookupVisibleDecls.cpp | 6 -- lib/Sema/MiscDiagnostics.cpp | 9 ++- lib/Sema/TypeCheckConstraints.cpp | 3 - lib/Sema/TypeCheckDecl.cpp | 16 +---- lib/Sema/TypeCheckDeclObjC.cpp | 5 +- lib/Sema/TypeCheckExpr.cpp | 3 - lib/Sema/TypeCheckPattern.cpp | 2 +- lib/Sema/TypeCheckProtocol.cpp | 6 +- lib/Sema/TypeCheckProtocolInference.cpp | 7 +- lib/Sema/TypeChecker.cpp | 5 +- lib/Sema/TypeChecker.h | 2 +- 23 files changed, 98 insertions(+), 80 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 56f1c196fc306..6191f1dcfa0be 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -807,10 +807,10 @@ class alignas(1 << DeclAlignInBits) Decl { bool walk(ASTWalker &walker); /// Return whether this declaration has been determined invalid. - bool isInvalid() const { return Bits.Decl.Invalid; } + bool isInvalid() const; /// Mark this declaration invalid. - void setInvalid() { Bits.Decl.Invalid = true; } + void setInvalid(); /// Determine whether this declaration was implicitly generated by the /// compiler (rather than explicitly written in source code). diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index fc81ee3a8faf4..af8c349bbffb2 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2366,7 +2366,7 @@ CanType ASTMangler::getDeclTypeForMangling( parentGenericSig = GenericSignature(); auto &C = decl->getASTContext(); - if (!decl->getInterfaceType() || decl->getInterfaceType()->is()) { + if (decl->isInvalid()) { if (isa(decl)) return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)}, C.TheErrorType); diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 30b39552c30e8..5939349ed421a 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2872,7 +2872,7 @@ void PrintAST::printEnumElement(EnumElementDecl *elt) { auto params = ArrayRef(); - if (elt->hasInterfaceType() && !elt->getInterfaceType()->hasError()) { + if (elt->hasInterfaceType() && !elt->isInvalid()) { // Walk to the params of the associated values. // (EnumMetaType) -> (AssocValues) -> Enum params = elt->getInterfaceType()->castTo() @@ -2969,7 +2969,7 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) { }, [&] { // Parameters printGenericDeclGenericParams(decl); auto params = ArrayRef(); - if (decl->hasInterfaceType() && !decl->getInterfaceType()->hasError()) { + if (decl->hasInterfaceType() && !decl->isInvalid()) { // Walk to the params of the subscript's indices. params = decl->getInterfaceType()->castTo()->getParams(); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 51805082a89df..076e25d46894c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -376,6 +376,77 @@ DeclContext *Decl::getInnermostDeclContext() const { return getDeclContext(); } +bool Decl::isInvalid() const { + switch (getKind()) { +#define VALUE_DECL(ID, PARENT) +#define DECL(ID, PARENT) \ + case DeclKind::ID: +#include "swift/AST/DeclNodes.def" + return Bits.Decl.Invalid; + case DeclKind::Param: { + // Parameters are special because closure parameters may not have type + // annotations. In which case, the interface type request returns + // ErrorType. Therefore, consider parameters with implicit types to always + // be valid. + auto *PD = cast(this); + if (!PD->getTypeRepr() && !PD->hasInterfaceType()) + return false; + } + LLVM_FALLTHROUGH; + case DeclKind::Enum: + case DeclKind::Struct: + case DeclKind::Class: + case DeclKind::Protocol: + case DeclKind::OpaqueType: + case DeclKind::TypeAlias: + case DeclKind::GenericTypeParam: + case DeclKind::AssociatedType: + case DeclKind::Module: + case DeclKind::Var: + case DeclKind::Subscript: + case DeclKind::Constructor: + case DeclKind::Destructor: + case DeclKind::Func: + case DeclKind::Accessor: + case DeclKind::EnumElement: + return cast(this)->getInterfaceType()->hasError(); + } + + llvm_unreachable("Unknown decl kind"); +} + +void Decl::setInvalid() { + switch (getKind()) { +#define VALUE_DECL(ID, PARENT) +#define DECL(ID, PARENT) \ + case DeclKind::ID: +#include "swift/AST/DeclNodes.def" + Bits.Decl.Invalid = true; + return; + case DeclKind::Enum: + case DeclKind::Struct: + case DeclKind::Class: + case DeclKind::Protocol: + case DeclKind::OpaqueType: + case DeclKind::TypeAlias: + case DeclKind::GenericTypeParam: + case DeclKind::AssociatedType: + case DeclKind::Module: + case DeclKind::Var: + case DeclKind::Param: + case DeclKind::Subscript: + case DeclKind::Constructor: + case DeclKind::Destructor: + case DeclKind::Func: + case DeclKind::Accessor: + case DeclKind::EnumElement: + cast(this)->setInterfaceType(ErrorType::get(getASTContext())); + return; + } + + llvm_unreachable("Unknown decl kind"); +} + void Decl::setDeclContext(DeclContext *DC) { Context = DC; } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 164c7e9bcffdb..8985872b71897 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -212,14 +212,15 @@ void SourceLookupCache::addToUnqualifiedLookupCache(Range decls, if (!NTD->hasUnparsedMembers() || NTD->maybeHasOperatorDeclarations()) addToUnqualifiedLookupCache(NTD->getMembers(), true); - // Avoid populating the cache with the members of invalid extension - // declarations. These members can be used to point validation inside of - // a malformed context. - if (D->isInvalid()) continue; + if (auto *ED = dyn_cast(D)) { + // Avoid populating the cache with the members of invalid extension + // declarations. These members can be used to point validation inside of + // a malformed context. + if (ED->isInvalid()) continue; - if (auto *ED = dyn_cast(D)) if (!ED->hasUnparsedMembers() || ED->maybeHasOperatorDeclarations()) addToUnqualifiedLookupCache(ED->getMembers(), true); + } } } diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 08d8a07be87e9..2f58ecbb543f8 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -1020,9 +1020,6 @@ void InterfaceTypeRequest::cacheResult(Type type) const { assert(!type->hasTypeVariable() && "Type variable in interface type"); assert(!type->is() && "Interface type must be materializable"); assert(!type->hasArchetype() && "Archetype in interface type"); - - if (type->hasError()) - decl->setInvalid(); } decl->TypeAndAccess.setPointer(type); } diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 3f76e24087c2b..cf9d7895f71b9 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -258,9 +258,6 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, llvm::Expected swift::MangleLocalTypeDeclRequest::evaluate(Evaluator &evaluator, const TypeDecl *D) const { - if (!D->getInterfaceType()) - return std::string(); - if (isa(D)) return std::string(); // Ignore. diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 26d303b897642..94596247d10d0 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2431,8 +2431,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { addTypeAnnotation(Builder, AFT->getResult()); }; - if (!AFD || !AFD->getInterfaceType() || - !AFD->getInterfaceType()->is()) { + if (!AFD || !AFD->getInterfaceType()->is()) { // Probably, calling closure type expression. foundFunction(AFT); addPattern(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 86da96b8b5725..b1b9343dd6aec 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1940,7 +1940,6 @@ namespace { auto maxFloatTypeDecl = tc.Context.get_MaxBuiltinFloatTypeDecl(); if (!maxFloatTypeDecl || - !maxFloatTypeDecl->getInterfaceType() || !maxFloatTypeDecl->getDeclaredInterfaceType()->is()) { tc.diagnose(expr->getLoc(), diag::no_MaxBuiltinFloatType_found); return nullptr; diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 87ac015d56cd0..c61e9fbf22590 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -961,8 +961,6 @@ namespace { if (!decl) return nullptr; - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)decl->getInterfaceType(); if (decl->isInvalid()) return nullptr; @@ -1427,8 +1425,6 @@ namespace { // If the result is invalid, skip it. // FIXME: Note this as invalid, in case we don't find a solution, // so we don't let errors cascade further. - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)decls[i]->getInterfaceType(); if (decls[i]->isInvalid()) continue; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 60f9a3fc37ca0..048f303025147 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -5009,8 +5009,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName, } // If the result is invalid, skip it. - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)decl->getInterfaceType(); if (decl->isInvalid()) { result.markErrorAlreadyDiagnosed(); return; @@ -5386,8 +5384,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName, auto *cand = entry.getValueDecl(); // If the result is invalid, skip it. - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)cand->getInterfaceType(); if (cand->isInvalid()) { result.markErrorAlreadyDiagnosed(); return result; @@ -7337,8 +7333,6 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint( // Record the 'dynamicallyCall` method overload set. SmallVector choices; for (auto candidate : candidates) { - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)candidate->getInterfaceType(); if (candidate->isInvalid()) continue; choices.push_back( OverloadChoice(type2, candidate, FunctionRefKind::SingleApply)); diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index 827178486cdb4..5014f28e2192e 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -482,8 +482,6 @@ static bool canSynthesizeRawRepresentable(DerivedConformance &derived) { if (elt->hasAssociatedValues()) return false; - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface type. - (void)elt->getInterfaceType(); if (elt->isInvalid()) { return false; } diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index bc79d3ea5acdf..45d525495f8fb 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -765,9 +765,6 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { if (VD->isRecursiveValidation()) continue; - // FIXME: This is used to compute isInvalid() below. - (void) VD->getInterfaceType(); - auto &PossiblyConflicting = DeclsByName[VD->getBaseName()]; if (VD->isInvalid()) { @@ -811,9 +808,6 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { if (OtherVD->isRecursiveValidation()) continue; - // FIXME: This is used to compute isInvalid() below. - (void) OtherVD->getInterfaceType(); - if (OtherVD->isInvalid()) continue; diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index afe97ebe13c00..a6a339756654a 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -2103,7 +2103,7 @@ class VarDeclUsageChecker : public ASTWalker { // If the variable was invalid, ignore it and notice that the code is // malformed. - if (!VD->getInterfaceType() || VD->isInvalid()) { + if (VD->isInvalid()) { sawError = true; return false; } @@ -3792,8 +3792,7 @@ static void diagnoseUnintendedOptionalBehavior(TypeChecker &TC, const Expr *E, ValueDecl * fnDecl = appendMethod.getDecl(); // If things aren't set up right, just hope for the best. - if (!fnDecl || !fnDecl->getInterfaceType() || - fnDecl->getInterfaceType()->hasError()) + if (!fnDecl || fnDecl->isInvalid()) return false; // If the decl expects an optional, that's fine. @@ -4205,7 +4204,7 @@ static OmissionTypeName getTypeNameForOmission(Type type) { Optional TypeChecker::omitNeedlessWords(AbstractFunctionDecl *afd) { auto &Context = afd->getASTContext(); - if (!afd->getInterfaceType() || afd->isInvalid() || isa(afd)) + if (afd->isInvalid() || isa(afd)) return None; DeclName name = afd->getFullName(); @@ -4285,7 +4284,7 @@ Optional TypeChecker::omitNeedlessWords(AbstractFunctionDecl *afd) { Optional TypeChecker::omitNeedlessWords(VarDecl *var) { auto &Context = var->getASTContext(); - if (!var->getInterfaceType() || var->isInvalid()) + if (var->isInvalid()) return None; if (var->getName().empty()) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 2d502ab576e9f..632faa22a0e4e 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1354,9 +1354,6 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) { // afterwards. This allows for better diagnostics, and keeps the // closure expression type well-formed. for (auto param : *PL) { - // FIXME: Forces computation of isInvalid(). - (void) param->getInterfaceType(); - hadParameterError |= param->isInvalid(); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index babbbce443497..b11fad3872f81 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -634,13 +634,8 @@ static void checkRedeclaration(ASTContext &ctx, ValueDecl *current) { // Make sure we don't do this checking again. current->setCheckedRedeclaration(true); - // FIXME: Computes isInvalid() below. - (void) current->getInterfaceType(); - // Ignore invalid and anonymous declarations. - if (current->isInvalid() || - !current->hasInterfaceType() || - !current->hasName()) + if (current->isInvalid() || !current->hasName()) return; // If this declaration isn't from a source file, don't check it. @@ -704,9 +699,6 @@ static void checkRedeclaration(ASTContext &ctx, ValueDecl *current) { if (!conflicting(currentSig, otherSig)) continue; - // FIXME: Computes isInvalid() below. - (void) other->getInterfaceType(); - // Skip invalid declarations. if (other->isInvalid()) continue; @@ -1593,9 +1585,6 @@ EnumRawValuesRequest::evaluate(Evaluator &eval, EnumDecl *ED, Optional valueKind; for (auto elt : ED->getAllElements()) { - // FIXME: Computes isInvalid() below. - (void) elt->getInterfaceType(); - // If the element has been diagnosed up to now, skip it. if (elt->isInvalid()) continue; @@ -4375,7 +4364,8 @@ NamingPatternRequest::evaluate(Evaluator &evaluator, VarDecl *VD) const { // // Once that's through, this will only fire during circular validation. if (!namingPattern) { - if (!VD->isInvalid() && !VD->getParentPattern()->isImplicit()) { + if (VD->hasInterfaceType() && + !VD->isInvalid() && !VD->getParentPattern()->isImplicit()) { VD->diagnose(diag::variable_bound_by_no_pattern, VD->getName()); } diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 7e11a3654a9d0..720ac52aa6107 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -811,10 +811,7 @@ bool swift::isRepresentableInObjC( bool swift::isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason) { // If you change this function, you must add or modify a test in PrintAsObjC. - - // FIXME: Computes isInvalid() below. - (void) VD->getInterfaceType(); - + if (VD->isInvalid()) return false; diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index 758eeeb54403f..2da43043c05b0 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -652,9 +652,6 @@ static Type lookupDefaultLiteralType(const DeclContext *dc, if (!TD) return Type(); - // FIXME: Make isInvalid ask for the interface type. - (void)TD->getInterfaceType(); - if (TD->isInvalid()) return Type(); diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 106b14d3755a1..455cdbea81d83 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -977,7 +977,7 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, case PatternKind::Named: { NamedPattern *NP = cast(P); VarDecl *var = NP->getDecl(); - if (var->isInvalid()) + if (var->hasInterfaceType() && var->isInvalid()) type = ErrorType::get(Context); // In SIL mode, VarDecls are written as having reference storage types. diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 664bd33c555ab..fd1318a5e4c8a 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1536,10 +1536,6 @@ checkIndividualConformance(NormalProtocolConformance *conformance, conformance->setState(ProtocolConformanceState::Checking); SWIFT_DEFER { conformance->setState(ProtocolConformanceState::Complete); }; - // FIXME(InterfaceTypeRequest): isInvalid() should be based on the interface - // type. - (void)Proto->getInterfaceType(); - // If the protocol itself is invalid, there's nothing we can do. if (Proto->isInvalid()) { conformance->setInvalid(); @@ -3868,7 +3864,7 @@ void ConformanceChecker::resolveValueWitnesses() { } // Make sure we've got an interface type. - if (!requirement->getInterfaceType() || requirement->isInvalid()) { + if (requirement->isInvalid()) { Conformance->setInvalid(); continue; } diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 82231b664d112..430a0c49759df 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -447,7 +447,7 @@ AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses( } // Validate the requirement. - if (!req->getInterfaceType() || req->isInvalid()) + if (req->isInvalid()) continue; // Check whether any of the associated types we care about are @@ -495,9 +495,6 @@ static Type getWitnessTypeForMatching(TypeChecker &tc, if (witness->isRecursiveValidation()) return Type(); - // FIXME: This is here to trigger the isInvalid() computation. - (void) witness->getInterfaceType(); - if (witness->isInvalid()) return Type(); @@ -2038,7 +2035,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) { SWIFT_DEFER { ResolvingWitnesses.erase(requirement); }; // Make sure we've validated the requirement. - if (!requirement->getInterfaceType() || requirement->isInvalid()) { + if (requirement->isInvalid()) { Conformance->setInvalid(); return; } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index dd5f0864b1605..3f4a317936f23 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -69,9 +69,8 @@ ProtocolDecl *TypeChecker::getProtocol(ASTContext &Context, SourceLoc loc, Context.getIdentifier(getProtocolName(kind))); } - if (protocol && !protocol->getInterfaceType()) { - if (protocol->isInvalid()) - return nullptr; + if (protocol && protocol->isInvalid()) { + return nullptr; } return protocol; diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 51b18806fd0d1..02f810695ce3f 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1420,7 +1420,7 @@ class TypeChecker final : public LazyResolver { return getUnopenedTypeOfReference( value, baseType, UseDC, [&](VarDecl *var) -> Type { - if (!var->getInterfaceType() || var->isInvalid()) + if (var->isInvalid()) return ErrorType::get(Context); return wantInterfaceType ? value->getInterfaceType() From 5a7040e2a47b5da2733091e4ac071f98e4e504fd Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 21 Oct 2019 18:11:54 -0700 Subject: [PATCH 3/6] Remove PossiblyInvalidDecls --- lib/Sema/CSDiag.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 03866a4df80af..78571e23bf8dc 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -860,7 +860,6 @@ namespace { llvm::DenseMap TypeLocTypes; llvm::DenseMap PatternTypes; llvm::DenseMap ParamDeclInterfaceTypes; - llvm::DenseSet PossiblyInvalidDecls; ExprTypeSaverAndEraser(const ExprTypeSaverAndEraser&) = delete; void operator=(const ExprTypeSaverAndEraser&) = delete; public: @@ -909,7 +908,6 @@ namespace { TS->ParamDeclInterfaceTypes[P] = P->getInterfaceType(); P->setInterfaceType(Type()); } - TS->PossiblyInvalidDecls.insert(P); } expr->setType(nullptr); @@ -960,16 +958,10 @@ namespace { paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second->getInOutObjectType()); } - if (!PossiblyInvalidDecls.empty()) - for (auto D : PossiblyInvalidDecls) - if (D->hasInterfaceType()) - D->setInvalid(D->getInterfaceType()->hasError()); - // Done, don't do redundant work on destruction. ExprTypes.clear(); TypeLocTypes.clear(); PatternTypes.clear(); - PossiblyInvalidDecls.clear(); } // On destruction, if a type got wiped out, reset it from null to its @@ -997,11 +989,6 @@ namespace { paramDeclIfaceElt.first->setInterfaceType( getParamBaseType(paramDeclIfaceElt)); } - - if (!PossiblyInvalidDecls.empty()) - for (auto D : PossiblyInvalidDecls) - if (D->hasInterfaceType()) - D->setInvalid(D->getInterfaceType()->hasError()); } private: From db79d063e970078720169954514e09576f06bcc2 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 28 Oct 2019 11:36:32 -0700 Subject: [PATCH 4/6] Break a cycle --- lib/Sema/TypeCheckDecl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index b11fad3872f81..ab86d6529a004 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -674,7 +674,9 @@ static void checkRedeclaration(ASTContext &ctx, ValueDecl *current) { ModuleDecl *currentModule = current->getModuleContext(); for (auto other : otherDefinitions) { // Skip invalid declarations and ourselves. - if (current == other || other->isInvalid()) + // + // FIXME: Breaking a cycle here with hasInterfaceType() is bogus. + if (current == other || (other->hasInterfaceType() && other->isInvalid())) continue; // Skip declarations in other modules. From efe877e6ee8206627672a216470c5fe27e59689d Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 28 Oct 2019 11:41:13 -0700 Subject: [PATCH 5/6] Remove unnecesary interface type resets Now that setInvalid() is a semantic property, drop the explicit calls to reset the interface type. It is already ErrorType. --- lib/Sema/ConstraintSystem.cpp | 2 +- lib/Sema/TypeCheckConstraints.cpp | 6 +++--- lib/Sema/TypeCheckDecl.cpp | 11 ++--------- lib/Sema/TypeCheckGeneric.cpp | 7 ++----- lib/Sema/TypeCheckPattern.cpp | 1 - lib/Sema/TypeCheckStmt.cpp | 11 ----------- lib/Sema/TypeCheckStorage.cpp | 1 - 7 files changed, 8 insertions(+), 31 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 277d9e5696147..8f7b234a1d4ff 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -828,7 +828,7 @@ Type ConstraintSystem::getUnopenedTypeOfReference(VarDecl *value, Type baseType, if (!var->isInvalid()) { TC.diagnose(var->getLoc(), diag::recursive_decl_reference, var->getDescriptiveKind(), var->getName()); - var->setInterfaceType(ErrorType::get(getASTContext())); + var->setInvalid(); } return ErrorType::get(TC.Context); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 632faa22a0e4e..6ecf70bedaecb 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2815,10 +2815,10 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer, // compute a type for. if (var->hasInterfaceType() && !var->getType()->hasUnboundGenericType() && - !var->getType()->hasError()) + !var->isInvalid()) return; - var->setInterfaceType(ErrorType::get(Context)); + var->setInvalid(); }); } @@ -3034,7 +3034,7 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, // compute a type for. if (var->hasInterfaceType() && !var->getType()->hasError()) return; - var->setInterfaceType(ErrorType::get(Context)); + var->setInvalid(); }); }; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index ab86d6529a004..a6e48a0ede875 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -713,19 +713,13 @@ static void checkRedeclaration(ASTContext &ctx, ValueDecl *current) { if (!other->isAccessibleFrom(currentDC)) continue; - const auto markInvalid = [¤t]() { - current->setInvalid(); - if (current->hasInterfaceType()) - current->setInterfaceType(ErrorType::get(current->getInterfaceType())); - }; - // Thwart attempts to override the same declaration more than once. const auto *currentOverride = current->getOverriddenDecl(); const auto *otherOverride = other->getOverriddenDecl(); if (currentOverride && currentOverride == otherOverride) { current->diagnose(diag::multiple_override, current->getFullName()); other->diagnose(diag::multiple_override_prev, other->getFullName()); - markInvalid(); + current->setInvalid(); break; } @@ -872,7 +866,7 @@ static void checkRedeclaration(ASTContext &ctx, ValueDecl *current) { other->diagnose(diag::invalid_redecl_prev, other->getFullName()); }); } - markInvalid(); + current->setInvalid(); } // Make sure we don't do this checking again for the same decl. We also @@ -2463,7 +2457,6 @@ class DeclChecker : public DeclVisitor { auto markVarAndPBDInvalid = [PBD, var] { PBD->setInvalid(); var->setInvalid(); - var->setInterfaceType(ErrorType::get(var->getASTContext())); }; // Properties with an opaque return type need an initializer to diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index ba84644ab1424..f3a0b7571eb4a 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -421,7 +421,6 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) { // Check that every generic parameter type from the signature is // among referencedGenericParams. - auto &ctx = decl->getASTContext(); for (auto *genParam : genericSig->getGenericParams()) { auto *paramDecl = genParam->getDecl(); if (paramDecl->getDepth() != fnGenericParamsDepth) @@ -439,10 +438,8 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) { continue; } // Produce an error that this generic parameter cannot be bound. - ctx.Diags.diagnose(paramDecl->getLoc(), - diag::unreferenced_generic_parameter, - paramDecl->getNameStr()); - decl->setInterfaceType(ErrorType::get(ctx)); + paramDecl->diagnose(diag::unreferenced_generic_parameter, + paramDecl->getNameStr()); decl->setInvalid(); } } diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 455cdbea81d83..1fdee6f6cbd55 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -787,7 +787,6 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc, P->setType(ErrorType::get(Context)); if (auto named = dyn_cast(P)) { if (auto var = named->getDecl()) { - var->setInterfaceType(ErrorType::get(Context)); var->setInvalid(); } } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index bde99d7c8b3d9..5bc3318cc7faf 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1064,7 +1064,6 @@ class StmtChecker : public StmtVisitor { // If that failed, mark any variables binding pieces of the pattern // as invalid to silence follow-on errors. pattern->forEachVariable([&](VarDecl *VD) { - VD->setInterfaceType(ErrorType::get(TC.Context)); VD->setInvalid(); }); } @@ -1142,10 +1141,7 @@ class StmtChecker : public StmtVisitor { !vd->getType()->isEqual(initialCaseVarDecl->getType())) { TC.diagnose(vd->getLoc(), diag::type_mismatch_multiple_pattern_list, vd->getType(), initialCaseVarDecl->getType()); - vd->setInterfaceType(ErrorType::get(TC.Context)); vd->setInvalid(); - - initialCaseVarDecl->setInterfaceType(ErrorType::get(TC.Context)); initialCaseVarDecl->setInvalid(); } @@ -1166,10 +1162,7 @@ class StmtChecker : public StmtVisitor { if (foundVP) diag.fixItReplace(foundVP->getLoc(), initialCaseVarDecl->isLet() ? "let" : "var"); - vd->setInterfaceType(ErrorType::get(TC.Context)); vd->setInvalid(); - - initialCaseVarDecl->setInterfaceType(ErrorType::get(TC.Context)); initialCaseVarDecl->setInvalid(); } }); @@ -1237,10 +1230,7 @@ class StmtChecker : public StmtVisitor { TC.diagnose(previous->getLoc(), diag::type_mismatch_fallthrough_pattern_list, previous->getType(), expected->getType()); - previous->setInterfaceType(ErrorType::get(TC.Context)); previous->setInvalid(); - - expected->setInterfaceType(ErrorType::get(TC.Context)); expected->setInvalid(); } @@ -1476,7 +1466,6 @@ bool TypeChecker::typeCheckCatchPattern(CatchStmt *S, DeclContext *DC) { // before we type-check the guard. (This will probably kill // most of the type-checking, but maybe not.) pattern->forEachVariable([&](VarDecl *var) { - var->setInterfaceType(ErrorType::get(Context)); var->setInvalid(); }); } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index f0c1fe4c0049e..877bddc284029 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -42,7 +42,6 @@ void swift::setBoundVarsTypeError(Pattern *pattern, ASTContext &ctx) { if (var->hasInterfaceType()) return; - var->setInterfaceType(ErrorType::get(var->getASTContext())); var->setInvalid(); }); } From 0267384e111a4b72492471b987846ae8c2275d24 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 28 Oct 2019 16:15:53 -0700 Subject: [PATCH 6/6] Fixup SourceKit and Tests Patch up all the places that are making a syntactic judgement about the isInvalid() bit in a ValueDecl. They may continue to use that query, but most guard themselves on whether the interface type has been set. --- lib/AST/AccessRequests.cpp | 2 +- lib/AST/NameLookup.cpp | 2 +- lib/IDE/ExprContextAnalysis.cpp | 15 ++++++--------- lib/Sema/ConstraintSystem.cpp | 5 ----- lib/Sema/TypeCheckDeclOverride.cpp | 3 ++- lib/Sema/TypeCheckProtocol.cpp | 8 ++++---- test/Constraints/diagnostics.swift | 2 +- test/Constraints/members.swift | 2 +- test/Constraints/patterns.swift | 6 +++--- test/Generics/deduction.swift | 2 +- .../complete_single_expression_return.swift | 2 +- test/NameBinding/name_lookup.swift | 19 +++++++++++-------- test/Parse/EOF/unfinished-for-at-eof.swift | 1 - test/Parse/enum_element_pattern_swift4.swift | 1 - test/Parse/foreach.swift | 1 - test/Parse/matching_patterns.swift | 5 ----- test/Parse/recovery.swift | 5 +---- test/Parse/toplevel_library_invalid.swift | 1 - test/Sema/editor_placeholders.swift | 2 +- .../placeholders.swift.placeholders.response | 8 -------- test/attr/attr_dynamic_member_lookup.swift | 1 - test/decl/var/variables.swift | 5 ++--- test/stmt/c_style_for.swift | 8 -------- test/stmt/foreach.swift | 4 ---- test/stmt/if_while_var.swift | 3 --- tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp | 4 ++-- 26 files changed, 38 insertions(+), 79 deletions(-) diff --git a/lib/AST/AccessRequests.cpp b/lib/AST/AccessRequests.cpp index f3fc0de11f186..8a14df9f95f4d 100644 --- a/lib/AST/AccessRequests.cpp +++ b/lib/AST/AccessRequests.cpp @@ -81,7 +81,7 @@ AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const { // Special case for dtors and enum elements: inherit from container if (D->getKind() == DeclKind::Destructor || D->getKind() == DeclKind::EnumElement) { - if (D->isInvalid()) { + if (D->hasInterfaceType() && D->isInvalid()) { return AccessLevel::Private; } else { auto container = cast(D->getDeclContext()); diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index d49f281c375fb..1027452780bfa 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -69,7 +69,7 @@ void DebuggerClient::anchor() {} void AccessFilteringDeclConsumer::foundDecl( ValueDecl *D, DeclVisibilityKind reason, DynamicLookupInfo dynamicLookupInfo) { - if (D->isInvalid()) + if (D->hasInterfaceType() && D->isInvalid()) return; if (!D->isAccessibleFrom(DC)) return; diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index f1181eccfd548..33ad5cfad2db4 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -160,13 +160,11 @@ Expr *swift::ide::findParsedExpr(const DeclContext *DC, Type swift::ide::getReturnTypeFromContext(const DeclContext *DC) { if (auto FD = dyn_cast(DC)) { - if (FD->hasInterfaceType()) { - auto Ty = FD->getInterfaceType(); - if (FD->getDeclContext()->isTypeContext()) - Ty = FD->getMethodInterfaceType(); - if (auto FT = Ty->getAs()) - return DC->mapTypeIntoContext(FT->getResult()); - } + auto Ty = FD->getInterfaceType(); + if (FD->getDeclContext()->isTypeContext()) + Ty = FD->getMethodInterfaceType(); + if (auto FT = Ty->getAs()) + return DC->mapTypeIntoContext(FT->getResult()); } else if (auto ACE = dyn_cast(DC)) { if (ACE->getType() && !ACE->getType()->hasError()) return ACE->getResultType(); @@ -743,8 +741,7 @@ class ExprContextAnalyzer { if (!AFD) return; auto param = AFD->getParameters()->get(initDC->getIndex()); - if (param->hasInterfaceType()) - recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType())); + recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType())); break; } } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 8f7b234a1d4ff..0bad3e5dff02e 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -825,11 +825,6 @@ Type ConstraintSystem::getUnopenedTypeOfReference(VarDecl *value, Type baseType, return getType(param); if (!var->hasInterfaceType()) { - if (!var->isInvalid()) { - TC.diagnose(var->getLoc(), diag::recursive_decl_reference, - var->getDescriptiveKind(), var->getName()); - var->setInvalid(); - } return ErrorType::get(TC.Context); } diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index e95bd97845a2d..1900b346175a9 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -693,7 +693,8 @@ OverrideMatcher::OverrideMatcher(ValueDecl *decl) // The final step for this constructor is to set up the superclass type, // without which we will not perform an matching. Early exits therefore imply // that there is no way we can match this declaration. - if (decl->isInvalid()) + // FIXME: Break the cycle here. + if (decl->hasInterfaceType() && decl->isInvalid()) return; auto *dc = decl->getDeclContext(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index fd1318a5e4c8a..b8b748a775df2 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -327,13 +327,13 @@ swift::matchWitness( if (req->getKind() != witness->getKind()) return RequirementMatch(witness, MatchKind::KindConflict); - // If the witness is invalid, record that and stop now. - if (witness->isInvalid()) - return RequirementMatch(witness, MatchKind::WitnessInvalid); - // If we're currently validating the witness, bail out. if (witness->isRecursiveValidation()) return RequirementMatch(witness, MatchKind::Circularity); + + // If the witness is invalid, record that and stop now. + if (witness->isInvalid()) + return RequirementMatch(witness, MatchKind::WitnessInvalid); // Get the requirement and witness attributes. const auto &reqAttrs = req->getAttrs(); diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index 31c01ef75e52f..f22141bc67364 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -86,7 +86,7 @@ struct A : P2 { func wonka() {} } let a = A() -for j in i.wibble(a, a) { // expected-error {{for-in loop requires 'A' to conform to 'Sequence'}} expected-error{{variable 'j' is not bound by any pattern}} +for j in i.wibble(a, a) { // expected-error {{for-in loop requires 'A' to conform to 'Sequence'}} } // Generic as part of function/tuple types diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index d64e5c4a053f3..f504113ce3163 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -316,7 +316,7 @@ struct S22490787 { func f22490787() { var path: S22490787 = S22490787() - for p in path { // expected-error {{for-in loop requires 'S22490787' to conform to 'Sequence'}} expected-error{{variable 'p' is not bound by any pattern}} + for p in path { // expected-error {{for-in loop requires 'S22490787' to conform to 'Sequence'}} } } diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index 973a7f5146a6e..8d48e0ebea3c0 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -290,7 +290,7 @@ switch staticMembers { case .init(0): break case .init(_): break // expected-error{{'_' can only appear in a pattern}} - case .init(let x): break // expected-error{{cannot appear in an expression}} expected-error{{variable 'x' is not bound by any pattern}} + case .init(let x): break // expected-error{{cannot appear in an expression}} case .init(opt: 0): break // expected-error{{value of optional type 'StaticMembers?' must be unwrapped to a value of type 'StaticMembers'}} // expected-note@-1 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} // expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} @@ -302,12 +302,12 @@ switch staticMembers { case .method: break // expected-error{{cannot match}} case .method(0): break case .method(_): break // expected-error{{'_' can only appear in a pattern}} - case .method(let x): break // expected-error{{cannot appear in an expression}} expected-error{{variable 'x' is not bound by any pattern}} + case .method(let x): break // expected-error{{cannot appear in an expression}} case .method(withLabel:): break // expected-error{{cannot match}} case .method(withLabel: 0): break case .method(withLabel: _): break // expected-error{{'_' can only appear in a pattern}} - case .method(withLabel: let x): break // expected-error{{cannot appear in an expression}} expected-error{{variable 'x' is not bound by any pattern}} + case .method(withLabel: let x): break // expected-error{{cannot appear in an expression}} case .optMethod: break // expected-error{{cannot match}} case .optMethod(0): break diff --git a/test/Generics/deduction.swift b/test/Generics/deduction.swift index bcc2f244c8058..364a6db63b1fc 100644 --- a/test/Generics/deduction.swift +++ b/test/Generics/deduction.swift @@ -311,7 +311,7 @@ class DeducePropertyParams { // SR-69 struct A {} func foo() { - for i in min(1,2) { // expected-error{{for-in loop requires 'Int' to conform to 'Sequence'}} expected-error {{variable 'i' is not bound by any pattern}} + for i in min(1,2) { // expected-error{{for-in loop requires 'Int' to conform to 'Sequence'}} } let j = min(Int(3), Float(2.5)) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} let k = min(A(), A()) // expected-error{{global function 'min' requires that 'A' conform to 'Comparable'}} diff --git a/test/IDE/complete_single_expression_return.swift b/test/IDE/complete_single_expression_return.swift index 4e7a4f0212a38..8573a1ff1a3d8 100644 --- a/test/IDE/complete_single_expression_return.swift +++ b/test/IDE/complete_single_expression_return.swift @@ -556,7 +556,7 @@ struct TestSingleExprSubscriptGlobal { // TestSingleExprSubscriptGlobal: Begin completions // TestSingleExprSubscriptGlobal-DAG: Decl[InstanceMethod]/CurrNominal: str()[#String#]; -// TestSingleExprSubscriptGlobal-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: int()[#Int#]; +// TestSingleExprSubscriptGlobal-DAG: Decl[InstanceMethod]/CurrNominal: int()[#Int#]; // TestSingleExprSubscriptGlobal-DAG: Decl[InstanceMethod]/CurrNominal: void()[#Void#]; // TestSingleExprSubscriptGlobal: End completions } diff --git a/test/NameBinding/name_lookup.swift b/test/NameBinding/name_lookup.swift index f5796ecb22711..0bed144e8de89 100644 --- a/test/NameBinding/name_lookup.swift +++ b/test/NameBinding/name_lookup.swift @@ -224,7 +224,7 @@ class ThisDerived1 : ThisBase1 { self.baseProp = 42 // expected-error {{member 'baseProp' cannot be used on type 'ThisDerived1'}} self.baseFunc0() // expected-error {{instance member 'baseFunc0' cannot be used on type 'ThisDerived1'}} self.baseFunc0(ThisBase1())() // expected-error {{cannot convert value of type 'ThisBase1' to expected argument type 'ThisDerived1'}} - + self.baseFunc0(ThisDerived1())() self.baseFunc1(42) // expected-error {{instance member 'baseFunc1' cannot be used on type 'ThisDerived1'}} self.baseFunc1(ThisBase1())(42) // expected-error {{cannot convert value of type 'ThisBase1' to expected argument type 'ThisDerived1'}} @@ -482,7 +482,7 @@ struct MyStruct { // QoI: poor diagnostic initializing a variable with a non-class func class Test19935319 { let i = getFoo() // expected-error {{cannot use instance member 'getFoo' within property initializer; property initializers run before 'self' is available}} - + func getFoo() -> Int {} } @@ -616,18 +616,21 @@ struct PatternBindingWithTwoVars1 { var x = 3, y = x } // expected-error@-1 {{cannot use instance member 'x' within property initializer; property initializers run before 'self' is available}} struct PatternBindingWithTwoVars2 { var x = y, y = 3 } -// expected-error@-1 {{property 'y' references itself}} -// expected-error@-2 {{cannot use instance member 'y' within property initializer; property initializers run before 'self' is available}} +// expected-error@-1 {{cannot use instance member 'y' within property initializer; property initializers run before 'self' is available}} -// This one should be accepted, but for now PatternBindingDecl validation -// circularity detection is not fine grained enough. struct PatternBindingWithTwoVars3 { var x = y, y = x } // expected-error@-1 {{cannot use instance member 'x' within property initializer; property initializers run before 'self' is available}} // expected-error@-2 {{cannot use instance member 'y' within property initializer; property initializers run before 'self' is available}} -// expected-error@-3 {{property 'y' references itself}} +// expected-error@-3 {{circular reference}} +// expected-note@-4 {{through reference here}} +// expected-note@-5 {{through reference here}} +// expected-note@-6 {{through reference here}} +// expected-note@-7 {{through reference here}} +// expected-note@-8 {{through reference here}} + // https://bugs.swift.org/browse/SR-9015 func sr9015() { - let closure1 = { closure2() } // expected-error {{circular reference}} expected-error{{variable 'closure1' is not bound by any pattern}} expected-note {{through reference here}} expected-note {{through reference here}} + let closure1 = { closure2() } // expected-error {{circular reference}} expected-note {{through reference here}} expected-note {{through reference here}} let closure2 = { closure1() } // expected-note {{through reference here}} expected-note {{through reference here}} expected-note {{through reference here}} } diff --git a/test/Parse/EOF/unfinished-for-at-eof.swift b/test/Parse/EOF/unfinished-for-at-eof.swift index b6bc8f8bc582c..2bb21a03e528d 100644 --- a/test/Parse/EOF/unfinished-for-at-eof.swift +++ b/test/Parse/EOF/unfinished-for-at-eof.swift @@ -5,5 +5,4 @@ func fuzz() { for var H // expected-error@-2{{expected Sequence expression for for-each loop}} // expected-error@-3{{expected '{' to start the body of for-each loop}} // expected-note@-4 {{to match this opening '{'}} -// expected-error@-5 {{variable 'H' is not bound by any pattern}} // expected-error@+1{{expected '}' at end of brace statement}} diff --git a/test/Parse/enum_element_pattern_swift4.swift b/test/Parse/enum_element_pattern_swift4.swift index 61c82f11ad353..41c86e974275e 100644 --- a/test/Parse/enum_element_pattern_swift4.swift +++ b/test/Parse/enum_element_pattern_swift4.swift @@ -43,7 +43,6 @@ func testE(e: E) { // expected-note@-1 {{remove associated values to make the pattern match}} {{12-14=}} case .D(let payload) = e // expected-error {{pattern with associated values does not match enum case 'D'}} // expected-note@-1 {{remove associated values to make the pattern match}} {{12-25=}} - // expected-error@-2 {{variable 'payload' is not bound by any pattern}} else { return } } diff --git a/test/Parse/foreach.swift b/test/Parse/foreach.swift index bc20e22dc487d..dd02f8e721f9d 100644 --- a/test/Parse/foreach.swift +++ b/test/Parse/foreach.swift @@ -36,6 +36,5 @@ func for_each(r: Range, iir: IntRange) { // expected-note {{'r' declar // expected-note @-2 {{join the identifiers together with camel-case}} // expected-error @-3 {{expected 'in' after for-each pattern}} // expected-error @-4 {{expected Sequence expression for for-each loop}} - // expected-error @-5 {{variable 'i' is not bound by any pattern}} for i in r sum = sum + i; // expected-error{{expected '{' to start the body of for-each loop}} } diff --git a/test/Parse/matching_patterns.swift b/test/Parse/matching_patterns.swift index 9795e3cdc377f..d32ab35273643 100644 --- a/test/Parse/matching_patterns.swift +++ b/test/Parse/matching_patterns.swift @@ -118,10 +118,8 @@ enum Voluntary : Equatable { 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=}} - // expected-error@-2 {{variable 'value' is not bound by any pattern}} 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=}} - // expected-error@-2 {{variable 'value1' is not bound by any pattern}} @@ -284,12 +282,10 @@ case (1, 2, 3): case +++(_, var d, 3): // expected-error@-1{{'_' can only appear in a pattern or on the left side of an assignment}} // expected-error@-2{{'var' binding pattern cannot appear in an expression}} -// expected-error@-3 {{variable 'd' is not bound by any pattern}} () case (_, var e, 3) +++ (1, 2, 3): // expected-error@-1{{'_' can only appear in a pattern}} // expected-error@-2{{'var' binding pattern cannot appear in an expression}} -// expected-error@-3 {{variable 'e' is not bound by any pattern}} () case (let (_, _, _)) + 1: // expected-error@-1 2 {{'var' binding pattern cannot appear in an expression}} @@ -305,7 +301,6 @@ 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}} - // expected-error@-1 {{variable 'ds' is not bound by any pattern}} () case is [Derived]: // expected-error{{collection downcast in cast pattern is not implemented; use an explicit downcast to '[Derived]' instead}} () diff --git a/test/Parse/recovery.swift b/test/Parse/recovery.swift index 31b820f1ebffc..b73b5ee11e352 100644 --- a/test/Parse/recovery.swift +++ b/test/Parse/recovery.swift @@ -152,7 +152,7 @@ func missingControllingExprInFor() { for ; true { // expected-error {{C-style for statement has been removed in Swift 3}} } - for var i = 0; true { // expected-error {{C-style for statement has been removed in Swift 3}} expected-error{{variable 'i' is not bound by any pattern}} + for var i = 0; true { // expected-error {{C-style for statement has been removed in Swift 3}} i += 1 } } @@ -174,13 +174,11 @@ func missingControllingExprInForEach() { { } - // expected-error @+3 {{variable 'i' is not bound by any pattern}} // expected-error @+2 {{expected 'in' after for-each pattern}} // expected-error @+1 {{expected Sequence expression for for-each loop}} for i { } - // expected-error @+3 {{variable 'i' is not bound by any pattern}} // expected-error @+2 {{expected 'in' after for-each pattern}} // expected-error @+1 {{expected Sequence expression for for-each loop}} for var i { @@ -201,7 +199,6 @@ func missingControllingExprInForEach() { for for in { } - // expected-error @+1 {{variable 'i' is not bound by any pattern}} for i in { // expected-error {{expected Sequence expression for for-each loop}} } diff --git a/test/Parse/toplevel_library_invalid.swift b/test/Parse/toplevel_library_invalid.swift index 1b4fe537b8da0..7b2eb68d5cdea 100644 --- a/test/Parse/toplevel_library_invalid.swift +++ b/test/Parse/toplevel_library_invalid.swift @@ -10,7 +10,6 @@ x + x; // expected-error {{expressions are not allowed at the top level}} expect // expected-warning @-1 {{result of call to closure returning 'Int' is unused}} -// expected-error @+4 {{variable 'i' is not bound by any pattern}} // expected-error @+3 {{expected 'in' after for-each pattern}} // expected-error @+2 {{expected Sequence expression for for-each loop}} // expected-error @+1 {{expected '{' to start the body of for-each loop}} diff --git a/test/Sema/editor_placeholders.swift b/test/Sema/editor_placeholders.swift index 504d945269917..19a796e9b93b4 100644 --- a/test/Sema/editor_placeholders.swift +++ b/test/Sema/editor_placeholders.swift @@ -27,5 +27,5 @@ f(<#T##Int#>) // expected-error{{editor placeholder in source file}} f(<#T##String#>) // expected-error{{editor placeholder in source file}} expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}} for x in <#T#> { // expected-error{{editor placeholder in source file}} expected-error{{for-in loop requires '()' to conform to 'Sequence'}} - // expected-error@-1{{variable 'x' is not bound by any pattern}} + } diff --git a/test/SourceKit/Sema/placeholders.swift.placeholders.response b/test/SourceKit/Sema/placeholders.swift.placeholders.response index 62e9d3d55ee99..c5c69719ff3c9 100644 --- a/test/SourceKit/Sema/placeholders.swift.placeholders.response +++ b/test/SourceKit/Sema/placeholders.swift.placeholders.response @@ -14,14 +14,6 @@ } ] }, - { - key.line: 4, - key.column: 7, - key.filepath: placeholders.swift, - key.severity: source.diagnostic.severity.error, - key.description: "variable '<#name#>' is not bound by any pattern", - key.diagnostic_stage: source.diagnostic.stage.swift.sema - }, { key.line: 4, key.column: 19, diff --git a/test/attr/attr_dynamic_member_lookup.swift b/test/attr/attr_dynamic_member_lookup.swift index 4be33187192d3..43a6695ca8a2d 100644 --- a/test/attr/attr_dynamic_member_lookup.swift +++ b/test/attr/attr_dynamic_member_lookup.swift @@ -604,7 +604,6 @@ func keypath_with_incorrect_return_type(_ arr: Lens>) { // expected-error@-2 {{protocol 'Sequence' requires that 'Lens.Stride' conform to 'SignedInteger'}} // expected-error@-3 {{cannot convert value of type 'Int' to expected argument type 'Lens'}} // expected-error@-4 {{referencing operator function '..<' on 'Comparable' requires that 'Lens' conform to 'Comparable'}} - // expected-error@-5 {{variable 'idx' is not bound by any pattern}} let _ = arr[idx] } } diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index 24e6ffe88085f..0befba6d924e1 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -66,13 +66,12 @@ class SomeClass {} 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 {{variable 'a' is not bound by any pattern}} -// expected-error@-2 {{circular reference}} +// 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}} -// expected-note@-7 {{through reference here}} // Swift should warn about immutable default initialized values let uselessValue : String? diff --git a/test/stmt/c_style_for.swift b/test/stmt/c_style_for.swift index 2426b2e92ff0e..7ef1575d912a2 100644 --- a/test/stmt/c_style_for.swift +++ b/test/stmt/c_style_for.swift @@ -2,35 +2,27 @@ for var i = 0; i < 10; i++ {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 0; i < 10; i += 1 {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 0; i <= 10; i++ {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 0; i <= 10; i += 1 {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 10; i > 0; i-- {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 10; i > 0; i -= 1 {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 10; i >= 0; i-- {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} for var i = 10; i >= 0; i -= 1 {} // expected-error @-1 {{C-style for statement has been removed in Swift 3}} {{none}} -// expected-error @-2 {{variable 'i' is not bound by any pattern}} let start = Int8(4) let count = Int8(10) diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift index 0319146848177..a81faa7005388 100644 --- a/test/stmt/foreach.swift +++ b/test/stmt/foreach.swift @@ -6,7 +6,6 @@ struct BadContainer1 { func bad_containers_1(bc: BadContainer1) { for e in bc { } // expected-error{{for-in loop requires 'BadContainer1' to conform to 'Sequence'}} - // expected-error@-1{{variable 'e' is not bound by any pattern}} } struct BadContainer2 : Sequence { // expected-error{{type 'BadContainer2' does not conform to protocol 'Sequence'}} @@ -130,7 +129,6 @@ func testForEachInference() { // Overloaded sequence not resolved contextually for v in getOvlSeq() { } // expected-error{{ambiguous use of 'getOvlSeq()'}} - // expected-error@-1{{variable 'v' is not bound by any pattern}} // Generic sequence resolved contextually for i: Int in getGenericSeq() { } @@ -177,14 +175,12 @@ func testMatchingPatterns() { func testOptionalSequence() { let array : [Int]? for x in array { // expected-error {{for-in loop requires '[Int]?' to conform to 'Sequence'; did you mean to unwrap optional?}} - // expected-error@-1{{variable 'x' is not bound by any pattern}} } } // Crash with (invalid) for each over an existential func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}} for x in s { // expected-error {{value of protocol type 'Sequence' cannot conform to 'Sequence'; only struct/enum/class types can conform to protocols}} - // expected-error@-1{{variable 'x' is not bound by any pattern}} _ = x } } diff --git a/test/stmt/if_while_var.swift b/test/stmt/if_while_var.swift index 4bd7db64758a8..bffe794086c42 100644 --- a/test/stmt/if_while_var.swift +++ b/test/stmt/if_while_var.swift @@ -30,9 +30,7 @@ guard let _ = nonOptionalStruct() else { fatalError() } // expected-error{{initi guard let _ = nonOptionalEnum() else { fatalError() } // expected-error{{initializer for conditional binding must have Optional type, not 'NonOptionalEnum'}} if case let x? = nonOptionalStruct() { } // expected-error{{'?' pattern cannot match values of type 'NonOptionalStruct'}} -// expected-error@-1{{variable 'x' is not bound by any pattern}} if case let x? = nonOptionalEnum() { } // expected-error{{'?' pattern cannot match values of type 'NonOptionalEnum'}} -// expected-error@-1{{variable 'x' is not bound by any pattern}} class B {} // expected-note * {{did you mean 'B'?}} class D : B {}// expected-note * {{did you mean 'D'?}} @@ -66,7 +64,6 @@ if var x = opt {} // expected-warning {{value 'x' was defined but never used; co let someInteger = 1 if let y = someInteger {} // expected-error {{initializer for conditional binding must have Optional type, not 'Int'}} if case let y? = someInteger {} // expected-error {{'?' pattern cannot match values of type 'Int'}} -// expected-error@-1{{variable 'y' is not bound by any pattern}} // Test multiple clauses on "if let". if let x = opt, let y = opt, x != y, diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index b84e1d7d3d4f8..a911eab4f072a 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -1264,12 +1264,12 @@ class SwiftDocumentStructureWalker: public ide::SyntaxModelWalker { } StringRef getObjCRuntimeName(const Decl *D, SmallString<64> &Buf) { - if (!D || D->isInvalid()) + if (!D) return StringRef(); if (!isa(D) && !isa(D)) return StringRef(); auto *VD = cast(D); - if (!VD->hasName()) + if (!VD->hasName() || (VD->hasInterfaceType() && VD->isInvalid())) return StringRef(); auto ident = VD->getBaseName().getIdentifier().str(); if (ident.empty() || Mangle::isDigit(ident.front()))