-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #21721: make case TypeBlock(_, _) not match non-type Block #21722
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
Conversation
TypeBlocks are represented as normal Blocks in the Quotes API. The current TypeTest for TypeBlock is exactly the same as the TypeTest for Block, which means that case TypeBlock(_, _) matches every block. The implementation of unapply on TypeBlockModule, however, gives back (List[TypeDef], TypeTree). It constructs the List[TypeDef] by mapping over every statement, turning it into a TypeDef by using a match with the pattern case alias: TypeDef => alias Since the TypeTest matches any Block and not only Blocks that are TypeBlocks, the statemnts can be anything, not just TypeDefs, which lets the whole case TypeBlock(_, _) pattern fail with a MatchError. This commit fixes the problem by making the TypeTest check whether the Block is a type (which in turns checks whether the blocks expression is a type)
I'm a bit unsure whether the failure of the CI has anything to do with the change proposed in this PR. On my machine,
I got:
|
Hi @felher, the CI failure has nothing to do with the proposed change. I've restarted the failed job. |
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.
Thank you for submitting this PR, the changes look good. The underlying isType checks if the Block result is a TypeTree, which is only supposed to happen for TypeBlocks, which makes this added guard sufficient.
Apologies for the very long wait - I must have missed this one initially. After some testing, we might also need to add an opposite check for regular Blocks, since now TypeBlocks can be matched into Blocks while containing different types, resulting in similar creashes, but all of this can be done separately.
Part 2 to #21722 We do the same thing as there, but this time to make sure TypeBlocks are not matched as Blocks. The tests from that PR were also moved, as I did not realize they were put in `tests/pos` instead of `tests/pos-macros` when making the review.
FYI: I believe there is an issue with this PR. I've summarized the problem and shared it with @jchyb. |
The problem @hamzaremmal mentioned is that in the reflection api docs we specify that all of the statements of a TypeBlock are supposed to be TypeDefs, but we do not check that here…. I want to refute this point. As I mentioned in my review comment: The underlying isType checks if the Block result is a TypeTree, which is only supposed to happen for TypeBlocks, which makes this added guard sufficient. It is impossible in the reflection API to create a regular Block with a TypeTree expr field, so none of that would be matched against TypeBlock. TypeBlock apply however only allows using TypeDefs in place of statements (or, for TypeBlock, aliases). Looking at the types of both, the isType check (which internally actually checks if the expr field is a TypeTree) is sufficient, as it's impossible to create a tpd.Block with non-TypeDef statements and TypeTree result using the reflection API. About TypeBlocks generated by the compiler (users cannot, and were never able to create them themselves by code)… I actually were not able to get any in a macro. Currently, I believe only parser can create those when parsing a quoted type pattern (like |
TypeBlock
s are represented as normalBlocks
in the Quotes API's implementation. The currentTypeTest
forTypeBlock
is exactly the same as theTypeTest
forBlock
, which means thatcase TypeBlock(_, _)
"matches" every block.The implementation of
unapply
onTypeBlockModule
, however, gives back(List[TypeDef], TypeTree)
. It constructs theList[TypeDef]
by mapping over every statement of the block, trying to turn it into aTypeDef
by using a match with the patternThis seems fine since
TypeBlock
s are supposed to be just a list ofTypeDefs
followed by a type as the last expression. Since theTypeTest
matches anyBlock
and not onlyBlocks
that areTypeBlocks
, the statements can be anything, not justTypeDef
s, which lets the wholecase TypeBlock(_, _)
pattern die with aMatchError
.This commit fixes the problem by making the
TypeTest
check whether theBlock
is a type (which in turns checks whether theBlock
s expression is a type)This is my first PR, please let me know if I should change anything or am completely going about fixing this the wrong way, etc.
Also, I could not run the complete test suite on my machine, it died even without making any changes. But I could at least run the positive compilation tests.
Closes #21721