Skip to content

Commit b909122

Browse files
committed
Support module selectors in (ModName::+)
1 parent 15ebf01 commit b909122

File tree

5 files changed

+26
-21
lines changed

5 files changed

+26
-21
lines changed

include/swift/Parse/Parser.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,8 @@ class Parser {
568568
/// \returns the value returned by \c f
569569
/// \note When calling, you may need to specify the \c Val type
570570
/// explicitly as a type parameter.
571-
template <typename Val>
572-
Val lookahead(unsigned char K,
573-
llvm::function_ref<Val(CancellableBacktrackingScope &)> f) {
571+
template <typename Fn>
572+
decltype(auto) lookahead(unsigned char K, Fn f) {
574573
CancellableBacktrackingScope backtrackScope(*this);
575574

576575
for (unsigned char i = 0; i < K; ++i)

lib/Parse/ParseExpr.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,6 +3202,17 @@ Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
32023202
/*Implicit=*/false));
32033203
}
32043204

3205+
bool listElementIsBinaryOperator(Parser &P, tok rightTok) {
3206+
// Look past a module selector, if present.
3207+
if (P.Tok.is(tok::identifier) && P.peekToken().is(tok::colon_colon)) {
3208+
return P.lookahead(2, [&](auto &scope) {
3209+
return listElementIsBinaryOperator(P, rightTok);
3210+
});
3211+
}
3212+
3213+
return P.Tok.isBinaryOperator() && P.peekToken().isAny(rightTok, tok::comma);
3214+
}
3215+
32053216
/// parseExprList - Parse a list of expressions.
32063217
///
32073218
/// expr-paren:
@@ -3246,12 +3257,10 @@ ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
32463257
// follows a proper subexpression.
32473258
ParserStatus Status;
32483259
Expr *SubExpr = nullptr;
3249-
if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
3260+
if (listElementIsBinaryOperator(*this, rightTok)) {
32503261
SyntaxParsingContext operatorContext(SyntaxContext,
32513262
SyntaxKind::IdentifierExpr);
32523263
DeclNameLoc Loc;
3253-
// FIXME: We would like to allow module selectors on binary operators, but
3254-
// the condition above won't let us reach this code.
32553264
auto OperName = parseDeclNameRef(Loc, diag::expected_operator_ref,
32563265
DeclNameFlag::AllowOperators |
32573266
DeclNameFlag::AllowModuleSelector);

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ bool Parser::startsParameterName(bool isClosure) {
175175
// "isolated" can be an argument label, but it's also a contextual keyword,
176176
// so look ahead one more token (two total) see if we have a ':' that would
177177
// indicate that this is an argument label.
178-
return lookahead<bool>(2, [&](CancellableBacktrackingScope &) {
178+
return lookahead(2, [&](CancellableBacktrackingScope &) {
179179
if (Tok.is(tok::colon))
180180
return true; // isolated :
181181

@@ -281,7 +281,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
281281
}
282282

283283
// is this 'isolated' token the identifier of an argument label?
284-
bool partOfArgumentLabel = lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
284+
bool partOfArgumentLabel = lookahead(1, [&](CancellableBacktrackingScope &) {
285285
if (Tok.is(tok::colon))
286286
return true; // isolated :
287287

test/NameLookup/module_selector.swift

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ extension ModuleSelectorTestingKit::A: Swift::Equatable {
3434

3535
@_dynamicReplacement(for: ModuleSelectorTestingKit::negate())
3636
mutating func myNegate() {
37-
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
38-
(+)
39-
// TODO: it'd be nice to handle module selectors on operators.
37+
let fn: (Swift::Int, Swift::Int) -> Swift::Int = (Swift::+)
4038

4139
let magnitude: Int.Swift::Magnitude = main::magnitude
4240
// expected-error@-1 {{cannot convert value of type 'Never' to specified type 'Int.Magnitude' (aka 'UInt')}}
@@ -93,9 +91,6 @@ extension B: main::Equatable {
9391
// expected-note@-3 {{did you mean module 'Swift'?}} {{25-29=Swift}}
9492
// expected-note@-4 {{did you mean module 'Swift'?}} {{39-43=Swift}}
9593
(main::+)
96-
// TODO: it'd be nice to handle module selectors on operators.
97-
// expected-error@-2 {{expected expression}}
98-
// expected-error@-3 {{expected expression after operator}}
9994

10095
let magnitude: Int.main::Magnitude = main::magnitude
10196
// expected-error@-1 {{type 'Magnitude' is not imported through module 'main'}}
@@ -160,9 +155,6 @@ extension C: ModuleSelectorTestingKit::Equatable {
160155
// expected-note@-3 {{did you mean module 'Swift'?}} {{45-69=Swift}}
161156
// expected-note@-4 {{did you mean module 'Swift'?}} {{79-103=Swift}}
162157
(ModuleSelectorTestingKit::+)
163-
// TODO: it'd be nice to handle module selectors on operators.
164-
// expected-error@-2 {{expected expression}}
165-
// expected-error@-3 {{expected expression after operator}}
166158

167159
let magnitude: Int.ModuleSelectorTestingKit::Magnitude = ModuleSelectorTestingKit::magnitude
168160
// expected-error@-1 {{type 'Magnitude' is not imported through module 'ModuleSelectorTestingKit'}}
@@ -225,10 +217,6 @@ extension D: Swift::Equatable {
225217

226218
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
227219
(Swift::+)
228-
// TODO: it'd be nice to handle module selectors on operators.
229-
// expected-error@-2 {{cannot convert value of type '()' to specified type '(Int, Int) -> Int'}}
230-
// expected-error@-3 {{expected expression}}
231-
// expected-error@-4 {{expected expression after operator}}
232220
let magnitude: Int.Swift::Magnitude = Swift::magnitude
233221
// expected-error@-1 {{declaration 'magnitude' is not imported through module 'Swift'}}
234222
// expected-note@-2 {{did you mean module 'main'?}}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
func fn() {
4+
_ = 1.description
5+
_ = 1.5.description
6+
7+
print(1.description)
8+
print(1.5.description)
9+
}

0 commit comments

Comments
 (0)