[dmd-internals] Type mangling for deduced attributes

kenji hara k.hara.pg at gmail.com
Thu Nov 17 18:10:54 PST 2011


2011/11/17 Don Clugston <dclugston at googlemail.com>:
> On 17 November 2011 13:43, kenji hara <k.hara.pg at gmail.com> wrote:
>> 2011/11/17 Don Clugston <dclugston at googlemail.com>:
>>> On 17 November 2011 11:09, kenji hara <k.hara.pg at gmail.com> wrote:
>>>> Withdraw a previous statement, I still argue that is better to apply
>>>> result of inference into mangleof.
>>>> First of all, the pure/safe/nothrow inference runs against only
>>>> function literals and template functions.
>>>
>>> This is true at present. But are we confident that it will never apply
>>> to anything else?
>>>
>>>> For function literal, its
>>>> type determines in the place its written.For template function, its
>>>> type determines in its instantiation.Both of cases can always see
>>>> their function bodies.
>>>
>>> Are we happy to say that when full type inference is used, it does NOT
>>> invoke safe/pure/nothrow inference?
>>
>> Template function instantiation and function literal type inference
>> always also invoke attribute inference.
>> They are inseparable.
>>
>>> immutable fptr = &foo!(7);
>>> immutable fptr2 = (){ return 0; }
>>>
>>> That is, both fptr and fptr2 will always be impure, @system, and throw?
>>> Or does it invoke safe/pure/nothrow inference? In which case the
>>> situation I mentioned arises.
>>
>> Maybe you are worried about breaking pure/safe/nothrow-ness silently,
>> but it does not happen.
>
> No, I'm worried about noisy breaking of pure/nothrow. It can even go
> in the other direction. Delete a read from a static variable in the
> body of a template function (not the signature) and now your code
> won't link, because the function suddenly became pure. The issue is
> predictability.
>
> Absence of an attribute means either  "impure" _or_ "don't know/don't
> care/please work it out for me". Somehow, we have to keep this
> ambiguity out of external interfaces. It's not much of a problem with
> safe, because we have the @system qualifier. But we have no @impure,
> @maythrow -- there is no way to say, "this is *intentionally* not
> pure, even if it's inferred as pure at the moment".
>
> As Rainer says, it does seem odd to restrict purity inference to
> templates functions and delegate literals. It would not be at all
> difficult to implement it for functions as well. That would be nice,
> because then code wouldn't need to be littered with annotations. As
> far as I can tell, the only argument against doing it, is this
> unpredictability problem. Arguably, the inference for templates
> generates so much unpredicatibility, that we might as well extend it
> to functions.
>
> Something I should clarify -- I'm just playing devil's advocate here,
> I don't actually have an opinion on what we should do.

OK, I understand what you're worried.
But, conservative mangling of template function never rescue anything, IMO.
It just decrease the type information and cause inconsistent confusion.
See following example.

---- a.d
int g;
int foo(int n)() {
    version (impure) g = n;
    return n;
}
int call() {
    return foo!1();
    pragma(msg, "in a: ", typeof(&foo!1));
}

---- b.d
import a;
void main() {
    assert(a.call() == 1);
    assert(a.g == 0);   // Line4: should fail if you compile a.d with
-version=impure

    pragma(msg, "in b: ", typeof(&foo!1));
    assert(foo!1() == 1);
    assert(a.g == 0);   // Line8: should fail if you compile b,d with
-version=impure
}

---- cmd
$ dmd -c a.d
in a: int function() pure nothrow @safe
$ dmd -c b.d -version=impure
in b: int function() nothrow @safe
$ dmd -ofx -map a.obj b.obj
$ x
  <----- Merged foo!1() instantiation into pure version.

$ dmd -ofx -map b.obj a.obj    // change object file order
$ x
core.exception.AssertError at b(4): Assertion failure
----------------
40D01C
40CE93
40204D
402664
40225B
412759
----------------
  <----- Merged foo!1() instantiation into impure version.


a.obj and b.obj have different instantiation of foo!1, but their
manglings are same, "_D1a11__T3fooVi1Z3fooFZi".
Then the calls of foo!1 jump into same code, that is unfortunately shared.

If we can have different manglings depending on whether foo!1 is pure or not,
module a will have a foo!1 mangled as "_D1a11__T3fooVi1Z3fooFNaNbNfZi", and
module b will have a foo!1 mangled as "_D1a11__T3fooVi1Z3fooFNbNfZi".
And the assertion in b:Line4 will always fail independing of the
object file order in command line.

Kenji Hara


More information about the dmd-internals mailing list