Skip to content

Commit 5794c53

Browse files
committed
Support module selectors in (ModName::+)
1 parent 914a3b0 commit 5794c53

File tree

5 files changed

+30
-27
lines changed

5 files changed

+30
-27
lines changed

include/swift/Parse/Parser.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,8 @@ class Parser {
487487
/// \returns the value returned by \c f
488488
/// \note When calling, you may need to specify the \c Val type
489489
/// explicitly as a type parameter.
490-
template <typename Val>
491-
Val lookahead(unsigned char K,
492-
llvm::function_ref<Val(CancellableBacktrackingScope &)> f) {
490+
template <typename Fn>
491+
decltype(auto) lookahead(unsigned char K, Fn f) {
493492
CancellableBacktrackingScope backtrackScope(*this);
494493

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

lib/Parse/ParseExpr.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,19 +3268,26 @@ Parser::parseArgumentList(tok leftTok, tok rightTok, bool isExprBasic,
32683268
return makeParserResult(status, argList);
32693269
}
32703270

3271+
/// See if we have an operator decl ref '(<op>)'. The operator token in
3272+
/// this case lexes as a binary operator because it neither leads nor
3273+
/// follows a proper subexpression.
3274+
bool listElementIsBinaryOperator(Parser &P, tok rightTok) {
3275+
// Look past a module selector, if present.
3276+
if (P.Tok.is(tok::identifier) && P.peekToken().is(tok::colon_colon)) {
3277+
return P.lookahead(2, [&](auto &scope) {
3278+
return listElementIsBinaryOperator(P, rightTok);
3279+
});
3280+
}
3281+
3282+
return P.Tok.isBinaryOperator() && P.peekToken().isAny(rightTok, tok::comma);
3283+
}
3284+
32713285
ParserStatus Parser::parseExprListElement(tok rightTok, bool isArgumentList, SourceLoc leftLoc, SmallVectorImpl<ExprListElt> &elts) {
32723286
Identifier FieldName;
32733287
SourceLoc FieldNameLoc;
32743288
parseOptionalArgumentLabel(FieldName, FieldNameLoc);
32753289

3276-
// See if we have an operator decl ref '(<op>)'. The operator token in
3277-
// this case lexes as a binary operator because it neither leads nor
3278-
// follows a proper subexpression.
3279-
auto isUnappliedOperator = [&]() {
3280-
return Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma);
3281-
};
3282-
3283-
if (isUnappliedOperator()) {
3290+
if (listElementIsBinaryOperator(*this, rightTok)) {
32843291
// Check to see if we have the start of a regex literal `/.../`. We need
32853292
// to do this for an unapplied operator reference, as e.g `(/, /)` might
32863293
// be a regex literal.
@@ -3289,7 +3296,7 @@ ParserStatus Parser::parseExprListElement(tok rightTok, bool isArgumentList, Sou
32893296

32903297
ParserStatus Status;
32913298
Expr *SubExpr = nullptr;
3292-
if (isUnappliedOperator()) {
3299+
if (listElementIsBinaryOperator(*this, rightTok)) {
32933300
DeclNameLoc Loc;
32943301
// FIXME: We would like to allow module selectors on binary operators, but
32953302
// the condition above won't let us reach this code.

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ bool Parser::startsParameterName(bool isClosure) {
122122
// contextual keywords, so look ahead one more token (two total) and see
123123
// if we have a ':' that would
124124
// indicate that this is an argument label.
125-
return lookahead<bool>(2, [&](CancellableBacktrackingScope &) {
125+
return lookahead(2, [&](CancellableBacktrackingScope &) {
126126
if (Tok.is(tok::colon))
127127
return true; // isolated :
128128

@@ -241,7 +241,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
241241
// is this token the identifier of an argument label? `inout` is a
242242
// reserved keyword but the other modifiers are not.
243243
if (!Tok.is(tok::kw_inout)) {
244-
bool partOfArgumentLabel = lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
244+
bool partOfArgumentLabel = lookahead(1, [&](CancellableBacktrackingScope &) {
245245
if (Tok.is(tok::colon))
246246
return true; // isolated :
247247

test/NameLookup/module_selector.swift

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

3737
@_dynamicReplacement(for: ModuleSelectorTestingKit::negate())
3838
mutating func myNegate() {
39-
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
40-
(+)
41-
// TODO: it'd be nice to handle module selectors on operators.
39+
let fn: (Swift::Int, Swift::Int) -> Swift::Int = (Swift::+)
4240

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

10297
let magnitude: Int.main::Magnitude = main::magnitude
10398
// expected-error@-1 {{type 'Magnitude' is not imported through module 'main'}}
@@ -163,9 +158,6 @@ extension C: ModuleSelectorTestingKit::Equatable {
163158
// expected-note@-3 {{did you mean module 'Swift'?}} {{45-69=Swift}}
164159
// expected-note@-4 {{did you mean module 'Swift'?}} {{79-103=Swift}}
165160
(ModuleSelectorTestingKit::+)
166-
// TODO: it'd be nice to handle module selectors on operators.
167-
// expected-error@-2 {{expected expression}}
168-
// expected-error@-3 {{expected expression after operator}}
169161

170162
let magnitude: Int.ModuleSelectorTestingKit::Magnitude = ModuleSelectorTestingKit::magnitude
171163
// expected-error@-1 {{type 'Magnitude' is not imported through module 'ModuleSelectorTestingKit'}}
@@ -228,10 +220,6 @@ extension D: @retroactive Swift::Equatable {
228220

229221
let fn: (Swift::Int, Swift::Int) -> Swift::Int =
230222
(Swift::+)
231-
// TODO: it'd be nice to handle module selectors on operators.
232-
// expected-error@-2 {{cannot convert value of type '()' to specified type '(Int, Int) -> Int'}}
233-
// expected-error@-3 {{expected expression}}
234-
// expected-error@-4 {{expected expression after operator}}
235223
let magnitude: Int.Swift::Magnitude = Swift::magnitude
236224
// expected-error@-1 {{declaration 'magnitude' is not imported through module 'Swift'}}
237225
// 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)