From 4ed3665f8610f308c21701770c019d5e3e0face4 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 15 Apr 2020 12:20:16 -0700 Subject: [PATCH 1/8] [Diagnostics] Provide anchors on demand instead of storing in `FailureDiagnostic` This decouples `FailureDiagnostic` from expression. --- lib/Sema/CSDiagnostics.cpp | 2 +- lib/Sema/CSDiagnostics.h | 16 +++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index afdefb654c000..5d35eca086792 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -50,7 +50,7 @@ bool FailureDiagnostic::diagnoseAsNote() { return false; } -Expr *FailureDiagnostic::computeAnchor() const { +Expr *FailureDiagnostic::getAnchor() const { auto &cs = getConstraintSystem(); auto *locator = getLocator(); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 85534ebffcb32..c52d5fcda8928 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -41,15 +41,9 @@ class FailureDiagnostic { const Solution &S; ConstraintLocator *Locator; - /// The original anchor before any simplification. - Expr *RawAnchor; - /// Simplified anchor associated with the given locator. - Expr *Anchor; - public: FailureDiagnostic(const Solution &solution, ConstraintLocator *locator) - : S(solution), Locator(locator), RawAnchor(locator->getAnchor()), - Anchor(computeAnchor()) {} + : S(solution), Locator(locator) {} FailureDiagnostic(const Solution &solution, Expr *anchor) : FailureDiagnostic(solution, solution.getConstraintLocator(anchor)) {} @@ -83,9 +77,9 @@ class FailureDiagnostic { /// e.g. ambiguity error. virtual bool diagnoseAsNote(); - Expr *getRawAnchor() const { return RawAnchor; } + Expr *getRawAnchor() const { return Locator->getAnchor(); } - virtual Expr *getAnchor() const { return Anchor; } + virtual Expr *getAnchor() const; ConstraintLocator *getLocator() const { return Locator; } @@ -201,10 +195,6 @@ class FailureDiagnostic { Type type, llvm::function_ref substitution = [](GenericTypeParamType *, Type) {}); - -private: - /// Compute anchor expression associated with current diagnostic. - Expr *computeAnchor() const; }; /// Base class for all of the diagnostics related to generic requirement From f5714bf50d314c29283407091431f07b22a15763 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 15 Apr 2020 16:45:24 -0700 Subject: [PATCH 2/8] [Diagnostics] Switch `get{Raw}Anchor` to return `TypedNode` In preparation to anchor `ConstraintLocator` from `TypedNode` let's refactor diagnostics (which is the biggest user of locators) to support `TypedNode` instead of `Expr *`. --- lib/Sema/CSDiagnostics.cpp | 362 ++++++++++++++++++++++--------------- lib/Sema/CSDiagnostics.h | 25 +-- 2 files changed, 228 insertions(+), 159 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 5d35eca086792..a2861ef8e0c08 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -34,6 +34,7 @@ #include "swift/Basic/SourceLoc.h" #include "swift/Parse/Lexer.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallString.h" #include @@ -50,7 +51,7 @@ bool FailureDiagnostic::diagnoseAsNote() { return false; } -Expr *FailureDiagnostic::getAnchor() const { +TypedNode FailureDiagnostic::getAnchor() const { auto &cs = getConstraintSystem(); auto *locator = getLocator(); @@ -71,6 +72,30 @@ Expr *FailureDiagnostic::getAnchor() const { return anchor; } +SourceLoc FailureDiagnostic::getLoc(TypedNode anchor) { + if (auto *E = anchor.dyn_cast()) { + return E->getLoc(); + } else if (auto *T = anchor.dyn_cast()) { + return T->getLoc(); + } else if (auto *V = anchor.dyn_cast()) { + return V->getNameLoc(); + } else { + return anchor.get()->getLoc(); + } +} + +SourceRange FailureDiagnostic::getSourceRange(TypedNode anchor) { + if (auto *E = anchor.dyn_cast()) { + return E->getSourceRange(); + } else if (auto *T = anchor.dyn_cast()) { + return T->getSourceRange(); + } else if (auto *V = anchor.dyn_cast()) { + return V->getSourceRange(); + } else { + return anchor.get()->getSourceRange(); + } +} + Type FailureDiagnostic::getType(Expr *expr, bool wantRValue) const { return resolveType(S.getType(expr), /*reconstituteSugar=*/false, wantRValue); } @@ -151,7 +176,7 @@ Type FailureDiagnostic::restoreGenericParameters( } Type RequirementFailure::getOwnerType() const { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); // If diagnostic is anchored at assignment expression // it means that requirement failure happend while trying @@ -193,7 +218,8 @@ ProtocolConformance *RequirementFailure::getConformanceForConditionalReq( return nullptr; auto path = locator->getPath(); - auto *typeReqLoc = getConstraintLocator(getRawAnchor(), path.drop_back()); + auto *typeReqLoc = getConstraintLocator(getRawAnchor().get(), + path.drop_back()); auto result = llvm::find_if( cs.CheckedConformances, @@ -399,7 +425,7 @@ void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs, } bool MissingConformanceFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto nonConformingType = getLHS(); auto protocolType = getRHS(); @@ -501,7 +527,7 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform( } bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); auto *ODRE = dyn_cast(anchor); if (!ODRE) return false; @@ -605,7 +631,7 @@ void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) { } bool GenericArgumentsMismatchFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto path = getLocator()->getPath(); auto fromType = getFromType(); @@ -677,7 +703,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { } case ConstraintLocator::TupleElement: { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); if (isa(anchor)) { diagnostic = getDiagnosticFor(CTP_ArrayElement); @@ -715,7 +741,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { if (!diagnostic) return false; - emitDiagnosticAt(anchor->getLoc(), *diagnostic, fromType, toType); + emitDiagnostic(*diagnostic, fromType, toType); emitNotesForMismatches(); return true; } @@ -726,7 +752,7 @@ bool LabelingFailure::diagnoseAsError() { return false; auto &cs = getConstraintSystem(); - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); return diagnoseArgumentLabelError(cs.getASTContext(), argExpr, CorrectLabels, isa(anchor)); } @@ -792,7 +818,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { if (!convertTo->is()) return false; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto diagnostic = diag::general_noescape_to_escaping; ParamDecl *PD = nullptr; @@ -838,7 +864,8 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { // only mean that parameter is expecting @escaping function type. diagnostic = diag::passing_noescape_to_escaping; } - } else if (auto *AE = dyn_cast(getRawAnchor())) { + } else if (auto *AE = + dyn_cast(getRawAnchor().get())) { if (auto *DRE = dyn_cast(AE->getSrc())) { PD = dyn_cast(DRE->getDecl()); diagnostic = diag::assigning_noescape_to_escaping; @@ -863,13 +890,15 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { return true; } -Expr *MissingForcedDowncastFailure::getAnchor() const { - auto *expr = FailureDiagnostic::getAnchor(); +TypedNode MissingForcedDowncastFailure::getAnchor() const { + auto anchor = FailureDiagnostic::getAnchor(); - if (auto *assignExpr = dyn_cast(expr)) - return assignExpr->getSrc(); + if (auto *E = anchor.dyn_cast()) { + if (auto *assignExpr = dyn_cast(E)) + return assignExpr->getSrc(); + } - return expr; + return anchor; } bool MissingForcedDowncastFailure::diagnoseAsError() { @@ -896,21 +925,23 @@ bool MissingAddressOfFailure::diagnoseAsError() { return true; } -Expr *MissingExplicitConversionFailure::getAnchor() const { - auto *anchor = FailureDiagnostic::getAnchor(); +TypedNode MissingExplicitConversionFailure::getAnchor() const { + auto anchor = FailureDiagnostic::getAnchor(); - if (auto *assign = dyn_cast(anchor)) - return assign->getSrc(); + if (auto *E = anchor.dyn_cast()) { + if (auto *assign = dyn_cast(E)) + return assign->getSrc(); - if (auto *paren = dyn_cast(anchor)) - return paren->getSubExpr(); + if (auto *paren = dyn_cast(E)) + return paren->getSubExpr(); + } return anchor; } bool MissingExplicitConversionFailure::diagnoseAsError() { auto *DC = getDC(); - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto fromType = getFromType(); auto toType = getToType(); @@ -966,7 +997,7 @@ bool MissingExplicitConversionFailure::diagnoseAsError() { } bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto baseType = getType(anchor); bool resultIsOptional = ResultTypeIsOptional; @@ -1005,7 +1036,7 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( DeclContext *DC, Expr *expr) const { assert(expr); - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); // If anchor is n explicit address-of, or expression which produces // an l-value (e.g. first argument of `+=` operator), let's not // suggest default value here because that would produce r-value type. @@ -1093,7 +1124,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { return true; } - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); // If this is an unresolved member expr e.g. `.foo` its // base type is going to be the same as result type minus @@ -1201,7 +1232,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { bool RValueTreatedAsLValueFailure::diagnoseAsError() { Diag subElementDiagID; Diag rvalueDiagID = diag::assignment_lhs_not_lvalue; - Expr *diagExpr = getRawAnchor(); + Expr *diagExpr = getRawAnchor().get(); SourceLoc loc = diagExpr->getLoc(); // Assignment is not allowed inside of a condition, @@ -1402,13 +1433,14 @@ bool TypeChecker::diagnoseSelfAssignment(const Expr *expr) { } bool TrailingClosureAmbiguityFailure::diagnoseAsNote() { - const auto *expr = findParentExpr(getAnchor()); + auto *anchor = getAnchor().get(); + const auto *expr = findParentExpr(anchor); auto *callExpr = dyn_cast_or_null(expr); if (!callExpr) return false; if (!callExpr->hasTrailingClosure()) return false; - if (callExpr->getFn() != getAnchor()) + if (callExpr->getFn() != anchor) return false; llvm::SmallMapVector choicesByLabel; @@ -1879,7 +1911,7 @@ Diag AssignmentFailure::findDeclDiagonstic(ASTContext &ctx, } bool ContextualFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto path = getLocator()->getPath(); if (CTP == CTP_ReturnSingleExpr || CTP == CTP_ReturnStmt) { @@ -1938,7 +1970,7 @@ bool ContextualFailure::diagnoseAsError() { switch (path.back().getKind()) { case ConstraintLocator::ClosureBody: case ConstraintLocator::ClosureResult: { - auto *closure = cast(getRawAnchor()); + auto *closure = cast(getRawAnchor().get()); if (closure->hasExplicitResultType() && closure->getExplicitResultTypeLoc().getTypeRepr()) { auto resultRepr = closure->getExplicitResultTypeLoc().getTypeRepr(); @@ -1970,7 +2002,7 @@ bool ContextualFailure::diagnoseAsError() { } case ConstraintLocator::TernaryBranch: { - auto *ifExpr = cast(getRawAnchor()); + auto *ifExpr = cast(getRawAnchor().get()); fromType = getType(ifExpr->getThenExpr()); toType = getType(ifExpr->getElseExpr()); diagnostic = diag::if_expr_cases_mismatch; @@ -2149,7 +2181,7 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) { } bool ContextualFailure::diagnoseConversionToNil() const { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); if (!isa(anchor)) return false; @@ -2238,7 +2270,8 @@ bool ContextualFailure::diagnoseConversionToNil() const { emitDiagnostic(*diagnostic, getToType()); if (CTP == CTP_Initialization) { - auto *patternTR = getContextualTypeLoc(getRawAnchor()).getTypeRepr(); + auto *rawAnchor = getRawAnchor().get(); + auto *patternTR = getContextualTypeLoc(rawAnchor).getTypeRepr(); if (!patternTR) return true; @@ -2321,8 +2354,8 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const { } bool ContextualFailure::diagnoseCoercionToUnrelatedType() const { - auto *anchor = getAnchor(); - + auto *anchor = getAnchor().get(); + if (auto *coerceExpr = dyn_cast(anchor)) { auto fromType = getType(coerceExpr->getSubExpr()); auto toType = getType(coerceExpr->getCastTypeLoc()); @@ -2345,9 +2378,9 @@ bool ContextualFailure::diagnoseConversionToBool() const { if (!toType->isBool()) return false; - const auto *expr = getAnchor(); + auto *anchor = getAnchor().get(); // Check for "=" converting to Bool. The user probably meant ==. - if (auto *AE = dyn_cast(expr->getValueProvidingExpr())) { + if (auto *AE = dyn_cast(anchor->getValueProvidingExpr())) { emitDiagnosticAt(AE->getEqualLoc(), diag::use_of_equal_instead_of_equality) .fixItReplace(AE->getEqualLoc(), "==") .highlight(AE->getDest()->getLoc()) @@ -2360,7 +2393,7 @@ bool ContextualFailure::diagnoseConversionToBool() const { // diagnostics if someone attempts to use an optional or integer as a boolean // condition. SourceLoc notOperatorLoc; - if (Expr *parent = findParentExpr(getAnchor())) { + if (Expr *parent = findParentExpr(anchor)) { if (isa(parent) && parent->isImplicit()) { if ((parent = findParentExpr(parent))) { auto parentOperatorApplication = dyn_cast(parent); @@ -2391,7 +2424,7 @@ bool ContextualFailure::diagnoseConversionToBool() const { // Technically we only need them if there's something in 'expr' with // lower precedence than '!=', but the code actually comes out nicer // in most cases with parens on anything non-trivial. - if (expr->canAppendPostfixExpression()) { + if (anchor->canAppendPostfixExpression()) { prefix = prefix.drop_back(); suffix = suffix.drop_front(); } @@ -2422,7 +2455,7 @@ bool ContextualFailure::diagnoseConversionToBool() const { // Technically we only need them if there's something in 'expr' with // lower precedence than '!=', but the code actually comes out nicer // in most cases with parens on anything non-trivial. - if (expr->canAppendPostfixExpression()) { + if (anchor->canAppendPostfixExpression()) { prefix = prefix.drop_back(); suffix = suffix.drop_front(); } @@ -2446,7 +2479,7 @@ bool ContextualFailure::diagnoseThrowsTypeMismatch() const { if (CTP != CTP_ThrowStmt) return false; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); // If we tried to throw the error code of an error type, suggest object // construction. @@ -2486,7 +2519,7 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const { if (CTP != CTP_YieldByReference) return false; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto exprType = getType(anchor, /*wantRValue=*/false); auto contextualType = getToType(); @@ -2506,7 +2539,7 @@ bool ContextualFailure::tryRawRepresentableFixIts( InFlightDiagnostic &diagnostic, KnownProtocolKind rawRepresentableProtocol) const { auto &CS = getConstraintSystem(); - auto *expr = getAnchor(); + auto *expr = getAnchor().get(); auto fromType = getFromType(); auto toType = getToType(); @@ -2645,7 +2678,7 @@ bool ContextualFailure::tryIntegerCastFixIts( return parenE->getSubExpr(); }; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); if (Expr *innerE = getInnerCastedExpr(anchor)) { Type innerTy = getType(innerE); if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) { @@ -2681,7 +2714,8 @@ bool ContextualFailure::trySequenceSubsequenceFixIts( // Wrap in String.init if (getFromType()->isEqual(Substring)) { if (getToType()->isEqual(String)) { - auto *anchor = getAnchor()->getSemanticsProvidingExpr(); + auto *anchor = + getAnchor().get()->getSemanticsProvidingExpr(); if (auto *CE = dyn_cast(anchor)) { anchor = CE->getSubExpr(); } @@ -2824,7 +2858,7 @@ bool ContextualFailure::tryProtocolConformanceFixIt( } void ContextualFailure::tryComputedPropertyFixIts() const { - if (!isa(getAnchor())) + if (!isa(getAnchor().get())) return; // It is possible that we're looking at a stored property being @@ -2963,7 +2997,8 @@ bool TupleContextualFailure::diagnoseAsError() { auto purpose = getContextualTypePurpose(); if (isNumElementsMismatch()) diagnostic = diag::tuple_types_not_convertible_nelts; - else if ((purpose == CTP_Initialization) && !getContextualType(getAnchor())) + else if ((purpose == CTP_Initialization) && + !getContextualType(getAnchor().get())) diagnostic = diag::tuple_types_not_convertible; else if (auto diag = getDiagnosticFor(purpose, getToType())) diagnostic = *diag; @@ -2990,7 +3025,8 @@ bool AutoClosureForwardingFailure::diagnoseAsError() { // We need a raw anchor here because `getAnchor()` is simplified // to the argument expression. - auto *argExpr = getArgumentExpr(getRawAnchor(), last.getArgIdx()); + auto *argExpr = + getArgumentExpr(getRawAnchor().get(), last.getArgIdx()); emitDiagnosticAt(argExpr->getLoc(), diag::invalid_autoclosure_forwarding) .highlight(argExpr->getSourceRange()) .fixItInsertAfter(argExpr->getEndLoc(), "()"); @@ -3005,7 +3041,7 @@ bool AutoClosurePointerConversionFailure::diagnoseAsError() { } bool NonOptionalUnwrapFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto diagnostic = diag::invalid_optional_chain; if (isa(anchor)) @@ -3016,15 +3052,18 @@ bool NonOptionalUnwrapFailure::diagnoseAsError() { return true; } -Expr *MissingCallFailure::getAnchor() const { - auto *anchor = FailureDiagnostic::getAnchor(); - if (auto *FVE = dyn_cast(anchor)) - return FVE->getSubExpr(); +TypedNode MissingCallFailure::getAnchor() const { + auto anchor = FailureDiagnostic::getAnchor(); + + if (auto *E = anchor.dyn_cast()) { + if (auto *FVE = dyn_cast(E)) + return FVE->getSubExpr(); + } return anchor; } bool MissingCallFailure::diagnoseAsError() { - auto *baseExpr = getAnchor(); + auto *baseExpr = getAnchor().get(); SourceLoc insertLoc = baseExpr->getEndLoc(); // Calls are not yet supported by key path, but it @@ -3056,7 +3095,8 @@ bool MissingCallFailure::diagnoseAsError() { } case ConstraintLocator::AutoclosureResult: { - auto loc = getConstraintLocator(getRawAnchor(), path.drop_back()); + auto loc = getConstraintLocator(getRawAnchor().get(), + path.drop_back()); AutoClosureForwardingFailure failure(getSolution(), loc); return failure.diagnoseAsError(); } @@ -3122,7 +3162,7 @@ bool ExtraneousPropertyWrapperUnwrapFailure::diagnoseAsError() { } bool MissingPropertyWrapperUnwrapFailure::diagnoseAsError() { - auto endLoc = getAnchor()->getLoc().getAdvancedLoc(1); + auto endLoc = getLoc(getAnchor()).getAdvancedLoc(1); if (auto *member = getReferencedMember()) { emitDiagnostic(diag::incorrect_property_wrapper_reference_member, @@ -3141,8 +3181,9 @@ bool MissingPropertyWrapperUnwrapFailure::diagnoseAsError() { bool SubscriptMisuseFailure::diagnoseAsError() { auto &sourceMgr = getASTContext().SourceMgr; - auto *memberExpr = cast(getRawAnchor()); - auto *baseExpr = getAnchor(); + auto *memberExpr = + cast(getRawAnchor().get()); + auto *baseExpr = getAnchor().get(); auto memberRange = getSourceRange(); (void)simplifyLocator(getConstraintSystem(), getLocator(), memberRange); @@ -3211,8 +3252,8 @@ DeclName MissingMemberFailure::findCorrectEnumCaseName( } bool MissingMemberFailure::diagnoseAsError() { - auto *anchor = getRawAnchor(); - auto *baseExpr = getAnchor(); + auto *anchor = getRawAnchor().get(); + auto *baseExpr = getAnchor().get(); if (!anchor || !baseExpr) return false; @@ -3404,9 +3445,9 @@ bool MissingMemberFailure::diagnoseForDynamicCallable() const { } bool InvalidMemberRefOnExistential::diagnoseAsError() { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); - Expr *baseExpr = getAnchor(); + Expr *baseExpr = getAnchor().get(); DeclNameLoc nameLoc; if (auto *UDE = dyn_cast(anchor)) { baseExpr = UDE->getBase(); @@ -3442,7 +3483,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return expr; }; - Expr *expr = findParentExpr(getAnchor()); + Expr *expr = findParentExpr(getAnchor().get()); SourceRange baseRange = expr ? expr->getSourceRange() : SourceRange(); // If the base is an implicit self type reference, and we're in a @@ -3468,7 +3509,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { if (Name.isSimpleName(DeclBaseName::createConstructor()) && !BaseType->is()) { - if (auto ctorRef = dyn_cast(getRawAnchor())) { + if (auto ctorRef = + dyn_cast(getRawAnchor().get())) { if (isa(ctorRef->getBase())) { emitDiagnostic(diag::super_initializer_not_in_initializer); return true; @@ -3547,7 +3589,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } } - auto maybeCallExpr = getRawAnchor(); + auto maybeCallExpr = getRawAnchor().get(); if (auto UDE = dyn_cast(maybeCallExpr)) { maybeCallExpr = UDE->getBase(); @@ -3583,7 +3625,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return true; } - if (auto *UDE = dyn_cast(getRawAnchor())) { + if (auto *UDE = + dyn_cast(getRawAnchor().get())) { auto *baseExpr = UDE->getBase(); if (isa(baseExpr)) { emitDiagnostic(diag::instance_member_use_on_type, instanceTy, Name) @@ -3667,11 +3710,12 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { baseTy, Name)); } - Diag->highlight(getAnchor()->getSourceRange()); + Diag->highlight(getSourceRange()); if (Name.isSimpleName(DeclBaseName::createConstructor()) && !baseTy->is()) { - if (auto ctorRef = dyn_cast(getRawAnchor())) { + if (auto ctorRef = + dyn_cast(getRawAnchor().get())) { SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange(); Diag->fixItInsert(fixItRng.Start, "type(of: "); Diag->fixItInsertAfter(fixItRng.End, ")"); @@ -3680,7 +3724,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } // Determine the contextual type of the expression - Type contextualType = getContextualType(getRawAnchor()); + Type contextualType = getContextualType(getRawAnchor().get()); // Try to provide a fix-it that only contains a '.' if (contextualType && baseTy->isEqual(contextualType)) { Diag->fixItInsert(loc, "."); @@ -3689,7 +3733,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // Check if the expression is the matching operator ~=, most often used in // case statements. If so, try to provide a single dot fix-it - const Expr *contextualTypeNode = getRootExpr(getAnchor()); + const Expr *contextualTypeNode = + getRootExpr(getAnchor().get()); // The '~=' operator is an overloaded decl ref inside a binaryExpr if (auto binaryExpr = dyn_cast(contextualTypeNode)) { @@ -3717,9 +3762,10 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // Fall back to a fix-it with a full type qualifier const Expr *baseExpr = nullptr; - if (const auto SE = dyn_cast(getRawAnchor())) + auto *rawAnchor = getRawAnchor().get(); + if (const auto SE = dyn_cast(rawAnchor)) baseExpr = SE->getBase(); - else if (const auto UDE = dyn_cast(getRawAnchor())) + else if (const auto UDE = dyn_cast(rawAnchor)) baseExpr = UDE->getBase(); // An implicit 'self' reference base expression means we should @@ -3739,7 +3785,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { bool PartialApplicationFailure::diagnoseAsError() { auto &cs = getConstraintSystem(); - auto *anchor = cast(getRawAnchor()); + auto *anchor = cast(getRawAnchor().get()); RefKind kind = RefKind::MutatingMethod; @@ -3783,8 +3829,11 @@ bool InitOnProtocolMetatypeFailure::diagnoseAsError() { } SourceLoc ImplicitInitOnNonConstMetatypeFailure::getLoc() const { - auto *apply = cast(getRawAnchor()); - return apply->getArg()->getStartLoc(); + if (auto *E = getRawAnchor().dyn_cast()) { + if (auto *apply = dyn_cast(E)) + return apply->getArg()->getStartLoc(); + } + return FailureDiagnostic::getLoc(); } bool ImplicitInitOnNonConstMetatypeFailure::diagnoseAsError() { @@ -3793,10 +3842,14 @@ bool ImplicitInitOnNonConstMetatypeFailure::diagnoseAsError() { return true; } -Expr *MissingArgumentsFailure::getAnchor() const { - auto *anchor = FailureDiagnostic::getAnchor(); - if (auto *captureList = dyn_cast(anchor)) - return captureList->getClosureBody(); +TypedNode MissingArgumentsFailure::getAnchor() const { + auto anchor = FailureDiagnostic::getAnchor(); + + if (auto *E = anchor.dyn_cast()) { + if (auto *captureList = dyn_cast(E)) + return captureList->getClosureBody(); + } + return anchor; } @@ -3815,7 +3868,7 @@ bool MissingArgumentsFailure::diagnoseAsError() { if (isMisplacedMissingArgument(getSolution(), locator)) return false; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); if (auto *closure = dyn_cast(anchor)) return diagnoseClosure(closure); @@ -3846,8 +3899,9 @@ bool MissingArgumentsFailure::diagnoseAsError() { // let _: (Int) -> Void = foo // ``` if (locator->isLastElement()) { - emitDiagnostic(diag::cannot_convert_initializer_value, getType(anchor), - resolveType(getContextualType(getAnchor()))); + emitDiagnostic( + diag::cannot_convert_initializer_value, getType(anchor), + resolveType(getContextualType(getAnchor().get()))); // TODO: It would be great so somehow point out which arguments are missing. return true; } @@ -3888,7 +3942,7 @@ bool MissingArgumentsFailure::diagnoseAsError() { bool hasTrailingClosure = false; std::tie(fnExpr, argExpr, numArguments, hasTrailingClosure) = - getCallInfo(getRawAnchor()); + getCallInfo(getRawAnchor().get()); // TODO(diagnostics): We should be able to suggest this fix-it // unconditionally. @@ -3937,7 +3991,7 @@ bool MissingArgumentsFailure::diagnoseAsNote() { bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { auto &ctx = getASTContext(); - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); if (!(isa(anchor) || isa(anchor) || isa(anchor) || isa(anchor))) return false; @@ -4069,7 +4123,7 @@ bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) { locator->isLastElement()) { // Based on the locator we know this this is something like this: // `let _: () -> ((Int) -> Void) = { return {} }`. - funcType = getType(getRawAnchor()) + funcType = getType(getRawAnchor().get()) ->castTo() ->getResult() ->castTo(); @@ -4149,7 +4203,7 @@ bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const { if (SynthesizedArgs.size() < 2) return false; - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); Expr *argExpr = nullptr; // Something like `foo(x: (1, 2))` @@ -4190,7 +4244,7 @@ bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const { } bool MissingArgumentsFailure::isPropertyWrapperInitialization() const { - auto *call = dyn_cast(getRawAnchor()); + auto *call = dyn_cast(getRawAnchor().get()); if (!(call && call->isImplicit())) return false; @@ -4306,19 +4360,19 @@ void MissingArgumentsFailure::forFixIt( } SourceLoc ClosureParamDestructuringFailure::getLoc() const { - auto *closure = cast(getAnchor()); + auto *closure = cast(getAnchor().get()); auto paramList = closure->getParameters(); return paramList->getStartLoc(); } SourceRange ClosureParamDestructuringFailure::getSourceRange() const { - auto *closure = cast(getAnchor()); + auto *closure = cast(getAnchor().get()); auto paramList = closure->getParameters(); return paramList->getSourceRange(); } bool ClosureParamDestructuringFailure::diagnoseAsError() { - auto *closure = cast(getAnchor()); + auto *closure = cast(getAnchor().get()); auto params = closure->getParameters(); // In case of implicit parameters e.g. $0, $1 we @@ -4448,7 +4502,7 @@ bool ClosureParamDestructuringFailure::diagnoseAsError() { } bool OutOfOrderArgumentFailure::diagnoseAsError() { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); auto *argExpr = isa(anchor) ? anchor : getArgumentListExprFor(getLocator()); if (!argExpr) @@ -4538,7 +4592,7 @@ bool OutOfOrderArgumentFailure::diagnoseAsError() { bool ExtraneousArgumentsFailure::diagnoseAsError() { // Simplified anchor would point directly to the // argument in case of contextual mismatch. - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); if (auto *closure = dyn_cast(anchor)) { auto fnType = ContextualType; auto params = closure->getParameters(); @@ -4616,7 +4670,7 @@ bool ExtraneousArgumentsFailure::diagnoseAsNote() { return false; auto *decl = overload->choice.getDecl(); - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto numArgs = getTotalNumArguments(); emitDiagnosticAt(decl, diag::candidate_with_extraneous_args, ContextualType, ContextualType->getNumParams(), numArgs, (numArgs == 1), @@ -4630,7 +4684,7 @@ bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const { // This specifically handles a case of `Void(...)` which generates // constraints differently from other constructor invocations and // wouldn't have `ApplyArgument` as a last element in the locator. - if (auto *call = dyn_cast(getRawAnchor())) { + if (auto *call = dyn_cast(getRawAnchor().get())) { auto *TE = dyn_cast(call->getFn()); if (TE && getType(TE)->getMetatypeInstanceType()->isVoid()) { emitDiagnosticAt(call->getLoc(), diag::extra_argument_to_nullary_call) @@ -4680,7 +4734,7 @@ bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const { } bool InaccessibleMemberFailure::diagnoseAsError() { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); // Let's try to avoid over-diagnosing chains of inaccessible // members e.g.: // @@ -4732,21 +4786,29 @@ bool InaccessibleMemberFailure::diagnoseAsError() { } SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { - if (auto KPE = dyn_cast(getAnchor())) { - if (auto rootTyRepr = KPE->getRootType()) - return rootTyRepr->getLoc(); + auto anchor = getAnchor(); + + if (auto *E = anchor.dyn_cast()) { + if (auto *KPE = dyn_cast(E)) { + if (auto rootTyRepr = KPE->getRootType()) + return rootTyRepr->getLoc(); + } } - return FailureDiagnostic::getLoc(); + return FailureDiagnostic::getLoc(anchor); } SourceRange AnyObjectKeyPathRootFailure::getSourceRange() const { - if (auto KPE = dyn_cast(getAnchor())) { - if (auto rootTyRepr = KPE->getRootType()) - return rootTyRepr->getSourceRange(); + auto anchor = getAnchor(); + + if (auto *E = anchor.dyn_cast()) { + if (auto *KPE = dyn_cast(E)) { + if (auto rootTyRepr = KPE->getRootType()) + return rootTyRepr->getSourceRange(); + } } - return FailureDiagnostic::getSourceRange(); + return FailureDiagnostic::getSourceRange(anchor); } bool AnyObjectKeyPathRootFailure::diagnoseAsError() { @@ -4760,7 +4822,7 @@ SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const { auto *locator = getLocator(); if (locator->isKeyPathSubscriptComponent()) { - auto *KPE = cast(getAnchor()); + auto *KPE = cast(getAnchor().get()); if (auto kpElt = locator->findFirst()) return KPE->getComponents()[kpElt->getIndex()].getLoc(); } @@ -4775,16 +4837,18 @@ bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() { } SourceLoc InvalidMemberRefInKeyPath::getLoc() const { - auto *anchor = getRawAnchor(); + auto anchor = getRawAnchor(); - if (auto *KPE = dyn_cast(anchor)) { - auto *locator = getLocator(); - auto component = locator->findFirst(); - assert(component); - return KPE->getComponents()[component->getIndex()].getLoc(); + if (auto *E = anchor.dyn_cast()) { + if (auto *KPE = dyn_cast(E)) { + auto *locator = getLocator(); + auto component = locator->findFirst(); + assert(component); + return KPE->getComponents()[component->getIndex()].getLoc(); + } } - return anchor->getLoc(); + return FailureDiagnostic::getLoc(anchor); } bool InvalidStaticMemberRefInKeyPath::diagnoseAsError() { @@ -4806,12 +4870,14 @@ bool InvalidMethodRefInKeyPath::diagnoseAsError() { } SourceLoc InvalidUseOfAddressOf::getLoc() const { - auto *anchor = getAnchor(); + auto anchor = getAnchor(); - if (auto *assign = dyn_cast(anchor)) - anchor = assign->getSrc(); + if (auto *E = anchor.dyn_cast()) { + if (auto *assign = dyn_cast(E)) + return assign->getSrc()->getLoc(); + } - return anchor->getLoc(); + return FailureDiagnostic::getLoc(anchor); } bool InvalidUseOfAddressOf::diagnoseAsError() { @@ -4851,18 +4917,19 @@ bool ExtraneousReturnFailure::diagnoseAsError() { } bool CollectionElementContextualFailure::diagnoseAsError() { + auto *anchor = getRawAnchor().get(); auto *locator = getLocator(); auto eltType = getFromType(); auto contextualType = getToType(); Optional diagnostic; - if (isa(getRawAnchor())) { + if (isa(anchor)) { diagnostic.emplace(emitDiagnostic(diag::cannot_convert_array_element, eltType, contextualType)); } - if (isa(getRawAnchor())) { + if (isa(anchor)) { auto eltLoc = locator->castLastElementTo(); switch (eltLoc.getIndex()) { case 0: // key @@ -4885,7 +4952,7 @@ bool CollectionElementContextualFailure::diagnoseAsError() { // If this is a conversion failure related to binding of `for-each` // statement it has to be diagnosed as pattern match if there are // holes present in the contextual type. - if (cs.getContextualTypePurpose(getAnchor()) == + if (cs.getContextualTypePurpose(getAnchor().get()) == ContextualTypePurpose::CTP_ForEachStmt && contextualType->hasHole()) { diagnostic.emplace(emitDiagnostic( @@ -4910,7 +4977,7 @@ bool CollectionElementContextualFailure::diagnoseAsError() { } bool MissingContextualConformanceFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto path = getLocator()->getPath(); Optional> diagnostic; @@ -4972,7 +5039,7 @@ bool MissingGenericArgumentsFailure::diagnoseAsError() { }); if (!isScoped) - return diagnoseForAnchor(getAnchor(), Parameters); + return diagnoseForAnchor(getAnchor().get(), Parameters); bool diagnosed = false; for (const auto &scope : scopedParameters) @@ -5018,7 +5085,7 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( Anchor anchor, GenericTypeParamType *GP) const { auto &cs = getConstraintSystem(); - auto loc = anchor.is() ? anchor.get()->getLoc() + auto loc = anchor.is() ? anchor.get()->getLoc() : anchor.get()->getLoc(); auto *locator = getLocator(); @@ -5033,7 +5100,8 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( return false; } - if (auto *CE = dyn_cast(getRawAnchor())) { + if (auto *CE = + dyn_cast(getRawAnchor().get())) { auto castTo = getType(CE->getCastTypeLoc()); auto *NTD = castTo->getAnyNominal(); emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP, @@ -5130,7 +5198,7 @@ bool MissingGenericArgumentsFailure::findArgumentLocations( llvm::function_ref callback) { using Callback = llvm::function_ref; - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); TypeLoc typeLoc; if (auto *TE = dyn_cast(anchor)) @@ -5230,7 +5298,7 @@ bool SkipUnhandledConstructInFunctionBuilderFailure::diagnoseAsNote() { } bool MutatingMemberRefOnImmutableBase::diagnoseAsError() { - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); auto baseExpr = getBaseExprFor(anchor); if (!baseExpr) return false; @@ -5338,7 +5406,6 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() { } bool InOutConversionFailure::diagnoseAsError() { - auto *anchor = getAnchor(); auto *locator = getLocator(); auto path = locator->getPath(); @@ -5349,6 +5416,7 @@ bool InOutConversionFailure::diagnoseAsError() { argApplyInfo->getArgType(), argApplyInfo->getParamType()); } else { assert(locator->findLast()); + auto *anchor = getAnchor().get(); auto contextualType = getContextualType(anchor); auto purpose = getContextualTypePurpose(); auto diagnostic = getDiagnosticFor(purpose, contextualType); @@ -5369,7 +5437,7 @@ bool InOutConversionFailure::diagnoseAsError() { } void InOutConversionFailure::fixItChangeArgumentType() const { - auto *argExpr = getAnchor(); + auto *argExpr = getAnchor().get(); auto *DC = getDC(); if (auto *IOE = dyn_cast(argExpr)) @@ -5476,7 +5544,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() { // If argument is an l-value type and parameter is a pointer type, // let's match up its element type to the argument to see whether // it would be appropriate to suggest adding `&`. - auto *argExpr = getAnchor(); + auto *argExpr = getAnchor().get(); if (getType(argExpr, /*wantRValue=*/false)->is()) { auto elementTy = paramType->getAnyPointerElementType(); if (elementTy && argType->isEqual(elementTy)) { @@ -5508,7 +5576,7 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { if (!isArgumentOfReferenceEqualityOperator(locator)) return false; - auto *binaryOp = cast(getRawAnchor()); + auto *binaryOp = cast(getRawAnchor().get()); auto *lhs = binaryOp->getArg()->getElement(0); auto *rhs = binaryOp->getArg()->getElement(1); @@ -5520,7 +5588,7 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { // If both arguments where incorrect e.g. both are function types, // let's avoid producing a diagnostic second time, because first // one would cover both arguments. - if (getAnchor() == rhs && rhsType->is()) { + if (getAnchor().get() == rhs && rhsType->is()) { auto &cs = getConstraintSystem(); if (cs.hasFixFor(cs.getConstraintLocator( binaryOp, {ConstraintLocator::ApplyArgument, @@ -5572,7 +5640,7 @@ bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const { if (!isArgumentOfPatternMatchingOperator(getLocator())) return false; - auto *op = cast(getRawAnchor()); + auto *op = cast(getRawAnchor().get()); auto *lhsExpr = op->getArg()->getElement(0); auto *rhsExpr = op->getArg()->getElement(1); @@ -5652,7 +5720,7 @@ bool ArgumentMismatchFailure::diagnoseMisplacedMissingArgument() const { auto *fnType = getFnType(); const auto ¶m = fnType->getParams()[0]; - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); MissingArgumentsFailure failure( solution, {std::make_pair(0, param)}, @@ -5667,7 +5735,7 @@ bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const { // Verify that this is an implicit call to a property wrapper initializer // in a form of `init(wrappedValue:)` or deprecated `init(initialValue:)`. - auto *call = dyn_cast(getRawAnchor()); + auto *call = dyn_cast(getRawAnchor().get()); if (!(call && call->isImplicit() && isa(call->getFn()) && call->getNumArguments() == 1 && (call->getArgumentLabels().front() == getASTContext().Id_wrappedValue || @@ -5702,7 +5770,7 @@ void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt( } bool ExpandArrayIntoVarargsFailure::diagnoseAsError() { - if (auto anchor = getAnchor()) { + if (auto *anchor = getAnchor().dyn_cast()) { emitDiagnostic(diag::cannot_convert_array_to_variadic, getFromType(), getToType()); tryDropArrayBracketsFixIt(anchor); @@ -5714,7 +5782,7 @@ bool ExpandArrayIntoVarargsFailure::diagnoseAsError() { bool ExpandArrayIntoVarargsFailure::diagnoseAsNote() { auto overload = getCalleeOverloadChoiceIfAvailable(getLocator()); - auto anchor = getAnchor(); + auto anchor = getAnchor().get(); if (!overload || !anchor) return false; @@ -5728,16 +5796,14 @@ bool ExpandArrayIntoVarargsFailure::diagnoseAsNote() { } bool ExtraneousCallFailure::diagnoseAsError() { - auto &cs = getConstraintSystem(); - - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); auto *locator = getLocator(); // If this is something like `foo()` where `foo` is a variable // or a property, let's suggest dropping `()`. auto removeParensFixIt = [&](InFlightDiagnostic &diagnostic) { - auto *argLoc = cs.getConstraintLocator(getRawAnchor(), - ConstraintLocator::ApplyArgument); + auto *argLoc = getConstraintLocator(getRawAnchor().get(), + ConstraintLocator::ApplyArgument); if (auto *TE = dyn_cast_or_null(simplifyLocatorToAnchor(argLoc))) { @@ -5761,7 +5827,7 @@ bool ExtraneousCallFailure::diagnoseAsError() { if (auto *UDE = dyn_cast(anchor)) { auto *baseExpr = UDE->getBase(); - auto *call = cast(getRawAnchor()); + auto *call = cast(getRawAnchor().get()); if (getType(baseExpr)->isAnyObject()) { emitDiagnostic(diag::cannot_call_with_params, @@ -5936,7 +6002,7 @@ bool NonEphemeralConversionFailure::diagnosePointerInit() const { ? diag::cannot_construct_dangling_pointer_warning : diag::cannot_construct_dangling_pointer; - auto *anchor = getRawAnchor(); + auto *anchor = getRawAnchor().get(); emitDiagnosticAt(anchor->getLoc(), diagID, constructedTy, constructorKind) .highlight(anchor->getSourceRange()); @@ -6032,7 +6098,7 @@ bool AssignmentTypeMismatchFailure::diagnoseAsError() { } bool AssignmentTypeMismatchFailure::diagnoseAsNote() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); if (auto overload = getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor))) { @@ -6048,7 +6114,7 @@ bool AssignmentTypeMismatchFailure::diagnoseAsNote() { } bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { - auto *anchor = getAnchor(); + auto *anchor = getAnchor().get(); // Member reference could be wrapped into a number of parens // e.g. `((.foo))`. auto *parentExpr = findParentExpr(anchor); @@ -6069,7 +6135,7 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { } bool UnableToInferClosureReturnType::diagnoseAsError() { - auto *closure = cast(getRawAnchor()); + auto *closure = cast(getRawAnchor().get()); auto diagnostic = emitDiagnostic(diag::cannot_infer_closure_result_type, closure->hasSingleExpressionBody()); @@ -6126,13 +6192,13 @@ getImportModuleAndDefaultType(const ASTContext &ctx, ObjectLiteralExpr *expr) { } SourceLoc UnableToInferProtocolLiteralType::getLoc() const { - return getRawAnchor()->getLoc(); + return FailureDiagnostic::getLoc(getRawAnchor()); } bool UnableToInferProtocolLiteralType::diagnoseAsError() { auto &cs = getConstraintSystem(); auto &ctx = cs.getASTContext(); - auto *expr = cast(getRawAnchor()); + auto *expr = cast(getRawAnchor().get()); StringRef importModule; StringRef importDefaultTypeName; @@ -6154,7 +6220,7 @@ bool MissingQuialifierInMemberRefFailure::diagnoseAsError() { if (!selectedOverload) return false; - auto *UDE = cast(getRawAnchor()); + auto *UDE = cast(getRawAnchor().get()); auto baseType = getType(UDE->getBase()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index c52d5fcda8928..dbb7aa81fae8d 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -50,10 +50,10 @@ class FailureDiagnostic { virtual ~FailureDiagnostic(); - virtual SourceLoc getLoc() const { return getAnchor()->getLoc(); } + virtual SourceLoc getLoc() const { return getLoc(getAnchor()); } virtual SourceRange getSourceRange() const { - return getAnchor()->getSourceRange(); + return getSourceRange(getAnchor()); } /// Try to diagnose a problem given affected expression, @@ -77,9 +77,9 @@ class FailureDiagnostic { /// e.g. ambiguity error. virtual bool diagnoseAsNote(); - Expr *getRawAnchor() const { return Locator->getAnchor(); } + TypedNode getRawAnchor() const { return Locator->getAnchor(); } - virtual Expr *getAnchor() const; + virtual TypedNode getAnchor() const; ConstraintLocator *getLocator() const { return Locator; } @@ -195,6 +195,9 @@ class FailureDiagnostic { Type type, llvm::function_ref substitution = [](GenericTypeParamType *, Type) {}); + + static SourceLoc getLoc(TypedNode node); + static SourceRange getSourceRange(TypedNode node); }; /// Base class for all of the diagnostics related to generic requirement @@ -241,7 +244,7 @@ class RequirementFailure : public FailureDiagnostic { assert(getGenericContext() && "Affected decl not within a generic context?"); - if (auto *parentExpr = findParentExpr(getRawAnchor())) + if (auto *parentExpr = findParentExpr(getRawAnchor().get())) Apply = dyn_cast(parentExpr); } @@ -776,7 +779,7 @@ class MissingExplicitConversionFailure final : public ContextualFailure { Type toType, ConstraintLocator *locator) : ContextualFailure(solution, fromType, toType, locator) {} - Expr *getAnchor() const override; + TypedNode getAnchor() const override; bool diagnoseAsError() override; @@ -935,7 +938,7 @@ class MissingCallFailure final : public FailureDiagnostic { MissingCallFailure(const Solution &solution, ConstraintLocator *locator) : FailureDiagnostic(solution, locator) {} - Expr *getAnchor() const override; + TypedNode getAnchor() const override; bool diagnoseAsError() override; }; @@ -1033,7 +1036,7 @@ class MissingMemberFailure final : public InvalidMemberRefFailure { SourceLoc getLoc() const override { // Diagnostic should point to the member instead of its base expression. - return getRawAnchor()->getLoc(); + return FailureDiagnostic::getLoc(getRawAnchor()); } bool diagnoseAsError() override; @@ -1130,7 +1133,7 @@ class InvalidInitRefFailure : public FailureDiagnostic { const ConstructorDecl *Init; SourceRange BaseRange; - Expr *getAnchor() const override { return getRawAnchor(); } + TypedNode getAnchor() const override { return getRawAnchor(); } InvalidInitRefFailure(const Solution &solution, Type baseTy, const ConstructorDecl *init, SourceRange baseRange, @@ -1224,7 +1227,7 @@ class MissingArgumentsFailure final : public FailureDiagnostic { assert(!SynthesizedArgs.empty() && "No missing arguments?!"); } - Expr *getAnchor() const override; + TypedNode getAnchor() const override; bool diagnoseAsError() override; @@ -1852,7 +1855,7 @@ class MissingForcedDowncastFailure final : public ContextualFailure { Type toType, ConstraintLocator *locator) : ContextualFailure(solution, fromType, toType, locator) {} - Expr *getAnchor() const override; + TypedNode getAnchor() const override; bool diagnoseAsError() override; }; From 71ab19bdced37694bbcad48acda1361da4ef52b9 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 15 Apr 2020 17:48:00 -0700 Subject: [PATCH 3/8] [Diagnostics] Switch `getConstraintLocator` variants to accept `TypedNode` --- lib/Sema/CSApply.cpp | 11 ++++++-- lib/Sema/CSDiagnostics.cpp | 51 ++++++++++++++++--------------------- lib/Sema/CSDiagnostics.h | 15 ++++++++--- lib/Sema/ConstraintSystem.h | 6 ++++- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 9d13caa396e1f..4bfd9ef7b399d 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -166,10 +166,17 @@ ConstraintLocator *Solution::getCalleeLocator(ConstraintLocator *locator, } ConstraintLocator * -Solution::getConstraintLocator(Expr *anchor, +Solution::getConstraintLocator(const Expr *anchor, ArrayRef path) const { auto &cs = getConstraintSystem(); - return cs.getConstraintLocator(anchor, path); + return cs.getConstraintLocator(const_cast(anchor), path); +} + +ConstraintLocator * +Solution::getConstraintLocator(ConstraintLocator *base, + ArrayRef path) const { + auto &cs = getConstraintSystem(); + return cs.getConstraintLocator(base, path); } /// Return the implicit access kind for a MemberRefExpr with the diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index a2861ef8e0c08..9c816edd0b8d4 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -132,8 +132,7 @@ FailureDiagnostic::getArgumentListExprFor(ConstraintLocator *locator) const { // Form a new locator that ends at the ApplyArgument element, then simplify // to get the argument list. auto newPath = ArrayRef(path.begin(), iter + 1); - auto &cs = getConstraintSystem(); - auto argListLoc = cs.getConstraintLocator(locator->getAnchor(), newPath); + auto argListLoc = getConstraintLocator(locator->getAnchor(), newPath); return simplifyLocatorToAnchor(argListLoc); } @@ -218,8 +217,7 @@ ProtocolConformance *RequirementFailure::getConformanceForConditionalReq( return nullptr; auto path = locator->getPath(); - auto *typeReqLoc = getConstraintLocator(getRawAnchor().get(), - path.drop_back()); + auto *typeReqLoc = getConstraintLocator(getRawAnchor(), path.drop_back()); auto result = llvm::find_if( cs.CheckedConformances, @@ -1733,7 +1731,6 @@ bool AssignmentFailure::diagnoseAsError() { std::pair> AssignmentFailure::resolveImmutableBase(Expr *expr) const { - auto &cs = getConstraintSystem(); auto *DC = getDC(); expr = expr->getValueProvidingExpr(); @@ -1763,7 +1760,7 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { } Optional member = getMemberRef( - cs.getConstraintLocator(SE, ConstraintLocator::SubscriptMember)); + getConstraintLocator(SE, ConstraintLocator::SubscriptMember)); // If it isn't settable, return it. if (member) { @@ -1798,7 +1795,7 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { // Look through property references. if (auto *UDE = dyn_cast(expr)) { // If we found a decl for the UDE, check it. - auto loc = cs.getConstraintLocator(UDE, ConstraintLocator::Member); + auto loc = getConstraintLocator(UDE, ConstraintLocator::Member); auto member = getMemberRef(loc); @@ -1864,7 +1861,6 @@ AssignmentFailure::getMemberRef(ConstraintLocator *locator) const { // If this is a keypath dynamic member lookup, we have to // adjust the locator to find member referred by it. if (isValidKeyPathDynamicMemberLookup(subscript)) { - auto &cs = getConstraintSystem(); // Type has a following format: // `(Self) -> (dynamicMember: {Writable}KeyPath) -> U` auto *fullType = member->openedFullType->castTo(); @@ -1872,7 +1868,7 @@ AssignmentFailure::getMemberRef(ConstraintLocator *locator) const { auto paramTy = fnType->getParams()[0].getPlainType(); auto keyPath = paramTy->getAnyNominal(); - auto memberLoc = cs.getConstraintLocator( + auto memberLoc = getConstraintLocator( locator, LocatorPathElt::KeyPathDynamicMember(keyPath)); auto memberRef = getOverloadChoiceIfAvailable(memberLoc); @@ -2025,7 +2021,7 @@ bool ContextualFailure::diagnoseAsError() { auto &cs = getConstraintSystem(); MissingOptionalUnwrapFailure failure(getSolution(), getType(anchor), toType, - cs.getConstraintLocator(anchor)); + getConstraintLocator(anchor)); if (failure.diagnoseAsError()) return true; } @@ -3095,8 +3091,7 @@ bool MissingCallFailure::diagnoseAsError() { } case ConstraintLocator::AutoclosureResult: { - auto loc = getConstraintLocator(getRawAnchor().get(), - path.drop_back()); + auto loc = getConstraintLocator(getRawAnchor(), path.drop_back()); AutoClosureForwardingFailure failure(getSolution(), loc); return failure.diagnoseAsError(); } @@ -3517,15 +3512,14 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } auto isCallArgument = [this](Expr *expr) { - auto &cs = getConstraintSystem(); - auto argExpr = cs.getParentExpr(expr); + auto argExpr = findParentExpr(expr); if (!argExpr) return false; - auto possibleApplyExpr = cs.getParentExpr(expr); + auto possibleApplyExpr = findParentExpr(expr); return possibleApplyExpr && isa(possibleApplyExpr); }; - auto *initCall = cs.getParentExpr(cs.getParentExpr(ctorRef)); + auto *initCall = findParentExpr(findParentExpr(ctorRef)); auto isMutable = [&DC](ValueDecl *decl) { if (auto *storage = dyn_cast(decl)) @@ -3534,7 +3528,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return true; }; - auto *baseLoc = cs.getConstraintLocator(ctorRef->getBase()); + auto *baseLoc = getConstraintLocator(ctorRef->getBase()); if (auto selection = getCalleeOverloadChoiceIfAvailable(baseLoc)) { OverloadChoice choice = selection->choice; if (choice.isDecl() && isMutable(choice.getDecl()) && @@ -3563,8 +3557,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } if (getRawAnchor() && - cs.DC->getContextKind() == DeclContextKind::Initializer) { - auto *TypeDC = cs.DC->getParent(); + getDC()->getContextKind() == DeclContextKind::Initializer) { + auto *TypeDC = getDC()->getParent(); bool propertyInitializer = true; // If the parent context is not a type context, we expect it // to be a defaulted parameter in a function declaration. @@ -3785,13 +3779,13 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { bool PartialApplicationFailure::diagnoseAsError() { auto &cs = getConstraintSystem(); - auto *anchor = cast(getRawAnchor().get()); + auto anchor = cast(getRawAnchor().get()); RefKind kind = RefKind::MutatingMethod; // If this is initializer delegation chain, we have a tailored message. - if (getOverloadChoiceIfAvailable(cs.getConstraintLocator( - anchor, ConstraintLocator::ConstructorMember))) { + if (getOverloadChoiceIfAvailable( + getConstraintLocator(anchor, ConstraintLocator::ConstructorMember))) { kind = anchor->getBase()->isSuperExpr() ? RefKind::SuperInit : RefKind::SelfInit; } else if (anchor->getBase()->isSuperExpr()) { @@ -4763,8 +4757,7 @@ bool InaccessibleMemberFailure::diagnoseAsError() { if (baseExpr) { auto &cs = getConstraintSystem(); - auto *locator = - cs.getConstraintLocator(baseExpr, ConstraintLocator::Member); + auto *locator = getConstraintLocator(baseExpr, ConstraintLocator::Member); if (cs.hasFixFor(locator)) return false; } @@ -5590,7 +5583,7 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { // one would cover both arguments. if (getAnchor().get() == rhs && rhsType->is()) { auto &cs = getConstraintSystem(); - if (cs.hasFixFor(cs.getConstraintLocator( + if (cs.hasFixFor(getConstraintLocator( binaryOp, {ConstraintLocator::ApplyArgument, LocatorPathElt::ApplyArgToParam( 0, 0, getParameterFlagsAtIndex(0))}))) @@ -5720,7 +5713,7 @@ bool ArgumentMismatchFailure::diagnoseMisplacedMissingArgument() const { auto *fnType = getFnType(); const auto ¶m = fnType->getParams()[0]; - auto *anchor = getRawAnchor().get(); + auto anchor = getRawAnchor(); MissingArgumentsFailure failure( solution, {std::make_pair(0, param)}, @@ -5802,8 +5795,8 @@ bool ExtraneousCallFailure::diagnoseAsError() { // If this is something like `foo()` where `foo` is a variable // or a property, let's suggest dropping `()`. auto removeParensFixIt = [&](InFlightDiagnostic &diagnostic) { - auto *argLoc = getConstraintLocator(getRawAnchor().get(), - ConstraintLocator::ApplyArgument); + auto *argLoc = + getConstraintLocator(getRawAnchor(), ConstraintLocator::ApplyArgument); if (auto *TE = dyn_cast_or_null(simplifyLocatorToAnchor(argLoc))) { @@ -6098,7 +6091,7 @@ bool AssignmentTypeMismatchFailure::diagnoseAsError() { } bool AssignmentTypeMismatchFailure::diagnoseAsNote() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); if (auto overload = getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor))) { diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index dbb7aa81fae8d..d910d367989ff 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -158,16 +158,23 @@ class FailureDiagnostic { } ConstraintLocator * - getConstraintLocator(Expr *anchor, + getConstraintLocator(TypedNode anchor, ConstraintLocator::PathElement element) const { - return S.getConstraintLocator(anchor, {element}); + return S.getConstraintLocator(anchor.get(), {element}); } /// Retrive the constraint locator for the given anchor and /// path, uniqued and automatically calculate the summary flags ConstraintLocator *getConstraintLocator( - Expr *anchor, ArrayRef path = {}) const { - return S.getConstraintLocator(anchor, path); + TypedNode anchor, + ArrayRef path = {}) const { + return S.getConstraintLocator(anchor.get(), path); + } + + ConstraintLocator * + getConstraintLocator(ConstraintLocator *baseLocator, + ConstraintLocator::PathElement element) const { + return S.getConstraintLocator(baseLocator, element); } Optional diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index fe95854aec002..ea96247527c18 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -999,7 +999,11 @@ class Solution { bool lookThroughApply = true) const; ConstraintLocator * - getConstraintLocator(Expr *anchor, ArrayRef path = {}) const; + getConstraintLocator(const Expr *anchor, + ArrayRef path = {}) const; + + ConstraintLocator *getConstraintLocator(ConstraintLocator *baseLocator, + ArrayRef path) const; void setExprTypes(Expr *expr) const; From 66a07bab956f8ee9c76e85745aa41ed152699e13 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 16 Apr 2020 11:02:26 -0700 Subject: [PATCH 4/8] [Diagnostics] Switch `getContextualType*` to use `TypedNode` --- lib/Sema/CSDiagnostics.cpp | 21 ++++++++------------- lib/Sema/CSDiagnostics.h | 12 ++++++------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 9c816edd0b8d4..ffbeb1d2bb772 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -249,8 +249,7 @@ ValueDecl *RequirementFailure::getDeclRef() const { }; if (isFromContextualType()) - return getAffectedDeclFromType( - getContextualType(getLocator()->getAnchor())); + return getAffectedDeclFromType(getContextualType(getRawAnchor())); if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) { // If there is a declaration associated with this @@ -2266,8 +2265,7 @@ bool ContextualFailure::diagnoseConversionToNil() const { emitDiagnostic(*diagnostic, getToType()); if (CTP == CTP_Initialization) { - auto *rawAnchor = getRawAnchor().get(); - auto *patternTR = getContextualTypeLoc(rawAnchor).getTypeRepr(); + auto *patternTR = getContextualTypeLoc(getRawAnchor()).getTypeRepr(); if (!patternTR) return true; @@ -2993,8 +2991,7 @@ bool TupleContextualFailure::diagnoseAsError() { auto purpose = getContextualTypePurpose(); if (isNumElementsMismatch()) diagnostic = diag::tuple_types_not_convertible_nelts; - else if ((purpose == CTP_Initialization) && - !getContextualType(getAnchor().get())) + else if ((purpose == CTP_Initialization) && !getContextualType(getAnchor())) diagnostic = diag::tuple_types_not_convertible; else if (auto diag = getDiagnosticFor(purpose, getToType())) diagnostic = *diag; @@ -3718,7 +3715,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } // Determine the contextual type of the expression - Type contextualType = getContextualType(getRawAnchor().get()); + Type contextualType = getContextualType(getRawAnchor()); // Try to provide a fix-it that only contains a '.' if (contextualType && baseTy->isEqual(contextualType)) { Diag->fixItInsert(loc, "."); @@ -3893,9 +3890,8 @@ bool MissingArgumentsFailure::diagnoseAsError() { // let _: (Int) -> Void = foo // ``` if (locator->isLastElement()) { - emitDiagnostic( - diag::cannot_convert_initializer_value, getType(anchor), - resolveType(getContextualType(getAnchor().get()))); + emitDiagnostic(diag::cannot_convert_initializer_value, getType(anchor), + resolveType(getContextualType(getAnchor()))); // TODO: It would be great so somehow point out which arguments are missing. return true; } @@ -4941,11 +4937,10 @@ bool CollectionElementContextualFailure::diagnoseAsError() { } if (locator->isForSequenceElementType()) { - auto &cs = getConstraintSystem(); // If this is a conversion failure related to binding of `for-each` // statement it has to be diagnosed as pattern match if there are // holes present in the contextual type. - if (cs.getContextualTypePurpose(getAnchor().get()) == + if (getContextualTypePurpose(getAnchor()) == ContextualTypePurpose::CTP_ForEachStmt && contextualType->hasHole()) { diagnostic.emplace(emitDiagnostic( @@ -5409,7 +5404,7 @@ bool InOutConversionFailure::diagnoseAsError() { argApplyInfo->getArgType(), argApplyInfo->getParamType()); } else { assert(locator->findLast()); - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto contextualType = getContextualType(anchor); auto purpose = getContextualTypePurpose(); auto diagnostic = getDiagnosticFor(purpose, contextualType); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index d910d367989ff..d5e53cf8d5e97 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -118,19 +118,19 @@ class FailureDiagnostic { return S.getConstraintSystem(); } - Type getContextualType(Expr *anchor) const { + Type getContextualType(TypedNode anchor) const { auto &cs = getConstraintSystem(); - return cs.getContextualType(anchor); + return cs.getContextualType(anchor.get()); } - TypeLoc getContextualTypeLoc(Expr *anchor) const { + TypeLoc getContextualTypeLoc(TypedNode anchor) const { auto &cs = getConstraintSystem(); - return cs.getContextualTypeLoc(anchor); + return cs.getContextualTypeLoc(anchor.get()); } - ContextualTypePurpose getContextualTypePurpose(Expr *anchor) const { + ContextualTypePurpose getContextualTypePurpose(TypedNode anchor) const { auto &cs = getConstraintSystem(); - return cs.getContextualTypePurpose(anchor); + return cs.getContextualTypePurpose(anchor.get()); } DeclContext *getDC() const { From 08e09fc68519ab7a40590561633012e5704c7869 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 16 Apr 2020 12:55:31 -0700 Subject: [PATCH 5/8] [Diagnostics] Switch `getType` to use `TypedNode` --- lib/Sema/CSDiagnostics.cpp | 51 +++++++++++++++++++------------------- lib/Sema/CSDiagnostics.h | 3 +-- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index ffbeb1d2bb772..fc116be6e35cb 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -96,12 +96,8 @@ SourceRange FailureDiagnostic::getSourceRange(TypedNode anchor) { } } -Type FailureDiagnostic::getType(Expr *expr, bool wantRValue) const { - return resolveType(S.getType(expr), /*reconstituteSugar=*/false, wantRValue); -} - -Type FailureDiagnostic::getType(const TypeLoc &loc, bool wantRValue) const { - return resolveType(S.getType(&loc), /*reconstituteSugar=*/false, wantRValue); +Type FailureDiagnostic::getType(TypedNode node, bool wantRValue) const { + return resolveType(S.getType(node), /*reconstituteSugar=*/false, wantRValue); } template @@ -175,15 +171,17 @@ Type FailureDiagnostic::restoreGenericParameters( } Type RequirementFailure::getOwnerType() const { - auto *anchor = getRawAnchor().get(); + auto anchor = getRawAnchor(); // If diagnostic is anchored at assignment expression // it means that requirement failure happend while trying // to convert source to destination, which means that // owner type is actually not an assignment expression // itself but its source. - if (auto *assignment = dyn_cast(anchor)) - anchor = assignment->getSrc(); + if (auto *E = anchor.dyn_cast()) { + if (auto *assignment = dyn_cast(E)) + anchor = assignment->getSrc(); + } return getType(anchor)->getInOutObjectType()->getMetatypeInstanceType(); } @@ -524,8 +522,8 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform( } bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() { - auto *anchor = getRawAnchor().get(); - auto *ODRE = dyn_cast(anchor); + auto anchor = getRawAnchor(); + auto *ODRE = dyn_cast(anchor.get()); if (!ODRE) return false; @@ -994,7 +992,7 @@ bool MissingExplicitConversionFailure::diagnoseAsError() { } bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto baseType = getType(anchor); bool resultIsOptional = ResultTypeIsOptional; @@ -2017,7 +2015,6 @@ bool ContextualFailure::diagnoseAsError() { if (isa(anchor) || isa(anchor)) { auto objectType = fromType->getOptionalObjectType(); if (objectType->isEqual(toType)) { - auto &cs = getConstraintSystem(); MissingOptionalUnwrapFailure failure(getSolution(), getType(anchor), toType, getConstraintLocator(anchor)); @@ -2352,7 +2349,8 @@ bool ContextualFailure::diagnoseCoercionToUnrelatedType() const { if (auto *coerceExpr = dyn_cast(anchor)) { auto fromType = getType(coerceExpr->getSubExpr()); - auto toType = getType(coerceExpr->getCastTypeLoc()); + const auto &typeLoc = coerceExpr->getCastTypeLoc(); + auto toType = getType(&typeLoc); auto diagnostic = getDiagnosticFor(CTP_CoerceOperand, toType); @@ -2513,7 +2511,7 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const { if (CTP != CTP_YieldByReference) return false; - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto exprType = getType(anchor, /*wantRValue=*/false); auto contextualType = getToType(); @@ -3740,8 +3738,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // If the rhs of '~=' is the enum type, a single dot suffixes // since the type can be inferred - Type secondArgType = - cs.getType(binaryExpr->getArg()->getElement(1)); + Type secondArgType = getType(binaryExpr->getArg()->getElement(1)); if (secondArgType->isEqual(baseTy)) { Diag->fixItInsert(loc, "."); return true; @@ -3859,9 +3856,9 @@ bool MissingArgumentsFailure::diagnoseAsError() { if (isMisplacedMissingArgument(getSolution(), locator)) return false; - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); - if (auto *closure = dyn_cast(anchor)) + if (auto *closure = dyn_cast(anchor.dyn_cast())) return diagnoseClosure(closure); // This is a situation where function type is passed as an argument @@ -4113,7 +4110,7 @@ bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) { locator->isLastElement()) { // Based on the locator we know this this is something like this: // `let _: () -> ((Int) -> Void) = { return {} }`. - funcType = getType(getRawAnchor().get()) + funcType = getType(getRawAnchor()) ->castTo() ->getResult() ->castTo(); @@ -4582,8 +4579,9 @@ bool OutOfOrderArgumentFailure::diagnoseAsError() { bool ExtraneousArgumentsFailure::diagnoseAsError() { // Simplified anchor would point directly to the // argument in case of contextual mismatch. - auto *anchor = getAnchor().get(); - if (auto *closure = dyn_cast(anchor)) { + auto *anchor = getAnchor(); + + if (auto *closure = dyn_cast(anchor.dyn_cast()) { auto fnType = ContextualType; auto params = closure->getParameters(); @@ -5090,7 +5088,8 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( if (auto *CE = dyn_cast(getRawAnchor().get())) { - auto castTo = getType(CE->getCastTypeLoc()); + const auto &typeLoc = CE->getCastTypeLoc(); + auto castTo = getType(&typeLoc); auto *NTD = castTo->getAnyNominal(); emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP, NTD ? NTD->getDeclaredType() : castTo); @@ -5532,7 +5531,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() { // If argument is an l-value type and parameter is a pointer type, // let's match up its element type to the argument to see whether // it would be appropriate to suggest adding `&`. - auto *argExpr = getAnchor().get(); + auto argExpr = getAnchor(); if (getType(argExpr, /*wantRValue=*/false)->is()) { auto elementTy = paramType->getAnyPointerElementType(); if (elementTy && argType->isEqual(elementTy)) { @@ -5784,7 +5783,7 @@ bool ExpandArrayIntoVarargsFailure::diagnoseAsNote() { } bool ExtraneousCallFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto *locator = getLocator(); // If this is something like `foo()` where `foo` is a variable @@ -5813,7 +5812,7 @@ bool ExtraneousCallFailure::diagnoseAsError() { } } - if (auto *UDE = dyn_cast(anchor)) { + if (auto *UDE = dyn_cast(anchor.dyn_cast())) { auto *baseExpr = UDE->getBase(); auto *call = cast(getRawAnchor().get()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index d5e53cf8d5e97..f20059c2c7dce 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -83,8 +83,7 @@ class FailureDiagnostic { ConstraintLocator *getLocator() const { return Locator; } - Type getType(Expr *expr, bool wantRValue = true) const; - Type getType(const TypeLoc &loc, bool wantRValue = true) const; + Type getType(TypedNode node, bool wantRValue = true) const; /// Resolve type variables present in the raw type, if any. Type resolveType(Type rawType, bool reconstituteSugar = false, From 6335a4f2efb400ef8ed6261349cf0cf592c95e7d Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 16 Apr 2020 14:11:24 -0700 Subject: [PATCH 6/8] [Diagnostics] Resolve const-ness problems introduced by `TypedNode` Since `TypedNode` elements are all marked as `const` diagnostics need to get some of the APIs adjusted to support passing `const Expr *`. --- include/swift/AST/Expr.h | 7 +- lib/Sema/CSDiagnostics.cpp | 139 ++++++++++++++++++------------------- lib/Sema/CSDiagnostics.h | 40 ++++++----- 3 files changed, 97 insertions(+), 89 deletions(-) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 90a11c96eff43..7d394ee03b65e 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -3759,7 +3759,12 @@ class ClosureExpr : public AbstractClosureExpr { assert(hasExplicitResultType() && "No explicit result type"); return ExplicitResultType; } - + + TypeRepr *getExplicitResultTypeRepr() const { + assert(hasExplicitResultType() && "No explicit result type"); + return ExplicitResultType.getTypeRepr(); + } + void setExplicitResultType(SourceLoc arrowLoc, TypeLoc resultType) { ArrowLoc = arrowLoc; ExplicitResultType = resultType; diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index fc116be6e35cb..7d970108e07f6 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -113,9 +113,9 @@ FailureDiagnostic::emitDiagnosticAt(ArgTypes &&... Args) const { return DE.diagnose(std::forward(Args)...); } -Expr *FailureDiagnostic::findParentExpr(Expr *subExpr) const { +Expr *FailureDiagnostic::findParentExpr(const Expr *subExpr) const { auto &cs = getConstraintSystem(); - return cs.getParentExpr(subExpr); + return cs.getParentExpr(const_cast(subExpr)); } Expr * @@ -132,7 +132,7 @@ FailureDiagnostic::getArgumentListExprFor(ConstraintLocator *locator) const { return simplifyLocatorToAnchor(argListLoc); } -Expr *FailureDiagnostic::getBaseExprFor(Expr *anchor) const { +Expr *FailureDiagnostic::getBaseExprFor(const Expr *anchor) const { if (!anchor) return nullptr; @@ -178,7 +178,7 @@ Type RequirementFailure::getOwnerType() const { // to convert source to destination, which means that // owner type is actually not an assignment expression // itself but its source. - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *assignment = dyn_cast(E)) anchor = assignment->getSrc(); } @@ -429,7 +429,7 @@ bool MissingConformanceFailure::diagnoseAsError() { // with it and if so skip conformance error, otherwise we'd // produce an unrelated ` doesn't conform to Equatable protocol` // diagnostic. - if (isPatternMatchingOperator(anchor)) { + if (isPatternMatchingOperator(const_cast(anchor))) { if (auto *binaryOp = dyn_cast_or_null(findParentExpr(anchor))) { auto *caseExpr = binaryOp->getArg()->getElement(0); @@ -888,7 +888,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { TypedNode MissingForcedDowncastFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *assignExpr = dyn_cast(E)) return assignExpr->getSrc(); } @@ -923,7 +923,7 @@ bool MissingAddressOfFailure::diagnoseAsError() { TypedNode MissingExplicitConversionFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *assign = dyn_cast(E)) return assign->getSrc(); @@ -950,7 +950,7 @@ bool MissingExplicitConversionFailure::diagnoseAsError() { auto *expr = findParentExpr(anchor); if (!expr) - expr = anchor; + expr = const_cast(anchor); // If we're performing pattern matching, // "as" means something completely different... @@ -1028,7 +1028,7 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() { } void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( - DeclContext *DC, Expr *expr) const { + DeclContext *DC, const Expr *expr) const { assert(expr); auto *anchor = getAnchor().get(); @@ -1046,10 +1046,10 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( // Figure out what we need to parenthesize. bool needsParensInside = - exprNeedsParensBeforeAddingNilCoalescing(DC, expr); + exprNeedsParensBeforeAddingNilCoalescing(DC, const_cast(expr)); auto parentExpr = findParentExpr(anchor); - bool needsParensOutside = - exprNeedsParensAfterAddingNilCoalescing(DC, expr, parentExpr); + bool needsParensOutside = exprNeedsParensAfterAddingNilCoalescing( + DC, const_cast(expr), parentExpr); llvm::SmallString<2> insertBefore; llvm::SmallString<32> insertAfter; @@ -1071,7 +1071,8 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( } // Suggest a force-unwrap. -void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt(Expr *expr) const { +void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt( + const Expr *expr) const { auto diag = emitDiagnosticAt(expr->getLoc(), diag::unwrap_with_force_value); // If expr is optional as the result of an optional chain and this last @@ -1227,7 +1228,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { bool RValueTreatedAsLValueFailure::diagnoseAsError() { Diag subElementDiagID; Diag rvalueDiagID = diag::assignment_lhs_not_lvalue; - Expr *diagExpr = getRawAnchor().get(); + auto *diagExpr = getRawAnchor().get(); SourceLoc loc = diagExpr->getLoc(); // Assignment is not allowed inside of a condition, @@ -1481,7 +1482,8 @@ bool TrailingClosureAmbiguityFailure::diagnoseAsNote() { return true; } -AssignmentFailure::AssignmentFailure(Expr *destExpr, const Solution &solution, +AssignmentFailure::AssignmentFailure(const Expr *destExpr, + const Solution &solution, SourceLoc diagnosticLoc) : FailureDiagnostic(solution, destExpr), DestExpr(destExpr), Loc(diagnosticLoc), @@ -1880,7 +1882,7 @@ AssignmentFailure::getMemberRef(ConstraintLocator *locator) const { } Diag AssignmentFailure::findDeclDiagonstic(ASTContext &ctx, - Expr *destExpr) { + const Expr *destExpr) { if (isa(destExpr) || isa(destExpr)) return diag::assignment_lhs_is_apply_expression; @@ -1965,8 +1967,8 @@ bool ContextualFailure::diagnoseAsError() { case ConstraintLocator::ClosureResult: { auto *closure = cast(getRawAnchor().get()); if (closure->hasExplicitResultType() && - closure->getExplicitResultTypeLoc().getTypeRepr()) { - auto resultRepr = closure->getExplicitResultTypeLoc().getTypeRepr(); + closure->getExplicitResultTypeRepr()) { + auto resultRepr = closure->getExplicitResultTypeRepr(); emitDiagnosticAt(resultRepr->getStartLoc(), diag::incorrect_explicit_closure_result, fromType, toType) @@ -2347,10 +2349,9 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const { bool ContextualFailure::diagnoseCoercionToUnrelatedType() const { auto *anchor = getAnchor().get(); - if (auto *coerceExpr = dyn_cast(anchor)) { + if (auto *coerceExpr = dyn_cast(const_cast(anchor))) { auto fromType = getType(coerceExpr->getSubExpr()); - const auto &typeLoc = coerceExpr->getCastTypeLoc(); - auto toType = getType(&typeLoc); + auto toType = getType(&coerceExpr->getCastTypeLoc()); auto diagnostic = getDiagnosticFor(CTP_CoerceOperand, toType); @@ -2655,7 +2656,7 @@ bool ContextualFailure::tryIntegerCastFixIts( if (!isIntegerType(fromType) || !isIntegerType(toType)) return false; - auto getInnerCastedExpr = [&](Expr *expr) -> Expr * { + auto getInnerCastedExpr = [&](const Expr *expr) -> Expr * { if (auto *CE = dyn_cast(expr)) return CE->getSubExpr(); @@ -3011,16 +3012,10 @@ bool FunctionTypeMismatch::diagnoseAsError() { } bool AutoClosureForwardingFailure::diagnoseAsError() { - auto *loc = getLocator(); - auto last = loc->castLastElementTo(); - - // We need a raw anchor here because `getAnchor()` is simplified - // to the argument expression. - auto *argExpr = - getArgumentExpr(getRawAnchor().get(), last.getArgIdx()); - emitDiagnosticAt(argExpr->getLoc(), diag::invalid_autoclosure_forwarding) - .highlight(argExpr->getSourceRange()) - .fixItInsertAfter(argExpr->getEndLoc(), "()"); + auto argRange = getSourceRange(); + emitDiagnostic(diag::invalid_autoclosure_forwarding) + .highlight(argRange) + .fixItInsertAfter(argRange.End, "()"); return true; } @@ -3046,7 +3041,7 @@ bool NonOptionalUnwrapFailure::diagnoseAsError() { TypedNode MissingCallFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *FVE = dyn_cast(E)) return FVE->getSubExpr(); } @@ -3272,7 +3267,7 @@ bool MissingMemberFailure::diagnoseAsError() { diagnostic = diag::could_not_find_tuple_member; bool hasUnresolvedPattern = false; - anchor->forEachChildExpr([&](Expr *expr) { + const_cast(anchor)->forEachChildExpr([&](Expr *expr) { hasUnresolvedPattern |= isa(expr); return hasUnresolvedPattern ? nullptr : expr; }); @@ -3436,8 +3431,8 @@ bool MissingMemberFailure::diagnoseForDynamicCallable() const { bool InvalidMemberRefOnExistential::diagnoseAsError() { auto *anchor = getRawAnchor().get(); + auto *baseExpr = getAnchor().get(); - Expr *baseExpr = getAnchor().get(); DeclNameLoc nameLoc; if (auto *UDE = dyn_cast(anchor)) { baseExpr = UDE->getBase(); @@ -3467,10 +3462,11 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return true; } - auto getRootExpr = [&cs](Expr *expr) { - while (auto parent = cs.getParentExpr(expr)) - expr = parent; - return expr; + auto getRootExpr = [&cs](const Expr *childExpr) { + auto *currExpr = const_cast(childExpr); + while (auto parent = cs.getParentExpr(currExpr)) + currExpr = parent; + return currExpr; }; Expr *expr = findParentExpr(getAnchor().get()); @@ -3499,7 +3495,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { if (Name.isSimpleName(DeclBaseName::createConstructor()) && !BaseType->is()) { - if (auto ctorRef = + if (auto *ctorRef = dyn_cast(getRawAnchor().get())) { if (isa(ctorRef->getBase())) { emitDiagnostic(diag::super_initializer_not_in_initializer); @@ -3551,8 +3547,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { instanceTy = AMT->getInstanceType(); } - if (getRawAnchor() && - getDC()->getContextKind() == DeclContextKind::Initializer) { + if (getDC()->getContextKind() == DeclContextKind::Initializer) { auto *TypeDC = getDC()->getParent(); bool propertyInitializer = true; // If the parent context is not a type context, we expect it @@ -3772,8 +3767,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } bool PartialApplicationFailure::diagnoseAsError() { - auto &cs = getConstraintSystem(); - auto anchor = cast(getRawAnchor().get()); + auto *anchor = cast(getRawAnchor().get()); RefKind kind = RefKind::MutatingMethod; @@ -3817,7 +3811,7 @@ bool InitOnProtocolMetatypeFailure::diagnoseAsError() { } SourceLoc ImplicitInitOnNonConstMetatypeFailure::getLoc() const { - if (auto *E = getRawAnchor().dyn_cast()) { + if (auto *E = getRawAnchor().dyn_cast()) { if (auto *apply = dyn_cast(E)) return apply->getArg()->getStartLoc(); } @@ -3833,7 +3827,7 @@ bool ImplicitInitOnNonConstMetatypeFailure::diagnoseAsError() { TypedNode MissingArgumentsFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *captureList = dyn_cast(E)) return captureList->getClosureBody(); } @@ -3858,7 +3852,7 @@ bool MissingArgumentsFailure::diagnoseAsError() { auto anchor = getAnchor(); - if (auto *closure = dyn_cast(anchor.dyn_cast())) + if (auto *closure = dyn_cast(anchor.dyn_cast())) return diagnoseClosure(closure); // This is a situation where function type is passed as an argument @@ -3928,8 +3922,9 @@ bool MissingArgumentsFailure::diagnoseAsError() { unsigned numArguments = 0; bool hasTrailingClosure = false; + auto *rawAnchor = getRawAnchor().get(); std::tie(fnExpr, argExpr, numArguments, hasTrailingClosure) = - getCallInfo(getRawAnchor().get()); + getCallInfo(const_cast(rawAnchor)); // TODO(diagnostics): We should be able to suggest this fix-it // unconditionally. @@ -4004,7 +3999,7 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { bool hasTrailingClosure = false; std::tie(fnExpr, argExpr, insertableEndIdx, hasTrailingClosure) = - getCallInfo(anchor); + getCallInfo(const_cast(anchor)); if (!argExpr) return false; @@ -4093,7 +4088,7 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { return true; } -bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) { +bool MissingArgumentsFailure::diagnoseClosure(const ClosureExpr *closure) { FunctionType *funcType = nullptr; auto *locator = getLocator(); @@ -4579,9 +4574,9 @@ bool OutOfOrderArgumentFailure::diagnoseAsError() { bool ExtraneousArgumentsFailure::diagnoseAsError() { // Simplified anchor would point directly to the // argument in case of contextual mismatch. - auto *anchor = getAnchor(); + auto anchor = getAnchor(); - if (auto *closure = dyn_cast(anchor.dyn_cast()) { + if (auto *closure = dyn_cast(anchor.dyn_cast())) { auto fnType = ContextualType; auto params = closure->getParameters(); @@ -4775,7 +4770,7 @@ bool InaccessibleMemberFailure::diagnoseAsError() { SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *KPE = dyn_cast(E)) { if (auto rootTyRepr = KPE->getRootType()) return rootTyRepr->getLoc(); @@ -4788,7 +4783,7 @@ SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { SourceRange AnyObjectKeyPathRootFailure::getSourceRange() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *KPE = dyn_cast(E)) { if (auto rootTyRepr = KPE->getRootType()) return rootTyRepr->getSourceRange(); @@ -4826,7 +4821,7 @@ bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() { SourceLoc InvalidMemberRefInKeyPath::getLoc() const { auto anchor = getRawAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *KPE = dyn_cast(E)) { auto *locator = getLocator(); auto component = locator->findFirst(); @@ -4859,7 +4854,7 @@ bool InvalidMethodRefInKeyPath::diagnoseAsError() { SourceLoc InvalidUseOfAddressOf::getLoc() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { + if (auto *E = anchor.dyn_cast()) { if (auto *assign = dyn_cast(E)) return assign->getSrc()->getLoc(); } @@ -4938,7 +4933,7 @@ bool CollectionElementContextualFailure::diagnoseAsError() { // If this is a conversion failure related to binding of `for-each` // statement it has to be diagnosed as pattern match if there are // holes present in the contextual type. - if (getContextualTypePurpose(getAnchor()) == + if (FailureDiagnostic::getContextualTypePurpose(getAnchor()) == ContextualTypePurpose::CTP_ForEachStmt && contextualType->hasHole()) { diagnostic.emplace(emitDiagnostic( @@ -5071,8 +5066,8 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( Anchor anchor, GenericTypeParamType *GP) const { auto &cs = getConstraintSystem(); - auto loc = anchor.is() ? anchor.get()->getLoc() - : anchor.get()->getLoc(); + auto loc = anchor.is() ? anchor.get()->getLoc() + : anchor.get()->getLoc(); auto *locator = getLocator(); // Type variables associated with missing generic parameters are @@ -5086,10 +5081,9 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( return false; } - if (auto *CE = - dyn_cast(getRawAnchor().get())) { - const auto &typeLoc = CE->getCastTypeLoc(); - auto castTo = getType(&typeLoc); + auto *rawAnchor = getRawAnchor().get(); + if (auto *CE = dyn_cast(const_cast(rawAnchor))) { + auto castTo = getType(&CE->getCastTypeLoc()); auto *NTD = castTo->getAnyNominal(); emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP, NTD ? NTD->getDeclaredType() : castTo); @@ -5128,7 +5122,7 @@ void MissingGenericArgumentsFailure::emitGenericSignatureNote( return; auto *GTD = dyn_cast(paramDC); - if (!GTD || anchor.is()) + if (!GTD || anchor.is()) return; auto getParamDecl = @@ -5535,7 +5529,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() { if (getType(argExpr, /*wantRValue=*/false)->is()) { auto elementTy = paramType->getAnyPointerElementType(); if (elementTy && argType->isEqual(elementTy)) { - diag.fixItInsert(argExpr->getStartLoc(), "&"); + diag.fixItInsert(getSourceRange(argExpr).Start, "&"); return true; } } @@ -5742,7 +5736,7 @@ bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const { } void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt( - Expr *anchor) const { + const Expr *anchor) const { // If this is an array literal, offer to remove the brackets and pass the // elements directly as variadic arguments. if (auto *arrayExpr = dyn_cast(anchor)) { @@ -5757,7 +5751,7 @@ void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt( } bool ExpandArrayIntoVarargsFailure::diagnoseAsError() { - if (auto *anchor = getAnchor().dyn_cast()) { + if (auto *anchor = getAnchor().dyn_cast()) { emitDiagnostic(diag::cannot_convert_array_to_variadic, getFromType(), getToType()); tryDropArrayBracketsFixIt(anchor); @@ -5812,7 +5806,8 @@ bool ExtraneousCallFailure::diagnoseAsError() { } } - if (auto *UDE = dyn_cast(anchor.dyn_cast())) { + if (auto *UDE = + dyn_cast(anchor.dyn_cast())) { auto *baseExpr = UDE->getBase(); auto *call = cast(getRawAnchor().get()); @@ -6148,9 +6143,10 @@ bool UnableToInferClosureReturnType::diagnoseAsError() { } static std::pair -getImportModuleAndDefaultType(const ASTContext &ctx, ObjectLiteralExpr *expr) { +getImportModuleAndDefaultType(const ASTContext &ctx, + const ObjectLiteralExpr *expr) { const auto &target = ctx.LangOpts.Target; - + switch (expr->getLiteralKind()) { case ObjectLiteralExpr::colorLiteral: { if (target.isMacOSX()) { @@ -6183,8 +6179,7 @@ SourceLoc UnableToInferProtocolLiteralType::getLoc() const { } bool UnableToInferProtocolLiteralType::diagnoseAsError() { - auto &cs = getConstraintSystem(); - auto &ctx = cs.getASTContext(); + auto &ctx = getASTContext(); auto *expr = cast(getRawAnchor().get()); StringRef importModule; diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index f20059c2c7dce..95f1aaf6d0547 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -45,7 +45,7 @@ class FailureDiagnostic { FailureDiagnostic(const Solution &solution, ConstraintLocator *locator) : S(solution), Locator(locator) {} - FailureDiagnostic(const Solution &solution, Expr *anchor) + FailureDiagnostic(const Solution &solution, const Expr *anchor) : FailureDiagnostic(solution, solution.getConstraintLocator(anchor)) {} virtual ~FailureDiagnostic(); @@ -183,11 +183,11 @@ class FailureDiagnostic { /// \returns A parent expression if sub-expression is contained anywhere /// in the root expression or `nullptr` otherwise. - Expr *findParentExpr(Expr *subExpr) const; + Expr *findParentExpr(const Expr *subExpr) const; /// If given expression is some kind of a member reference e.g. /// `x.foo` or `x[0]` extract and return its base expression. - Expr *getBaseExprFor(Expr *anchor) const; + Expr *getBaseExprFor(const Expr *anchor) const; /// For a given locator describing an argument application, or a constraint /// within an argument application, returns the argument list for that @@ -506,16 +506,16 @@ class TrailingClosureAmbiguityFailure final : public FailureDiagnostic { /// trying to assign something to immutable value, or trying /// to access mutating member on immutable base. class AssignmentFailure final : public FailureDiagnostic { - Expr *DestExpr; + const Expr *DestExpr; SourceLoc Loc; Diag DeclDiagnostic; Diag TypeDiagnostic; public: - AssignmentFailure(Expr *destExpr, const Solution &solution, + AssignmentFailure(const Expr *destExpr, const Solution &solution, SourceLoc diagnosticLoc); - AssignmentFailure(Expr *destExpr, const Solution &solution, + AssignmentFailure(const Expr *destExpr, const Solution &solution, SourceLoc diagnosticLoc, Diag declDiag, Diag typeDiag) : FailureDiagnostic(solution, destExpr), DestExpr(destExpr), @@ -536,7 +536,13 @@ class AssignmentFailure final : public FailureDiagnostic { std::pair> resolveImmutableBase(Expr *expr) const; - static Diag findDeclDiagonstic(ASTContext &ctx, Expr *destExpr); + std::pair> + resolveImmutableBase(const Expr *expr) const { + return resolveImmutableBase(const_cast(expr)); + } + + static Diag findDeclDiagonstic(ASTContext &ctx, + const Expr *destExpr); /// Retrive an member reference associated with given member /// looking through dynamic member lookup on the way. @@ -707,9 +713,9 @@ class MissingOptionalUnwrapFailure final : public ContextualFailure { } /// Suggest a default value via `?? ` - void offerDefaultValueUnwrapFixIt(DeclContext *DC, Expr *expr) const; + void offerDefaultValueUnwrapFixIt(DeclContext *DC, const Expr *expr) const; /// Suggest a force optional unwrap via `!` - void offerForceUnwrapFixIt(Expr *expr) const; + void offerForceUnwrapFixIt(const Expr *expr) const; }; /// Diagnostics for mismatched generic arguments e.g @@ -790,23 +796,25 @@ class MissingExplicitConversionFailure final : public ContextualFailure { bool diagnoseAsError() override; private: - bool exprNeedsParensBeforeAddingAs(Expr *expr) { + bool exprNeedsParensBeforeAddingAs(const Expr *expr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); if (!asPG) return true; - return exprNeedsParensInsideFollowingOperator(DC, expr, asPG); + return exprNeedsParensInsideFollowingOperator(DC, const_cast(expr), + asPG); } - bool exprNeedsParensAfterAddingAs(Expr *expr, Expr *rootExpr) { + bool exprNeedsParensAfterAddingAs(const Expr *expr, const Expr *rootExpr) { auto *DC = getDC(); auto asPG = TypeChecker::lookupPrecedenceGroup( DC, DC->getASTContext().Id_CastingPrecedence, SourceLoc()); if (!asPG) return true; - return exprNeedsParensOutsideFollowingOperator(DC, expr, rootExpr, asPG); + return exprNeedsParensOutsideFollowingOperator( + DC, const_cast(expr), const_cast(rootExpr), asPG); } }; @@ -1244,7 +1252,7 @@ class MissingArgumentsFailure final : public FailureDiagnostic { private: /// If missing arguments come from a closure, /// let's produce tailored diagnostics. - bool diagnoseClosure(ClosureExpr *closure); + bool diagnoseClosure(const ClosureExpr *closure); /// Diagnose cases when instead of multiple distinct arguments /// call got a single tuple argument with expected arity/types. @@ -1625,7 +1633,7 @@ class InOutConversionFailure final : public ContextualFailure { /// _ = S() /// ``` class MissingGenericArgumentsFailure final : public FailureDiagnostic { - using Anchor = llvm::PointerUnion; + using Anchor = llvm::PointerUnion; SmallVector Parameters; @@ -1721,7 +1729,7 @@ class ExpandArrayIntoVarargsFailure final : public ContextualFailure { bool diagnoseAsError() override; bool diagnoseAsNote() override; - void tryDropArrayBracketsFixIt(Expr *anchor) const; + void tryDropArrayBracketsFixIt(const Expr *anchor) const; }; /// Diagnose a situation there is a mismatch between argument and parameter From 4ea7f3bbb1ef544586e2acbf823e162aa75036e0 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 17 Apr 2020 13:15:12 -0700 Subject: [PATCH 7/8] [Diagnostics] Add helper functions to work with anchors - `{castTo, getAs, is}Expr` --- lib/Sema/CSDiagnostics.cpp | 474 ++++++++++++++++++------------------- lib/Sema/CSDiagnostics.h | 15 ++ 2 files changed, 243 insertions(+), 246 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 7d970108e07f6..d016f4041a2d2 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -178,10 +178,8 @@ Type RequirementFailure::getOwnerType() const { // to convert source to destination, which means that // owner type is actually not an assignment expression // itself but its source. - if (auto *E = anchor.dyn_cast()) { - if (auto *assignment = dyn_cast(E)) - anchor = assignment->getSrc(); - } + if (auto *assignment = getAsExpr(anchor)) + anchor = assignment->getSrc(); return getType(anchor)->getInOutObjectType()->getMetatypeInstanceType(); } @@ -523,7 +521,7 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform( bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() { auto anchor = getRawAnchor(); - auto *ODRE = dyn_cast(anchor.get()); + auto *ODRE = getAsExpr(anchor); if (!ODRE) return false; @@ -626,7 +624,7 @@ void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) { } bool GenericArgumentsMismatchFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto path = getLocator()->getPath(); auto fromType = getFromType(); @@ -634,9 +632,9 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { Optional> diagnostic; if (path.empty()) { - if (isa(anchor)) { + if (isExpr(anchor)) { diagnostic = getDiagnosticFor(CTP_AssignSource); - } else if (isa(anchor)) { + } else if (isExpr(anchor)) { diagnostic = getDiagnosticFor(CTP_CoerceOperand); } else { return false; @@ -650,7 +648,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { // If this is call to a closure e.g. `let _: A = { B() }()` // let's point diagnostic to its result. - if (auto *call = dyn_cast(anchor)) { + if (auto *call = getAsExpr(anchor)) { auto *fnExpr = call->getFn(); if (auto *closure = dyn_cast(fnExpr)) { purpose = CTP_ClosureResult; @@ -688,7 +686,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { case ConstraintLocator::OptionalPayload: { // If we have an inout expression, this comes from an // InoutToPointer argument mismatch failure. - if (isa(anchor)) { + if (isExpr(anchor)) { diagnostic = diag::cannot_convert_argument_value; auto applyInfo = getFunctionArgApplyInfo(getLocator()); if (applyInfo) @@ -698,11 +696,11 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { } case ConstraintLocator::TupleElement: { - auto *anchor = getRawAnchor().get(); + auto rawAnchor = getRawAnchor(); - if (isa(anchor)) { + if (isExpr(rawAnchor)) { diagnostic = getDiagnosticFor(CTP_ArrayElement); - } else if (isa(anchor)) { + } else if (isExpr(rawAnchor)) { auto eltLoc = last.castTo(); diagnostic = getDiagnosticFor( eltLoc.getIndex() == 0 ? CTP_DictionaryKey : CTP_DictionaryValue); @@ -717,7 +715,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { if (!diagnostic) { // Handle all mismatches involving an `AssignExpr` - if (auto *assignExpr = dyn_cast(anchor)) { + if (auto *assignExpr = getAsExpr(anchor)) { diagnostic = getDiagnosticFor(CTP_AssignSource); fromType = getType(assignExpr->getSrc()); toType = getType(assignExpr->getDest()); @@ -736,7 +734,7 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { if (!diagnostic) return false; - emitDiagnostic(*diagnostic, fromType, toType); + emitDiagnosticAt(getLoc(anchor), *diagnostic, fromType, toType); emitNotesForMismatches(); return true; } @@ -746,10 +744,8 @@ bool LabelingFailure::diagnoseAsError() { if (!argExpr) return false; - auto &cs = getConstraintSystem(); - auto *anchor = getRawAnchor().get(); - return diagnoseArgumentLabelError(cs.getASTContext(), argExpr, CorrectLabels, - isa(anchor)); + return diagnoseArgumentLabelError(getASTContext(), argExpr, CorrectLabels, + isExpr(getRawAnchor())); } bool LabelingFailure::diagnoseAsNote() { @@ -813,11 +809,11 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { if (!convertTo->is()) return false; - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto diagnostic = diag::general_noescape_to_escaping; ParamDecl *PD = nullptr; - if (auto *DRE = dyn_cast(anchor)) { + if (auto *DRE = getAsExpr(anchor)) { PD = dyn_cast(DRE->getDecl()); // If anchor is not a parameter declaration there @@ -859,8 +855,7 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { // only mean that parameter is expecting @escaping function type. diagnostic = diag::passing_noescape_to_escaping; } - } else if (auto *AE = - dyn_cast(getRawAnchor().get())) { + } else if (auto *AE = getAsExpr(getRawAnchor())) { if (auto *DRE = dyn_cast(AE->getSrc())) { PD = dyn_cast(DRE->getDecl()); diagnostic = diag::assigning_noescape_to_escaping; @@ -887,12 +882,8 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const { TypedNode MissingForcedDowncastFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - - if (auto *E = anchor.dyn_cast()) { - if (auto *assignExpr = dyn_cast(E)) - return assignExpr->getSrc(); - } - + if (auto *assignExpr = getAsExpr(anchor)) + return assignExpr->getSrc(); return anchor; } @@ -923,13 +914,11 @@ bool MissingAddressOfFailure::diagnoseAsError() { TypedNode MissingExplicitConversionFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *assign = dyn_cast(E)) - return assign->getSrc(); + if (auto *assign = getAsExpr(anchor)) + return assign->getSrc(); - if (auto *paren = dyn_cast(E)) - return paren->getSubExpr(); - } + if (auto *paren = getAsExpr(anchor)) + return paren->getSubExpr(); return anchor; } @@ -1031,7 +1020,7 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( DeclContext *DC, const Expr *expr) const { assert(expr); - auto *anchor = getAnchor().get(); + auto *anchor = getAnchor().dyn_cast(); // If anchor is n explicit address-of, or expression which produces // an l-value (e.g. first argument of `+=` operator), let's not // suggest default value here because that would produce r-value type. @@ -1228,7 +1217,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { bool RValueTreatedAsLValueFailure::diagnoseAsError() { Diag subElementDiagID; Diag rvalueDiagID = diag::assignment_lhs_not_lvalue; - auto *diagExpr = getRawAnchor().get(); + auto diagExpr = getRawAnchor().get(); SourceLoc loc = diagExpr->getLoc(); // Assignment is not allowed inside of a condition, @@ -1906,7 +1895,7 @@ Diag AssignmentFailure::findDeclDiagonstic(ASTContext &ctx, } bool ContextualFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto path = getLocator()->getPath(); if (CTP == CTP_ReturnSingleExpr || CTP == CTP_ReturnStmt) { @@ -1922,23 +1911,23 @@ bool ContextualFailure::diagnoseAsError() { return true; if (path.empty()) { - if (auto *KPE = dyn_cast(anchor)) { + if (auto *KPE = getAsExpr(anchor)) { emitDiagnosticAt(KPE->getLoc(), diag::expr_smart_keypath_value_covert_to_contextual_type, getFromType(), getToType()); return true; } - + if (diagnoseCoercionToUnrelatedType()) return true; - if (isa(anchor)) { + if (isExpr(anchor)) { emitDiagnostic(diag::cannot_convert_initializer_value, getFromType(), getToType()); return true; } - if (isa(anchor)) { + if (isExpr(anchor)) { emitDiagnostic(diag::cannot_convert_assign, getFromType(), getToType()); return true; } @@ -1965,7 +1954,7 @@ bool ContextualFailure::diagnoseAsError() { switch (path.back().getKind()) { case ConstraintLocator::ClosureBody: case ConstraintLocator::ClosureResult: { - auto *closure = cast(getRawAnchor().get()); + auto *closure = castToExpr(getRawAnchor()); if (closure->hasExplicitResultType() && closure->getExplicitResultTypeRepr()) { auto resultRepr = closure->getExplicitResultTypeRepr(); @@ -1997,7 +1986,7 @@ bool ContextualFailure::diagnoseAsError() { } case ConstraintLocator::TernaryBranch: { - auto *ifExpr = cast(getRawAnchor().get()); + auto *ifExpr = castToExpr(getRawAnchor()); fromType = getType(ifExpr->getThenExpr()); toType = getType(ifExpr->getElseExpr()); diagnostic = diag::if_expr_cases_mismatch; @@ -2014,7 +2003,8 @@ bool ContextualFailure::diagnoseAsError() { if (diagnoseYieldByReferenceMismatch()) return true; - if (isa(anchor) || isa(anchor)) { + if (isExpr(anchor) || + isExpr(anchor)) { auto objectType = fromType->getOptionalObjectType(); if (objectType->isEqual(toType)) { MissingOptionalUnwrapFailure failure(getSolution(), getType(anchor), @@ -2039,7 +2029,7 @@ bool ContextualFailure::diagnoseAsError() { return true; } - if (auto *call = dyn_cast(anchor)) { + if (auto *call = getAsExpr(anchor)) { if (isa(call->getFn())) CTP = CTP_ClosureResult; } @@ -2175,9 +2165,9 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) { } bool ContextualFailure::diagnoseConversionToNil() const { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); - if (!isa(anchor)) + if (!isExpr(anchor)) return false; auto *locator = getLocator(); @@ -2191,7 +2181,7 @@ bool ContextualFailure::diagnoseConversionToNil() const { // It could be e.g. an argument to a subscript/call, assignment // source like `s[0] = nil` or an array element like `[nil]` or // `[nil: 42]` as a sub-expression to a larger one. - auto *parentExpr = findParentExpr(anchor); + auto *parentExpr = findParentExpr(anchor.dyn_cast()); // Looks like it's something similar to `let _ = nil`. if (!parentExpr) { @@ -2224,8 +2214,9 @@ bool ContextualFailure::diagnoseConversionToNil() const { // out whether nil is a "key" or a "value". if (isa(enclosingExpr)) { assert(TE->getNumElements() == 2); - CTP = TE->getElement(0) == anchor ? CTP_DictionaryKey - : CTP_DictionaryValue; + CTP = TE->getElement(0) == anchor.get() + ? CTP_DictionaryKey + : CTP_DictionaryValue; } else { // Can't initialize one of the tuple elements with `nil`. CTP = CTP_Initialization; @@ -2347,9 +2338,9 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const { } bool ContextualFailure::diagnoseCoercionToUnrelatedType() const { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); - if (auto *coerceExpr = dyn_cast(const_cast(anchor))) { + if (auto *coerceExpr = getAsExpr(anchor)) { auto fromType = getType(coerceExpr->getSubExpr()); auto toType = getType(&coerceExpr->getCastTypeLoc()); @@ -2472,7 +2463,7 @@ bool ContextualFailure::diagnoseThrowsTypeMismatch() const { if (CTP != CTP_ThrowStmt) return false; - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); // If we tried to throw the error code of an error type, suggest object // construction. @@ -2491,7 +2482,7 @@ bool ContextualFailure::diagnoseThrowsTypeMismatch() const { if (errorType) { auto diagnostic = emitDiagnostic(diag::cannot_throw_error_code, errorCodeType, errorType); - if (auto *UDE = dyn_cast(anchor)) { + if (auto *UDE = getAsExpr(anchor)) { diagnostic.fixItInsert(UDE->getDotLoc(), "("); diagnostic.fixItInsertAfter(UDE->getEndLoc(), ")"); } @@ -2532,7 +2523,7 @@ bool ContextualFailure::tryRawRepresentableFixIts( InFlightDiagnostic &diagnostic, KnownProtocolKind rawRepresentableProtocol) const { auto &CS = getConstraintSystem(); - auto *expr = getAnchor().get(); + auto anchor = getAnchor(); auto fromType = getFromType(); auto toType = getToType(); @@ -2545,7 +2536,8 @@ bool ContextualFailure::tryRawRepresentableFixIts( if (fromTypeIsOptional) fromType = fromTypeUnwrapped; - auto fixIt = [&](StringRef convWrapBefore, StringRef convWrapAfter) { + auto fixIt = [&](StringRef convWrapBefore, StringRef convWrapAfter, + const Expr *expr) { SourceRange exprRange = expr->getSourceRange(); if (fromTypeIsOptional && toTypeIsOptional) { // Use optional's map function to convert conditionally, like so: @@ -2587,9 +2579,9 @@ bool ContextualFailure::tryRawRepresentableFixIts( if (conformsToKnownProtocol(CS, fromType, rawRepresentableProtocol)) { if (conformsToKnownProtocol(CS, fromType, KnownProtocolKind::OptionSet) && - isa(expr) && - cast(expr)->getDigitsText() == "0") { - diagnostic.fixItReplace(expr->getSourceRange(), "[]"); + isExpr(anchor) && + castToExpr(anchor)->getDigitsText() == "0") { + diagnostic.fixItReplace(getSourceRange(anchor), "[]"); return true; } if (auto rawTy = isRawRepresentable(CS, toType, rawRepresentableProtocol)) { @@ -2598,7 +2590,7 @@ bool ContextualFailure::tryRawRepresentableFixIts( std::string convWrapBefore = toType.getString(); convWrapBefore += "(rawValue: "; std::string convWrapAfter = ")"; - if (!isa(expr) && + if (!isExpr(anchor) && !TypeChecker::isConvertibleTo(fromType, rawTy, getDC())) { // Only try to insert a converting construction if the protocol is a // literal protocol and not some other known protocol. @@ -2615,7 +2607,9 @@ bool ContextualFailure::tryRawRepresentableFixIts( convWrapBefore += "("; convWrapAfter += ")"; } - fixIt(convWrapBefore, convWrapAfter); + + if (auto *E = anchor.dyn_cast()) + fixIt(convWrapBefore, convWrapAfter, E); return true; } } @@ -2640,7 +2634,9 @@ bool ContextualFailure::tryRawRepresentableFixIts( convWrapBefore += "("; convWrapAfter += ")"; } - fixIt(convWrapBefore, convWrapAfter); + + if (auto *E = anchor.dyn_cast()) + fixIt(convWrapBefore, convWrapAfter, E); return true; } } @@ -2671,14 +2667,15 @@ bool ContextualFailure::tryIntegerCastFixIts( return parenE->getSubExpr(); }; - auto *anchor = getAnchor().get(); - if (Expr *innerE = getInnerCastedExpr(anchor)) { - Type innerTy = getType(innerE); - if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) { - // Remove the unnecessary cast. - diagnostic.fixItRemoveChars(getLoc(), innerE->getStartLoc()) - .fixItRemove(getSourceRange().End); - return true; + if (auto *anchor = getAnchor().dyn_cast()) { + if (Expr *innerE = getInnerCastedExpr(anchor)) { + Type innerTy = getType(innerE); + if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) { + // Remove the unnecessary cast. + diagnostic.fixItRemoveChars(getLoc(), innerE->getStartLoc()) + .fixItRemove(getSourceRange().End); + return true; + } } } @@ -2707,7 +2704,7 @@ bool ContextualFailure::trySequenceSubsequenceFixIts( // Wrap in String.init if (getFromType()->isEqual(Substring)) { if (getToType()->isEqual(String)) { - auto *anchor = + auto anchor = getAnchor().get()->getSemanticsProvidingExpr(); if (auto *CE = dyn_cast(anchor)) { anchor = CE->getSubExpr(); @@ -2851,7 +2848,7 @@ bool ContextualFailure::tryProtocolConformanceFixIt( } void ContextualFailure::tryComputedPropertyFixIts() const { - if (!isa(getAnchor().get())) + if (!isExpr(getAnchor())) return; // It is possible that we're looking at a stored property being @@ -3027,10 +3024,10 @@ bool AutoClosurePointerConversionFailure::diagnoseAsError() { } bool NonOptionalUnwrapFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto diagnostic = diag::invalid_optional_chain; - if (isa(anchor)) + if (isExpr(anchor)) diagnostic = diag::invalid_force_unwrap; auto range = getSourceRange(); @@ -3041,22 +3038,21 @@ bool NonOptionalUnwrapFailure::diagnoseAsError() { TypedNode MissingCallFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *FVE = dyn_cast(E)) - return FVE->getSubExpr(); - } + if (auto *FVE = getAsExpr(anchor)) + return FVE->getSubExpr(); + return anchor; } bool MissingCallFailure::diagnoseAsError() { - auto *baseExpr = getAnchor().get(); - SourceLoc insertLoc = baseExpr->getEndLoc(); + auto anchor = getAnchor(); + SourceLoc insertLoc = getSourceRange(anchor).End; // Calls are not yet supported by key path, but it // is useful to record this fix to diagnose chaining // where one of the key path components is a method // reference. - if (isa(baseExpr)) + if (isExpr(anchor)) return false; auto path = getLocator()->getPath(); @@ -3066,7 +3062,7 @@ bool MissingCallFailure::diagnoseAsError() { switch (last.getKind()) { case ConstraintLocator::ContextualType: case ConstraintLocator::ApplyArgToParam: { - auto fnType = getType(baseExpr)->castTo(); + auto fnType = getType(anchor)->castTo(); emitDiagnostic(diag::missing_nullary_call, fnType->getResult()) .fixItInsertAfter(getSourceRange().End, "()"); return true; @@ -3090,21 +3086,21 @@ bool MissingCallFailure::diagnoseAsError() { } } - if (auto *DRE = dyn_cast(baseExpr)) { + if (auto *DRE = getAsExpr(anchor)) { emitDiagnostic(diag::did_not_call_function, DRE->getDecl()->getBaseIdentifier()) .fixItInsertAfter(insertLoc, "()"); return true; } - if (auto *UDE = dyn_cast(baseExpr)) { + if (auto *UDE = getAsExpr(anchor)) { emitDiagnostic(diag::did_not_call_method, UDE->getName().getBaseIdentifier()) .fixItInsertAfter(insertLoc, "()"); return true; } - if (auto *DSCE = dyn_cast(baseExpr)) { + if (auto *DSCE = getAsExpr(anchor)) { if (auto *DRE = dyn_cast(DSCE->getFn())) { emitDiagnostic(diag::did_not_call_method, DRE->getDecl()->getBaseIdentifier()) @@ -3113,7 +3109,7 @@ bool MissingCallFailure::diagnoseAsError() { } } - if (auto *AE = dyn_cast(baseExpr)) { + if (auto *AE = getAsExpr(anchor)) { auto *srcExpr = AE->getSrc(); if (auto *fnType = getType(srcExpr)->getAs()) { emitDiagnosticAt(srcExpr->getLoc(), diag::missing_nullary_call, @@ -3166,9 +3162,7 @@ bool MissingPropertyWrapperUnwrapFailure::diagnoseAsError() { bool SubscriptMisuseFailure::diagnoseAsError() { auto &sourceMgr = getASTContext().SourceMgr; - auto *memberExpr = - cast(getRawAnchor().get()); - auto *baseExpr = getAnchor().get(); + auto *memberExpr = castToExpr(getRawAnchor()); auto memberRange = getSourceRange(); (void)simplifyLocator(getConstraintSystem(), getLocator(), memberRange); @@ -3176,7 +3170,7 @@ bool SubscriptMisuseFailure::diagnoseAsError() { auto nameLoc = DeclNameLoc(memberRange.Start); auto diag = emitDiagnostic(diag::could_not_find_subscript_member_did_you_mean, - getType(baseExpr)); + getType(getAnchor())); diag.highlight(memberRange).highlight(nameLoc.getSourceRange()); @@ -3237,21 +3231,18 @@ DeclName MissingMemberFailure::findCorrectEnumCaseName( } bool MissingMemberFailure::diagnoseAsError() { - auto *anchor = getRawAnchor().get(); - auto *baseExpr = getAnchor().get(); - - if (!anchor || !baseExpr) - return false; + auto anchor = getRawAnchor(); + auto memberBase = getAnchor(); if (diagnoseForDynamicCallable()) return true; auto baseType = resolveType(getBaseType())->getWithoutSpecifierType(); - DeclNameLoc nameLoc(anchor->getStartLoc()); - if (auto *UDE = dyn_cast(anchor)) { + DeclNameLoc nameLoc(FailureDiagnostic::getLoc(anchor)); + if (auto *UDE = getAsExpr(anchor)) { nameLoc = UDE->getNameLoc(); - } else if (auto *UME = dyn_cast(anchor)) { + } else if (auto *UME = getAsExpr(anchor)) { nameLoc = UME->getNameLoc(); } @@ -3267,10 +3258,13 @@ bool MissingMemberFailure::diagnoseAsError() { diagnostic = diag::could_not_find_tuple_member; bool hasUnresolvedPattern = false; - const_cast(anchor)->forEachChildExpr([&](Expr *expr) { - hasUnresolvedPattern |= isa(expr); - return hasUnresolvedPattern ? nullptr : expr; - }); + if (auto *E = anchor.dyn_cast()) { + const_cast(E)->forEachChildExpr([&](Expr *expr) { + hasUnresolvedPattern |= isa(expr); + return hasUnresolvedPattern ? nullptr : expr; + }); + } + if (hasUnresolvedPattern && !baseType->getAs()) { emitDiagnostic(diag::cannot_match_unresolved_expr_pattern_with_value, baseType); @@ -3343,7 +3337,8 @@ bool MissingMemberFailure::diagnoseAsError() { emitBasicError(baseType); } } else if (auto moduleTy = baseType->getAs()) { - emitDiagnosticAt(baseExpr->getLoc(), diag::no_member_of_module, + emitDiagnosticAt(FailureDiagnostic::getLoc(memberBase), + diag::no_member_of_module, moduleTy->getModule()->getName(), getName()) .highlight(getSourceRange()) .highlight(nameLoc.getSourceRange()); @@ -3373,13 +3368,13 @@ bool MissingMemberFailure::diagnoseAsError() { // If locator points to the member found via key path dynamic member lookup, // we provide a custom diagnostic and emit typo corrections for the wrapper type too. if (getLocator()->isForKeyPathDynamicMemberLookup()) { - auto baseExprType = getType(baseExpr)->getWithoutSpecifierType(); - - tryTypoCorrection(baseExprType); - + auto memberBaseType = getType(memberBase)->getWithoutSpecifierType(); + + tryTypoCorrection(memberBaseType); + if (auto correction = corrections.claimUniqueCorrection()) { auto diagnostic = emitDiagnostic( - diag::could_not_find_value_dynamic_member_corrected, baseExprType, + diag::could_not_find_value_dynamic_member_corrected, memberBaseType, baseType, getName(), correction->CorrectedName); diagnostic.highlight(getSourceRange()) .highlight(nameLoc.getSourceRange()); @@ -3387,7 +3382,7 @@ bool MissingMemberFailure::diagnoseAsError() { } else { auto diagnostic = emitDiagnostic(diag::could_not_find_value_dynamic_member, - baseExprType, baseType, getName()); + memberBaseType, baseType, getName()); diagnostic.highlight(getSourceRange()) .highlight(nameLoc.getSourceRange()); } @@ -3430,19 +3425,13 @@ bool MissingMemberFailure::diagnoseForDynamicCallable() const { } bool InvalidMemberRefOnExistential::diagnoseAsError() { - auto *anchor = getRawAnchor().get(); - auto *baseExpr = getAnchor().get(); + auto anchor = getRawAnchor(); DeclNameLoc nameLoc; - if (auto *UDE = dyn_cast(anchor)) { - baseExpr = UDE->getBase(); + if (auto *UDE = getAsExpr(anchor)) { nameLoc = UDE->getNameLoc(); - } else if (auto *UME = dyn_cast(anchor)) { + } else if (auto *UME = getAsExpr(anchor)) { nameLoc = UME->getNameLoc(); - } else if (auto *SE = dyn_cast(anchor)) { - baseExpr = SE->getBase(); - } else if (auto *call = dyn_cast(anchor)) { - baseExpr = call->getFn(); } emitDiagnostic(diag::could_not_use_member_on_existential, getBaseType(), @@ -3454,7 +3443,6 @@ bool InvalidMemberRefOnExistential::diagnoseAsError() { bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { auto loc = getLoc(); - auto &cs = getConstraintSystem(); auto *DC = getDC(); auto locator = getLocator(); @@ -3462,14 +3450,19 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return true; } - auto getRootExpr = [&cs](const Expr *childExpr) { + auto getRootExpr = [this](const Expr *childExpr) { auto *currExpr = const_cast(childExpr); - while (auto parent = cs.getParentExpr(currExpr)) + while (auto parent = findParentExpr(currExpr)) currExpr = parent; return currExpr; }; - Expr *expr = findParentExpr(getAnchor().get()); + auto anchor = getAnchor(); + + if (!anchor.is()) + return false; + + Expr *expr = findParentExpr(anchor.get()); SourceRange baseRange = expr ? expr->getSourceRange() : SourceRange(); // If the base is an implicit self type reference, and we're in a @@ -3495,8 +3488,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { if (Name.isSimpleName(DeclBaseName::createConstructor()) && !BaseType->is()) { - if (auto *ctorRef = - dyn_cast(getRawAnchor().get())) { + if (auto *ctorRef = getAsExpr(getRawAnchor())) { if (isa(ctorRef->getBase())) { emitDiagnostic(diag::super_initializer_not_in_initializer); return true; @@ -3547,8 +3539,9 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { instanceTy = AMT->getInstanceType(); } - if (getDC()->getContextKind() == DeclContextKind::Initializer) { - auto *TypeDC = getDC()->getParent(); + auto *DC = getDC(); + if (DC->getContextKind() == DeclContextKind::Initializer) { + auto *TypeDC = DC->getParent(); bool propertyInitializer = true; // If the parent context is not a type context, we expect it // to be a defaulted parameter in a function declaration. @@ -3573,22 +3566,22 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } } - auto maybeCallExpr = getRawAnchor().get(); - - if (auto UDE = dyn_cast(maybeCallExpr)) { - maybeCallExpr = UDE->getBase(); - } + if (auto *maybeCallExpr = getRawAnchor().dyn_cast()) { + if (auto *UDE = dyn_cast(maybeCallExpr)) { + maybeCallExpr = UDE->getBase(); + } - if (auto callExpr = dyn_cast(maybeCallExpr)) { - auto fnExpr = callExpr->getFn(); - auto fnType = cs.getType(fnExpr)->getRValueType(); - auto arg = callExpr->getArg(); + if (auto callExpr = dyn_cast(maybeCallExpr)) { + auto fnExpr = callExpr->getFn(); + auto fnType = getType(fnExpr)->getRValueType(); + auto arg = callExpr->getArg(); - if (fnType->is()) { - emitDiagnosticAt(arg->getStartLoc(), - diag::missing_init_on_metatype_initialization) - .highlight(fnExpr->getSourceRange()); - return true; + if (fnType->is()) { + emitDiagnosticAt(arg->getStartLoc(), + diag::missing_init_on_metatype_initialization) + .highlight(fnExpr->getSourceRange()); + return true; + } } } @@ -3596,8 +3589,8 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // provide more specialized message. auto memberTypeContext = Member->getDeclContext()->getInnermostTypeContext(); - auto currentTypeContext = cs.DC->getInnermostTypeContext(); - + auto currentTypeContext = getDC()->getInnermostTypeContext(); + if (memberTypeContext && currentTypeContext && memberTypeContext->getSemanticDepth() < currentTypeContext->getSemanticDepth()) { @@ -3609,8 +3602,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { return true; } - if (auto *UDE = - dyn_cast(getRawAnchor().get())) { + if (auto *UDE = getAsExpr(getRawAnchor())) { auto *baseExpr = UDE->getBase(); if (isa(baseExpr)) { emitDiagnostic(diag::instance_member_use_on_type, instanceTy, Name) @@ -3664,7 +3656,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { Diag->highlight(baseRange).highlight(getSourceRange()); // See through function decl context - if (auto parent = cs.DC->getInnermostTypeContext()) { + if (auto parent = getDC()->getInnermostTypeContext()) { // If we are in a protocol extension of 'Proto' and we see // 'Proto.static', suggest 'Self.static' if (auto extensionContext = parent->getExtendedProtocolDecl()) { @@ -3698,8 +3690,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { if (Name.isSimpleName(DeclBaseName::createConstructor()) && !baseTy->is()) { - if (auto ctorRef = - dyn_cast(getRawAnchor().get())) { + if (auto ctorRef = getAsExpr(getRawAnchor())) { SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange(); Diag->fixItInsert(fixItRng.Start, "type(of: "); Diag->fixItInsertAfter(fixItRng.End, ")"); @@ -3718,7 +3709,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // Check if the expression is the matching operator ~=, most often used in // case statements. If so, try to provide a single dot fix-it const Expr *contextualTypeNode = - getRootExpr(getAnchor().get()); + getRootExpr(getAnchor().dyn_cast()); // The '~=' operator is an overloaded decl ref inside a binaryExpr if (auto binaryExpr = dyn_cast(contextualTypeNode)) { @@ -3745,10 +3736,9 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { // Fall back to a fix-it with a full type qualifier const Expr *baseExpr = nullptr; - auto *rawAnchor = getRawAnchor().get(); - if (const auto SE = dyn_cast(rawAnchor)) + if (const auto *SE = getAsExpr(getRawAnchor())) baseExpr = SE->getBase(); - else if (const auto UDE = dyn_cast(rawAnchor)) + else if (const auto UDE = getAsExpr(getRawAnchor())) baseExpr = UDE->getBase(); // An implicit 'self' reference base expression means we should @@ -3767,7 +3757,7 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() { } bool PartialApplicationFailure::diagnoseAsError() { - auto *anchor = cast(getRawAnchor().get()); + auto *anchor = castToExpr(getRawAnchor()); RefKind kind = RefKind::MutatingMethod; @@ -3811,10 +3801,9 @@ bool InitOnProtocolMetatypeFailure::diagnoseAsError() { } SourceLoc ImplicitInitOnNonConstMetatypeFailure::getLoc() const { - if (auto *E = getRawAnchor().dyn_cast()) { - if (auto *apply = dyn_cast(E)) - return apply->getArg()->getStartLoc(); - } + if (auto *apply = getAsExpr(getRawAnchor())) + return apply->getArg()->getStartLoc(); + return FailureDiagnostic::getLoc(); } @@ -3827,10 +3816,8 @@ bool ImplicitInitOnNonConstMetatypeFailure::diagnoseAsError() { TypedNode MissingArgumentsFailure::getAnchor() const { auto anchor = FailureDiagnostic::getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *captureList = dyn_cast(E)) - return captureList->getClosureBody(); - } + if (auto *captureList = getAsExpr(anchor)) + return captureList->getClosureBody(); return anchor; } @@ -3852,7 +3839,7 @@ bool MissingArgumentsFailure::diagnoseAsError() { auto anchor = getAnchor(); - if (auto *closure = dyn_cast(anchor.dyn_cast())) + if (auto *closure = getAsExpr(anchor)) return diagnoseClosure(closure); // This is a situation where function type is passed as an argument @@ -3973,9 +3960,10 @@ bool MissingArgumentsFailure::diagnoseAsNote() { bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { auto &ctx = getASTContext(); - auto *anchor = getRawAnchor().get(); - if (!(isa(anchor) || isa(anchor) || - isa(anchor) || isa(anchor))) + auto anchor = getRawAnchor(); + if (!(isExpr(anchor) || isExpr(anchor) || + isExpr(anchor) || + isExpr(anchor))) return false; if (SynthesizedArgs.size() != 1) @@ -3999,7 +3987,7 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { bool hasTrailingClosure = false; std::tie(fnExpr, argExpr, insertableEndIdx, hasTrailingClosure) = - getCallInfo(const_cast(anchor)); + getCallInfo(const_cast(anchor.get())); if (!argExpr) return false; @@ -4053,7 +4041,7 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { // fn { closure }: // fn[(argMissing)] { closure } // fn[(closureLabel:] { closure }[, missingArg)] // Not impl. - assert(!isa(anchor) && "bracket less subscript"); + assert(!isExpr(anchor) && "bracket less subscript"); assert(PE->hasTrailingClosure() && "paren less ParenExpr without trailing closure"); insertBuf.insert(insertBuf.begin(), '('); @@ -4185,15 +4173,15 @@ bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const { if (SynthesizedArgs.size() < 2) return false; - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); Expr *argExpr = nullptr; // Something like `foo(x: (1, 2))` - if (auto *TE = dyn_cast(anchor)) { + if (auto *TE = getAsExpr(anchor)) { if (TE->getNumElements() == 1) argExpr = TE->getElement(0); } else { // or `foo((1, 2))` - argExpr = cast(anchor)->getSubExpr(); + argExpr = castToExpr(anchor)->getSubExpr(); } if (!(argExpr && getType(argExpr)->getRValueType()->is())) @@ -4226,7 +4214,7 @@ bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const { } bool MissingArgumentsFailure::isPropertyWrapperInitialization() const { - auto *call = dyn_cast(getRawAnchor().get()); + auto *call = getAsExpr(getRawAnchor()); if (!(call && call->isImplicit())) return false; @@ -4342,19 +4330,19 @@ void MissingArgumentsFailure::forFixIt( } SourceLoc ClosureParamDestructuringFailure::getLoc() const { - auto *closure = cast(getAnchor().get()); + auto *closure = castToExpr(getAnchor()); auto paramList = closure->getParameters(); return paramList->getStartLoc(); } SourceRange ClosureParamDestructuringFailure::getSourceRange() const { - auto *closure = cast(getAnchor().get()); + auto *closure = castToExpr(getAnchor()); auto paramList = closure->getParameters(); return paramList->getSourceRange(); } bool ClosureParamDestructuringFailure::diagnoseAsError() { - auto *closure = cast(getAnchor().get()); + auto *closure = castToExpr(getAnchor()); auto params = closure->getParameters(); // In case of implicit parameters e.g. $0, $1 we @@ -4484,9 +4472,10 @@ bool ClosureParamDestructuringFailure::diagnoseAsError() { } bool OutOfOrderArgumentFailure::diagnoseAsError() { - auto *anchor = getRawAnchor().get(); - auto *argExpr = isa(anchor) ? anchor - : getArgumentListExprFor(getLocator()); + auto anchor = getRawAnchor(); + auto *argExpr = isExpr(anchor) + ? castToExpr(anchor) + : getArgumentListExprFor(getLocator()); if (!argExpr) return false; @@ -4545,17 +4534,18 @@ bool OutOfOrderArgumentFailure::diagnoseAsError() { firstRange.End); diag.fixItRemove(removalRange); diag.fixItInsert(secondRange.Start, - text.str() + (isa(anchor) ? "" : ", ")); + text.str() + (isExpr(anchor) ? "" : ", ")); }; // There are 4 diagnostic messages variations depending on // labeled/unlabeled arguments. if (first.empty() && second.empty()) { - addFixIts(emitDiagnosticAt( - diagLoc, - isa(anchor) ? diag::argument_out_of_order_binary_op - : diag::argument_out_of_order_unnamed_unnamed, - ArgIdx + 1, PrevArgIdx + 1)); + addFixIts( + emitDiagnosticAt(diagLoc, + isExpr(anchor) + ? diag::argument_out_of_order_binary_op + : diag::argument_out_of_order_unnamed_unnamed, + ArgIdx + 1, PrevArgIdx + 1)); } else if (first.empty() && !second.empty()) { addFixIts(emitDiagnosticAt(diagLoc, diag::argument_out_of_order_unnamed_named, @@ -4576,7 +4566,7 @@ bool ExtraneousArgumentsFailure::diagnoseAsError() { // argument in case of contextual mismatch. auto anchor = getAnchor(); - if (auto *closure = dyn_cast(anchor.dyn_cast())) { + if (auto *closure = getAsExpr(anchor)) { auto fnType = ContextualType; auto params = closure->getParameters(); @@ -4653,11 +4643,10 @@ bool ExtraneousArgumentsFailure::diagnoseAsNote() { return false; auto *decl = overload->choice.getDecl(); - auto *anchor = getAnchor().get(); auto numArgs = getTotalNumArguments(); emitDiagnosticAt(decl, diag::candidate_with_extraneous_args, ContextualType, ContextualType->getNumParams(), numArgs, (numArgs == 1), - isa(anchor)); + isExpr(getAnchor())); return true; } @@ -4667,7 +4656,7 @@ bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const { // This specifically handles a case of `Void(...)` which generates // constraints differently from other constructor invocations and // wouldn't have `ApplyArgument` as a last element in the locator. - if (auto *call = dyn_cast(getRawAnchor().get())) { + if (auto *call = getAsExpr(getRawAnchor())) { auto *TE = dyn_cast(call->getFn()); if (TE && getType(TE)->getMetatypeInstanceType()->isVoid()) { emitDiagnosticAt(call->getLoc(), diag::extra_argument_to_nullary_call) @@ -4717,7 +4706,7 @@ bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const { } bool InaccessibleMemberFailure::diagnoseAsError() { - auto *anchor = getRawAnchor().get(); + auto anchor = getRawAnchor(); // Let's try to avoid over-diagnosing chains of inaccessible // members e.g.: // @@ -4733,25 +4722,27 @@ bool InaccessibleMemberFailure::diagnoseAsError() { // sense to diagnose only `B` and consider the rest hidden. Expr *baseExpr = nullptr; DeclNameLoc nameLoc; - if (auto *UDE = dyn_cast(anchor)) { + if (auto *UDE = getAsExpr(anchor)) { baseExpr = UDE->getBase(); nameLoc = UDE->getNameLoc(); - } else if (auto *UME = dyn_cast(anchor)) { + } else if (auto *UME = getAsExpr(anchor)) { nameLoc = UME->getNameLoc(); - } else if (auto *SE = dyn_cast(anchor)) { + } else if (auto *SE = getAsExpr(anchor)) { baseExpr = SE->getBase(); - } else if (auto *call = dyn_cast(anchor)) { + } else if (auto *call = getAsExpr(anchor)) { baseExpr = call->getFn(); } if (baseExpr) { - auto &cs = getConstraintSystem(); auto *locator = getConstraintLocator(baseExpr, ConstraintLocator::Member); - if (cs.hasFixFor(locator)) + const auto &solution = getSolution(); + if (llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) { + return fix->getLocator() == locator; + })) return false; } - auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : anchor->getLoc(); + auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : getLoc(anchor); auto accessLevel = Member->getFormalAccessScope().accessLevelForDiagnostics(); if (auto *CD = dyn_cast(Member)) { emitDiagnosticAt(loc, diag::init_candidate_inaccessible, @@ -4770,11 +4761,9 @@ bool InaccessibleMemberFailure::diagnoseAsError() { SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *KPE = dyn_cast(E)) { - if (auto rootTyRepr = KPE->getRootType()) - return rootTyRepr->getLoc(); - } + if (auto *KPE = getAsExpr(anchor)) { + if (auto rootTyRepr = KPE->getRootType()) + return rootTyRepr->getLoc(); } return FailureDiagnostic::getLoc(anchor); @@ -4783,11 +4772,9 @@ SourceLoc AnyObjectKeyPathRootFailure::getLoc() const { SourceRange AnyObjectKeyPathRootFailure::getSourceRange() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *KPE = dyn_cast(E)) { - if (auto rootTyRepr = KPE->getRootType()) - return rootTyRepr->getSourceRange(); - } + if (auto *KPE = getAsExpr(anchor)) { + if (auto rootTyRepr = KPE->getRootType()) + return rootTyRepr->getSourceRange(); } return FailureDiagnostic::getSourceRange(anchor); @@ -4804,7 +4791,7 @@ SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const { auto *locator = getLocator(); if (locator->isKeyPathSubscriptComponent()) { - auto *KPE = cast(getAnchor().get()); + auto *KPE = castToExpr(getAnchor()); if (auto kpElt = locator->findFirst()) return KPE->getComponents()[kpElt->getIndex()].getLoc(); } @@ -4821,13 +4808,11 @@ bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() { SourceLoc InvalidMemberRefInKeyPath::getLoc() const { auto anchor = getRawAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *KPE = dyn_cast(E)) { - auto *locator = getLocator(); - auto component = locator->findFirst(); - assert(component); - return KPE->getComponents()[component->getIndex()].getLoc(); - } + if (auto *KPE = getAsExpr(anchor)) { + auto *locator = getLocator(); + auto component = locator->findFirst(); + assert(component); + return KPE->getComponents()[component->getIndex()].getLoc(); } return FailureDiagnostic::getLoc(anchor); @@ -4854,10 +4839,8 @@ bool InvalidMethodRefInKeyPath::diagnoseAsError() { SourceLoc InvalidUseOfAddressOf::getLoc() const { auto anchor = getAnchor(); - if (auto *E = anchor.dyn_cast()) { - if (auto *assign = dyn_cast(E)) - return assign->getSrc()->getLoc(); - } + if (auto *assign = getAsExpr(anchor)) + return assign->getSrc()->getLoc(); return FailureDiagnostic::getLoc(anchor); } @@ -4899,19 +4882,19 @@ bool ExtraneousReturnFailure::diagnoseAsError() { } bool CollectionElementContextualFailure::diagnoseAsError() { - auto *anchor = getRawAnchor().get(); + auto anchor = getRawAnchor(); auto *locator = getLocator(); auto eltType = getFromType(); auto contextualType = getToType(); Optional diagnostic; - if (isa(anchor)) { + if (isExpr(anchor)) { diagnostic.emplace(emitDiagnostic(diag::cannot_convert_array_element, eltType, contextualType)); } - if (isa(anchor)) { + if (isExpr(anchor)) { auto eltLoc = locator->castLastElementTo(); switch (eltLoc.getIndex()) { case 0: // key @@ -4958,13 +4941,13 @@ bool CollectionElementContextualFailure::diagnoseAsError() { } bool MissingContextualConformanceFailure::diagnoseAsError() { - auto *anchor = getAnchor().get(); + auto anchor = getAnchor(); auto path = getLocator()->getPath(); Optional> diagnostic; if (path.empty()) { - assert(isa(anchor)); - if (isa(cast(anchor)->getDest())) { + assert(isExpr(anchor)); + if (isa(castToExpr(anchor)->getDest())) { diagnostic = getDiagnosticFor(CTP_SubscriptAssignSource, getToType()); } else { diagnostic = getDiagnosticFor(CTP_AssignSource, getToType()); @@ -4995,7 +4978,7 @@ bool MissingContextualConformanceFailure::diagnoseAsError() { emitDiagnostic(*diagnostic, srcType, dstType); - if (isa(anchor)) + if (isExpr(anchor)) return true; if (srcType->isAny() && dstType->isAnyObject()) { @@ -5081,8 +5064,7 @@ bool MissingGenericArgumentsFailure::diagnoseParameter( return false; } - auto *rawAnchor = getRawAnchor().get(); - if (auto *CE = dyn_cast(const_cast(rawAnchor))) { + if (auto *CE = getAsExpr(getRawAnchor())) { auto castTo = getType(&CE->getCastTypeLoc()); auto *NTD = castTo->getAnyNominal(); emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP, @@ -5179,12 +5161,12 @@ bool MissingGenericArgumentsFailure::findArgumentLocations( llvm::function_ref callback) { using Callback = llvm::function_ref; - auto *anchor = getRawAnchor().get(); + auto anchor = getRawAnchor(); TypeLoc typeLoc; - if (auto *TE = dyn_cast(anchor)) + if (auto *TE = getAsExpr(anchor)) typeLoc = TE->getTypeLoc(); - else if (auto *ECE = dyn_cast(anchor)) + else if (auto *ECE = getAsExpr(anchor)) typeLoc = ECE->getCastTypeLoc(); if (!typeLoc.hasLocation()) @@ -5525,11 +5507,11 @@ bool ArgumentMismatchFailure::diagnoseAsError() { // If argument is an l-value type and parameter is a pointer type, // let's match up its element type to the argument to see whether // it would be appropriate to suggest adding `&`. - auto argExpr = getAnchor(); - if (getType(argExpr, /*wantRValue=*/false)->is()) { + auto argument = getAnchor(); + if (getType(argument, /*wantRValue=*/false)->is()) { auto elementTy = paramType->getAnyPointerElementType(); if (elementTy && argType->isEqual(elementTy)) { - diag.fixItInsert(getSourceRange(argExpr).Start, "&"); + diag.fixItInsert(getSourceRange(argument).Start, "&"); return true; } } @@ -5557,7 +5539,7 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { if (!isArgumentOfReferenceEqualityOperator(locator)) return false; - auto *binaryOp = cast(getRawAnchor().get()); + auto *binaryOp = castToExpr(getRawAnchor()); auto *lhs = binaryOp->getArg()->getElement(0); auto *rhs = binaryOp->getArg()->getElement(1); @@ -5569,7 +5551,8 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const { // If both arguments where incorrect e.g. both are function types, // let's avoid producing a diagnostic second time, because first // one would cover both arguments. - if (getAnchor().get() == rhs && rhsType->is()) { + if (getAnchor().dyn_cast() == rhs && + rhsType->is()) { auto &cs = getConstraintSystem(); if (cs.hasFixFor(getConstraintLocator( binaryOp, {ConstraintLocator::ApplyArgument, @@ -5621,7 +5604,7 @@ bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const { if (!isArgumentOfPatternMatchingOperator(getLocator())) return false; - auto *op = cast(getRawAnchor().get()); + auto *op = castToExpr(getRawAnchor()); auto *lhsExpr = op->getArg()->getElement(0); auto *rhsExpr = op->getArg()->getElement(1); @@ -5716,7 +5699,7 @@ bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const { // Verify that this is an implicit call to a property wrapper initializer // in a form of `init(wrappedValue:)` or deprecated `init(initialValue:)`. - auto *call = dyn_cast(getRawAnchor().get()); + auto *call = getAsExpr(getRawAnchor()); if (!(call && call->isImplicit() && isa(call->getFn()) && call->getNumArguments() == 1 && (call->getArgumentLabels().front() == getASTContext().Id_wrappedValue || @@ -5763,7 +5746,7 @@ bool ExpandArrayIntoVarargsFailure::diagnoseAsError() { bool ExpandArrayIntoVarargsFailure::diagnoseAsNote() { auto overload = getCalleeOverloadChoiceIfAvailable(getLocator()); - auto anchor = getAnchor().get(); + auto *anchor = getAnchor().dyn_cast(); if (!overload || !anchor) return false; @@ -5806,10 +5789,9 @@ bool ExtraneousCallFailure::diagnoseAsError() { } } - if (auto *UDE = - dyn_cast(anchor.dyn_cast())) { + if (auto *UDE = getAsExpr(anchor)) { auto *baseExpr = UDE->getBase(); - auto *call = cast(getRawAnchor().get()); + auto *call = castToExpr(getRawAnchor()); if (getType(baseExpr)->isAnyObject()) { emitDiagnostic(diag::cannot_call_with_params, @@ -5984,9 +5966,9 @@ bool NonEphemeralConversionFailure::diagnosePointerInit() const { ? diag::cannot_construct_dangling_pointer_warning : diag::cannot_construct_dangling_pointer; - auto *anchor = getRawAnchor().get(); - emitDiagnosticAt(anchor->getLoc(), diagID, constructedTy, constructorKind) - .highlight(anchor->getSourceRange()); + auto anchor = getRawAnchor(); + emitDiagnosticAt(getLoc(anchor), diagID, constructedTy, constructorKind) + .highlight(getSourceRange(anchor)); emitSuggestionNotes(); return true; @@ -6117,7 +6099,7 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { } bool UnableToInferClosureReturnType::diagnoseAsError() { - auto *closure = cast(getRawAnchor().get()); + auto *closure = castToExpr(getRawAnchor()); auto diagnostic = emitDiagnostic(diag::cannot_infer_closure_result_type, closure->hasSingleExpressionBody()); @@ -6180,7 +6162,7 @@ SourceLoc UnableToInferProtocolLiteralType::getLoc() const { bool UnableToInferProtocolLiteralType::diagnoseAsError() { auto &ctx = getASTContext(); - auto *expr = cast(getRawAnchor().get()); + auto *expr = castToExpr(getRawAnchor()); StringRef importModule; StringRef importDefaultTypeName; @@ -6202,7 +6184,7 @@ bool MissingQuialifierInMemberRefFailure::diagnoseAsError() { if (!selectedOverload) return false; - auto *UDE = cast(getRawAnchor().get()); + auto *UDE = castToExpr(getRawAnchor()); auto baseType = getType(UDE->getBase()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 95f1aaf6d0547..acb011aad440e 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -204,6 +204,21 @@ class FailureDiagnostic { static SourceLoc getLoc(TypedNode node); static SourceRange getSourceRange(TypedNode node); + + template static const T *castToExpr(TypedNode node) { + return cast(node.get()); + } + + template static T *getAsExpr(TypedNode node) { + if (const auto *E = node.dyn_cast()) + return dyn_cast(const_cast(E)); + return nullptr; + } + + template static bool isExpr(TypedNode node) { + auto *E = node.get(); + return isa(E); + } }; /// Base class for all of the diagnostics related to generic requirement From 967b3a3c8dc4c1674c34384d781aff3e9bd79111 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 17 Apr 2020 13:28:06 -0700 Subject: [PATCH 8/8] [Diagnostics] Adjust `getCallInfo` to accept `TypedNode` instead of expression --- lib/Sema/CSDiagnostics.cpp | 15 +++++++-------- lib/Sema/CSDiagnostics.h | 5 +++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index d016f4041a2d2..3916799e41405 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -3909,9 +3909,8 @@ bool MissingArgumentsFailure::diagnoseAsError() { unsigned numArguments = 0; bool hasTrailingClosure = false; - auto *rawAnchor = getRawAnchor().get(); std::tie(fnExpr, argExpr, numArguments, hasTrailingClosure) = - getCallInfo(const_cast(rawAnchor)); + getCallInfo(getRawAnchor()); // TODO(diagnostics): We should be able to suggest this fix-it // unconditionally. @@ -3987,7 +3986,7 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const { bool hasTrailingClosure = false; std::tie(fnExpr, argExpr, insertableEndIdx, hasTrailingClosure) = - getCallInfo(const_cast(anchor.get())); + getCallInfo(anchor); if (!argExpr) return false; @@ -4293,17 +4292,17 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument( } std::tuple -MissingArgumentsFailure::getCallInfo(Expr *anchor) const { - if (auto *call = dyn_cast(anchor)) { +MissingArgumentsFailure::getCallInfo(TypedNode anchor) const { + if (auto *call = getAsExpr(anchor)) { return std::make_tuple(call->getFn(), call->getArg(), call->getNumArguments(), call->hasTrailingClosure()); - } else if (auto *UME = dyn_cast(anchor)) { + } else if (auto *UME = getAsExpr(anchor)) { return std::make_tuple(UME, UME->getArgument(), UME->getNumArguments(), UME->hasTrailingClosure()); - } else if (auto *SE = dyn_cast(anchor)) { + } else if (auto *SE = getAsExpr(anchor)) { return std::make_tuple(SE, SE->getIndex(), SE->getNumArguments(), SE->hasTrailingClosure()); - } else if (auto *OLE = dyn_cast(anchor)) { + } else if (auto *OLE = getAsExpr(anchor)) { return std::make_tuple(OLE, OLE->getArg(), OLE->getNumArguments(), OLE->hasTrailingClosure()); } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index acb011aad440e..dd0fadb6f03b8 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -1278,10 +1278,11 @@ class MissingArgumentsFailure final : public FailureDiagnostic { /// `@Foo(answer: 42) var question = "ultimate question"` bool isPropertyWrapperInitialization() const; - /// Gather informatioin associated with expression that represents + /// Gather information associated with expression that represents /// a call - function, arguments, # of arguments and whether it has /// a trailing closure. - std::tuple getCallInfo(Expr *anchor) const; + std::tuple + getCallInfo(TypedNode anchor) const; /// Transform given argument into format suitable for a fix-it /// text e.g. `[