Bug 16410 – attribute inference for final methods of templated classes
Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-08-21T13:42:02Z
Last change time
2022-11-10T13:15:10Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
Lodovico Giaretta
Comments
Comment #0 by lodovico — 2016-08-21T13:42:02Z
Example code:
class Bar(T)
{
T t;
// the following function is not inferred @nogc
// changing return type to auto solves the issue
ulong get()
{
return t.length;
}
}
@nogc void main()
{
import std.experimental.allocator;
import std.experimental.allocator.mallocator;
auto alloc = Mallocator.instance;
auto x = alloc.make!(Bar!string).check;
// error: @nogc main cannot call non-@nogc function check
}
Comment #1 by lodovico — 2016-08-21T13:50:13Z
I forgot to mention that if Bar is a templated struct, attribute inference happens correctly, even with an explicit return type.
So this is a bug specific to templated classes.
Comment #2 by b2.temp — 2016-08-21T14:11:48Z
This is an enhancement request not a bug report.
The member function itself is not a template and since attribs are infered only for templated functions the error message is correct.
With "auto" return type the member function becomes a template so it works. It would also work with a template this parameter or with empty CT parameters.
°°°°°°°°°°°°°°°°°°°°°°°
class Bar(T)
{
T t;
ulong a()(){return t.length;}
ulong b(this T)(){return t.length;}
auto c(){return t.length;}
}
@nogc void main()
{
import std.experimental.allocator;
import std.experimental.allocator.mallocator;
auto alloc = Mallocator.instance;
auto a = alloc.make!(Bar!string).a;
auto b = alloc.make!(Bar!string).b;
auto c = alloc.make!(Bar!string).c;
}
°°°°°°°°°°°°°°°°°°°°°°°
Definitively not a "rejects-valid".
Comment #3 by lodovico — 2016-08-21T14:24:43Z
(In reply to b2.temp from comment #2)
> This is an enhancement request not a bug report.
I have to disagree with you. See my points below.
> The member function itself is not a template and since attribs are infered
> only for templated functions the error message is correct.
The member function is not a template, but it's part of a template and depends on the template arguments. I would understand your point if the function did not depend on T.
Also, the same thing, with `struct Bar(T)` instead of `class Bar(T)` supports inference, so your argument does not hold, because even there the member function is not a template itself, but only part of a template.
> With "auto" return type the member function becomes a template so it works.
I don't think that `auto` as a return types makes a function become a template. If it does, it's worth an enhancement, as I don't want the following function to be a template, it does not make any sense:
auto get3() { return 3UL; }
Comment #4 by b2.temp — 2016-08-21T14:58:09Z
(In reply to Lodovico Giaretta from comment #3)
> (In reply to b2.temp from comment #2)
> > With "auto" return type the member function becomes a template so it works.
>
> I don't think that `auto` as a return types makes a function become a
> template. If it does, it's worth an enhancement, as I don't want the
> following function to be a template, it does not make any sense:
>
> auto get3() { return 3UL; }
Yes you're right this is not a template:
https://dlang.org/spec/attribute.html#auto
but auto return type is made for this case, i.e when attribute inference is needed.
Comment #5 by lodovico — 2016-08-21T15:05:42Z
(In reply to b2.temp from comment #4)
> but auto return type is made for this case, i.e when attribute inference is
> needed.
The problem is that I'm in this situation:
==========================
interface Foo
{
int doSomething();
}
class Bar(T): Foo
{
override int doSomething()
{
// do something with T
}
}
==========================
There's no way to have Bar.doSomething @nogc currently because
1) I cannot put @nogc on Foo.doSomething, because in general it is not @nogc.
2) I cannot put @nogc on Bar.doSomething, because it may use the gc depending on T
3) I cannot use the "auto return trick" to trigger inference, because auto return cannot be used with override.
So currently there's no way to use Bar!T in @nogc code even for T's that are @nogc.
Comment #6 by b2.temp — 2016-08-21T15:07:18Z
(In reply to Lodovico Giaretta from comment #1)
> I forgot to mention that if Bar is a templated struct, attribute inference
> happens correctly, even with an explicit return type.
> So this is a bug specific to templated classes.
oops I've forget to read that. Repairing modifications now.
Comment #7 by schveiguy — 2016-08-23T13:51:21Z
I thought that templated classes would infer attributes. But thinking about this some more, I wonder if that's correct for virtual base functions?
I can envision this scenario:
class Foo(T)
{
string bar() { return "hi"; }
}
class Bar(T) : Foo!T
{
override string bar() { return super.bar() ~ T.stringof; }
}
Should Foo(T).bar be @nogc? It would be inferred that if Foo was a struct. But in this case, it is preventing possibly intended behavior.
Comment #8 by lodovico — 2016-08-23T14:51:53Z
(In reply to Steven Schveighoffer from comment #7)
> I thought that templated classes would infer attributes. But thinking about
> this some more, I wonder if that's correct for virtual base functions?
>
> I can envision this scenario:
>
> class Foo(T)
> {
> string bar() { return "hi"; }
> }
>
> class Bar(T) : Foo!T
> {
> override string bar() { return super.bar() ~ T.stringof; }
> }
>
> Should Foo(T).bar be @nogc? It would be inferred that if Foo was a struct.
> But in this case, it is preventing possibly intended behavior.
Sorry, I don't understand why Foo!T.bar being @nogc would prevent possibly intended behaviour. Can you please elaborate on this?
Comment #9 by lodovico — 2016-08-23T15:04:24Z
(In reply to Lodovico Giaretta from comment #8)
> Sorry, I don't understand why Foo!T.bar being @nogc would prevent possibly
> intended behaviour. Can you please elaborate on this?
Nevermind, got that. If a method is inferred @nogc, it can no longer be overridden as non-@nogc. This is correct. My bad.
Then a new question arises: why cannot attribute inference happen for *final* methods of templated classes?
Comment #10 by lodovico — 2016-08-23T15:08:06Z
(In reply to Lodovico Giaretta from comment #9)
> Then a new question arises: why cannot attribute inference happen for
> *final* methods of templated classes?
Small precisation: I mean *final override* methods. For final (non-virtual) methods it already happens.
Comment #11 by schveiguy — 2016-08-23T15:52:52Z
(In reply to Lodovico Giaretta from comment #10)
> (In reply to Lodovico Giaretta from comment #9)
> > Then a new question arises: why cannot attribute inference happen for
> > *final* methods of templated classes?
>
> Small precisation: I mean *final override* methods. For final (non-virtual)
> methods it already happens.
I think it should, where possible. That is, if you can override a non-@nogc method with a @nogc method (and if not, I think you should be able to), then inference of the attribute should happen for final methods.
Comment #12 by razvan.nitu1305 — 2022-11-10T13:15:10Z
(In reply to Lodovico Giaretta from comment #10)
> (In reply to Lodovico Giaretta from comment #9)
> > Then a new question arises: why cannot attribute inference happen for
> > *final* methods of templated classes?
>
> Small precisation: I mean *final override* methods. For final (non-virtual)
> methods it already happens.
The compiler cannot infer the attributes for final override methods because you already may have some constraints from the overriding function. For example, if the overriden function is @safe, the overriding function must also be @safe. Technically, the overriden function dictates the interface. I think it might be surprising to the attributes for overrides, even if they are final.
I think we can close this issue as INVALID.