Skip to content

[Parse] Do not parse generic arguments of a cast destination if the token is more than a < #60088

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

Closed
wants to merge 9 commits into from

Conversation

simanerush
Copy link
Member

Resolves #43053.

@AnthonyLatsis
Copy link
Collaborator

@swift-ci please smoke test macOS

@AnthonyLatsis
Copy link
Collaborator

@swift-ci please smoke test Linux

Copy link
Collaborator

@AnthonyLatsis AnthonyLatsis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great overall!

Copy link
Collaborator

@AnthonyLatsis AnthonyLatsis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! One more thing.

@AnthonyLatsis AnthonyLatsis requested a review from rintaro July 19, 2022 19:25
@AnthonyLatsis
Copy link
Collaborator

@swift-ci please smoke test macOS

@simanerush simanerush changed the title [Parse] Do not parse generic arguments of a cast destination if the token is more than a "<" [Parse] Do not parse generic arguments of a cast destination if the token is more than a < Jul 20, 2022
@AnthonyLatsis AnthonyLatsis requested a review from xedin July 23, 2022 22:36
Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me! @rintaro please take a look as well!

@xedin
Copy link
Contributor

xedin commented Jul 26, 2022

@swift-ci please smoke test

@AnthonyLatsis
Copy link
Collaborator

Note
Reminder to squash

Co-authored-by: Luciano Almeida <[email protected]>
@xedin
Copy link
Contributor

xedin commented Jul 27, 2022

@swift-ci please test

Copy link
Member

@rintaro rintaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late reviewing 🙇

Comment on lines 725 to +730
if (startsWithLess(Tok)) {
auto genericArgsStatus = parseGenericArguments(GenericArgs, LAngle, RAngle);
if (genericArgsStatus.isErrorOrHasCompletion())
return genericArgsStatus;
// Only attempt to parse a generic argument list in a cast destination
// type if the token text is just "<", because it can be an operator,
// for example: "1 as Int16 << 7".
if (Tok.getText().equals("<") ||
reason != ParseTypeReason::CastDestination) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just use canParseAsGenericArgumentList() instead of startsWithLess(Tok) like expression parsing?
It only accepts single <, but I'm not sure there's a place we need to accept << for a generic arguments in the first place. If we cannot use canParseAsGenericArgumentList(), could you add some code-comment to explain why not?

Copy link
Member

@rintaro rintaro Jul 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we don't use canParseAsGenericArgumentList() probably because of the SIL type parsing which has generic function types like <T> (T) -> Void. And for non-expression position, we probably want to diagnose errors inside <...> as a generic argument error, but not as a bogus random tokens after a type. E.g.

let a: Dictionary<String: Int>

The error in <String: Int> should be diagnosed as like expected ',' instead of ':' inside parseGenericArguments(). But if we used canParseAsGenericArgumentList() here, it would be parsed as a random tokens after let a: Dictionary.

So I think having ParseTypeReason::CastDestination actually makes sense. And we can use canParseAsGenericArgumentList() only for CastDestination case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback!

Copy link
Contributor

@CodaFi CodaFi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This embeds a form of unbounded lookahead in the Swift type grammar. We should be careful committing to additional lookahead like this to disambiguate parses. This is strictly a change to the language and should probably be discussed on evolution.

@CodaFi
Copy link
Contributor

CodaFi commented Jul 27, 2022

As discussed in #60146, I don't mind if we use unbounded lookahead to diagnose this case, but to accept this production as a result of a lookahead is a much bigger change than I think you intend to make here.

@rintaro
Copy link
Member

rintaro commented Jul 27, 2022

@CodaFi

to accept this production as a result of a lookahead is a much bigger change than I think you intend to make here.

I don't think a lookahead changes the behavior for currently accepted cases. Currently at this position, all < after a type identifier is unconditionally parsed as a generic parameter clause, and that won't change even if we lookahead and decide how to parse it as a result of a lookahead as long as it was successfully parsed as a generic argument clause.

I agree this might be strictly a change to the language, but I don't think this would break any existing code.

@simanerush
Copy link
Member Author

@CodaFi I agree with you in some sense, I was also afraid that that might be a bigger change than just a small bug fix. As we can see, this fix had already caused concern with <. But ultimately i was only trying to fix a bug. I was also thinking maybe we could rethink this and emit some helpful diagnostics like Rust does instead of the current approach.

Co-authored-by: Rintaro Ishizaki <[email protected]>
@AnthonyLatsis
Copy link
Collaborator

I tend to agree with Robert we should be more principled and farsighted in approaching disambiguation problems that require unbounded lookahead in the general case. The ambiguity can easily be worked around, and I would not want this to ever hinder a hypothetical proposal on dependent types. For now though, we can learn from Rust and improve the diagnostic.

@simanerush WDYT?

@simanerush
Copy link
Member Author

simanerush commented Jul 28, 2022

@AnthonyLatsis I agree with you. Should I close this PR then and open an issue proposing new diagnostics rather than silencing the current diagnostics?

@AnthonyLatsis
Copy link
Collaborator

Sounds good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SR-436] Parse failure that shouldn’t be
6 participants