D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3572 - declaring pure function with void return type should be compile time error
Summary: declaring pure function with void return type should be compile time error
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks:
 
Reported: 2009-12-04 02:37 UTC by Michal Minich
Modified: 2020-03-25 09:00 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Michal Minich 2009-12-04 02:37:33 UTC
In D specification is written: "Pure functions are functions that produce the same result for the same arguments. To that end, a pure function has parameters that are all immutable or are implicitly convertible to immutable

void function cannot produce any result, thus they are meaningless as pure functions. Also when all parameters are implicitly immutable, there is no possibility to modify "out" parameters. So the only way for function to produce result, is by returning it (and void has no value).
Comment 1 Don 2009-12-04 12:01:56 UTC
(In reply to comment #0)
> In D specification is written: "Pure functions are functions that produce the
> same result for the same arguments. To that end, a pure function has parameters
> that are all immutable or are implicitly convertible to immutable
> 
> void function cannot produce any result, thus they are meaningless as pure
> functions. Also when all parameters are implicitly immutable, there is no
> possibility to modify "out" parameters. So the only way for function to produce
> result, is by returning it (and void has no value).

I think the restriction on 'out' parameters will be removed. I don't think there's any reason for it.
A void pure function that doesn't have any 'out' parameters does seem to be pretty useless (you can use it as a metaprogramming test that anything inside it is pure, but that's about all I can think of).
Comment 2 David Simcha 2009-12-04 15:52:01 UTC
?????  Why would you allow out parameters in a pure function?  This seems reasonable for simple value types (ints, floats, etc.), but when you start passing objects in, you start allowing the modification of whole object subgraphs from pure functions.  This makes no sense.
Comment 3 Don 2009-12-04 18:28:11 UTC
(In reply to comment #2)
> ?????  Why would you allow out parameters in a pure function?  This seems
> reasonable for simple value types (ints, floats, etc.), but when you start
> passing objects in, you start allowing the modification of whole object
> subgraphs from pure functions.  This makes no sense.

Why doesn't it make sense? Aren't you thinking of inout parameters? A pure function  void foo(out A a); ought to be exactly the same as A foo(); together with an assignment. I'm not seeing anything impure in that.
BTW, it works fine in CTFE. (CTFE isn't quite the same concept as pure, but it's close).
Comment 4 David Simcha 2010-02-17 18:38:36 UTC
(In reply to comment #3)
> Why doesn't it make sense? Aren't you thinking of inout parameters? A pure
> function  void foo(out A a); ought to be exactly the same as A foo(); together
> with an assignment. I'm not seeing anything impure in that.
> BTW, it works fine in CTFE. (CTFE isn't quite the same concept as pure, but
> it's close).

You're right, I did get confused between out and ref.  Allowing out parameters in pure functions makes sense.  I tend to forget how out parameters work because I almost never use them.  I almost always just return a tuple or a struct.
Comment 5 Trass3r 2012-01-05 14:19:40 UTC
Also you shouldn't be able to throw away the result of a pure function.
http://d.puremagic.com/issues/show_bug.cgi?id=7235
Comment 6 Andrej Mitrovic 2013-02-03 15:53:14 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > ?????  Why would you allow out parameters in a pure function?  This seems
> > reasonable for simple value types (ints, floats, etc.), but when you start
> > passing objects in, you start allowing the modification of whole object
> > subgraphs from pure functions.  This makes no sense.
> 
> Why doesn't it make sense? Aren't you thinking of inout parameters? A pure
> function  void foo(out A a); ought to be exactly the same as A foo(); together
> with an assignment. I'm not seeing anything impure in that.
> BTW, it works fine in CTFE. (CTFE isn't quite the same concept as pure, but
> it's close).

Should we close this report then?
Comment 7 Kenji Hara 2013-02-03 18:50:45 UTC
In current, we can declare a pure function which has "weak" purity.

pure void foo(int* p, out string s, ref int[] arr);

All results are returned through its parameters.
So, returning void itself has no problem in pure functions.
Comment 8 yebblies 2013-03-06 02:46:46 UTC
(In reply to comment #7)
> In current, we can declare a pure function which has "weak" purity.
> 
> pure void foo(int* p, out string s, ref int[] arr);
> 
> All results are returned through its parameters.
> So, returning void itself has no problem in pure functions.

This would still be meaningful for strongly-pure or const-pure functions.

eg.
pure void foo(string x)
By definition calling foo does no observable work.

While this might be WONTFIX or LATER like issue 3882, it is not invalid.
Comment 9 Dennis 2020-03-24 11:10:21 UTC
(In reply to yebblies from comment #8)
> eg.
> pure void foo(string x)
> By definition calling foo does no observable work.

False.

```
pure void foo(string x) {
    throw new Exception(x);
}
```

Here's a nothrow one:
```
pure nothrow void assertPositive(int x) {
    assert(x > 0);
}
```

> While this might be WONTFIX or LATER like issue 3882, it is not invalid.

Until a case can be identified where there is actually "no observable work" guaranteed, this is invalid.

(And even then, it's debatable whether "no observable work" is enough grounds to make something not compile. `int x = 0; x += 0;` does nothing, but it does and should compile.)
Comment 10 Michal Minich 2020-03-25 09:00:37 UTC
Agreed. even 

pure void nothrow never() { assert(false); } 

can throw Error, which is observable effect.