Restrict parsing integer types in certain contexts

This commit is contained in:
Alejandro Alonso
2024-09-18 10:30:10 -07:00
parent 5520baeab0
commit 90ce2cd361
5 changed files with 68 additions and 22 deletions

View File

@@ -1411,6 +1411,11 @@ public:
ParserResult<TypeRepr> parseTypeSimple(
Diag<> MessageID, ParseTypeReason reason);
ParserResult<TypeRepr> parseTypeOrValue();
ParserResult<TypeRepr> parseTypeOrValue(Diag<> MessageID,
ParseTypeReason reason = ParseTypeReason::Unspecified,
bool fromASTGen = false);
/// Parse layout constraint.
LayoutConstraint parseLayoutConstraint(Identifier LayoutConstraintID);

View File

@@ -317,7 +317,9 @@ ParserStatus Parser::parseGenericWhereClause(
// Parse the leading type. It doesn't necessarily have to be just a type
// identifier if we're dealing with a same-type constraint.
ParserResult<TypeRepr> FirstType = parseType();
//
// Note: This can be a value type, e.g. '123 == N' or 'N == 123'.
ParserResult<TypeRepr> FirstType = parseTypeOrValue();
if (FirstType.hasCodeCompletion()) {
Status.setHasCodeCompletionAndIsError();
@@ -377,7 +379,9 @@ ParserStatus Parser::parseGenericWhereClause(
SourceLoc EqualLoc = consumeToken();
// Parse the second type.
ParserResult<TypeRepr> SecondType = parseType();
//
// Note: This can be a value type, e.g. '123 == N' or 'N == 123'.
ParserResult<TypeRepr> SecondType = parseTypeOrValue();
Status |= SecondType;
if (SecondType.isNull())
SecondType = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc));

View File

@@ -175,12 +175,6 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
tildeLoc = consumeToken();
}
// Eat any '-' preceding integer literals.
SourceLoc minusLoc;
if (Tok.isMinus() && peekToken().is(tok::integer_literal)) {
minusLoc = consumeToken();
}
switch (Tok.getKind()) {
case tok::kw_Self:
case tok::identifier:
@@ -237,12 +231,6 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
}
return makeParserCodeCompletionResult<TypeRepr>(
ErrorTypeRepr::create(Context, consumeToken(tok::code_complete)));
case tok::integer_literal: {
auto text = copyAndStripUnderscores(Tok.getText());
auto loc = consumeToken(tok::integer_literal);
ty = makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc));
break;
}
case tok::l_square: {
ty = parseTypeCollection();
break;
@@ -739,7 +727,8 @@ ParserStatus Parser::parseGenericArguments(SmallVectorImpl<TypeRepr *> &Args,
// variadic generic types.
if (!startsWithGreater(Tok)) {
while (true) {
ParserResult<TypeRepr> Ty = parseType(diag::expected_type);
// Note: This can be a value type, e.g. 'Vector<3, Int>'.
ParserResult<TypeRepr> Ty = parseTypeOrValue(diag::expected_type);
if (Ty.isNull() || Ty.hasCodeCompletion()) {
// Skip until we hit the '>'.
RAngleLoc = skipUntilGreaterInTypeList();
@@ -1481,6 +1470,31 @@ Parser::parseTypeImplicitlyUnwrappedOptional(ParserResult<TypeRepr> base) {
return makeParserResult(ParserStatus(base), TyR);
}
ParserResult<TypeRepr> Parser::parseTypeOrValue() {
return parseTypeOrValue(diag::expected_type);
}
ParserResult<TypeRepr> Parser::parseTypeOrValue(Diag<> MessageID,
ParseTypeReason reason,
bool fromASTGen) {
// Eat any '-' preceding integer literals.
SourceLoc minusLoc;
if (Tok.isMinus() && peekToken().is(tok::integer_literal)) {
minusLoc = consumeToken();
}
// Attempt to parse values first. Right now the only value that can be parsed
// as a type are integers.
if (Tok.is(tok::integer_literal)) {
auto text = copyAndStripUnderscores(Tok.getText());
auto loc = consumeToken(tok::integer_literal);
return makeParserResult(new (Context) IntegerTypeRepr(text, loc, minusLoc));
}
// Otherwise, attempt to parse a regular type.
return parseType(MessageID, reason, fromASTGen);
}
//===----------------------------------------------------------------------===//
// Speculative type list parsing
//===----------------------------------------------------------------------===//

View File

@@ -1,8 +1,12 @@
// RUN: %target-typecheck-verify-swift
let a: 123 // expected-error {{integer unexpectedly used in a type position}}
let a: 123 // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-warning@-2 {{integer literal is unused}}
let b: -123 // expected-error {{integer unexpectedly used in a type position}}
let b: -123 // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-warning@-2 {{integer literal is unused}}
let c: -Int // expected-error {{expected type}}
// 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
// expected-error@-1 {{missing whitespace between '<' and '-' operators}}
// expected-error@-2 {{'>' is not a postfix unary operator}}
// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}}
let g: 123.Type // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-error@-2 {{value of type 'Int' has no member 'Type'}}
let h: 123.Protocol // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-error@-2 {{value of type 'Int' has no member 'Protocol'}}
let i: 123? // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-error@-2 {{cannot use optional chaining on non-optional value of type 'Int'}}
let j: 123! // expected-error {{consecutive statements on a line must be separated by ';'}}
// expected-error@-1 {{expected type}}
// expected-error@-2 {{cannot force unwrap value of non-optional type 'Int'}}

View File

@@ -53,18 +53,21 @@ struct Generic<T: ~Copyable & ~Escapable> {}
struct GenericWithIntParam<T: ~Copyable & ~Escapable, let N: Int> {}
extension Generic where T == 123 {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
extension Generic where T == 123.Type {} // expected-error {{integer unexpectedly used in a type position}}
extension Generic where T == 123.Type {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
// expected-error@-1 {{expected '{' in extension}}
extension Generic where T == 123? {} // expected-error {{cannot constrain type parameter 'T' to be integer '123'}}
// expected-error@-1 {{expected '{' in extension}}
func f(_: Generic<123>) {} // expected-error {{integer unexpectedly used in a type position}}
func g<let N: Int>(_: Generic<N>) {} // expected-error {{cannot use value type 'N' for generic argument 'T'}}
func h(_: (Int, 123)) {} // expected-error {{integer unexpectedly used in a type position}}
func i(_: () -> 123) {} // expected-error {{integer unexpectedly used in a type position}}
func h(_: (Int, 123)) {} // expected-error {{expected type}}
func i(_: () -> 123) {} // expected-error {{expected type}}
func j(_: (A<123>) -> ()) {} // OK
func k(_: some 123) {} // expected-error {{integer unexpectedly used in a type position}}
func k(_: some 123) {} // expected-error {{expected parameter type following ':'}}
func l(_: GenericWithIntParam<123, Int>) {} // expected-error {{cannot pass type 'Int' as a value for generic value 'N'}}
func m(_: GenericWithIntParam<Int, 123>) {} // OK
typealias One = 1 // expected-error {{integer unexpectedly used in a type position}}
typealias One = 1 // expected-error {{expected type in type alias declaration}}
struct B<let N: UInt8> {} // expected-error {{'UInt8' is not a supported value type for 'N'}}