Skip to content

Commit c59da27

Browse files
authored
Merge pull request #2864 from swiftwasm/main
[pull] swiftwasm from main
2 parents 129e912 + 2e0bda5 commit c59da27

19 files changed

+529
-134
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ SIMPLE_DECL_ATTR(reasync, AtReasync,
624624
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
625625
110)
626626

627-
DECL_ATTR(hasAsyncAlternative, HasAsyncAlternative,
627+
DECL_ATTR(completionHandlerAsync, CompletionHandlerAsync,
628628
OnAbstractFunction | ConcurrencyOnly |
629629
ABIStableToAdd | ABIStableToRemove |
630630
APIStableToAdd | APIStableToRemove,

include/swift/AST/Attr.h

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,27 +2147,59 @@ class TransposeAttr final
21472147
}
21482148
};
21492149

2150-
/// The `@hasAsyncAlternative` attribute marks a function as having an async
2150+
/// The `@completionHandlerAsync` attribute marks a function as having an async
21512151
/// alternative, optionally providing a name (for cases when the alternative
21522152
/// has a different name).
2153-
class HasAsyncAlternativeAttr final : public DeclAttribute {
2153+
class CompletionHandlerAsyncAttr final : public DeclAttribute {
2154+
private:
2155+
/// DeclName of the async function in the attribute
2156+
const DeclNameRef AsyncFunctionName;
2157+
21542158
public:
2155-
/// An optional name of the async alternative function, where the name of the
2156-
/// attributed function is used otherwise.
2157-
const DeclNameRef Name;
2159+
/// Source location of the async function name in the attribute
2160+
const SourceLoc AsyncFunctionNameLoc;
21582161

2159-
HasAsyncAlternativeAttr(DeclNameRef Name, SourceLoc AtLoc, SourceRange Range)
2160-
: DeclAttribute(DAK_HasAsyncAlternative, AtLoc, Range, false),
2161-
Name(Name) {}
2162+
/// Get the name of the async function
2163+
///
2164+
/// The name will come from the AsyncFunctionDecl if available, otherwise will
2165+
/// fall back on the user-provided name. If that is not defined, this function
2166+
/// will abort.
2167+
DeclNameRef getAsyncFunctionName() const;
2168+
2169+
/// The index of the completion handler
2170+
const size_t CompletionHandlerIndex;
2171+
2172+
/// Source location of the completion handler index passed to the index
2173+
const SourceLoc CompletionHandlerIndexLoc;
2174+
2175+
AbstractFunctionDecl *AsyncFunctionDecl = nullptr;
2176+
2177+
CompletionHandlerAsyncAttr(DeclNameRef asyncFunctionName,
2178+
SourceLoc asyncFunctionNameLoc,
2179+
size_t completionHandlerIndex,
2180+
SourceLoc completionHandlerIndexLoc,
2181+
SourceLoc atLoc, SourceRange range)
2182+
: DeclAttribute(DAK_CompletionHandlerAsync, atLoc, range,
2183+
/*implicit*/ false),
2184+
AsyncFunctionName(asyncFunctionName),
2185+
AsyncFunctionNameLoc(asyncFunctionNameLoc),
2186+
CompletionHandlerIndex(completionHandlerIndex),
2187+
CompletionHandlerIndexLoc(completionHandlerIndexLoc) {}
2188+
2189+
CompletionHandlerAsyncAttr(AbstractFunctionDecl &asyncFunctionDecl,
2190+
size_t completionHandlerIndex,
2191+
SourceLoc completionHandlerIndexLoc,
2192+
SourceLoc atLoc, SourceRange range)
2193+
: DeclAttribute(DAK_CompletionHandlerAsync, atLoc, range,
2194+
/*implicit*/ false),
2195+
CompletionHandlerIndex(completionHandlerIndex),
2196+
CompletionHandlerIndexLoc(completionHandlerIndexLoc),
2197+
AsyncFunctionDecl(&asyncFunctionDecl) {}
21622198

2163-
HasAsyncAlternativeAttr(SourceLoc AtLoc, SourceRange Range)
2164-
: DeclAttribute(DAK_HasAsyncAlternative, AtLoc, Range, false) {}
21652199

2166-
/// Determine whether this attribute has a name associated with it.
2167-
bool hasName() const { return !Name.getBaseName().empty(); }
21682200

21692201
static bool classof(const DeclAttribute *DA) {
2170-
return DA->getKind() == DAK_HasAsyncAlternative;
2202+
return DA->getKind() == DAK_CompletionHandlerAsync;
21712203
}
21722204
};
21732205

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,9 @@ ERROR(attr_expected_comma,none,
13761376
ERROR(attr_expected_string_literal,none,
13771377
"expected string literal in '%0' attribute", (StringRef))
13781378

1379+
ERROR(attr_expected_integer_literal,none,
1380+
"expected integer literal in '%0' attribute", (StringRef))
1381+
13791382
ERROR(attr_expected_option_such_as,none,
13801383
"expected '%0' option such as '%1'", (StringRef, StringRef))
13811384

@@ -1675,8 +1678,8 @@ ERROR(sil_inst_autodiff_invalid_witness_generic_signature,PointsToFirstBadToken,
16751678
"parameters as original function generic signature '%1'",
16761679
(StringRef, StringRef))
16771680

1678-
// hasAsyncAlternative
1679-
ERROR(has_async_alternative_invalid_name, none,
1681+
// completionHandlerAsync
1682+
ERROR(attr_completion_handler_async_invalid_name, none,
16801683
"argument of '%0' attribute must be an identifier or full function name",
16811684
(StringRef))
16821685

include/swift/AST/DiagnosticsSema.def

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,9 @@ NOTE(unspaced_binary_operators_candidate,none,
854854
ERROR(unspaced_unary_operator,none,
855855
"unary operators must not be juxtaposed; parenthesize inner expression",
856856
())
857+
ERROR(nonexistent_power_operator,none,
858+
"no operator '**' is defined; did you mean 'pow(_:_:)'?",
859+
())
857860

858861
ERROR(cannot_find_in_scope,none,
859862
"cannot %select{find|find operator}1 %0 in scope", (DeclNameRef, bool))
@@ -3340,6 +3343,33 @@ ERROR(diff_params_clause_param_not_differentiable,none,
33403343
"can only differentiate with respect to parameters that conform to "
33413344
"'Differentiable', but %0 does not conform to 'Differentiable'", (Type))
33423345

3346+
// completionHanderAsync attribute
3347+
ERROR(attr_completion_handler_async_handler_not_func,none,
3348+
"'%0' should be attached to a non-async completion-handler function",
3349+
(DeclAttribute))
3350+
3351+
NOTE(note_attr_function_declared_async,none,
3352+
"function declared async", ())
3353+
3354+
NOTE(note_attr_completion_function_must_return_void,none,
3355+
"completion handler must return 'Void'", ())
3356+
3357+
NOTE(note_attr_completion_handler_async_type_is_not_function,none,
3358+
"%0 is not a function type", (Type))
3359+
3360+
NOTE(note_attr_completion_handler_async_handler_attr_req,none,
3361+
"completion handler must%select{ not|}0 be '@%1'",
3362+
(bool, StringRef))
3363+
3364+
ERROR(attr_completion_handler_async_handler_out_of_range,none,
3365+
"completion handler index out of range of the function parameters", ())
3366+
3367+
ERROR(attr_completion_handler_async_ambiguous_function,none,
3368+
"ambiguous '%0' async function %1", (DeclAttribute, DeclNameRef))
3369+
3370+
ERROR(attr_completion_handler_async_no_suitable_function,none,
3371+
"no corresponding async function named %0", (DeclNameRef))
3372+
33433373
//------------------------------------------------------------------------------
33443374
// MARK: Type Check Expressions
33453375
//------------------------------------------------------------------------------

lib/AST/Attr.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,8 +1225,8 @@ StringRef DeclAttribute::getAttrName() const {
12251225
return "derivative";
12261226
case DAK_Transpose:
12271227
return "transpose";
1228-
case DAK_HasAsyncAlternative:
1229-
return "hasAsyncAlternative";
1228+
case DAK_CompletionHandlerAsync:
1229+
return "completionHandlerAsync";
12301230
}
12311231
llvm_unreachable("bad DeclAttrKind");
12321232
}
@@ -2002,3 +2002,11 @@ void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {
20022002
if (attr)
20032003
attr->print(out);
20042004
}
2005+
2006+
DeclNameRef CompletionHandlerAsyncAttr::getAsyncFunctionName() const {
2007+
if (AsyncFunctionDecl)
2008+
return DeclNameRef(AsyncFunctionDecl->getName());
2009+
if (AsyncFunctionName)
2010+
return AsyncFunctionName;
2011+
llvm_unreachable("completionHandlerAsync attr missing async function name");
2012+
}

lib/Parse/ParseDecl.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,42 +1570,68 @@ void Parser::parseAllAvailabilityMacroArguments() {
15701570
AvailabilityMacrosComputed = true;
15711571
}
15721572

1573-
static HasAsyncAlternativeAttr *parseAsyncAlternativeAttribute(
1574-
Parser &P, StringRef AttrName, SourceLoc AtLoc, DeclAttrKind DK) {
1573+
static CompletionHandlerAsyncAttr *
1574+
parseCompletionHandlerAsyncAttribute(Parser &P, StringRef AttrName,
1575+
SourceLoc AtLoc, DeclAttrKind DK) {
15751576
SourceLoc Loc = P.PreviousLoc;
15761577

1577-
// Unnamed @hasAsyncAlternative attribute
1578-
if (P.Tok.isNot(tok::l_paren))
1579-
return new (P.Context) HasAsyncAlternativeAttr(AtLoc, Loc);
1580-
1581-
P.consumeToken(tok::l_paren);
1578+
if (!P.consumeIf(tok::l_paren)) {
1579+
P.diagnose(P.getEndOfPreviousLoc(), diag::attr_expected_lparen, AttrName,
1580+
DeclAttribute::isDeclModifier(DK));
1581+
return nullptr;
1582+
}
15821583

15831584
if (!P.Tok.is(tok::string_literal)) {
15841585
P.diagnose(Loc, diag::attr_expected_string_literal, AttrName);
15851586
return nullptr;
15861587
}
15871588

1588-
auto Value = P.getStringLiteralIfNotInterpolated(
1589-
Loc, ("argument of '" + AttrName + "'").str());
1589+
SourceLoc nameLoc = P.Tok.getLoc();
1590+
Optional<StringRef> asyncFunctionName = P.getStringLiteralIfNotInterpolated(
1591+
nameLoc, ("argument of '" + AttrName + "'").str());
15901592
P.consumeToken(tok::string_literal);
1591-
if (!Value)
1593+
1594+
if (!asyncFunctionName)
15921595
return nullptr;
15931596

1594-
ParsedDeclName parsedName = parseDeclName(Value.getValue());
1595-
if (!parsedName || !parsedName.ContextName.empty()) {
1596-
P.diagnose(AtLoc, diag::has_async_alternative_invalid_name, AttrName);;
1597+
ParsedDeclName parsedAsyncName = parseDeclName(*asyncFunctionName);
1598+
if (!parsedAsyncName || !parsedAsyncName.ContextName.empty()) {
1599+
P.diagnose(nameLoc, diag::attr_completion_handler_async_invalid_name,
1600+
AttrName);
15971601
return nullptr;
15981602
}
15991603

1604+
size_t handlerIndex = 0;
1605+
SourceLoc handlerIndexLoc = SourceLoc();
1606+
if (P.consumeIf(tok::comma)) {
1607+
// The completion handler is explicitly specified, parse it
1608+
if (P.parseSpecificIdentifier("completionHandlerIndex",
1609+
diag::attr_missing_label,
1610+
"completionHandlerIndex", AttrName) ||
1611+
P.parseToken(tok::colon, diag::expected_colon_after_label,
1612+
"completionHandlerIndex")) {
1613+
return nullptr;
1614+
}
1615+
1616+
if (P.Tok.getText().getAsInteger(0, handlerIndex)) {
1617+
P.diagnose(P.Tok.getLoc(), diag::attr_expected_integer_literal, AttrName);
1618+
return nullptr;
1619+
}
1620+
1621+
handlerIndexLoc = P.consumeToken(tok::integer_literal);
1622+
}
1623+
16001624
SourceRange AttrRange = SourceRange(Loc, P.Tok.getRange().getStart());
16011625
if (!P.consumeIf(tok::r_paren)) {
1602-
P.diagnose(Loc, diag::attr_expected_rparen, AttrName,
1626+
P.diagnose(P.getEndOfPreviousLoc(), diag::attr_expected_rparen, AttrName,
16031627
DeclAttribute::isDeclModifier(DK));
16041628
return nullptr;
16051629
}
16061630

1607-
return new (P.Context) HasAsyncAlternativeAttr(
1608-
parsedName.formDeclNameRef(P.Context), AtLoc, AttrRange);
1631+
return new (P.Context) CompletionHandlerAsyncAttr(
1632+
parsedAsyncName.formDeclNameRef(P.Context), nameLoc,
1633+
handlerIndex, handlerIndexLoc, AtLoc,
1634+
AttrRange);
16091635
}
16101636

16111637
bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
@@ -2686,8 +2712,9 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
26862712
name, AtLoc, range, /*implicit*/ false));
26872713
break;
26882714
}
2689-
case DAK_HasAsyncAlternative: {
2690-
auto *attr = parseAsyncAlternativeAttribute(*this, AttrName, AtLoc, DK);
2715+
case DAK_CompletionHandlerAsync: {
2716+
auto *attr =
2717+
parseCompletionHandlerAsyncAttribute(*this, AttrName, AtLoc, DK);
26912718
if (!attr) {
26922719
skipUntilDeclStmtRBrace(tok::r_paren);
26932720
consumeIf(tok::r_paren);

lib/Sema/PreCheckExpr.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,30 @@ static bool diagnoseRangeOperatorMisspell(DiagnosticEngine &Diags,
238238
return false;
239239
}
240240

241+
static bool diagnoseNonexistentPowerOperator(DiagnosticEngine &Diags,
242+
UnresolvedDeclRefExpr *UDRE,
243+
DeclContext *DC) {
244+
auto name = UDRE->getName().getBaseIdentifier();
245+
if (!(name.isOperator() && name.is("**")))
246+
return false;
247+
248+
DC = DC->getModuleScopeContext();
249+
250+
auto &ctx = DC->getASTContext();
251+
DeclNameRef powerName(ctx.getIdentifier("pow"));
252+
253+
// Look if 'pow(_:_:)' exists within current context.
254+
auto lookUp = TypeChecker::lookupUnqualified(
255+
DC, powerName, UDRE->getLoc(), defaultUnqualifiedLookupOptions);
256+
if (lookUp) {
257+
Diags.diagnose(UDRE->getLoc(), diag::nonexistent_power_operator)
258+
.highlight(UDRE->getSourceRange());
259+
return true;
260+
}
261+
262+
return false;
263+
}
264+
241265
static bool diagnoseIncDecOperator(DiagnosticEngine &Diags,
242266
UnresolvedDeclRefExpr *UDRE) {
243267
auto name = UDRE->getName().getBaseIdentifier();
@@ -446,7 +470,8 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
446470
// e.g. (x*-4) that needs whitespace.
447471
if (diagnoseRangeOperatorMisspell(Context.Diags, UDRE) ||
448472
diagnoseIncDecOperator(Context.Diags, UDRE) ||
449-
diagnoseOperatorJuxtaposition(UDRE, DC)) {
473+
diagnoseOperatorJuxtaposition(UDRE, DC) ||
474+
diagnoseNonexistentPowerOperator(Context.Diags, UDRE, DC)) {
450475
return errorResult();
451476
}
452477

0 commit comments

Comments
 (0)