-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Parse] Minor code improvement in function-type parsing #5721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -184,6 +184,7 @@ ParserResult<TypeRepr> Parser::parseType() { | |
/// | ||
/// type-function: | ||
/// type-composition '->' type | ||
/// type-composition 'throws' '->' type | ||
/// | ||
ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID, | ||
bool HandleCodeCompletion) { | ||
|
@@ -203,62 +204,45 @@ ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID, | |
parseTypeSimpleOrComposition(MessageID, HandleCodeCompletion); | ||
if (ty.hasCodeCompletion()) | ||
return makeParserCodeCompletionResult<TypeRepr>(); | ||
|
||
if (ty.isNull()) | ||
return nullptr; | ||
auto tyR = ty.get(); | ||
|
||
// Parse a throws specifier. 'throw' is probably a typo for 'throws', | ||
// but in local contexts we could just be at the end of a statement, | ||
// so we need to check for the arrow. | ||
ParserPosition beforeThrowsPos; | ||
// Parse a throws specifier. | ||
// Don't consume 'throws', if the next token is not '->', so we can emit a | ||
// more useful diagnostic when parsing a function decl. | ||
SourceLoc throwsLoc; | ||
bool rethrows = false; | ||
if (Tok.isAny(tok::kw_throws, tok::kw_rethrows) || | ||
(Tok.is(tok::kw_throw) && peekToken().is(tok::arrow))) { | ||
if (Tok.is(tok::kw_throw)) { | ||
diagnose(Tok.getLoc(), diag::throw_in_function_type) | ||
if (Tok.isAny(tok::kw_throws, tok::kw_rethrows, tok::kw_throw) && | ||
peekToken().is(tok::arrow)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is definitely a behavior change for the recovery in a partial line: let fn: () throws Can you add tests for this case, and see if it's a net benefit? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure. What you mention is
Actually, this behavior is from the original code: |
||
if (Tok.isNot(tok::kw_throws)) { | ||
// 'rethrows' is only allowed on function declarations for now. | ||
// 'throw' is probably a typo for 'throws'. | ||
Diag<> DiagID = Tok.is(tok::kw_rethrows) ? | ||
diag::rethrowing_function_type : diag::throw_in_function_type; | ||
diagnose(Tok.getLoc(), DiagID) | ||
.fixItReplace(Tok.getLoc(), "throws"); | ||
} | ||
|
||
beforeThrowsPos = getParserPosition(); | ||
rethrows = Tok.is(tok::kw_rethrows); | ||
throwsLoc = consumeToken(); | ||
} | ||
|
||
// Handle type-function if we have an arrow. | ||
SourceLoc arrowLoc; | ||
if (consumeIf(tok::arrow, arrowLoc)) { | ||
if (Tok.is(tok::arrow)) { | ||
// Handle type-function if we have an arrow. | ||
SourceLoc arrowLoc = consumeToken(); | ||
ParserResult<TypeRepr> SecondHalf = | ||
parseType(diag::expected_type_function_result); | ||
if (SecondHalf.hasCodeCompletion()) | ||
return makeParserCodeCompletionResult<TypeRepr>(); | ||
if (SecondHalf.isNull()) | ||
return nullptr; | ||
if (rethrows) { | ||
// 'rethrows' is only allowed on function declarations for now. | ||
diagnose(throwsLoc, diag::rethrowing_function_type); | ||
} | ||
auto fnTy = new (Context) FunctionTypeRepr(generics, ty.get(), | ||
throwsLoc, | ||
arrowLoc, | ||
SecondHalf.get()); | ||
return makeParserResult(applyAttributeToType(fnTy, inoutLoc, attrs)); | ||
} else if (throwsLoc.isValid()) { | ||
// Don't consume 'throws', so we can emit a more useful diagnostic when | ||
// parsing a function decl. | ||
restoreParserPosition(beforeThrowsPos); | ||
} | ||
|
||
// Only function types may be generic. | ||
if (generics) { | ||
tyR = new (Context) FunctionTypeRepr(generics, tyR, throwsLoc, arrowLoc, | ||
SecondHalf.get()); | ||
} else if (generics) { | ||
// Only function types may be generic. | ||
auto brackets = generics->getSourceRange(); | ||
diagnose(brackets.Start, diag::generic_non_function); | ||
} | ||
|
||
if (ty.isNonNull() && !ty.hasCodeCompletion()) { | ||
ty = makeParserResult(applyAttributeToType(ty.get(), inoutLoc, attrs)); | ||
} | ||
return ty; | ||
return makeParserResult(applyAttributeToType(tyR, inoutLoc, attrs)); | ||
} | ||
|
||
ParserResult<TypeRepr> Parser::parseTypeForInheritance( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense to me. The fact that
rethrows
isn't allowed in a function type (which I didn't realize until seeing this PR) seems like an unnecessary and surprising limitation. I would guess users will expect to be able to writerethrows
function types, so suggestingdid you mean 'throws'?
will just be confusing.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Maybe, rejecting
rethrows
is just a bug.From the language reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summoning @rjmccall. A
rethrows
function type is useful, but it also makes the language more complicated, and I thought we decided not to do it.