Skip to content

Commit 1b49a11

Browse files
committed
Parse module selectors in permitted locations
1 parent 3ae0642 commit 1b49a11

File tree

7 files changed

+383
-30
lines changed

7 files changed

+383
-30
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ ERROR(forbidden_interpolated_string,none,
9393
ERROR(forbidden_extended_escaping_string,none,
9494
"%0 cannot be an extended escaping string literal", (StringRef))
9595

96+
ERROR(expected_identifier_in_module_selector,none,
97+
"expected identifier in module selector", ())
98+
ERROR(module_selector_not_allowed_here,none,
99+
"name cannot be qualified with module selector here", ())
100+
96101
//------------------------------------------------------------------------------
97102
// MARK: Lexer diagnostics
98103
//------------------------------------------------------------------------------

include/swift/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1854,7 +1854,8 @@ class Parser {
18541854
/// unqualified-decl-base-name
18551855
/// unqualified-decl-base-name '(' ((identifier | '_') ':') + ')'
18561856
DeclNameRef parseDeclNameRef(DeclNameLoc &loc, DiagRef diag,
1857-
DeclNameOptions flags);
1857+
DeclNameOptions flags,
1858+
bool allowModSel);
18581859

18591860
/// Parse macro expansion.
18601861
///

lib/Parse/ParseDecl.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,8 @@ bool Parser::parseSpecializeAttributeArguments(
671671
DeclNameFlag::AllowZeroArgCompoundNames |
672672
DeclNameFlag::AllowKeywordsUsingSpecialNames |
673673
DeclNameFlag::AllowOperators |
674-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
674+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
675+
/*allowModSel=*/false);
675676
}
676677
}
677678
if (ParamLabel == "spiModule") {
@@ -1116,7 +1117,8 @@ Parser::parseImplementsAttribute(SourceLoc AtLoc, SourceLoc Loc) {
11161117
MemberNameLoc, diag::attr_implements_expected_member_name,
11171118
DeclNameFlag::AllowZeroArgCompoundNames |
11181119
DeclNameFlag::AllowOperators |
1119-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
1120+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
1121+
/*allowModSel=*/false);
11201122
if (!MemberName) {
11211123
Status.setIsParseError();
11221124
}
@@ -1587,7 +1589,8 @@ static bool parseQualifiedDeclName(Parser &P, Diag<> nameParseError,
15871589
Parser::DeclNameFlag::AllowZeroArgCompoundNames |
15881590
Parser::DeclNameFlag::AllowKeywordsUsingSpecialNames |
15891591
Parser::DeclNameFlag::AllowOperators |
1590-
Parser::DeclNameFlag::AllowLowercaseAndUppercaseSelf);
1592+
Parser::DeclNameFlag::AllowLowercaseAndUppercaseSelf,
1593+
/*allowModSel=*/true);
15911594
// The base type is optional, but the final unqualified declaration name is
15921595
// not. If name could not be parsed, return true for error.
15931596
if (!original.Name)
@@ -2419,7 +2422,8 @@ Parser::parseMacroRoleAttribute(
24192422
(DeclNameFlag::AllowOperators | DeclNameFlag::AllowKeywords |
24202423
DeclNameFlag::AllowKeywordsUsingSpecialNames |
24212424
DeclNameFlag::AllowCompoundNames |
2422-
DeclNameFlag::AllowZeroArgCompoundNames));
2425+
DeclNameFlag::AllowZeroArgCompoundNames),
2426+
/*allowModSel=*/false);
24232427
if (!name) {
24242428
status.setIsParseError();
24252429
return status;
@@ -3533,7 +3537,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
35333537
DeclNameFlag::AllowZeroArgCompoundNames |
35343538
DeclNameFlag::AllowKeywordsUsingSpecialNames |
35353539
DeclNameFlag::AllowOperators |
3536-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
3540+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
3541+
/*allowModSel=*/true);
35373542
}
35383543

35393544
// Parse the matching ')'.
@@ -4173,11 +4178,15 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
41734178
.warnUntilSwiftVersion(6);
41744179
}
41754180

4181+
bool hasModuleSelector = Context.LangOpts.hasFeature(Feature::ModuleSelector)
4182+
&& peekToken().is(tok::colon_colon);
4183+
41764184
// If this not an identifier, the attribute is malformed.
41774185
if (Tok.isNot(tok::identifier) &&
41784186
Tok.isNot(tok::kw_in) &&
41794187
Tok.isNot(tok::kw_inout) &&
4180-
Tok.isNot(tok::kw_rethrows)) {
4188+
Tok.isNot(tok::kw_rethrows) &&
4189+
!hasModuleSelector) {
41814190

41824191
if (Tok.is(tok::code_complete)) {
41834192
if (CodeCompletionCallbacks) {
@@ -4198,7 +4207,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
41984207

41994208
// If the attribute follows the new representation, switch
42004209
// over to the alternate parsing path.
4201-
std::optional<DeclAttrKind> DK =
4210+
std::optional<DeclAttrKind> DK = hasModuleSelector ? std::nullopt :
42024211
DeclAttribute::getAttrKindFromString(Tok.getText());
42034212
if (DK == DeclAttrKind::Rethrows) {
42044213
DK = DeclAttrKind::AtRethrows;
@@ -4210,7 +4219,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
42104219
auto checkInvalidAttrName =
42114220
[&](StringRef invalidName, StringRef correctName, DeclAttrKind kind,
42124221
std::optional<Diag<StringRef, StringRef>> diag = std::nullopt) {
4213-
if (!DK && Tok.getText() == invalidName) {
4222+
if (!DK && !hasModuleSelector && Tok.getText() == invalidName) {
42144223
DK = kind;
42154224

42164225
if (diag) {
@@ -4274,7 +4283,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
42744283
DeclAttrKind::Preconcurrency,
42754284
diag::attr_renamed_warning);
42764285

4277-
if (!DK && Tok.getText() == "warn_unused_result") {
4286+
if (!DK && !hasModuleSelector && Tok.getText() == "warn_unused_result") {
42784287
// The behavior created by @warn_unused_result is now the default. Emit a
42794288
// Fix-It to remove.
42804289
SourceLoc attrLoc = consumeToken();
@@ -4349,9 +4358,10 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
43494358
return parseNewDeclAttribute(Attributes, AtLoc, *DK, isFromClangAttribute);
43504359
}
43514360

4352-
if (TypeAttribute::getAttrKindFromString(Tok.getText()).has_value())
4361+
if (!hasModuleSelector &&
4362+
TypeAttribute::getAttrKindFromString(Tok.getText()).has_value())
43534363
diagnose(Tok, diag::type_attribute_applied_to_decl);
4354-
else if (Tok.isContextualKeyword("unknown")) {
4364+
else if (!hasModuleSelector && Tok.isContextualKeyword("unknown")) {
43554365
diagnose(Tok, diag::unknown_attr_name, "unknown");
43564366
} else {
43574367
// Change the context to create a custom attribute syntax.
@@ -4523,7 +4533,8 @@ bool Parser::parseConventionAttributeInternal(SourceLoc atLoc, SourceLoc attrLoc
45234533
DeclNameLoc unusedLoc;
45244534
witnessMethodProtocol = parseDeclNameRef(
45254535
unusedLoc, diag::convention_attribute_witness_method_expected_protocol,
4526-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
4536+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
4537+
/*allowModSel=*/true);
45274538
}
45284539

45294540
// Parse the ')'. We can't use parseMatchingToken if we're in
@@ -10122,7 +10133,8 @@ Parser::parseDeclOperatorImpl(SourceLoc OperatorLoc, Identifier Name,
1012210133

1012310134
groupName = parseDeclNameRef(groupLoc,
1012410135
diag::operator_decl_expected_precedencegroup,
10125-
{});
10136+
{},
10137+
/*allowModSel=*/false);
1012610138

1012710139
if (Context.TypeCheckerOpts.EnableOperatorDesignatedTypes) {
1012810140
// Designated types have been removed; consume the list (mainly for source
@@ -10420,7 +10432,8 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
1042010432
auto name = parseDeclNameRef(nameLoc,
1042110433
{ diag::expected_precedencegroup_relation,
1042210434
attrName },
10423-
{});
10435+
{},
10436+
/*allowModSel=*/false);
1042410437
if (!name) {
1042510438
return abortBody();
1042610439
}

lib/Parse/ParseExpr.cpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,8 @@ ParserResult<Expr> Parser::parseExprKeyPathObjC() {
829829
// Parse the next name.
830830
DeclNameLoc nameLoc;
831831
DeclNameRef name = parseDeclNameRef(nameLoc,
832-
diag::expr_keypath_expected_property_or_type, flags);
832+
diag::expr_keypath_expected_property_or_type, flags,
833+
/*allowModSel=*/false);
833834
if (!name) {
834835
status.setIsParseError();
835836
break;
@@ -1329,7 +1330,8 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
13291330
auto Name = parseDeclNameRef(
13301331
NameLoc, D,
13311332
DeclNameFlag::AllowKeywords | DeclNameFlag::AllowCompoundNames |
1332-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
1333+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
1334+
/*allowModSel=*/true);
13331335
if (!Name) {
13341336
SourceRange ErrorRange = Result.get()->getSourceRange();
13351337
ErrorRange.widen(TokLoc);
@@ -1803,7 +1805,8 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
18031805
Name = parseDeclNameRef(NameLoc, diag::expected_identifier_after_dot_expr,
18041806
DeclNameFlag::AllowKeywords |
18051807
DeclNameFlag::AllowCompoundNames |
1806-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
1808+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
1809+
/*allowModSel=*/true);
18071810
if (!Name)
18081811
return makeParserErrorResult(new (Context) ErrorExpr(DotLoc));
18091812

@@ -2266,7 +2269,34 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22662269

22672270
DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
22682271
DiagRef diag,
2269-
DeclNameOptions flags) {
2272+
DeclNameOptions flags,
2273+
bool allowModSel) {
2274+
// Consume the module name, if present.
2275+
SourceLoc moduleSelectorLoc;
2276+
Identifier moduleSelector;
2277+
if (Context.LangOpts.hasFeature(Feature::ModuleSelector) &&
2278+
peekToken().is(tok::colon_colon)) {
2279+
if (Tok.is(tok::identifier)) { // FIXME: tok::dollarident?
2280+
moduleSelectorLoc = consumeIdentifier(moduleSelector,
2281+
/*diagnoseDollarPrefix=*/true);
2282+
}
2283+
else {
2284+
diagnose(Tok, diag::expected_identifier_in_module_selector);
2285+
moduleSelector = Identifier();
2286+
moduleSelectorLoc = consumeToken();
2287+
}
2288+
2289+
// Diagnose if we don't allow a module selector here.
2290+
if (!allowModSel) {
2291+
diagnose(Tok, diag::module_selector_not_allowed_here)
2292+
.fixItRemove({moduleSelectorLoc, Tok.getLoc()});
2293+
moduleSelector = Identifier();
2294+
moduleSelectorLoc = SourceLoc();
2295+
}
2296+
2297+
consumeToken(tok::colon_colon);
2298+
}
2299+
22702300
// Consume the base name.
22712301
DeclBaseName baseName;
22722302
SourceLoc baseNameLoc;
@@ -2317,15 +2347,15 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
23172347
rparenLoc);
23182348

23192349
if (argumentLabelLocs.empty() || !hadArgList)
2320-
loc = DeclNameLoc(baseNameLoc);
2350+
loc = DeclNameLoc(Context, moduleSelectorLoc, baseNameLoc);
23212351
else
2322-
loc = DeclNameLoc(Context, baseNameLoc, lparenLoc, argumentLabelLocs,
2323-
rparenLoc);
2352+
loc = DeclNameLoc(Context, moduleSelectorLoc, baseNameLoc,
2353+
lparenLoc, argumentLabelLocs, rparenLoc);
23242354

23252355
if (!hadArgList)
2326-
return DeclNameRef(baseName);
2356+
return DeclNameRef(Context, moduleSelector, baseName);
23272357

2328-
return DeclNameRef({ Context, baseName, argumentLabels });
2358+
return DeclNameRef(Context, moduleSelector, baseName, argumentLabels);
23292359
}
23302360

23312361
ParserStatus Parser::parseFreestandingMacroExpansion(
@@ -2344,7 +2374,9 @@ ParserStatus Parser::parseFreestandingMacroExpansion(
23442374

23452375
bool hasWhitespaceBeforeName = poundEndLoc != Tok.getLoc();
23462376

2347-
macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameFlag::AllowKeywords);
2377+
macroNameRef = parseDeclNameRef(macroNameLoc, diag,
2378+
DeclNameFlag::AllowKeywords,
2379+
/*allowModSel=*/false);
23482380
if (!macroNameRef)
23492381
return makeParserError();
23502382

@@ -2401,7 +2433,8 @@ ParserResult<Expr> Parser::parseExprIdentifier(bool allowKeyword) {
24012433
}
24022434
// Parse the unqualified-decl-name.
24032435
DeclNameLoc loc;
2404-
DeclNameRef name = parseDeclNameRef(loc, diag::expected_expr, declNameFlags);
2436+
DeclNameRef name = parseDeclNameRef(loc, diag::expected_expr, declNameFlags,
2437+
/*allowModSel=*/true);
24052438

24062439
SmallVector<TypeRepr*, 8> args;
24072440
SourceLoc LAngleLoc, RAngleLoc;
@@ -3067,7 +3100,8 @@ Expr *Parser::parseExprAnonClosureArg() {
30673100
DeclNameLoc nameLoc;
30683101
DeclNameRef nameRef =
30693102
parseDeclNameRef(nameLoc, diag::impossible_parse,
3070-
DeclNameFlag::AllowAnonymousParamNames);
3103+
DeclNameFlag::AllowAnonymousParamNames,
3104+
/*allowModSel=*/false);
30713105

30723106
StringRef Name = nameRef.getBaseIdentifier().str();
30733107
SourceLoc Loc = nameLoc.getBaseNameLoc();
@@ -3236,10 +3270,13 @@ ParserStatus Parser::parseExprListElement(tok rightTok, bool isArgumentList, Sou
32363270
Expr *SubExpr = nullptr;
32373271
if (isUnappliedOperator()) {
32383272
DeclNameLoc Loc;
3273+
// FIXME: We would like to allow module selectors on binary operators, but
3274+
// the condition above won't let us reach this code.
32393275
auto OperName =
32403276
parseDeclNameRef(Loc, diag::expected_operator_ref,
32413277
DeclNameFlag::AllowOperators |
3242-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
3278+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
3279+
/*allowModSel=*/true);
32433280
if (!OperName) {
32443281
return makeParserError();
32453282
}

lib/Parse/ParseType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,8 @@ ParserResult<DeclRefTypeRepr> Parser::parseTypeIdentifier(TypeRepr *Base) {
853853
DeclNameLoc Loc;
854854
DeclNameRef Name =
855855
parseDeclNameRef(Loc, diag::expected_identifier_in_dotted_type,
856-
DeclNameFlag::AllowLowercaseAndUppercaseSelf);
856+
DeclNameFlag::AllowLowercaseAndUppercaseSelf,
857+
/*allowModSel=*/true);
857858
if (!Name)
858859
return makeParserError();
859860

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// swift-interface-format-version: 1.0
2+
// swift-module-flags: -module-name ModuleSelectorTestingKit -swift-version 5
3+
4+
import Swift
5+
6+
// These types are identical; we just use them to test with different scope
7+
// selectors.
8+
9+
public struct A {
10+
public init(value: Swift.Int)
11+
public dynamic mutating func negate()
12+
public var magnitude: Swift.UInt
13+
}
14+
15+
public struct B {
16+
public init(value: Swift.Int)
17+
public dynamic mutating func negate()
18+
public var magnitude: Swift.UInt
19+
}
20+
21+
public struct C {
22+
public init(value: Int)
23+
public dynamic mutating func negate()
24+
public var magnitude: Swift.UInt
25+
}
26+
27+
public struct D {
28+
public init(value: Int)
29+
public dynamic mutating func negate()
30+
public var magnitude: Swift.UInt
31+
}
32+
33+
@propertyWrapper
34+
public struct available {
35+
public init() {}
36+
public var wrappedValue: Int { 0 }
37+
}
38+
39+
@_functionBuilder
40+
public struct MyBuilder {
41+
public static func buildBlock()
42+
}

0 commit comments

Comments
 (0)