Skip to content

Commit c46b7c1

Browse files
committed
Parser: Parse member types with non-identifier qualifiers in type context
1 parent e180ee9 commit c46b7c1

File tree

4 files changed

+212
-47
lines changed

4 files changed

+212
-47
lines changed

include/swift/Parse/Parser.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace llvm {
3939
}
4040

4141
namespace swift {
42+
class IdentTypeRepr;
4243
class IDEInspectionCallbacks;
4344
class IDEInspectionCallbacksFactory;
4445
class DefaultArgumentInitializer;
@@ -1308,6 +1309,13 @@ class Parser {
13081309
/// an empty parser error.
13091310
ParserResult<TypeRepr> parseTypeIdentifier(
13101311
bool isParsingQualifiedDeclBaseType = false);
1312+
1313+
/// Parse an identifier type, e.g 'Foo' or 'Bar<Int>'.
1314+
ParserResult<IdentTypeRepr> parseSimpleTypeIdentifier();
1315+
1316+
/// Parse a dotted type, e.g. 'Foo<X>.Y.Z', 'P.Type', '[X].Y'.
1317+
ParserResult<TypeRepr> parseTypeDotted(ParserResult<TypeRepr> Base);
1318+
13111319
ParserResult<TypeRepr> parseOldStyleProtocolComposition();
13121320
ParserResult<TypeRepr> parseAnyType();
13131321
ParserResult<TypeRepr> parseSILBoxType(GenericParamList *generics,

lib/Parse/ParseExpr.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,6 @@ DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
21892189
Tok.setKind(tok::identifier);
21902190
baseNameLoc = consumeToken();
21912191
} else {
2192-
baseName = Context.getIdentifier(Tok.getText());
21932192
checkForInputIncomplete();
21942193
diagnose(Tok, diag);
21952194
return DeclNameRef();

lib/Parse/ParseType.cpp

Lines changed: 148 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,51 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
176176

177177
switch (Tok.getKind()) {
178178
case tok::kw_Self:
179+
case tok::identifier:
180+
// In SIL files (not just when parsing SIL types), accept the
181+
// Pack{} syntax for spelling variadic type packs.
182+
if (SIL && Tok.isContextualKeyword("Pack") &&
183+
peekToken().is(tok::l_brace)) {
184+
TokReceiver->registerTokenKindChange(Tok.getLoc(),
185+
tok::contextual_keyword);
186+
SourceLoc keywordLoc = consumeToken(tok::identifier);
187+
SourceLoc lbLoc = consumeToken(tok::l_brace);
188+
SourceLoc rbLoc;
189+
SmallVector<TypeRepr *, 8> elements;
190+
auto status = parseList(tok::r_brace, lbLoc, rbLoc,
191+
/*AllowSepAfterLast=*/false,
192+
diag::expected_rbrace_pack_type_list,
193+
[&] () -> ParserStatus {
194+
auto element = parseType(diag::expected_type);
195+
if (element.hasCodeCompletion())
196+
return makeParserCodeCompletionStatus();
197+
if (element.isNull())
198+
return makeParserError();
199+
elements.push_back(element.get());
200+
return makeParserSuccess();
201+
});
202+
203+
ty = makeParserResult(
204+
status, PackTypeRepr::create(Context, keywordLoc,
205+
SourceRange(lbLoc, rbLoc), elements));
206+
} else {
207+
ty = parseSimpleTypeIdentifier();
208+
if (auto *ITR = cast_or_null<IdentTypeRepr>(ty.getPtrOrNull())) {
209+
if (Tok.is(tok::code_complete) && !Tok.isAtStartOfLine()) {
210+
if (IDECallbacks)
211+
IDECallbacks->completeTypeIdentifierWithoutDot(ITR);
212+
213+
ty.setHasCodeCompletionAndIsError();
214+
consumeToken(tok::code_complete);
215+
return ty;
216+
}
217+
}
218+
}
219+
break;
179220
case tok::kw_Any:
180-
case tok::identifier: {
181-
ty = parseTypeIdentifier();
221+
ty = parseAnyType();
222+
// FIXME: Offer completions in 'Any<#HERE#>' and 'Any.<#HERE#>'.
182223
break;
183-
}
184224
case tok::l_paren:
185225
ty = parseTypeTupleBody();
186226
break;
@@ -219,23 +259,11 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
219259
return nullptr;
220260
}
221261

222-
// '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
262+
// '.X', '.Type', '.Protocol', '?', '!', '[]'.
223263
while (ty.isNonNull()) {
224-
if ((Tok.is(tok::period) || Tok.is(tok::period_prefix))) {
225-
if (peekToken().isContextualKeyword("Type")) {
226-
consumeToken();
227-
SourceLoc metatypeLoc = consumeToken(tok::identifier);
228-
ty = makeParserResult(ty,
229-
new (Context) MetatypeTypeRepr(ty.get(), metatypeLoc));
230-
continue;
231-
}
232-
if (peekToken().isContextualKeyword("Protocol")) {
233-
consumeToken();
234-
SourceLoc protocolLoc = consumeToken(tok::identifier);
235-
ty = makeParserResult(ty,
236-
new (Context) ProtocolTypeRepr(ty.get(), protocolLoc));
237-
continue;
238-
}
264+
if (Tok.isAny(tok::period, tok::period_prefix)) {
265+
ty = parseTypeDotted(ty);
266+
continue;
239267
}
240268

241269
if (!Tok.isAtStartOfLine()) {
@@ -733,33 +761,11 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) {
733761
SmallVector<IdentTypeRepr *, 4> ComponentsR;
734762
SourceLoc EndLoc;
735763
while (true) {
736-
DeclNameLoc Loc;
737-
DeclNameRef Name =
738-
parseDeclNameRef(Loc, diag::expected_identifier_in_dotted_type, {});
739-
if (!Name)
740-
Status.setIsParseError();
764+
auto IdentResult = parseSimpleTypeIdentifier();
765+
if (IdentResult.isParseErrorOrHasCompletion())
766+
return IdentResult;
741767

742-
if (Loc.isValid()) {
743-
SourceLoc LAngle, RAngle;
744-
SmallVector<TypeRepr*, 8> GenericArgs;
745-
bool HasGenericArgs = false;
746-
if (startsWithLess(Tok)) {
747-
HasGenericArgs = true;
748-
auto genericArgsStatus = parseGenericArguments(GenericArgs, LAngle, RAngle);
749-
if (genericArgsStatus.isErrorOrHasCompletion())
750-
return genericArgsStatus;
751-
}
752-
EndLoc = Loc.getEndLoc();
753-
754-
IdentTypeRepr *CompT;
755-
if (HasGenericArgs) {
756-
CompT = GenericIdentTypeRepr::create(Context, Loc, Name, GenericArgs,
757-
SourceRange(LAngle, RAngle));
758-
} else {
759-
CompT = new (Context) SimpleIdentTypeRepr(Loc, Name);
760-
}
761-
ComponentsR.push_back(CompT);
762-
}
768+
ComponentsR.push_back(cast<IdentTypeRepr>(IdentResult.get()));
763769

764770
// Treat 'Foo.<anything>' as an attempt to write a dotted type
765771
// unless <anything> is 'Type'.
@@ -813,6 +819,103 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) {
813819
return makeParserResult(Status, DeclRefTR);
814820
}
815821

822+
ParserResult<IdentTypeRepr> Parser::parseSimpleTypeIdentifier() {
823+
// FIXME: We should parse e.g. 'X.var'. Almost any keyword is a valid member
824+
// component.
825+
DeclNameLoc Loc;
826+
DeclNameRef Name =
827+
parseDeclNameRef(Loc, diag::expected_identifier_in_dotted_type, {});
828+
if (!Name)
829+
return makeParserError();
830+
831+
ParserStatus Status;
832+
IdentTypeRepr *IdTR;
833+
834+
if (startsWithLess(Tok)) {
835+
SourceLoc LAngle, RAngle;
836+
SmallVector<TypeRepr *, 8> GenericArgs;
837+
auto ArgsStatus = parseGenericArguments(GenericArgs, LAngle, RAngle);
838+
if (ArgsStatus.isErrorOrHasCompletion())
839+
return ArgsStatus;
840+
841+
IdTR = GenericIdentTypeRepr::create(Context, Loc, Name, GenericArgs,
842+
SourceRange(LAngle, RAngle));
843+
} else {
844+
IdTR = new (Context) SimpleIdentTypeRepr(Loc, Name);
845+
}
846+
847+
return makeParserResult(IdTR);
848+
}
849+
850+
ParserResult<TypeRepr> Parser::parseTypeDotted(ParserResult<TypeRepr> Base) {
851+
assert(Base.isNonNull());
852+
assert(Tok.isAny(tok::period, tok::period_prefix));
853+
854+
SmallVector<IdentTypeRepr *, 4> MemberComponents;
855+
856+
while (true) {
857+
if (Tok.isNot(tok::period, tok::period_prefix) ||
858+
peekToken().is(tok::code_complete)) {
859+
break;
860+
}
861+
862+
// Consume the period.
863+
consumeToken();
864+
865+
if (Tok.isContextualKeyword("Type") ||
866+
Tok.isContextualKeyword("Protocol")) {
867+
TypeRepr *MetaBase =
868+
MemberTypeRepr::create(Context, Base.get(), MemberComponents);
869+
if (Tok.getRawText() == "Type") {
870+
Base = makeParserResult(Base,
871+
new (Context) MetatypeTypeRepr(
872+
MetaBase, consumeToken(tok::identifier)));
873+
} else {
874+
Base = makeParserResult(Base,
875+
new (Context) ProtocolTypeRepr(
876+
MetaBase, consumeToken(tok::identifier)));
877+
}
878+
879+
// Start anew with a metatype base.
880+
MemberComponents.clear();
881+
continue;
882+
}
883+
884+
auto IdentResult = parseSimpleTypeIdentifier();
885+
if (IdentResult.isParseErrorOrHasCompletion())
886+
return IdentResult | ParserStatus(Base);
887+
888+
MemberComponents.push_back(cast<IdentTypeRepr>(IdentResult.get()));
889+
}
890+
891+
TypeRepr *TR = MemberTypeRepr::create(Context, Base.get(), MemberComponents);
892+
893+
// FIXME: Offer completions in 'X.Type<#HERE#>' and 'X.Type.<#HERE#>'.
894+
if (Tok.is(tok::code_complete)) {
895+
if (!Tok.isAtStartOfLine()) {
896+
Base.setHasCodeCompletionAndIsError();
897+
898+
if (IDECallbacks) {
899+
if (auto *DeclRefTR = dyn_cast<DeclRefTypeRepr>(TR))
900+
IDECallbacks->completeTypeIdentifierWithoutDot(DeclRefTR);
901+
}
902+
903+
consumeToken(tok::code_complete);
904+
}
905+
} else if (Tok.isAny(tok::period, tok::period_prefix)) {
906+
Base.setHasCodeCompletionAndIsError();
907+
consumeToken();
908+
909+
if (IDECallbacks) {
910+
if (auto *DeclRefTR = dyn_cast<DeclRefTypeRepr>(TR))
911+
IDECallbacks->completeTypeIdentifierWithDot(DeclRefTR);
912+
}
913+
consumeToken(tok::code_complete);
914+
}
915+
916+
return makeParserResult(Base, TR);
917+
}
918+
816919
/// parseTypeSimpleOrComposition
817920
///
818921
/// type-composition:

test/type/nested_types.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -module-name test
22

33
struct X {
44
typealias MyInt = Int
@@ -29,3 +29,58 @@ struct SequenceWrapper<T : MySequence> {
2929
return Iterator(index: 0, elements: input.makeIterator())
3030
}
3131
}
32+
33+
// Nested types with non-identifier qualifiers
34+
35+
protocol P1 {} // expected-note {{'P1' declared here}}
36+
protocol P2 {}
37+
38+
extension Optional {
39+
typealias Wrapped = Wrapped
40+
}
41+
42+
do {
43+
struct S {
44+
struct Bar {}
45+
struct Gen<T> {}
46+
}
47+
48+
// Used to check for type equality.
49+
enum CheckTypes<T, U> {
50+
enum Match where T == U {}
51+
}
52+
53+
// Valid examples.
54+
55+
let _: CheckTypes<S.Bar, (S).Bar>.Match
56+
let _: CheckTypes<S.Gen<S>, (S).Gen<S>>.Match
57+
58+
let _: CheckTypes<S, S?.Wrapped>.Match
59+
let _: CheckTypes<S, (S)?.Wrapped>.Match
60+
let _: CheckTypes<S, (S?).Wrapped>.Match
61+
let _: CheckTypes<S?, S??.Wrapped>.Match
62+
let _: CheckTypes<S, S?.Wrapped?.Wrapped>.Match
63+
let _: CheckTypes<S.Gen<S>, S?.Wrapped.Gen<S>>.Match
64+
let _: CheckTypes<S.Gen<S>, (S?.Wrapped).Gen<S>>.Match
65+
let _: CheckTypes<S, [S].Element>.Match
66+
let _: CheckTypes<Dictionary<Int, S>.Element, [Int : S].Element>.Match
67+
68+
// Invalid examples.
69+
70+
let _: Int!.Wrapped // expected-warning {{using '!' is not allowed here; treating this as '?' instead}}
71+
let _: (Int!).Wrapped // expected-warning {{using '!' is not allowed here; treating this as '?' instead}}
72+
73+
let _: Any.Undef // expected-error {{'Undef' is not a member type of type 'Any'}}
74+
let _: Int.Type.Undef // expected-error {{'Undef' is not a member type of type 'Swift.Int.Type'}}
75+
let _: P1.Protocol.Undef // expected-error {{'Undef' is not a member type of type '(any test.P1).Type'}}
76+
let _: (Int).Undef // expected-error {{'Undef' is not a member type of struct 'Swift.Int'}}
77+
let _: (Int.Undef1).Undef2 // expected-error {{'Undef1' is not a member type of struct 'Swift.Int'}}
78+
let _: Int?.Undef // expected-error {{'Undef' is not a member type of generic enum 'Swift.Int?'}}
79+
let _: [Int].Undef // expected-error {{'Undef' is not a member type of generic struct '[Swift.Int]}}
80+
let _: [Int : Int].Undef // expected-error {{'Undef' is not a member type of generic struct '[Swift.Int : Swift.Int]'}}
81+
let _: (any P1).Undef // expected-error {{'Undef' is not a member type of protocol 'any test.P1'}}
82+
let _: (any P1 & P2).Undef // expected-error {{'Undef' is not a member type of type 'any test.P1 & test.P2'}}
83+
let _: ().Undef // expected-error {{'Undef' is not a member type of type '()'}}
84+
let _: (Int, Int).Undef // expected-error {{'Undef' is not a member type of type '(Swift.Int, Swift.Int)'}}
85+
let _: ((Int) -> Void).Undef // expected-error {{'Undef' is not a member type of type '(Swift.Int) -> Swift.Void'}}
86+
}

0 commit comments

Comments
 (0)