Feedback Thread: DIP 1038-- at nodiscard--Final Review

Paul Backus snarwin at
Thu Feb 4 14:17:35 UTC 2021

On Thursday, 4 February 2021 at 09:09:02 UTC, Walter Bright wrote:
> 1. > Note that the former is a syntax-level check, while the 
> latter is a type-level check. This means that the value 
> returned from a @nodiscard function may in fact be discarded as 
> long as the function call itself is enclosed in some other 
> expression.
> These two sentences do not make sense together. The second 
> sentence only refers to the syntax-level check.

I intended "a @nodiscard function" to refer only to the 
syntax-level check, but I can see how it can be read as 
ambiguous. A clearer way to phrase it would be "a function 
annotated with @nodiscard."

> 2. Consider:
>     @nodiscard int foo();
>     a ? b : foo();
> discards the return result of foo(), but according to the DIP 
> no error will be detected. This is another case of the comma 
> expression one mentioned in the Description.
> This is a critical shortcoming in the DIP that needs to be 
> addressed. Perhaps this feature in other languages can provide 
> guidance.

This is exactly how the feature works in GCC, Clang, C++17, and 

We have a name for information about an expression that 
propagates, transitively, from sub-expressions to 
super-expressions the way you suggest @nodiscard ought to 
propagate. We call it the expression's "type." So what you are 
suggesting here, in effect, is that @nodiscard should become a 
type qualifier, and that we should write

     @nodiscard(int) foo();

While this would indeed detect an error in cases like the one you 
give above, there are second-order effects to making `T` and 
`@nodiscard(T)` distinct types. For example:

     @nodiscard(int) foo();
     int bar()
     auto a = foo();
     auto b = bar();
     b = a; // Error: cannot implicitly convert `@nodiscard(int)` 
to `int`

This kind of error is obviously not going to help anybody catch 
bugs in their code--it is pure noise.

If the syntax-level check is deemed inadequate, I think the best 
way to proceed is to simply remove it from the DIP and include 
only the type-level check (this is what Rust did, originally). 
But I think it's important to keep in mind that there is no 
perfect solution here, only tradeoffs.

More information about the Digitalmars-d mailing list