mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Restrict parsing integer types in certain contexts
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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'}}
|
||||
|
||||
@@ -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'}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user