Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,11 @@ class Parser {
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);

Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4116,7 +4116,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
return makeParserSuccess();
}

auto countType = parseType(diag::expected_type);
auto countType = parseTypeOrValue(diag::expected_type);
if (countType.isNull()) {
return makeParserSuccess();
}
Expand Down
8 changes: 6 additions & 2 deletions lib/Parse/ParseGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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));
Expand Down
40 changes: 27 additions & 13 deletions lib/Parse/ParseType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
24 changes: 22 additions & 2 deletions test/Parse/integer_types.swift
Original file line number Diff line number Diff line change
@@ -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 ';'}}
Expand Down Expand Up @@ -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'}}
13 changes: 8 additions & 5 deletions test/Sema/value_generics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,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'}}

Expand Down