//===--- PreCheckExpr.cpp - Expression pre-checking pass ------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // Pre-checking resolves unqualified name references, type expressions and // operators. // //===----------------------------------------------------------------------===// #include "TypeChecker.h" #include "TypeCheckType.h" #include "TypoCorrection.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/DiagnosticsParse.h" #include "swift/AST/NameLookup.h" #include "swift/AST/NameLookupRequests.h" #include "swift/AST/ParameterList.h" #include "swift/AST/PropertyWrappers.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Parse/Confusables.h" #include "swift/Parse/Lexer.h" #include "swift/Sema/ConstraintSystem.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" using namespace swift; using namespace constraints; //===----------------------------------------------------------------------===// // High-level entry points. //===----------------------------------------------------------------------===// static unsigned getNumArgs(ValueDecl *value) { if (auto *func = dyn_cast(value)) return func->getParameters()->size(); return ~0U; } static bool matchesDeclRefKind(ValueDecl *value, DeclRefKind refKind) { switch (refKind) { // An ordinary reference doesn't ignore anything. case DeclRefKind::Ordinary: return true; // A binary-operator reference only honors FuncDecls with a certain type. case DeclRefKind::BinaryOperator: return (getNumArgs(value) == 2); case DeclRefKind::PrefixOperator: return (!value->getAttrs().hasAttribute() && getNumArgs(value) == 1); case DeclRefKind::PostfixOperator: return (value->getAttrs().hasAttribute() && getNumArgs(value) == 1); } llvm_unreachable("bad declaration reference kind"); } static bool containsDeclRefKind(LookupResult &lookupResult, DeclRefKind refKind) { for (auto candidate : lookupResult) { ValueDecl *D = candidate.getValueDecl(); if (!D) continue; if (matchesDeclRefKind(D, refKind)) return true; } return false; } /// Emit a diagnostic with a fixit hint for an invalid binary operator, showing /// how to split it according to splitCandidate. static void diagnoseBinOpSplit(ASTContext &Context, UnresolvedDeclRefExpr *UDRE, std::pair splitCandidate, Diag diagID) { unsigned splitLoc = splitCandidate.first; bool isBinOpFirst = splitCandidate.second; StringRef nameStr = UDRE->getName().getBaseIdentifier().str(); auto startStr = nameStr.substr(0, splitLoc); auto endStr = nameStr.drop_front(splitLoc); // One valid split found, it is almost certainly the right answer. auto diag = Context.Diags.diagnose( UDRE->getLoc(), diagID, Context.getIdentifier(startStr), Context.getIdentifier(endStr), isBinOpFirst); // Highlight the whole operator. diag.highlight(UDRE->getLoc()); // Insert whitespace on the left if the binop is at the start, or to the // right if it is end. if (isBinOpFirst) diag.fixItInsert(UDRE->getLoc(), " "); else diag.fixItInsertAfter(UDRE->getLoc(), " "); // Insert a space between the operators. diag.fixItInsert(UDRE->getLoc().getAdvancedLoc(splitLoc), " "); } /// If we failed lookup of a binary operator, check to see it to see if /// it is a binary operator juxtaposed with a unary operator (x*-4) that /// needs whitespace. If so, emit specific diagnostics for it and return true, /// otherwise return false. static bool diagnoseOperatorJuxtaposition(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) { Identifier name = UDRE->getName().getBaseIdentifier(); StringRef nameStr = name.str(); if (!name.isOperator() || nameStr.size() < 2) return false; bool isBinOp = UDRE->getRefKind() == DeclRefKind::BinaryOperator; // If this is a binary operator, relex the token, to decide whether it has // whitespace around it or not. If it does "x +++ y", then it isn't likely to // be a case where a space was forgotten. auto &Context = DC->getASTContext(); if (isBinOp) { auto tok = Lexer::getTokenAtLocation(Context.SourceMgr, UDRE->getLoc()); if (tok.getKind() != tok::oper_binary_unspaced) return false; } // Okay, we have a failed lookup of a multicharacter operator. Check to see if // lookup succeeds if part is split off, and record the matches found. // // In the case of a binary operator, the bool indicated is false if the // first half of the split is the unary operator (x!*4) or true if it is the // binary operator (x*+4). std::vector> WorkableSplits; // Check all the potential splits. for (unsigned splitLoc = 1, e = nameStr.size(); splitLoc != e; ++splitLoc) { // For it to be a valid split, the start and end section must be valid // operators, splitting a unicode code point isn't kosher. auto startStr = nameStr.substr(0, splitLoc); auto endStr = nameStr.drop_front(splitLoc); if (!Lexer::isOperator(startStr) || !Lexer::isOperator(endStr)) continue; DeclNameRef startName(Context.getIdentifier(startStr)); DeclNameRef endName(Context.getIdentifier(endStr)); // Perform name lookup for the first and second pieces. If either fail to // be found, then it isn't a valid split. auto startLookup = TypeChecker::lookupUnqualified( DC, startName, UDRE->getLoc(), defaultUnqualifiedLookupOptions); if (!startLookup) continue; auto endLookup = TypeChecker::lookupUnqualified(DC, endName, UDRE->getLoc(), defaultUnqualifiedLookupOptions); if (!endLookup) continue; // If the overall operator is a binary one, then we're looking at // juxtaposed binary and unary operators. if (isBinOp) { // Look to see if the candidates found could possibly match. if (containsDeclRefKind(startLookup, DeclRefKind::PostfixOperator) && containsDeclRefKind(endLookup, DeclRefKind::BinaryOperator)) WorkableSplits.push_back({ splitLoc, false }); if (containsDeclRefKind(startLookup, DeclRefKind::BinaryOperator) && containsDeclRefKind(endLookup, DeclRefKind::PrefixOperator)) WorkableSplits.push_back({ splitLoc, true }); } else { // Otherwise, it is two of the same kind, e.g. "!!x" or "!~x". if (containsDeclRefKind(startLookup, UDRE->getRefKind()) && containsDeclRefKind(endLookup, UDRE->getRefKind())) WorkableSplits.push_back({ splitLoc, false }); } } switch (WorkableSplits.size()) { case 0: // No splits found, can't produce this diagnostic. return false; case 1: // One candidate: produce an error with a fixit on it. if (isBinOp) diagnoseBinOpSplit(Context, UDRE, WorkableSplits[0], diag::unspaced_binary_operator_fixit); else Context.Diags.diagnose( UDRE->getLoc().getAdvancedLoc(WorkableSplits[0].first), diag::unspaced_unary_operator); return true; default: // Otherwise, we have to produce a series of notes listing the various // options. Context.Diags .diagnose(UDRE->getLoc(), isBinOp ? diag::unspaced_binary_operator : diag::unspaced_unary_operator) .highlight(UDRE->getLoc()); if (isBinOp) { for (auto candidateSplit : WorkableSplits) diagnoseBinOpSplit(Context, UDRE, candidateSplit, diag::unspaced_binary_operators_candidate); } return true; } } static bool diagnoseRangeOperatorMisspell(DiagnosticEngine &Diags, UnresolvedDeclRefExpr *UDRE) { auto name = UDRE->getName().getBaseIdentifier(); if (!name.isOperator()) return false; auto corrected = StringRef(); if (name.str() == ".." || name.str() == "...." || name.str() == ".…" || name.str() == "…" || name.str() == "….") corrected = "..."; else if (name.str() == "...<" || name.str() == "....<" || name.str() == "…<") corrected = "..<"; if (!corrected.empty()) { Diags .diagnose(UDRE->getLoc(), diag::cannot_find_in_scope_corrected, UDRE->getName(), true, corrected) .highlight(UDRE->getSourceRange()) .fixItReplace(UDRE->getSourceRange(), corrected); return true; } return false; } static bool diagnoseNonexistentPowerOperator(DiagnosticEngine &Diags, UnresolvedDeclRefExpr *UDRE, DeclContext *DC) { auto name = UDRE->getName().getBaseIdentifier(); if (!(name.isOperator() && name.is("**"))) return false; DC = DC->getModuleScopeContext(); auto &ctx = DC->getASTContext(); DeclNameRef powerName(ctx.getIdentifier("pow")); // Look if 'pow(_:_:)' exists within current context. auto lookUp = TypeChecker::lookupUnqualified( DC, powerName, UDRE->getLoc(), defaultUnqualifiedLookupOptions); if (lookUp) { Diags.diagnose(UDRE->getLoc(), diag::nonexistent_power_operator) .highlight(UDRE->getSourceRange()); return true; } return false; } static bool diagnoseIncDecOperator(DiagnosticEngine &Diags, UnresolvedDeclRefExpr *UDRE) { auto name = UDRE->getName().getBaseIdentifier(); if (!name.isOperator()) return false; auto corrected = StringRef(); if (name.str() == "++") corrected = "+= 1"; else if (name.str() == "--") corrected = "-= 1"; if (!corrected.empty()) { Diags .diagnose(UDRE->getLoc(), diag::cannot_find_in_scope_corrected, UDRE->getName(), true, corrected) .highlight(UDRE->getSourceRange()); return true; } return false; } static bool findNonMembers(ArrayRef lookupResults, DeclRefKind refKind, bool breakOnMember, SmallVectorImpl &ResultValues, llvm::function_ref isValid) { bool AllDeclRefs = true; for (auto Result : lookupResults) { // If we find a member, then all of the results aren't non-members. bool IsMember = (Result.getBaseDecl() && !isa(Result.getBaseDecl())); if (IsMember) { AllDeclRefs = false; if (breakOnMember) break; continue; } ValueDecl *D = Result.getValueDecl(); if (!isValid(D)) return false; if (matchesDeclRefKind(D, refKind)) ResultValues.push_back(D); } return AllDeclRefs; } /// Find the next element in a chain of members. If this expression is (or /// could be) the base of such a chain, this will return \c nullptr. static Expr *getMemberChainSubExpr(Expr *expr) { assert(expr && "getMemberChainSubExpr called with null expr!"); if (auto *UDE = dyn_cast(expr)) { return UDE->getBase(); } else if (auto *CE = dyn_cast(expr)) { return CE->getFn(); } else if (auto *BOE = dyn_cast(expr)) { return BOE->getSubExpr(); } else if (auto *FVE = dyn_cast(expr)) { return FVE->getSubExpr(); } else if (auto *SE = dyn_cast(expr)) { return SE->getBase(); } else if (auto *CCE = dyn_cast(expr)) { return CCE->getBase(); } else { return nullptr; } } UnresolvedMemberExpr *TypeChecker::getUnresolvedMemberChainBase(Expr *expr) { if (auto *subExpr = getMemberChainSubExpr(expr)) return getUnresolvedMemberChainBase(subExpr); else return dyn_cast(expr); } /// Whether this expression sits at the end of a chain of member accesses. static bool isMemberChainTail(Expr *expr, Expr *parent) { assert(expr && "isMemberChainTail called with null expr!"); // If this expression's parent is not itself part of a chain (or, this expr // has no parent expr), this must be the tail of the chain. return !parent || getMemberChainSubExpr(parent) != expr; } static bool isValidForwardReference(ValueDecl *D, DeclContext *DC, ValueDecl **localDeclAfterUse) { *localDeclAfterUse = nullptr; // References to variables injected by lldb are always valid. if (isa(D) && cast(D)->isDebuggerVar()) return true; // If we find something in the current context, it must be a forward // reference, because otherwise if it was in scope, it would have // been returned by the call to ASTScope::lookupLocalDecls() above. if (D->getDeclContext()->isLocalContext()) { do { if (D->getDeclContext() == DC) { *localDeclAfterUse = D; return false; } // If we're inside of a 'defer' context, walk up to the parent // and check again. We don't want 'defer' bodies to forward // reference bindings in the immediate outer scope. } while (isa(DC) && cast(DC)->isDeferBody() && (DC = DC->getParent())); } return true; } /// Checks whether this is a BinaryExpr with operator `&` and returns the /// BinaryExpr, if so. static BinaryExpr *getCompositionExpr(Expr *expr) { if (auto *binaryExpr = dyn_cast(expr)) { // look at the name of the operator, if it is a '&' we can create the // composition TypeExpr auto fn = binaryExpr->getFn(); if (auto Overload = dyn_cast(fn)) { if (llvm::any_of(Overload->getDecls(), [](auto *decl) -> bool { return decl->getBaseName() == "&"; })) return binaryExpr; } else if (auto *Decl = dyn_cast(fn)) { if (Decl->getName().isSimpleName() && Decl->getName().getBaseName() == "&") return binaryExpr; } } return nullptr; } /// Whether the given expression "looks like" a (possibly sugared) type. For /// example, `(foo, bar)` "looks like" a type, but `foo + bar` does not. static bool exprLooksLikeAType(Expr *expr) { return isa(expr) || isa(expr) || isa(expr) || isa(expr) || isa(expr) || isa(expr) || (isa(expr) && cast(expr)->getElements().size() == 1) || (isa(expr) && cast(expr)->getElements().size() == 1) || getCompositionExpr(expr); } /// Bind an UnresolvedDeclRefExpr by performing name lookup and /// returning the resultant expression. Context is the DeclContext used /// for the lookup. Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC, bool replaceInvalidRefsWithErrors) { // Process UnresolvedDeclRefExpr by doing an unqualified lookup. DeclNameRef Name = UDRE->getName(); SourceLoc Loc = UDRE->getLoc(); DeclNameRef LookupName = Name; if (Name.isCompoundName()) { auto &context = DC->getASTContext(); // Remove any $ prefixes for lookup SmallVector lookupLabels; for (auto label : Name.getArgumentNames()) { if (label.hasDollarPrefix()) { auto unprefixed = label.str().drop_front(); lookupLabels.push_back(context.getIdentifier(unprefixed)); } else { lookupLabels.push_back(label); } } DeclName lookupName(context, Name.getBaseName(), lookupLabels); LookupName = DeclNameRef(lookupName); } auto errorResult = [&]() -> Expr * { if (replaceInvalidRefsWithErrors) return new (DC->getASTContext()) ErrorExpr(UDRE->getSourceRange()); return UDRE; }; // Perform standard value name lookup. NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions; // TODO: Include all of the possible members to give a solver a // chance to diagnose name shadowing which requires explicit // name/module qualifier to access top-level name. lookupOptions |= NameLookupFlags::IncludeOuterResults; LookupResult Lookup; bool AllDeclRefs = true; SmallVector ResultValues; auto &Context = DC->getASTContext(); // First, look for a local binding in scope. if (Loc.isValid() && !Name.isOperator()) { SmallVector localDecls; ASTScope::lookupLocalDecls(DC->getParentSourceFile(), LookupName.getFullName(), Loc, /*stopAfterInnermostBraceStmt=*/false, ResultValues); for (auto *localDecl : ResultValues) { Lookup.add(LookupResultEntry(localDecl), /*isOuter=*/false); } } if (!Lookup) { // Now, look for all local bindings, even forward references, as well // as type members and top-level declarations. if (Loc.isInvalid()) DC = DC->getModuleScopeContext(); Lookup = TypeChecker::lookupUnqualified(DC, LookupName, Loc, lookupOptions); ValueDecl *localDeclAfterUse = nullptr; AllDeclRefs = findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), /*breakOnMember=*/true, ResultValues, [&](ValueDecl *D) { return isValidForwardReference(D, DC, &localDeclAfterUse); }); // If local declaration after use is found, check outer results for // better matching candidates. if (ResultValues.empty() && localDeclAfterUse) { auto innerDecl = localDeclAfterUse; while (localDeclAfterUse) { if (Lookup.outerResults().empty()) { Context.Diags.diagnose(Loc, diag::use_local_before_declaration, Name); Context.Diags.diagnose(innerDecl, diag::decl_declared_here, localDeclAfterUse->getName()); Expr *error = new (Context) ErrorExpr(UDRE->getSourceRange()); return error; } Lookup.shiftDownResults(); ResultValues.clear(); localDeclAfterUse = nullptr; AllDeclRefs = findNonMembers(Lookup.innerResults(), UDRE->getRefKind(), /*breakOnMember=*/true, ResultValues, [&](ValueDecl *D) { return isValidForwardReference(D, DC, &localDeclAfterUse); }); } } } if (!Lookup) { // If we failed lookup of an operator, check to see if this is a range // operator misspelling. Otherwise try to diagnose a juxtaposition // e.g. (x*-4) that needs whitespace. if (diagnoseRangeOperatorMisspell(Context.Diags, UDRE) || diagnoseIncDecOperator(Context.Diags, UDRE) || diagnoseOperatorJuxtaposition(UDRE, DC) || diagnoseNonexistentPowerOperator(Context.Diags, UDRE, DC)) { return errorResult(); } // Try ignoring access control. NameLookupOptions relookupOptions = lookupOptions; relookupOptions |= NameLookupFlags::IgnoreAccessControl; auto inaccessibleResults = TypeChecker::lookupUnqualified(DC, LookupName, Loc, relookupOptions); if (inaccessibleResults) { // FIXME: What if the unviable candidates have different levels of access? const ValueDecl *first = inaccessibleResults.front().getValueDecl(); Context.Diags.diagnose( Loc, diag::candidate_inaccessible, first->getBaseName(), first->getFormalAccessScope().accessLevelForDiagnostics()); // FIXME: If any of the candidates (usually just one) are in the same // module we could offer a fix-it. for (auto lookupResult : inaccessibleResults) { auto *VD = lookupResult.getValueDecl(); VD->diagnose(diag::decl_declared_here, VD->getName()); } // Don't try to recover here; we'll get more access-related diagnostics // downstream if the type of the inaccessible decl is also inaccessible. return errorResult(); } // TODO: Name will be a compound name if it was written explicitly as // one, but we should also try to propagate labels into this. DeclNameLoc nameLoc = UDRE->getNameLoc(); Identifier simpleName = Name.getBaseIdentifier(); const char *buffer = simpleName.get(); llvm::SmallString<64> expectedIdentifier; bool isConfused = false; uint32_t codepoint; uint32_t firstConfusableCodepoint = 0; int totalCodepoints = 0; int offset = 0; while ((codepoint = validateUTF8CharacterAndAdvance(buffer, buffer + strlen(buffer))) != ~0U) { int length = (buffer - simpleName.get()) - offset; if (auto expectedCodepoint = confusable::tryConvertConfusableCharacterToASCII(codepoint)) { if (firstConfusableCodepoint == 0) { firstConfusableCodepoint = codepoint; } isConfused = true; expectedIdentifier += expectedCodepoint; } else { expectedIdentifier += (char)codepoint; } totalCodepoints++; offset += length; } auto emitBasicError = [&] { Context.Diags .diagnose(Loc, diag::cannot_find_in_scope, Name, Name.isOperator()) .highlight(UDRE->getSourceRange()); }; if (!isConfused) { if (Name.isSimpleName(Context.Id_Self)) { if (DeclContext *typeContext = DC->getInnermostTypeContext()){ Type SelfType = typeContext->getSelfInterfaceType(); if (typeContext->getSelfClassDecl()) SelfType = DynamicSelfType::get(SelfType, Context); return new (Context) TypeExpr(new (Context) FixedTypeRepr(SelfType, Loc)); } } TypoCorrectionResults corrections(Name, nameLoc); TypeChecker::performTypoCorrection(DC, UDRE->getRefKind(), Type(), lookupOptions, corrections); if (auto typo = corrections.claimUniqueCorrection()) { auto diag = Context.Diags.diagnose( Loc, diag::cannot_find_in_scope_corrected, Name, Name.isOperator(), typo->CorrectedName.getBaseIdentifier().str()); diag.highlight(UDRE->getSourceRange()); typo->addFixits(diag); } else { emitBasicError(); } corrections.noteAllCandidates(); } else { emitBasicError(); if (totalCodepoints == 1) { auto charNames = confusable::getConfusableAndBaseCodepointNames( firstConfusableCodepoint); Context.Diags .diagnose(Loc, diag::single_confusable_character, UDRE->getName().isOperator(), simpleName.str(), charNames.first, expectedIdentifier, charNames.second) .fixItReplace(Loc, expectedIdentifier); } else { Context.Diags .diagnose(Loc, diag::confusable_character, UDRE->getName().isOperator(), simpleName.str(), expectedIdentifier) .fixItReplace(Loc, expectedIdentifier); } } // TODO: consider recovering from here. We may want some way to suppress // downstream diagnostics, though. return errorResult(); } // FIXME: Need to refactor the way we build an AST node from a lookup result! // If we have an unambiguous reference to a type decl, form a TypeExpr. if (Lookup.size() == 1 && UDRE->getRefKind() == DeclRefKind::Ordinary && isa(Lookup[0].getValueDecl())) { auto *D = cast(Lookup[0].getValueDecl()); // FIXME: This is odd. if (isa(D)) { return new (Context) DeclRefExpr(D, UDRE->getNameLoc(), /*Implicit=*/false, AccessSemantics::Ordinary, D->getInterfaceType()); } auto *LookupDC = Lookup[0].getDeclContext(); if (UDRE->isImplicit()) { return TypeExpr::createImplicitForDecl( UDRE->getNameLoc(), D, LookupDC, LookupDC->mapTypeIntoContext(D->getInterfaceType())); } else { return TypeExpr::createForDecl(UDRE->getNameLoc(), D, LookupDC); } } if (AllDeclRefs) { // Diagnose uses of operators that found no matching candidates. if (ResultValues.empty()) { assert(UDRE->getRefKind() != DeclRefKind::Ordinary); Context.Diags.diagnose( Loc, diag::use_nonmatching_operator, Name, UDRE->getRefKind() == DeclRefKind::BinaryOperator ? 0 : UDRE->getRefKind() == DeclRefKind::PrefixOperator ? 1 : 2); return new (Context) ErrorExpr(UDRE->getSourceRange()); } // For operators, sort the results so that non-generic operations come // first. // Note: this is part of a performance hack to prefer non-generic operators // to generic operators, because the former is far more efficient to check. if (UDRE->getRefKind() != DeclRefKind::Ordinary) { std::stable_sort(ResultValues.begin(), ResultValues.end(), [&](ValueDecl *x, ValueDecl *y) -> bool { auto xGeneric = x->getInterfaceType()->getAs(); auto yGeneric = y->getInterfaceType()->getAs(); if (static_cast(xGeneric) != static_cast(yGeneric)) { return xGeneric? false : true; } if (!xGeneric) return false; unsigned xDepth = xGeneric->getGenericParams().back()->getDepth(); unsigned yDepth = yGeneric->getGenericParams().back()->getDepth(); return xDepth < yDepth; }); } return buildRefExpr(ResultValues, DC, UDRE->getNameLoc(), UDRE->isImplicit(), UDRE->getFunctionRefKind()); } ResultValues.clear(); bool AllMemberRefs = true; ValueDecl *Base = nullptr; DeclContext *BaseDC = nullptr; for (auto Result : Lookup) { auto ThisBase = Result.getBaseDecl(); // Track the base for member declarations. if (ThisBase && !isa(ThisBase)) { auto Value = Result.getValueDecl(); ResultValues.push_back(Value); if (Base && ThisBase != Base) { AllMemberRefs = false; break; } Base = ThisBase; BaseDC = Result.getDeclContext(); continue; } AllMemberRefs = false; break; } if (AllMemberRefs) { Expr *BaseExpr; if (auto PD = dyn_cast(Base)) { auto selfParam = PD->getGenericParams()->getParams().front(); BaseExpr = TypeExpr::createImplicitForDecl( UDRE->getNameLoc(), selfParam, /*DC*/ nullptr, DC->mapTypeIntoContext(selfParam->getInterfaceType())); } else if (auto NTD = dyn_cast(Base)) { BaseExpr = TypeExpr::createImplicitForDecl( UDRE->getNameLoc(), NTD, BaseDC, DC->mapTypeIntoContext(NTD->getInterfaceType())); } else { BaseExpr = new (Context) DeclRefExpr(Base, UDRE->getNameLoc(), /*Implicit=*/true); } auto isInClosureContext = [&](ValueDecl *decl) -> bool { auto *DC = decl->getDeclContext(); do { if (dyn_cast(DC)) return true; } while ((DC = DC->getParent())); return false; }; llvm::SmallVector outerAlternatives; (void)findNonMembers(Lookup.outerResults(), UDRE->getRefKind(), /*breakOnMember=*/false, outerAlternatives, /*isValid=*/[&](ValueDecl *choice) -> bool { // Values that are defined in a closure // that hasn't been type-checked yet, // cannot be outer candidates. if (isInClosureContext(choice)) { return choice->hasInterfaceType() && !choice->isInvalid(); } return !choice->isInvalid(); }); // Otherwise, form an UnresolvedDotExpr and sema will resolve it based on // type information. return new (Context) UnresolvedDotExpr( BaseExpr, SourceLoc(), Name, UDRE->getNameLoc(), UDRE->isImplicit(), Context.AllocateCopy(outerAlternatives)); } // FIXME: If we reach this point, the program we're being handed is likely // very broken, but it's still conceivable that this may happen due to // invalid shadowed declarations. // // Make sure we emit a diagnostic, since returning an ErrorExpr without // producing one will break things downstream. Context.Diags.diagnose(Loc, diag::ambiguous_decl_ref, Name); for (auto Result : Lookup) { auto *Decl = Result.getValueDecl(); Context.Diags.diagnose(Decl, diag::decl_declared_here, Decl->getName()); } return new (Context) ErrorExpr(UDRE->getSourceRange()); } /// If an expression references 'self.init' or 'super.init' in an /// initializer context, returns the implicit 'self' decl of the constructor. /// Otherwise, return nil. VarDecl * TypeChecker::getSelfForInitDelegationInConstructor(DeclContext *DC, UnresolvedDotExpr *ctorRef) { // If the reference isn't to a constructor, we're done. if (ctorRef->getName().getBaseName() != DeclBaseName::createConstructor()) return nullptr; if (auto ctorContext = dyn_cast_or_null(DC->getInnermostMethodContext())) { auto nestedArg = ctorRef->getBase(); if (auto inout = dyn_cast(nestedArg)) nestedArg = inout->getSubExpr(); if (nestedArg->isSuperExpr()) return ctorContext->getImplicitSelfDecl(); if (auto declRef = dyn_cast(nestedArg)) if (declRef->getDecl()->getName() == DC->getASTContext().Id_self) return ctorContext->getImplicitSelfDecl(); } return nullptr; } namespace { /// Update the function reference kind based on adding a direct call to a /// callee with this kind. FunctionRefKind addingDirectCall(FunctionRefKind kind) { switch (kind) { case FunctionRefKind::Unapplied: return FunctionRefKind::SingleApply; case FunctionRefKind::SingleApply: case FunctionRefKind::DoubleApply: return FunctionRefKind::DoubleApply; case FunctionRefKind::Compound: return FunctionRefKind::Compound; } llvm_unreachable("Unhandled FunctionRefKind in switch."); } /// Update a direct callee expression node that has a function reference kind /// based on seeing a call to this callee. templategetFunctionRefKind())> void tryUpdateDirectCalleeImpl(E *callee, int) { callee->setFunctionRefKind(addingDirectCall(callee->getFunctionRefKind())); } /// Version of tryUpdateDirectCalleeImpl for when the callee /// expression type doesn't carry a reference. template void tryUpdateDirectCalleeImpl(E *callee, ...) { } /// The given expression is the direct callee of a call expression; mark it to /// indicate that it has been called. void markDirectCallee(Expr *callee) { while (true) { // Look through identity expressions. if (auto identity = dyn_cast(callee)) { callee = identity->getSubExpr(); continue; } // Look through unresolved 'specialize' expressions. if (auto specialize = dyn_cast(callee)) { callee = specialize->getSubExpr(); continue; } // Look through optional binding. if (auto bindOptional = dyn_cast(callee)) { callee = bindOptional->getSubExpr(); continue; } // Look through forced binding. if (auto force = dyn_cast(callee)) { callee = force->getSubExpr(); continue; } // Calls compose. if (auto call = dyn_cast(callee)) { callee = call->getFn(); continue; } // We're done. break; } // Cast the callee to its most-specific class, then try to perform an // update. If the expression node has a declaration reference in it, the // update will succeed. Otherwise, we're done propagating. switch (callee->getKind()) { #define EXPR(Id, Parent) \ case ExprKind::Id: \ tryUpdateDirectCalleeImpl(cast(callee), 0); \ break; #include "swift/AST/ExprNodes.def" } } class PreCheckExpression : public ASTWalker { ASTContext &Ctx; DeclContext *DC; Expr *ParentExpr; /// Indicates whether pre-check is allowed to insert /// implicit `ErrorExpr` in place of invalid references. bool UseErrorExprs; bool LeaveClosureBodiesUnchecked; /// A stack of expressions being walked, used to determine where to /// insert RebindSelfInConstructorExpr nodes. llvm::SmallVector ExprStack; /// The 'self' variable to use when rebinding 'self' in a constructor. VarDecl *UnresolvedCtorSelf = nullptr; /// The expression that will be wrapped by a RebindSelfInConstructorExpr /// node when visited. Expr *UnresolvedCtorRebindTarget = nullptr; /// Keep track of acceptable DiscardAssignmentExpr's. llvm::SmallPtrSet CorrectDiscardAssignmentExprs; /// The current number of nested \c SequenceExprs that we're within. unsigned SequenceExprDepth = 0; /// Simplify expressions which are type sugar productions that got parsed /// as expressions due to the parser not knowing which identifiers are /// type names. TypeExpr *simplifyTypeExpr(Expr *E); /// Simplify unresolved dot expressions which are nested type productions. TypeExpr *simplifyNestedTypeExpr(UnresolvedDotExpr *UDE); TypeExpr *simplifyUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *USE); /// Simplify a key path expression into a canonical form. void resolveKeyPathExpr(KeyPathExpr *KPE); /// Simplify constructs like `UInt32(1)` into `1 as UInt32` if /// the type conforms to the expected literal protocol. Expr *simplifyTypeConstructionWithLiteralArg(Expr *E); /// Whether the current expression \p E is in a context that might turn out /// to be a \c TypeExpr after \c simplifyTypeExpr is called up the tree. /// This function allows us to make better guesses about whether invalid /// uses of '_' were "supposed" to be \c DiscardAssignmentExprs or patterns, /// which results in better diagnostics after type checking. bool possiblyInTypeContext(Expr *E); /// Whether we can simplify the given discard assignment expr. Not possible /// if it's been marked "valid" or if the current state of the AST disallows /// such simplification (see \c canSimplifyPlaceholderTypes above). bool canSimplifyDiscardAssignmentExpr(DiscardAssignmentExpr *DAE); /// In Swift < 5, diagnose and correct invalid multi-argument or /// argument-labeled interpolations. Returns \c true if the AST walk should /// continue, or \c false if it should be aborted. bool correctInterpolationIfStrange(InterpolatedStringLiteralExpr *ISLE) { // These expressions are valid in Swift 5+. if (getASTContext().isSwiftVersionAtLeast(5)) return true; /// Diagnoses appendInterpolation(...) calls with multiple /// arguments or argument labels and corrects them. class StrangeInterpolationRewriter : public ASTWalker { ASTContext &Context; public: StrangeInterpolationRewriter(ASTContext &Ctx) : Context(Ctx) {} virtual bool walkToDeclPre(Decl *D) override { // We don't want to look inside decls. return false; } virtual std::pair walkToExprPre(Expr *E) override { // One InterpolatedStringLiteralExpr should never be nested inside // another except as a child of a CallExpr, and we don't recurse into // the children of CallExprs. assert(!isa(E) && "StrangeInterpolationRewriter found nested interpolation?"); // We only care about CallExprs. if (!isa(E)) return { true, E }; auto *call = cast(E); auto *args = call->getArgs(); auto lParen = args->getLParenLoc(); auto rParen = args->getRParenLoc(); if (auto callee = dyn_cast(call->getFn())) { if (callee->getName().getBaseName() == Context.Id_appendInterpolation) { Optional newArg; if (args->size() > 1) { auto *secondArg = args->get(1).getExpr(); Context.Diags .diagnose(secondArg->getLoc(), diag::string_interpolation_list_changing) .highlightChars(secondArg->getLoc(), rParen); Context.Diags .diagnose(secondArg->getLoc(), diag::string_interpolation_list_insert_parens) .fixItInsertAfter(lParen, "(") .fixItInsert(rParen, ")"); // Make sure we don't have an inout arg somewhere, as that's // invalid even with the compatibility fix. for (auto arg : *args) { if (arg.isInOut()) { Context.Diags.diagnose(arg.getExpr()->getStartLoc(), diag::extraneous_address_of); return {false, nullptr}; } } // Form a new argument tuple from the argument list. auto *packed = args->packIntoImplicitTupleOrParen(Context); newArg = Argument::unlabeled(packed); } else if (args->size() == 1 && args->front().getLabel() != Identifier()) { // Form a new argument that drops the label. auto *argExpr = args->front().getExpr(); newArg = Argument::unlabeled(argExpr); SourceLoc argLabelLoc = args->front().getLabelLoc(), argLoc = argExpr->getStartLoc(); Context.Diags .diagnose(argLabelLoc, diag::string_interpolation_label_changing) .highlightChars(argLabelLoc, argLoc); Context.Diags .diagnose(argLabelLoc, diag::string_interpolation_remove_label, args->front().getLabel()) .fixItRemoveChars(argLabelLoc, argLoc); } // If newArg is no longer null, we need to build a new // appendInterpolation(_:) call that takes it to replace the bad // appendInterpolation(...) call. if (newArg) { auto newCallee = new (Context) UnresolvedDotExpr( callee->getBase(), /*dotloc=*/SourceLoc(), DeclNameRef(Context.Id_appendInterpolation), /*nameloc=*/DeclNameLoc(), /*Implicit=*/true); auto *newArgList = ArgumentList::create(Context, lParen, {*newArg}, rParen, /*trailingClosureIdx*/ None, /*implicit*/ false); E = CallExpr::create(Context, newCallee, newArgList, /*implicit=*/false); } } } // There is never a CallExpr between an InterpolatedStringLiteralExpr // and an un-typechecked appendInterpolation(...) call, so whether we // changed E or not, we don't need to recurse any deeper. return { false, E }; } }; return ISLE->getAppendingExpr()->walk( StrangeInterpolationRewriter(getASTContext())); } /// Scout out the specified destination of an AssignExpr to recursively /// identify DiscardAssignmentExpr in legal places. We can only allow them /// in simple pattern-like expressions, so we reject anything complex here. void markAcceptableDiscardExprs(Expr *E) { if (!E) return; if (auto *PE = dyn_cast(E)) return markAcceptableDiscardExprs(PE->getSubExpr()); if (auto *TE = dyn_cast(E)) { for (auto &elt : TE->getElements()) markAcceptableDiscardExprs(elt); return; } if (auto *BOE = dyn_cast(E)) return markAcceptableDiscardExprs(BOE->getSubExpr()); if (auto *DAE = dyn_cast(E)) CorrectDiscardAssignmentExprs.insert(DAE); // Otherwise, we can't support this. } public: PreCheckExpression(DeclContext *dc, Expr *parent, bool replaceInvalidRefsWithErrors, bool leaveClosureBodiesUnchecked) : Ctx(dc->getASTContext()), DC(dc), ParentExpr(parent), UseErrorExprs(replaceInvalidRefsWithErrors), LeaveClosureBodiesUnchecked(leaveClosureBodiesUnchecked) {} ASTContext &getASTContext() const { return Ctx; } bool walkToClosureExprPre(ClosureExpr *expr); bool shouldWalkCaptureInitializerExpressions() override { return true; } VarDecl *getImplicitSelfDeclForSuperContext(SourceLoc Loc) { auto *methodContext = DC->getInnermostMethodContext(); if (!methodContext) { Ctx.Diags.diagnose(Loc, diag::super_not_in_class_method); return nullptr; } // Do an actual lookup for 'self' in case it shows up in a capture list. auto *methodSelf = methodContext->getImplicitSelfDecl(); auto *lookupSelf = ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(), Ctx.Id_self, Loc); if (lookupSelf && lookupSelf != methodSelf) { // FIXME: This is the wrong diagnostic for if someone manually declares a // variable named 'self' using backticks. Ctx.Diags.diagnose(Loc, diag::super_in_closure_with_capture); Ctx.Diags.diagnose(lookupSelf->getLoc(), diag::super_in_closure_with_capture_here); return nullptr; } return methodSelf; } std::pair walkToExprPre(Expr *expr) override { // FIXME(diagnostics): `InOutType` could appear here as a result // of successful re-typecheck of the one of the sub-expressions e.g. // `let _: Int = { (s: inout S) in s.bar() }`. On the first // attempt to type-check whole expression `s.bar()` - is going // to have a base which points directly to declaration of `S`. // But when diagnostics attempts to type-check `s.bar()` standalone // its base would be tranformed into `InOutExpr -> DeclRefExr`, // and `InOutType` is going to be recorded in constraint system. // One possible way to fix this (if diagnostics still use typecheck) // might be to make it so self is not wrapped into `InOutExpr` // but instead used as @lvalue type in some case of mutable members. if (!expr->isImplicit()) { if (isa(expr) || isa(expr)) { auto *LE = cast(expr); if (auto *IOE = dyn_cast(LE->getBase())) LE->setBase(IOE->getSubExpr()); } if (auto *DSCE = dyn_cast(expr)) { if (auto *IOE = dyn_cast(DSCE->getBase())) DSCE->setBase(IOE->getSubExpr()); } } // Local function used to finish up processing before returning. Every // return site should call through here. auto finish = [&](bool recursive, Expr *expr) { // If we're going to recurse, record this expression on the stack. if (recursive) { if (isa(expr)) SequenceExprDepth++; ExprStack.push_back(expr); } return std::make_pair(recursive, expr); }; // Resolve 'super' references. if (auto *superRef = dyn_cast(expr)) { auto loc = superRef->getLoc(); auto *selfDecl = getImplicitSelfDeclForSuperContext(loc); if (selfDecl == nullptr) return finish(true, new (Ctx) ErrorExpr(loc)); superRef->setSelf(selfDecl); return finish(true, superRef); } // For closures, type-check the patterns and result type as written, // but do not walk into the body. That will be type-checked after // we've determine the complete function type. if (auto closure = dyn_cast(expr)) return finish(walkToClosureExprPre(closure), expr); if (auto unresolved = dyn_cast(expr)) { TypeChecker::checkForForbiddenPrefix( getASTContext(), unresolved->getName().getBaseName()); return finish(true, TypeChecker::resolveDeclRefExpr(unresolved, DC, UseErrorExprs)); } // Let's try to figure out if `InOutExpr` is out of place early // otherwise there is a risk of producing solutions which can't // be later applied to AST and would result in the crash in some // cases. Such expressions are only allowed in argument positions // of function/operator calls. if (isa(expr)) { // If this is an implicit `inout` expression we assume that // compiler knowns what it's doing. if (expr->isImplicit()) return finish(true, expr); auto parents = ParentExpr->getParentMap(); auto result = parents.find(expr); if (result != parents.end()) { auto *parent = result->getSecond(); if (isa(parent)) return finish(true, expr); SourceLoc lastInnerParenLoc; // Unwrap to the outermost paren in the sequence. // e.g. `foo(((&bar))` while (auto *PE = dyn_cast(parent)) { auto nextParent = parents.find(parent); if (nextParent == parents.end()) break; lastInnerParenLoc = PE->getLParenLoc(); parent = nextParent->second; } if (isa(parent) || isa(parent)) { // If outermost paren is associated with a call or // a member reference, it might be valid to have `&` // before all of the parens. if (lastInnerParenLoc.isValid()) { auto &DE = getASTContext().Diags; auto diag = DE.diagnose(expr->getStartLoc(), diag::extraneous_address_of); diag.fixItExchange(expr->getLoc(), lastInnerParenLoc); } return finish(true, expr); } if (isa(parent)) { getASTContext().Diags.diagnose( expr->getStartLoc(), diag::cannot_pass_inout_arg_to_subscript); return finish(false, nullptr); } } getASTContext().Diags.diagnose(expr->getStartLoc(), diag::extraneous_address_of); return finish(false, nullptr); } if (auto *ISLE = dyn_cast(expr)) { if (!correctInterpolationIfStrange(ISLE)) return finish(false, nullptr); } if (auto *assignment = dyn_cast(expr)) markAcceptableDiscardExprs(assignment->getDest()); return finish(true, expr); } Expr *walkToExprPost(Expr *expr) override { // Remove this expression from the stack. assert(ExprStack.back() == expr); ExprStack.pop_back(); // Mark the direct callee as being a callee. if (auto *call = dyn_cast(expr)) markDirectCallee(call->getFn()); // Fold sequence expressions. if (auto *seqExpr = dyn_cast(expr)) { auto result = TypeChecker::foldSequence(seqExpr, DC); SequenceExprDepth--; return result->walk(*this); } // Type check the type parameters in an UnresolvedSpecializeExpr. if (auto *us = dyn_cast(expr)) { if (auto *typeExpr = simplifyUnresolvedSpecializeExpr(us)) return typeExpr; } // If we're about to step out of a ClosureExpr, restore the DeclContext. if (auto *ce = dyn_cast(expr)) { assert(DC == ce && "DeclContext imbalance"); DC = ce->getParent(); } // A 'self.init' or 'super.init' application inside a constructor will // evaluate to void, with the initializer's result implicitly rebound // to 'self'. Recognize the unresolved constructor expression and // determine where to place the RebindSelfInConstructorExpr node. // When updating this logic, also update // RebindSelfInConstructorExpr::getCalledConstructor. auto &ctx = getASTContext(); if (auto unresolvedDot = dyn_cast(expr)) { if (auto self = TypeChecker::getSelfForInitDelegationInConstructor( DC, unresolvedDot)) { // Walk our ancestor expressions looking for the appropriate place // to insert the RebindSelfInConstructorExpr. Expr *target = nullptr; bool foundApply = false; bool foundRebind = false; for (auto ancestor : llvm::reverse(ExprStack)) { if (isa(ancestor)) { // If we already have a rebind, then we're re-typechecking an // expression and are done. foundRebind = true; break; } // Recognize applications. if (auto apply = dyn_cast(ancestor)) { // If we already saw an application, we're done. if (foundApply) break; // If the function being called is not our unresolved initializer // reference, we're done. if (apply->getSemanticFn() != unresolvedDot) break; foundApply = true; target = ancestor; continue; } // Look through identity, force-value, and 'try' expressions. if (isa(ancestor) || isa(ancestor) || isa(ancestor)) { if (target) target = ancestor; continue; } // No other expression kinds are permitted. break; } // If we found a rebind target, note the insertion point. if (target && !foundRebind) { UnresolvedCtorRebindTarget = target; UnresolvedCtorSelf = self; } } } // If the expression we've found is the intended target of an // RebindSelfInConstructorExpr, wrap it in the // RebindSelfInConstructorExpr. if (expr == UnresolvedCtorRebindTarget) { expr = new (ctx) RebindSelfInConstructorExpr(expr, UnresolvedCtorSelf); UnresolvedCtorRebindTarget = nullptr; return expr; } // Double check if there are any BindOptionalExpr remaining in the // tree (see comment below for more details), if there are no BOE // expressions remaining remove OptionalEvaluationExpr from the tree. if (auto OEE = dyn_cast(expr)) { bool hasBindOptional = false; OEE->forEachChildExpr([&](Expr *expr) -> Expr * { if (isa(expr)) hasBindOptional = true; // If at least a single BOE was found, no reason // to walk any further in the tree. return hasBindOptional ? nullptr : expr; }); return hasBindOptional ? OEE : OEE->getSubExpr(); } // Check if there are any BindOptionalExpr in the tree which // wrap DiscardAssignmentExpr, such situation corresponds to syntax // like - `_? = `, since it doesn't really make // sense to have optional assignment to discarded LValue which can // never be optional, we can remove BOE from the tree and avoid // generating any of the unnecessary constraints. if (auto BOE = dyn_cast(expr)) { if (auto DAE = dyn_cast(BOE->getSubExpr())) if (CorrectDiscardAssignmentExprs.count(DAE)) return DAE; } // If this is a sugared type that needs to be folded into a single // TypeExpr, do it. if (auto *simplified = simplifyTypeExpr(expr)) return simplified; // Diagnose a '_' that isn't on the immediate LHS of an assignment. We // skip diagnostics if we've explicitly marked the expression as valid, // or if we're inside a SequenceExpr (since the whole tree will be // re-checked when we finish folding anyway). if (auto *DAE = dyn_cast(expr)) { if (!CorrectDiscardAssignmentExprs.count(DAE) && SequenceExprDepth == 0) { ctx.Diags.diagnose(expr->getLoc(), diag::discard_expr_outside_of_assignment); return nullptr; } } if (auto KPE = dyn_cast(expr)) { resolveKeyPathExpr(KPE); return KPE; } if (auto *simplified = simplifyTypeConstructionWithLiteralArg(expr)) return simplified; // If we find an unresolved member chain, wrap it in an // UnresolvedMemberChainResultExpr (unless this has already been done). auto *parent = Parent.getAsExpr(); if (isMemberChainTail(expr, parent)) if (auto *UME = TypeChecker::getUnresolvedMemberChainBase(expr)) if (!parent || !isa(parent)) return new (ctx) UnresolvedMemberChainResultExpr(expr, UME); return expr; } std::pair walkToStmtPre(Stmt *stmt) override { return { true, stmt }; } bool walkToDeclPre(Decl *D) override { return isa(D); } std::pair walkToPatternPre(Pattern *pattern) override { // With multi-statement closure inference enabled, constraint generation // is responsible for pattern verification and type-checking in the body // of the closure, so there is no need to walk into patterns. bool walkIntoPatterns = !(isa(DC) && Ctx.TypeCheckerOpts.EnableMultiStatementClosureInference); return {walkIntoPatterns, pattern}; } }; } // end anonymous namespace /// Perform prechecking of a ClosureExpr before we dive into it. This returns /// true when we want the body to be considered part of this larger expression. bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) { // If we won't be checking the body of the closure, don't walk into it here. if (!closure->hasSingleExpressionBody()) { if (LeaveClosureBodiesUnchecked) return false; if (!Ctx.TypeCheckerOpts.EnableMultiStatementClosureInference) return false; } // Update the current DeclContext to be the closure we're about to // recurse into. assert((closure->getParent() == DC || closure->getParent()->isChildContextOf(DC)) && "Decl context isn't correct"); DC = closure; return true; } TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) { if (!UDE->getName().isSimpleName() || UDE->getName().isSpecial()) return nullptr; auto Name = UDE->getName(); auto NameLoc = UDE->getNameLoc().getBaseNameLoc(); // Qualified type lookup with a module base is represented as a DeclRefExpr // and not a TypeExpr. if (auto *DRE = dyn_cast(UDE->getBase())) { if (auto *TD = dyn_cast(DRE->getDecl())) { // See if the type has a member type with this name. auto Result = TypeChecker::lookupMemberType( DC, TD->getDeclaredInterfaceType(), Name, defaultMemberLookupOptions); // If there is no nested type with this name, we have a lookup of // a non-type member, so leave the expression as-is. if (Result.size() == 1) { return TypeExpr::createForMemberDecl( DRE->getNameLoc(), TD, UDE->getNameLoc(), Result.front().Member); } } return nullptr; } auto *TyExpr = dyn_cast(UDE->getBase()); if (!TyExpr) return nullptr; auto *InnerTypeRepr = TyExpr->getTypeRepr(); if (!InnerTypeRepr) return nullptr; // Fold 'T.Protocol' into a protocol metatype. if (Name.isSimpleName(getASTContext().Id_Protocol)) { auto *NewTypeRepr = new (getASTContext()) ProtocolTypeRepr(InnerTypeRepr, NameLoc); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold 'T.Type' into an existential metatype if 'T' is a protocol, // or an ordinary metatype otherwise. if (Name.isSimpleName(getASTContext().Id_Type)) { auto *NewTypeRepr = new (getASTContext()) MetatypeTypeRepr(InnerTypeRepr, NameLoc); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold 'T.U' into a nested type. if (auto *ITR = dyn_cast(InnerTypeRepr)) { // Resolve the TypeRepr to get the base type for the lookup. const auto BaseTy = TypeResolution::resolveContextualType( InnerTypeRepr, DC, TypeResolverContext::InExpression, [](auto unboundTy) { // FIXME: Don't let unbound generic types escape type resolution. // For now, just return the unbound generic type. return unboundTy; }, // FIXME: Don't let placeholder types escape type resolution. // For now, just return the placeholder type. PlaceholderType::get); if (BaseTy->mayHaveMembers()) { // See if there is a member type with this name. auto Result = TypeChecker::lookupMemberType(DC, BaseTy, Name, defaultMemberLookupOptions); // If there is no nested type with this name, we have a lookup of // a non-type member, so leave the expression as-is. if (Result.size() == 1) { return TypeExpr::createForMemberDecl(ITR, UDE->getNameLoc(), Result.front().Member); } } } return nullptr; } TypeExpr *PreCheckExpression::simplifyUnresolvedSpecializeExpr( UnresolvedSpecializeExpr *us) { // If this is a reference type a specialized type, form a TypeExpr. // The base should be a TypeExpr that we already resolved. if (auto *te = dyn_cast(us->getSubExpr())) { if (auto *ITR = dyn_cast_or_null(te->getTypeRepr())) { return TypeExpr::createForSpecializedDecl(ITR, us->getUnresolvedParams(), SourceRange(us->getLAngleLoc(), us->getRAngleLoc()), getASTContext()); } } return nullptr; } bool PreCheckExpression::possiblyInTypeContext(Expr *E) { // Walk back up the stack of parents looking for a valid type context. for (auto *ParentExpr : llvm::reverse(ExprStack)) { // We're considered to be in a type context if either: // - We have a valid parent for a TypeExpr, or // - The parent "looks like" a type (and is not a call arg), and we can // reach a valid parent for a TypeExpr if we continue walking. if (ParentExpr->isValidParentOfTypeExpr(E)) return true; if (!exprLooksLikeAType(ParentExpr)) return false; E = ParentExpr; } return false; } /// Only allow simplification of a DiscardAssignmentExpr if it hasn't already /// been explicitly marked as correct, and the current AST state allows it. bool PreCheckExpression::canSimplifyDiscardAssignmentExpr( DiscardAssignmentExpr *DAE) { return !CorrectDiscardAssignmentExprs.count(DAE) && SequenceExprDepth == 0 && possiblyInTypeContext(DAE); } /// Simplify expressions which are type sugar productions that got parsed /// as expressions due to the parser not knowing which identifiers are /// type names. TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) { // Fold member types. if (auto *UDE = dyn_cast(E)) { return simplifyNestedTypeExpr(UDE); } // Fold '_' into a placeholder type, if we're allowed. if (auto *DAE = dyn_cast(E)) { if (canSimplifyDiscardAssignmentExpr(DAE)) { auto *placeholderRepr = new (getASTContext()) PlaceholderTypeRepr(DAE->getLoc()); return new (getASTContext()) TypeExpr(placeholderRepr); } } // Fold T? into an optional type when T is a TypeExpr. if (isa(E) || isa(E)) { TypeExpr *TyExpr; SourceLoc QuestionLoc; if (auto *OOE = dyn_cast(E)) { TyExpr = dyn_cast(OOE->getSubExpr()); QuestionLoc = OOE->getLoc(); } else { TyExpr = dyn_cast(cast(E)->getSubExpr()); QuestionLoc = cast(E)->getQuestionLoc(); } if (!TyExpr) return nullptr; auto *InnerTypeRepr = TyExpr->getTypeRepr(); assert(!TyExpr->isImplicit() && InnerTypeRepr && "This doesn't work on implicit TypeExpr's, " "the TypeExpr should have been built correctly in the first place"); // The optional evaluation is passed through. if (isa(E)) return TyExpr; auto *NewTypeRepr = new (getASTContext()) OptionalTypeRepr(InnerTypeRepr, QuestionLoc); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold T! into an IUO type when T is a TypeExpr. if (auto *FVE = dyn_cast(E)) { auto *TyExpr = dyn_cast(FVE->getSubExpr()); if (!TyExpr) return nullptr; auto *InnerTypeRepr = TyExpr->getTypeRepr(); assert(!TyExpr->isImplicit() && InnerTypeRepr && "This doesn't work on implicit TypeExpr's, " "the TypeExpr should have been built correctly in the first place"); auto *NewTypeRepr = new (getASTContext()) ImplicitlyUnwrappedOptionalTypeRepr(InnerTypeRepr, FVE->getExclaimLoc()); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold (T) into a type T with parens around it. if (auto *PE = dyn_cast(E)) { auto *TyExpr = dyn_cast(PE->getSubExpr()); if (!TyExpr) return nullptr; TupleTypeReprElement InnerTypeRepr[] = { TyExpr->getTypeRepr() }; assert(!TyExpr->isImplicit() && InnerTypeRepr[0].Type && "SubscriptExpr doesn't work on implicit TypeExpr's, " "the TypeExpr should have been built correctly in the first place"); auto *NewTypeRepr = TupleTypeRepr::create(getASTContext(), InnerTypeRepr, PE->getSourceRange()); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold a tuple expr like (T1,T2) into a tuple type (T1,T2). if (auto *TE = dyn_cast(E)) { // FIXME: Decide what to do about (). It could be a type or an expr. if (TE->getNumElements() == 0) return nullptr; SmallVector Elts; unsigned EltNo = 0; for (auto Elt : TE->getElements()) { auto *eltTE = dyn_cast(Elt); if (!eltTE) return nullptr; TupleTypeReprElement elt; assert(eltTE->getTypeRepr() && !eltTE->isImplicit() && "This doesn't work on implicit TypeExpr's, the " "TypeExpr should have been built correctly in the first place"); // If the tuple element has a label, propagate it. elt.Type = eltTE->getTypeRepr(); Identifier name = TE->getElementName(EltNo); if (!name.empty()) { elt.Name = name; elt.NameLoc = TE->getElementNameLoc(EltNo); } Elts.push_back(elt); ++EltNo; } auto *NewTypeRepr = TupleTypeRepr::create( getASTContext(), Elts, TE->getSourceRange(), SourceLoc(), Elts.size()); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold [T] into an array type. if (auto *AE = dyn_cast(E)) { if (AE->getElements().size() != 1) return nullptr; auto *TyExpr = dyn_cast(AE->getElement(0)); if (!TyExpr) return nullptr; auto *NewTypeRepr = new (getASTContext()) ArrayTypeRepr(TyExpr->getTypeRepr(), SourceRange(AE->getLBracketLoc(), AE->getRBracketLoc())); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Fold [K : V] into a dictionary type. if (auto *DE = dyn_cast(E)) { if (DE->getElements().size() != 1) return nullptr; TypeRepr *keyTypeRepr, *valueTypeRepr; if (auto EltTuple = dyn_cast(DE->getElement(0))) { auto *KeyTyExpr = dyn_cast(EltTuple->getElement(0)); if (!KeyTyExpr) return nullptr; auto *ValueTyExpr = dyn_cast(EltTuple->getElement(1)); if (!ValueTyExpr) return nullptr; keyTypeRepr = KeyTyExpr->getTypeRepr(); valueTypeRepr = ValueTyExpr->getTypeRepr(); } else { auto *TE = dyn_cast(DE->getElement(0)); if (!TE) return nullptr; auto *TRE = dyn_cast_or_null(TE->getTypeRepr()); if (!TRE || TRE->getEllipsisLoc().isValid()) return nullptr; while (TRE->isParenType()) { TRE = dyn_cast_or_null(TRE->getElementType(0)); if (!TRE || TRE->getEllipsisLoc().isValid()) return nullptr; } assert(TRE->getElements().size() == 2); keyTypeRepr = TRE->getElementType(0); valueTypeRepr = TRE->getElementType(1); } auto *NewTypeRepr = new (getASTContext()) DictionaryTypeRepr( keyTypeRepr, valueTypeRepr, /*FIXME:colonLoc=*/SourceLoc(), SourceRange(DE->getLBracketLoc(), DE->getRBracketLoc())); return new (getASTContext()) TypeExpr(NewTypeRepr); } // Reinterpret arrow expr T1 -> T2 as function type. // FIXME: support 'inout', etc. if (auto *AE = dyn_cast(E)) { if (!AE->isFolded()) return nullptr; auto diagnoseMissingParens = [](ASTContext &ctx, TypeRepr *tyR) { bool isVoid = false; if (const auto Void = dyn_cast(tyR)) { if (Void->getNameRef().isSimpleName(ctx.Id_Void)) { isVoid = true; } } if (isVoid) { ctx.Diags.diagnose(tyR->getStartLoc(), diag::function_type_no_parens) .fixItReplace(tyR->getStartLoc(), "()"); } else { ctx.Diags.diagnose(tyR->getStartLoc(), diag::function_type_no_parens) .highlight(tyR->getSourceRange()) .fixItInsert(tyR->getStartLoc(), "(") .fixItInsertAfter(tyR->getEndLoc(), ")"); } }; auto &ctx = getASTContext(); auto extractInputTypeRepr = [&](Expr *E) -> TupleTypeRepr * { if (!E) return nullptr; if (auto *TyE = dyn_cast(E)) { auto ArgRepr = TyE->getTypeRepr(); if (auto *TTyRepr = dyn_cast(ArgRepr)) return TTyRepr; diagnoseMissingParens(ctx, ArgRepr); return TupleTypeRepr::create(ctx, {ArgRepr}, ArgRepr->getSourceRange()); } if (auto *TE = dyn_cast(E)) if (TE->getNumElements() == 0) return TupleTypeRepr::createEmpty(getASTContext(), TE->getSourceRange()); // When simplifying a type expr like "(P1 & P2) -> (P3 & P4) -> Int", // it may have been folded at the same time; recursively simplify it. if (auto ArgsTypeExpr = simplifyTypeExpr(E)) { auto ArgRepr = ArgsTypeExpr->getTypeRepr(); if (auto *TTyRepr = dyn_cast(ArgRepr)) return TTyRepr; diagnoseMissingParens(ctx, ArgRepr); return TupleTypeRepr::create(ctx, {ArgRepr}, ArgRepr->getSourceRange()); } return nullptr; }; auto extractTypeRepr = [&](Expr *E) -> TypeRepr * { if (!E) return nullptr; if (auto *TyE = dyn_cast(E)) return TyE->getTypeRepr(); if (auto *TE = dyn_cast(E)) if (TE->getNumElements() == 0) return TupleTypeRepr::createEmpty(ctx, TE->getSourceRange()); // When simplifying a type expr like "P1 & P2 -> P3 & P4 -> Int", // it may have been folded at the same time; recursively simplify it. if (auto ArgsTypeExpr = simplifyTypeExpr(E)) return ArgsTypeExpr->getTypeRepr(); return nullptr; }; TupleTypeRepr *ArgsTypeRepr = extractInputTypeRepr(AE->getArgsExpr()); if (!ArgsTypeRepr) { ctx.Diags.diagnose(AE->getArgsExpr()->getLoc(), diag::expected_type_before_arrow); auto ArgRange = AE->getArgsExpr()->getSourceRange(); auto ErrRepr = new (ctx) ErrorTypeRepr(ArgRange); ArgsTypeRepr = TupleTypeRepr::create(ctx, {ErrRepr}, ArgRange); } TypeRepr *ResultTypeRepr = extractTypeRepr(AE->getResultExpr()); if (!ResultTypeRepr) { ctx.Diags.diagnose(AE->getResultExpr()->getLoc(), diag::expected_type_after_arrow); ResultTypeRepr = new (ctx) ErrorTypeRepr(AE->getResultExpr()->getSourceRange()); } auto NewTypeRepr = new (ctx) FunctionTypeRepr(nullptr, ArgsTypeRepr, AE->getAsyncLoc(), AE->getThrowsLoc(), AE->getArrowLoc(), ResultTypeRepr); return new (ctx) TypeExpr(NewTypeRepr); } // Fold 'P & Q' into a composition type if (auto *binaryExpr = getCompositionExpr(E)) { // The protocols we are composing SmallVector Types; auto lhsExpr = binaryExpr->getLHS(); if (auto *lhs = dyn_cast(lhsExpr)) { Types.push_back(lhs->getTypeRepr()); } else if (isa(lhsExpr)) { // If the lhs is another binary expression, we have a multi element // composition: 'A & B & C' is parsed as ((A & B) & C); we get // the protocols from the lhs here if (auto expr = simplifyTypeExpr(lhsExpr)) if (auto *repr = dyn_cast(expr->getTypeRepr())) // add the protocols to our list for (auto proto : repr->getTypes()) Types.push_back(proto); else return nullptr; else return nullptr; } else return nullptr; // Add the rhs which is just a TypeExpr auto *rhs = dyn_cast(binaryExpr->getRHS()); if (!rhs) return nullptr; Types.push_back(rhs->getTypeRepr()); auto CompRepr = CompositionTypeRepr::create(getASTContext(), Types, lhsExpr->getStartLoc(), binaryExpr->getSourceRange()); return new (getASTContext()) TypeExpr(CompRepr); } return nullptr; } void PreCheckExpression::resolveKeyPathExpr(KeyPathExpr *KPE) { if (KPE->isObjC()) return; if (!KPE->getComponents().empty()) return; TypeRepr *rootType = nullptr; SmallVector components; auto &DE = getASTContext().Diags; // Pre-order visit of a sequence foo.bar[0]?.baz, which means that the // components are pushed in reverse order. auto traversePath = [&](Expr *expr, bool isInParsedPath, bool emitErrors = true) { Expr *outermostExpr = expr; // We can end up in scenarios where the key path has contextual type, // but is missing a leading dot. This can happen when we have an // implicit TypeExpr or an implicit DeclRefExpr. auto diagnoseMissingDot = [&]() { DE.diagnose(expr->getLoc(), diag::expr_swift_keypath_not_starting_with_dot) .fixItInsert(expr->getStartLoc(), "."); }; while (1) { // Base cases: we've reached the top. if (auto TE = dyn_cast(expr)) { assert(!isInParsedPath); rootType = TE->getTypeRepr(); if (TE->isImplicit() && !KPE->expectsContextualRoot()) diagnoseMissingDot(); return; } else if (isa(expr)) { assert(isInParsedPath); // Nothing here: the type is either the root, or is inferred. return; } else if (!KPE->expectsContextualRoot() && expr->isImplicit() && isa(expr)) { assert(!isInParsedPath); diagnoseMissingDot(); return; } // Recurring cases: if (auto SE = dyn_cast(expr)) { // .self, the identity component. components.push_back(KeyPathExpr::Component::forIdentity( SE->getSelfLoc())); expr = SE->getSubExpr(); } else if (auto UDE = dyn_cast(expr)) { // .foo components.push_back(KeyPathExpr::Component::forUnresolvedProperty( UDE->getName(), UDE->getLoc())); expr = UDE->getBase(); } else if (auto CCE = dyn_cast(expr)) { components.push_back( KeyPathExpr::Component::forCodeCompletion(CCE->getLoc())); expr = CCE->getBase(); if (!expr) { // We are completing on the key path's base. Stop iterating. return; } } else if (auto SE = dyn_cast(expr)) { // .[0] or just plain [0] components.push_back(KeyPathExpr::Component::forUnresolvedSubscript( getASTContext(), SE->getArgs())); expr = SE->getBase(); } else if (auto BOE = dyn_cast(expr)) { // .? or ? components.push_back(KeyPathExpr::Component::forUnresolvedOptionalChain( BOE->getQuestionLoc())); expr = BOE->getSubExpr(); } else if (auto FVE = dyn_cast(expr)) { // .! or ! components.push_back(KeyPathExpr::Component::forUnresolvedOptionalForce( FVE->getExclaimLoc())); expr = FVE->getSubExpr(); } else if (auto OEE = dyn_cast(expr)) { // Do nothing: this is implied to exist as the last expression, by the // BindOptionalExprs, but is irrelevant to the components. (void)outermostExpr; assert(OEE == outermostExpr); expr = OEE->getSubExpr(); } else { if (emitErrors) { // \() may be an attempt to write a string interpolation outside // of a string literal; diagnose this case specially. if (isa(expr) || isa(expr)) { DE.diagnose(expr->getLoc(), diag::expr_string_interpolation_outside_string); } else { DE.diagnose(expr->getLoc(), diag::expr_swift_keypath_invalid_component); } } components.push_back(KeyPathExpr::Component()); return; } } }; auto root = KPE->getParsedRoot(); auto path = KPE->getParsedPath(); if (path) { traversePath(path, /*isInParsedPath=*/true); // This path looks like \Foo.Bar.[0].baz, which means Foo.Bar has to be a // type. if (root) { if (auto TE = dyn_cast(root)) { rootType = TE->getTypeRepr(); } else { // FIXME: Probably better to catch this case earlier and force-eval as // TypeExpr. DE.diagnose(root->getLoc(), diag::expr_swift_keypath_not_starting_with_type); // Traverse this path for recovery purposes: it may be a typo like // \Foo.property.[0]. traversePath(root, /*isInParsedPath=*/false, /*emitErrors=*/false); } } } else { traversePath(root, /*isInParsedPath=*/false); } // Key paths must be spelled with at least one component. if (components.empty()) { // Passes further down the pipeline expect keypaths to always have at least // one component, so stuff an invalid component in the AST for recovery. components.push_back(KeyPathExpr::Component()); } std::reverse(components.begin(), components.end()); KPE->setRootType(rootType); KPE->setComponents(getASTContext(), components); } Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { // If constructor call is expected to produce an optional let's not attempt // this optimization because literal initializers aren't failable. if (!getASTContext().LangOpts.isSwiftVersionAtLeast(5)) { if (!ExprStack.empty()) { auto *parent = ExprStack.back(); if (isa(parent) || isa(parent)) return nullptr; } } auto *call = dyn_cast(E); if (!call) return nullptr; auto *typeExpr = dyn_cast(call->getFn()); if (!typeExpr) return nullptr; auto *unaryArg = call->getArgs()->getUnlabeledUnaryExpr(); if (!unaryArg) return nullptr; auto *literal = dyn_cast(unaryArg->getSemanticsProvidingExpr()); if (!literal) return nullptr; auto *protocol = TypeChecker::getLiteralProtocol(getASTContext(), literal); if (!protocol) return nullptr; Type castTy; if (auto precheckedTy = typeExpr->getInstanceType()) { castTy = precheckedTy; } else { const auto options = TypeResolutionOptions(TypeResolverContext::InExpression) | TypeResolutionFlags::SilenceErrors; const auto result = TypeResolution::resolveContextualType( typeExpr->getTypeRepr(), DC, options, [](auto unboundTy) { // FIXME: Don't let unbound generic types escape type resolution. // For now, just return the unbound generic type. return unboundTy; }, // FIXME: Don't let placeholder types escape type resolution. // For now, just return the placeholder type. PlaceholderType::get); if (result->hasError()) return nullptr; castTy = result; } if (!castTy->getAnyNominal()) return nullptr; // Don't bother to convert deprecated selector syntax. if (auto selectorTy = getASTContext().getSelectorType()) { if (castTy->isEqual(selectorTy)) return nullptr; } SmallVector conformances; return castTy->getAnyNominal()->lookupConformance(protocol, conformances) ? CoerceExpr::forLiteralInit(getASTContext(), literal, call->getSourceRange(), typeExpr->getTypeRepr()) : nullptr; } /// Pre-check the expression, validating any types that occur in the /// expression and folding sequence expressions. bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc, bool replaceInvalidRefsWithErrors, bool leaveClosureBodiesUnchecked) { auto &ctx = dc->getASTContext(); FrontendStatsTracer StatsTracer(ctx.Stats, "precheck-expr", expr); PreCheckExpression preCheck(dc, expr, replaceInvalidRefsWithErrors, leaveClosureBodiesUnchecked); // Perform the pre-check. if (auto result = expr->walk(preCheck)) { expr = result; return false; } return true; }