Skip to content

Commit 2fb88c6

Browse files
committed
Restrict parsing integer types in certain contexts
1 parent 6f25e17 commit 2fb88c6

File tree

5 files changed

+68
-22
lines changed

5 files changed

+68
-22
lines changed

include/swift/Parse/Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,11 @@ class Parser {
14171417
ParserResult<TypeRepr> parseTypeSimple(
14181418
Diag<> MessageID, ParseTypeReason reason);
14191419

1420+
ParserResult<TypeRepr> parseTypeOrValue();
1421+
ParserResult<TypeRepr> parseTypeOrValue(Diag<> MessageID,
1422+
ParseTypeReason reason = ParseTypeReason::Unspecified,
1423+
bool fromASTGen = false);
1424+
14201425
/// Parse layout constraint.
14211426
LayoutConstraint parseLayoutConstraint(Identifier LayoutConstraintID);
14221427

lib/Parse/ParseGeneric.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ ParserStatus Parser::parseGenericWhereClause(
317317

318318
// Parse the leading type. It doesn't necessarily have to be just a type
319319
// identifier if we're dealing with a same-type constraint.
320-
ParserResult<TypeRepr> FirstType = parseType();
320+
//
321+
// Note: This can be a value type, e.g. '123 == N' or 'N == 123'.
322+
ParserResult<TypeRepr> FirstType = parseTypeOrValue();
321323

322324
if (FirstType.hasCodeCompletion()) {
323325
Status.setHasCodeCompletionAndIsError();
@@ -377,7 +379,9 @@ ParserStatus Parser::parseGenericWhereClause(
377379
SourceLoc EqualLoc = consumeToken();
378380

379381
// Parse the second type.
380-
ParserResult<TypeRepr> SecondType = parseType();
382+
//
383+
// Note: This can be a value type, e.g. '123 == N' or 'N == 123'.
384+
ParserResult<TypeRepr> SecondType = parseTypeOrValue();
381385
Status |= SecondType;
382386
if (SecondType.isNull())
383387
SecondType = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc));

lib/Parse/ParseType.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,6 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
175175
tildeLoc = consumeToken();
176176
}
177177

178-
// Eat any '-' preceding integer literals.
179-
SourceLoc minusLoc;
180-
if (Tok.isMinus() && peekToken().is(tok::integer_literal)) {
181-
minusLoc = consumeToken();
182-
}
183-
184178
switch (Tok.getKind()) {
185179
case tok::kw_Self:
186180
case tok::identifier:
@@ -237,12 +231,6 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
237231
}
238232
return makeParserCodeCompletionResult<TypeRepr>(
239233
ErrorTypeRepr::create(Context, consumeToken(tok::code_complete)));
240-
case tok::integer_literal: {
241-
auto text = copyAndStripUnderscores(Tok.getText());
242-
auto loc = consumeToken(tok::integer_literal);
243-
ty = makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc));
244-
break;
245-
}
246234
case tok::l_square: {
247235
ty = parseTypeCollection();
248236
break;
@@ -739,7 +727,8 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &Args,
739727
// variadic generic types.
740728
if (!startsWithGreater(Tok)) {
741729
while (true) {
742-
ParserResult<TypeRepr> Ty = parseType(diag::expected_type);
730+
// Note: This can be a value type, e.g. 'Vector<3, Int>'.
731+
ParserResult<TypeRepr> Ty = parseTypeOrValue(diag::expected_type);
743732
if (Ty.isNull() || Ty.hasCodeCompletion()) {
744733
// Skip until we hit the '>'.
745734
RAngleLoc = skipUntilGreaterInTypeList();
@@ -1481,6 +1470,31 @@ Parser::parseTypeImplicitlyUnwrappedOptional(ParserResult<TypeRepr> base) {
14811470
return makeParserResult(ParserStatus(base), TyR);
14821471
}
14831472

1473+
ParserResult<TypeRepr> Parser::parseTypeOrValue() {
1474+
return parseTypeOrValue(diag::expected_type);
1475+
}
1476+
1477+
ParserResult<TypeRepr> Parser::parseTypeOrValue(Diag<> MessageID,
1478+
ParseTypeReason reason,
1479+
bool fromASTGen) {
1480+
// Eat any '-' preceding integer literals.
1481+
SourceLoc minusLoc;
1482+
if (Tok.isMinus() && peekToken().is(tok::integer_literal)) {
1483+
minusLoc = consumeToken();
1484+
}
1485+
1486+
// Attempt to parse values first. Right now the only value that can be parsed
1487+
// as a type are integers.
1488+
if (Tok.is(tok::integer_literal)) {
1489+
auto text = copyAndStripUnderscores(Tok.getText());
1490+
auto loc = consumeToken(tok::integer_literal);
1491+
return makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc));
1492+
}
1493+
1494+
// Otherwise, attempt to parse a regular type.
1495+
return parseType(MessageID, reason, fromASTGen);
1496+
}
1497+
14841498
//===----------------------------------------------------------------------===//
14851499
// Speculative type list parsing
14861500
//===----------------------------------------------------------------------===//

test/Parse/integer_types.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// RUN: %target-typecheck-verify-swift
22

3-
let a: 123 // expected-error {{integer unexpectedly used in a type position}}
3+
let a: 123 // expected-error {{consecutive statements on a line must be separated by ';'}}
4+
// expected-error@-1 {{expected type}}
5+
// expected-warning@-2 {{integer literal is unused}}
46

5-
let b: -123 // expected-error {{integer unexpectedly used in a type position}}
7+
let b: -123 // expected-error {{consecutive statements on a line must be separated by ';'}}
8+
// expected-error@-1 {{expected type}}
9+
// expected-warning@-2 {{integer literal is unused}}
610

711
let c: -Int // expected-error {{expected type}}
812
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
@@ -30,3 +34,19 @@ let f = Generic<-Int>.self // expected-error {{generic parameter 'T' could not b
3034
// expected-error@-1 {{missing whitespace between '<' and '-' operators}}
3135
// expected-error@-2 {{'>' is not a postfix unary operator}}
3236
// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}}
37+
38+
let g: 123.Type // expected-error {{consecutive statements on a line must be separated by ';'}}
39+
// expected-error@-1 {{expected type}}
40+
// expected-error@-2 {{value of type 'Int' has no member 'Type'}}
41+
42+
let h: 123.Protocol // expected-error {{consecutive statements on a line must be separated by ';'}}
43+
// expected-error@-1 {{expected type}}
44+
// expected-error@-2 {{value of type 'Int' has no member 'Protocol'}}
45+
46+
let i: 123? // expected-error {{consecutive statements on a line must be separated by ';'}}
47+
// expected-error@-1 {{expected type}}
48+
// expected-error@-2 {{cannot use optional chaining on non-optional value of type 'Int'}}
49+
50+
let j: 123! // expected-error {{consecutive statements on a line must be separated by ';'}}
51+
// expected-error@-1 {{expected type}}
52+
// expected-error@-2 {{cannot force unwrap value of non-optional type 'Int'}}

test/Sema/value_generics.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,21 @@ struct Generic<T: ~Copyable & ~Escapable> {}
4949
struct GenericWithIntParam<T: ~Copyable & ~Escapable, let N: Int> {}
5050

5151
extension Generic where T == 123 {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
52-
extension Generic where T == 123.Type {} // expected-error {{integer unexpectedly used in a type position}}
52+
extension Generic where T == 123.Type {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
53+
// expected-error@-1 {{expected '{' in extension}}
54+
extension Generic where T == 123? {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
55+
// expected-error@-1 {{expected '{' in extension}}
5356

5457
func f(_: Generic<123>) {} // expected-error {{integer unexpectedly used in a type position}}
5558
func g<let N: Int>(_: Generic<N>) {} // expected-error {{cannot use value type 'N' for generic argument 'T'}}
56-
func h(_: (Int, 123)) {} // expected-error {{integer unexpectedly used in a type position}}
57-
func i(_: () -> 123) {} // expected-error {{integer unexpectedly used in a type position}}
59+
func h(_: (Int, 123)) {} // expected-error {{expected type}}
60+
func i(_: () -> 123) {} // expected-error {{expected type}}
5861
func j(_: (A<123>) -> ()) {} // OK
59-
func k(_: some 123) {} // expected-error {{integer unexpectedly used in a type position}}
62+
func k(_: some 123) {} // expected-error {{expected parameter type following ':'}}
6063
func l(_: GenericWithIntParam<123, Int>) {} // expected-error {{cannot pass type 'Int' as a value for generic value 'N'}}
6164
func m(_: GenericWithIntParam<Int, 123>) {} // OK
6265

63-
typealias One = 1 // expected-error {{integer unexpectedly used in a type position}}
66+
typealias One = 1 // expected-error {{expected type in type alias declaration}}
6467

6568
struct B<let N: UInt8> {} // expected-error {{'UInt8' is not a supported value type for 'N'}}
6669

0 commit comments

Comments
 (0)