Bug 2753 – Cannot declare pointer to function returning ref

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2009-03-21T16:21:21Z
Last change time
2024-12-13T17:49:36Z
Keywords
pull, spec
Assigned to
No Owner
Creator
Jerry Quinn
Moved to GitHub: dmd#17505 →

Comments

Comment #0 by jlquinn — 2009-03-21T16:21:21Z
ref int c() { static int a=2; return a; } ref int function() d = &c; // line 8 foo.d(8): variable foo.d only parameters or foreach declarations can be ref Type inference, however, is able to figure it out: ref int c() { static int a=2; return a; } auto d = &c; // whee Correctly reporting the issue from bug 2735
Comment #1 by smjg — 2009-03-21T17:34:35Z
The problem seems to be an ambiguity in the grammar: is it ref (int function()) or (ref int) function()? Maybe we need a bracket notation for ref like we have for const and invariant. Note that, if we have both this and the notation proposed in bug 1961, ref and inout would no longer be synonyms.
Comment #2 by dfj1esp02 — 2009-03-22T03:00:31Z
judging from compiler error messages, ref is not a type modifier, it's a function attribute, so brackets won't help. It should also be noted, that others function attributes' grammar is also ambiguous. --- nothrow int function() foo(); --- What is nothrow here? --- const int foo(); --- What is const here? --- int foo(ref int function() goo); --- This one would probably give no error. Is it keyword saving issue? Semantically different things have the same syntax. If Walter wants context-dependent keywords, he should mark those contexts better. I would like to see function attributes at predictable, easy-to-spot locations, so it would be no chanse to mess storage class with function attributes. There are already good places for function attributes (after function) and storage class attributes (before type). If the attributes will be restricted to corresponding places, there will be no ambiguity (except const). --- int foo(ref int function() goo); //ref parameter int goo(int function() ref foo); //return byref function ---
Comment #3 by smjg — 2009-03-22T16:50:34Z
(In reply to comment #2) > judging from compiler error messages, ref is not a type modifier, it's a > function attribute, so brackets won't help. I'm a little confused - if that were the case, surely it would work? Moreover, what is there preventing ref from becoming a type modifier, if this would fix the problem? It should also be noted, that > others function attributes' grammar is also ambiguous. > --- > nothrow int function() foo(); > --- > What is nothrow here? So there's actually an advantage to the suffix notation for function attributes. > --- > const int foo(); > --- > What is const here? > > --- > int foo(ref int function() goo); > --- > This one would probably give no error. But that is a case that really is ambiguous. > Is it keyword saving issue? Semantically different things have the same syntax. > If Walter wants context-dependent keywords, he should mark those contexts > better. > I would like to see function attributes at predictable, easy-to-spot locations, > so it would be no chanse to mess storage class with function attributes. There > are already good places for function attributes (after function) and storage > class attributes (before type). If the attributes will be restricted to > corresponding places, there will be no ambiguity (except const). > --- > int foo(ref int function() goo); //ref parameter > int goo(int function() ref foo); //return byref function > --- I don't really like this. The ref essentially means the same thing, it's just whether it applies to the parameter or the return. In the latter, it's being moved further from what it applies to: the return type. IIRC, the equivalent C++ syntax is int foo(int (*&goo)()); // ref parameter int goo(int& (*foo)()); // ref return in parameter It isn't exactly clear, but at least it's unambiguous. If D got the & notation for reference, we would have int foo(int function()& goo); // ref parameter int goo(int& function() foo); // ref return in parameter Indeed, we could have ref take the place of & in this notation int foo(int function() ref goo); // ref parameter int goo(int ref function() foo); // ref return in parameter and so the syntax of ref/& would become consistent with that of *. We could do it like this, or we could make ref a type modifier along the lines of const. Take your pick.
Comment #4 by dfj1esp02 — 2009-03-24T04:17:38Z
(In reply to comment #3) > int foo(int function() ref goo); // ref parameter > int goo(int ref function() foo); // ref return in parameter Providing the place between return type and function name for function attributes... interesting...
Comment #5 by smjg — 2009-03-24T04:26:03Z
(In reply to comment #4) > (In reply to comment #3) >> int foo(int function() ref goo); // ref parameter >> int goo(int ref function() foo); // ref return in parameter > Providing the place between return type and function name for function > attributes... interesting... Any particular reason you feel it still has to count as a function attribute?
Comment #6 by dfj1esp02 — 2009-03-26T03:46:40Z
1) if it can why not? 2) this is usable for other function attributes
Comment #7 by yebblies — 2011-06-06T19:46:53Z
*** Issue 5421 has been marked as a duplicate of this issue. ***
Comment #8 by yebblies — 2011-06-06T21:26:33Z
*** Issue 5828 has been marked as a duplicate of this issue. ***
Comment #9 by bugzilla — 2012-01-23T00:34:00Z
ref is a storage class - not a function attribute or type modifier. The grammar isn't broken, it's just a quirk in it. Changing it would be an enhancement request.
Comment #10 by qs.il.paperinik — 2022-10-25T13:59:07Z
@Walter: It is “broken” in the sense that the grammar should(!) be able to express a type without requiring type aliases. I’d suggest minimal changes to the Type grammar to allow for it. TL;DR: The semantics is obvious, I hope. Let’s allow the following: ```d ref (int function()) f1(); (ref int function()) f2(); void g1(ref (int function()) fp); void g2((ref int function()) fp); void hImpl(DG : ref int delegate())(DG dg) { } alias h = fImpl!(ref int delegate() @safe); ``` ――― End of TL;DR ――― Note that `f1` and `g1` are equivalent to: ```d ref int function() f1(); void g1(ref int function() fp); ``` In the grammar, I use `?` to signify optional occurrence. ```diff Type: TypeCtors? BasicType TypeSuffixes? + ref TypeCtors? BasicType CallableSuffix TypeSuffixes? BasicType: FundamentalType . QualifiedIdentifier QualifiedIdentifier Typeof Typeof . QualifiedIdentifier − TypeCtor ( Type ) + TypeCtor? ( Type ) Vector TraitsExpression MixinType TypeSuffix: * [ ] [ AssignExpression ] [ AssignExpression .. AssignExpression ] [ Type ] + CallableSuffix + + CallableSuffix: delegate Parameters MemberFunctionAttributes? function Parameters FunctionAttributes? ``` (This grammar diff does not address the special casing for `alias` that is currently in place and superseded by this. As far as I can tell, it’ll be still good and should not be changed.) It is worth considering to deprecate the syntax without disambiguating parentheses, akin to comparison and bit-wise operators and `() => { }`. The deprecation only applies to cases where a non-aliased function pointer or delegate type is used on a `ref` parameter or as the return type of a `ref` returning function.
Comment #11 by dlang-bot — 2022-10-25T14:02:28Z
@Bolpat created dlang/dlang.org pull request #3446 "Fix Issue 2753" fixing this issue: - Fix Issue 2753 https://github.com/dlang/dlang.org/pull/3446
Comment #12 by dlang-bot — 2023-05-17T12:10:51Z
@ntrel updated dlang/dmd pull request #15243 "[new syntax] Support `function` `ref` Type Parameters for function pointer types" fixing this issue: - Fix Issue 2753 - Cannot declare pointer to function returning ref. https://github.com/dlang/dmd/pull/15243
Comment #13 by dlang-bot — 2023-05-17T17:08:05Z
@Bolpat updated dlang/dmd pull request #15245 "Fix Issue 2753" fixing this issue: - Fix issue 2753 - add good case tests https://github.com/dlang/dmd/pull/15245
Comment #14 by dlang-bot — 2023-05-26T11:29:36Z
@Bolpat created dlang/dlang.org pull request #3616 "Primary Type Syntax" fixing this issue: - Fix Issue 2753 https://github.com/dlang/dlang.org/pull/3616
Comment #15 by dlang-bot — 2023-05-26T11:34:07Z
@Bolpat created dlang/dmd pull request #15269 "Primary Type Syntax" fixing this issue: - Fix issue 2753 - add good case tests https://github.com/dlang/dmd/pull/15269
Comment #16 by nick — 2023-11-08T10:38:56Z
*** Issue 21521 has been marked as a duplicate of this issue. ***
Comment #17 by nick — 2024-10-19T10:00:20Z
(In reply to anonymous4 from comment #2) > int goo(int function() ref foo); //return byref function Allowing that would seem to be a simple fix to the problem, except now it would be confusing with the `return ref` attribute. The latter didn't exist when you wrote that though.
Comment #18 by smjg — 2024-10-19T10:23:51Z
(In reply to Nick Treleaven from comment #17) > (In reply to anonymous4 from comment #2) >> int goo(int function() ref foo); //return byref function > > Allowing that would seem to be a simple fix to the problem, except now it > would be confusing with the `return ref` attribute. The latter didn't exist > when you wrote that though. I stand by what I said before. It makes no sense to me to have the notation for "reference to an integer" split in two like this. To me, that notation reads as declaring foo as a byref parameter, not as a parameter of function-with-byref-return type. I think most people would agree. Hence my earlier proposal: > int foo(int function() ref goo); // ref parameter > int goo(int ref function() foo); // ref return in parameter Here, the 'ref' would be exactly the same as '*' for pointers and '[]' for arrays in terms of how it is placed. That 'ref' is a keyword rather than a symbol shouldn't have to make any difference to this.
Comment #19 by nick — 2024-10-19T11:51:27Z
> int foo(int function() ref goo); // ref parameter Again, that is going to be confusing with the `return ref` attribute. (And it looks weird having a parameter storage class not come first). >> int goo(int ref function() foo); // ref return in parameter > Here, the 'ref' would be exactly the same as '*' for pointers and '[]' for arrays in terms of how it is placed It would be a simple fix to the problem, though it might make people think `ref` is a type modifier.
Comment #20 by smjg — 2024-10-19T12:26:30Z
(In reply to Nick Treleaven from comment #19) > > int foo(int function() ref goo); // ref parameter > > Again, that is going to be confusing with the `return ref` attribute. (And > it looks weird having a parameter storage class not come first). Is the distinction between "storage class" and "type modifier" syntactic or semantic? I'm not sure where to find the exact definitions of these terms. dlang.org implies both in different places for "storage class", and I can't seem to find anything for "type modifier". If syntactic, then how would 'ref' be a storage class under such a syntax? This would surely mean '*' and '[]' are already storage classes, so if that's a problem then it's already a problem for these. If semantic, I would need to understand the definitions better to comment further.
Comment #21 by robert.schadek — 2024-12-13T17:49:36Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17505 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB