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

[REG 2.073] DMD in some cases forgets to generate wrapping TypeInfo for modifiers on classes #19432

Open
dlangBugzillaToGithub opened this issue May 6, 2018 · 4 comments
Labels
P1 Severity:Regression PRs that fix regressions

Comments

@dlangBugzillaToGithub
Copy link

Steven Schveighoffer (@schveiguy) reported this on 2018-05-06T13:08:59Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=18833

CC List

Description

Given an imported non-root module (e.g. one from a library), that instantiates a template class inside an auto function that is NOT a template, if you try to access a modified typeinfo for that object, it will fail to generate the wrapping TypeInfo.

For example a const(MyObject!params).

Simplest example:

mod1.d:
module mod1;

class C(T)
{
}

auto foo()
{
    return new C!int;
}

app.d:
import mod1;

void main()
{
    const s = foo();
    alias T = typeof(s);
    auto x = typeid(T);
}

Compile like this:

dmd -c mod1.d
dmd app.d mod1.o
Error:
Undefined symbols for architecture x86_64:
  "__D26TypeInfo_xC4mod1__T1CTiZQf6__initZ", referenced from:
      __Dmain in app.o
ld: symbol(s) not found for architecture x86_64

The missing TypeInfo is for const(C!int)

What I think happens is that in order to compile, it has to semantic the foo function, which means it sees that mod1 has already instantiated the C!int template. This is a situation pretty much reserved for auto functions. It requires a template instantiation in a non-root module, that is NOT inside another template. See typinf.d's function isSpeculativeType, where it checks a typeinfo's minst. That minst is set to null inside dsymbolsem.templateInstanceSemantic with this code:

    // https://issues.dlang.org/show_bug.cgi?id=10920
    // If the enclosing function is non-root symbol,
    // this instance should be speculative.
    if (!tempinst.tinst && sc.func && sc.func.inNonRoot())
    {
        tempinst.minst = null;
    }

So I don't know how to fix. You don't want to re-instantiate the template, but you still need the wrapping typeinfo. The compiler seems to ignore the type modifier when checking to see if it should emit the typeinfo.
@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2018-05-14T13:25:57Z

Since this is marked as a regression, when did it work?

@dlangBugzillaToGithub
Copy link
Author

schveiguy (@schveiguy) commented on 2018-05-14T14:34:18Z

I assumed since I reduced this from issue 17968 that it has the same regression point (i.e. 2.073 is when it regressed). I just now tested locally and indeed, 2.073.0 shows the failure, while 2.072.2 does not.

@dlangBugzillaToGithub
Copy link
Author

slavo5150 commented on 2018-05-25T04:03:43Z

I'm still trying to grok this, but from what I gather it sounds like `genTypeInfo` (https://github.com/dlang/dmd/blob/aa8fc584b92e736290f359596ec9e0aae857ae2c/src/dmd/typinf.d#L35) is not being run for one of the types (the template instantiation in the imported module?).

To fix, you may just need to enable logging in the compiler and find the appropriate place to call `genTypeInfo`.  grep for `genTypeInfo` to find usage examples in the source code.  There are quite a few.

@dlangBugzillaToGithub
Copy link
Author

schveiguy (@schveiguy) commented on 2018-05-25T11:08:46Z

Mike,

We worked through all that at dconf (including putting your recommended print statements, etc). What is happening is that the call to see if dmd should generate the TypeInfo *is* made, but the compiler decides it doesn't have to because it believes the TypeInfo has already been generated in the imported module.

The real problem here is that the compiler treats the class typeinfo that has the const flag set identically to how it treats the class typeinfo that doesn't have the const flag set. In other words, it elides generating the Const_TypeInfo wrapper because it has already generated the TypeInfo_Class.

It's really difficult to explain, but look at the function in dsymbolsem.d that sets the instantiated module to null.

Then look at typinf.d for isSpeculativeType.

The decision not to generate the Const_TypeInfo is confused with the decision not to instantiate the class that it wraps. I don't know how to extract them into 2 separate decisions, which is why I'm not the one to solve this. Still getting my feet wet with DMD development.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 Severity:Regression PRs that fix regressions
Projects
None yet
Development

No branches or pull requests

1 participant