Skip to content
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

Compiler: don't precompute sizeof on abstract structs and modules #7801

Merged
merged 3 commits into from
May 21, 2019

Conversation

asterite
Copy link
Member

Fixes #7741

And a few other fixes/improvements too.

I'm marking it as a breaking change too because instance_sizeof could be incorrectly invoked with non-class stuff (like structs) and so this will make compiling (but incorrect) code to stop compiling... but I think it's fine.

@asterite asterite added kind:bug A bug in the code. Does not apply to documentation, specs, etc. breaking-change topic:compiler:semantic labels May 20, 2019
@asterite
Copy link
Member Author

Some explanation: at some point we made sizeof be computed, if possible, at the semantic phase so that it can be used for generic type arguments, like StaticArray(UInt8, sizeof(Int32)). That works fine, but when the type given to sizeof is an abstract thing like a struct or a module, and there are generic subtypes, the final size (which is the size of the union of all actual instantiations in the program) can only be known at the end of compilation. This is what this PR fixes.

@@ -2568,7 +2568,8 @@ module Crystal
# Try to resolve the sizeof right now to a number literal
# (useful for sizeof inside as a generic type argument, but also
# to make it easier for LLVM to optimize things)
if type && !node.exp.is_a?(TypeOf)
if type && !node.exp.is_a?(TypeOf) &&
!(type.module? || (type.abstract? && type.struct?))
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 this be moved upwards together with the check of type.is_a?(GenericType)? I thought the notion of an instantiable type was already defined somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

Here in MainVisitor we compute it if we can. Later in CleanupTransformer we check that it's only a class. So, doing sizeof an abstract struct or module can be done and works, just not eagerly.

To be honest, now I'm not convinced that sizeof should work eagerly at all. I did that so one can do, for example, StaticArray(Int32, sizeof(Int32)), but that's a pretty contrived example. But for now I'm just fixing broken things, not changing the semantics of the language or introducing breaking changes. But eventually we can define the semantics we want for this and fix it.

And no, unfortunately there's no type.can_be_instantiated? method.

@Blacksmoke16
Copy link
Member

Can confirm this fixed my issue. Thanks again.

@asterite asterite added this to the 0.29.0 milestone May 21, 2019
@asterite asterite merged commit ee0df4e into crystal-lang:master May 21, 2019
@asterite asterite deleted the bug/sizeof branch May 21, 2019 01:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler:semantic
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Invalid memory access (signal 11) at address 0x0
4 participants