diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 2f616623e30..7afd8e75db8 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1741,17 +1741,6 @@ public: llvm::function_ref getType = [](const Expr *E) -> Type { return E->getType(); }); - /// Create a new dynamic subscript. - static DynamicSubscriptExpr *create(ASTContext &ctx, Expr *base, - SourceLoc lSquareLoc, - ArrayRef indexArgs, - ArrayRef indexArgLabels, - ArrayRef indexArgLabelLocs, - SourceLoc rSquareLoc, - Expr *trailingClosure, - ConcreteDeclRef decl, - bool implicit); - /// getIndex - Retrieve the index of the subscript expression, i.e., the /// "offset" into the base value. Expr *getIndex() const { return Index; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7eb779525f5..9296e947989 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1504,33 +1504,6 @@ DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, Expr *index, hasTrailingClosure, decl, implicit); } -DynamicSubscriptExpr * -DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, SourceLoc lSquareLoc, - ArrayRef indexArgs, - ArrayRef indexArgLabels, - ArrayRef indexArgLabelLocs, - SourceLoc rSquareLoc, - Expr *trailingClosure, - ConcreteDeclRef decl, - bool implicit) { - SmallVector indexArgLabelsScratch; - SmallVector indexArgLabelLocsScratch; - Expr *index = packSingleArgument(ctx, lSquareLoc, indexArgs, indexArgLabels, - indexArgLabelLocs, rSquareLoc, - trailingClosure, implicit, - indexArgLabelsScratch, - indexArgLabelLocsScratch); - - size_t size = totalSizeToAlloc(indexArgLabels, indexArgLabelLocs, - trailingClosure != nullptr); - - void *memory = ctx.Allocate(size, alignof(DynamicSubscriptExpr)); - return new (memory) DynamicSubscriptExpr(base, index, indexArgLabels, - indexArgLabelLocs, - trailingClosure != nullptr, - decl, implicit); -} - UnresolvedMemberExpr::UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, DeclNameRef name, Expr *argument, diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index e9d0a412b31..e9e409e069f 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1228,41 +1228,13 @@ namespace { bool hasTrailingClosure, ConstraintLocatorBuilder locator, bool isImplicit, AccessSemantics semantics, - Optional selected = None) { - - // Determine the declaration selected for this subscript operation. - if (!selected) - selected = solution.getOverloadChoiceIfAvailable( - cs.getConstraintLocator( - locator.withPathElement( - ConstraintLocator::SubscriptMember))); - - // Handles situation where there was a solution available but it didn't - // have a proper overload selected from subscript call, might be because - // solver was allowed to return free or unresolved types, which can - // happen while running diagnostics on one of the expressions. - if (!selected.hasValue()) { - auto &de = cs.getASTContext().Diags; - auto baseType = cs.getType(base); - - if (auto errorType = baseType->getAs()) { - de.diagnose(base->getLoc(), diag::cannot_subscript_base, - errorType->getOriginalType()) - .highlight(base->getSourceRange()); - } else { - de.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base) - .highlight(base->getSourceRange()); - } - - return nullptr; - } - + const SelectedOverload &selected) { // Build the new subscript. auto newSubscript = buildSubscriptHelper(base, index, argLabels, - *selected, hasTrailingClosure, + selected, hasTrailingClosure, locator, isImplicit, semantics); - if (selected->choice.getKind() == OverloadChoiceKind::DeclViaDynamic) { + if (selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic) { // Rewrite for implicit unwrapping if the solution requires it. auto *dynamicLocator = cs.getConstraintLocator( locator, {ConstraintLocator::SubscriptMember, @@ -1277,19 +1249,19 @@ namespace { } } - if (selected->choice.isDecl()) { + if (selected.choice.isDecl()) { auto locatorKind = ConstraintLocator::SubscriptMember; - if (selected->choice.getKind() == + if (selected.choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) locatorKind = ConstraintLocator::Member; - if (selected->choice.getKind() == + if (selected.choice.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup && !isa(locator.getAnchor())) locatorKind = ConstraintLocator::Member; newSubscript = - forceUnwrapIfExpected(newSubscript, selected->choice, + forceUnwrapIfExpected(newSubscript, selected.choice, locator.withPathElement(locatorKind)); } @@ -1298,7 +1270,7 @@ namespace { Expr *buildSubscriptHelper(Expr *base, Expr *index, ArrayRef argLabels, - SelectedOverload &selected, + const SelectedOverload &selected, bool hasTrailingClosure, ConstraintLocatorBuilder locator, bool isImplicit, AccessSemantics semantics) { @@ -2862,8 +2834,29 @@ namespace { cs.getConstraintLocator(expr, ConstraintLocator::SubscriptMember); auto overload = solution.getOverloadChoiceIfAvailable(memberLocator); - if (overload && overload->choice.getKind() == - OverloadChoiceKind::KeyPathDynamicMemberLookup) { + // Handles situation where there was a solution available but it didn't + // have a proper overload selected from subscript call, might be because + // solver was allowed to return free or unresolved types, which can + // happen while running diagnostics on one of the expressions. + if (!overload) { + const auto *base = expr->getBase(); + auto &de = cs.getASTContext().Diags; + auto baseType = cs.getType(base); + + if (auto errorType = baseType->getAs()) { + de.diagnose(base->getLoc(), diag::cannot_subscript_base, + errorType->getOriginalType()) + .highlight(base->getSourceRange()); + } else { + de.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base) + .highlight(base->getSourceRange()); + } + + return nullptr; + } + + if (overload->choice.getKind() == + OverloadChoiceKind::KeyPathDynamicMemberLookup) { return buildDynamicMemberLookupRef( expr, expr->getBase(), expr->getIndex()->getStartLoc(), SourceLoc(), *overload, memberLocator); @@ -2872,7 +2865,7 @@ namespace { return buildSubscript( expr->getBase(), expr->getIndex(), expr->getArgumentLabels(), expr->hasTrailingClosure(), cs.getConstraintLocator(expr), - expr->isImplicit(), expr->getAccessSemantics(), overload); + expr->isImplicit(), expr->getAccessSemantics(), *overload); } /// "Finish" an array expression by filling in the semantic expression. @@ -2967,11 +2960,14 @@ namespace { } Expr *visitDynamicSubscriptExpr(DynamicSubscriptExpr *expr) { + auto *memberLocator = + cs.getConstraintLocator(expr, ConstraintLocator::SubscriptMember); return buildSubscript(expr->getBase(), expr->getIndex(), expr->getArgumentLabels(), expr->hasTrailingClosure(), cs.getConstraintLocator(expr), - expr->isImplicit(), AccessSemantics::Ordinary); + expr->isImplicit(), AccessSemantics::Ordinary, + solution.getOverloadChoice(memberLocator)); } Expr *visitTupleElementExpr(TupleElementExpr *expr) { @@ -4193,8 +4189,6 @@ namespace { } auto kind = origComponent.getKind(); - Optional foundDecl; - auto locator = cs.getConstraintLocator( E, LocatorPathElt::KeyPathComponent(i)); @@ -4207,48 +4201,42 @@ namespace { // If this is an unresolved link, make sure we resolved it. if (kind == KeyPathExpr::Component::Kind::UnresolvedProperty || kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) { - foundDecl = solution.getOverloadChoiceIfAvailable(locator); - // Leave the component unresolved if the overload was not resolved. - if (foundDecl) { - isDynamicMember = - foundDecl->choice.getKind() == - OverloadChoiceKind::DynamicMemberLookup || - foundDecl->choice.getKind() == - OverloadChoiceKind::KeyPathDynamicMemberLookup; + auto foundDecl = solution.getOverloadChoiceIfAvailable(locator); + if (!foundDecl) { + // If we couldn't resolve the component, leave it alone. + resolvedComponents.push_back(origComponent); + baseTy = origComponent.getComponentType(); + continue; + } - // If this was a @dynamicMemberLookup property, then we actually - // form a subscript reference, so switch the kind. - if (isDynamicMember) { - kind = KeyPathExpr::Component::Kind::UnresolvedSubscript; - } + isDynamicMember = + foundDecl->choice.getKind() == + OverloadChoiceKind::DynamicMemberLookup || + foundDecl->choice.getKind() == + OverloadChoiceKind::KeyPathDynamicMemberLookup; + + // If this was a @dynamicMemberLookup property, then we actually + // form a subscript reference, so switch the kind. + if (isDynamicMember) { + kind = KeyPathExpr::Component::Kind::UnresolvedSubscript; } } switch (kind) { case KeyPathExpr::Component::Kind::UnresolvedProperty: { - // If we couldn't resolve the component, leave it alone. - if (!foundDecl) { - resolvedComponents.push_back(origComponent); - break; - } - - buildKeyPathPropertyComponent(*foundDecl, origComponent.getLoc(), + buildKeyPathPropertyComponent(solution.getOverloadChoice(locator), + origComponent.getLoc(), locator, resolvedComponents); break; } case KeyPathExpr::Component::Kind::UnresolvedSubscript: { - // Leave the component unresolved if the overload was not resolved. - if (!foundDecl) { - resolvedComponents.push_back(origComponent); - break; - } - ArrayRef subscriptLabels; if (!isDynamicMember) subscriptLabels = origComponent.getSubscriptLabels(); buildKeyPathSubscriptComponent( - *foundDecl, origComponent.getLoc(), origComponent.getIndexExpr(), + solution.getOverloadChoice(locator), + origComponent.getLoc(), origComponent.getIndexExpr(), subscriptLabels, locator, resolvedComponents); break; } @@ -4485,7 +4473,8 @@ namespace { } void buildKeyPathSubscriptComponent( - SelectedOverload &overload, SourceLoc componentLoc, Expr *indexExpr, + const SelectedOverload &overload, + SourceLoc componentLoc, Expr *indexExpr, ArrayRef labels, ConstraintLocator *locator, SmallVectorImpl &components) { auto subscript = cast(overload.choice.getDecl()); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 493dc657f42..bcbefc2315b 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -471,19 +471,19 @@ enum class SolutionCompareResult { /// declaration was opened, which may involve type variables. struct SelectedOverload { /// The overload choice. - OverloadChoice choice; + const OverloadChoice choice; /// The opened type of the base of the reference to this overload, if /// we're referencing a member. - Type openedFullType; + const Type openedFullType; /// The opened type produced by referring to this overload. - Type openedType; + const Type openedType; /// The type that this overload binds. Note that this may differ from /// openedType, for example it will include any IUO unwrapping that has taken /// place. - Type boundType; + const Type boundType; }; /// Provides information about the application of a function argument to a