Bug 9983 – inout type can not be used as a parameter for structure template

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-04-23T06:57:29Z
Last change time
2024-12-13T18:06:21Z
Assigned to
No Owner
Creator
Maksim Zholudev
See also
https://issues.dlang.org/show_bug.cgi?id=19126, https://issues.dlang.org/show_bug.cgi?id=15651
Moved to GitHub: dmd#18569 →

Comments

Comment #0 by maximzms — 2013-04-23T06:57:29Z
In the following code `inout(int)` is passed to template while it should be replaced with `int` or `const(int)` depending on the function argument qualifiers. -------------------- struct Foo(T) { T* p; // test.d(3) this(T* src) { p = src; } } auto f(inout int[] a) { return Foo!(inout(int))(a.ptr); // test.d(10) } void main() {} -------------------- test.d(3): Error: variable test.Foo!(inout(int)).Foo.p only parameters or stack based variables can be inout test.d(10): Error: template instance test.Foo!(inout(int)) error instantiating test.d(10): Error: function expected before (), not _error_ of type _error_ -------------------- Workaround: -------------------- struct Foo(T) { T* p; this(T* src) { p = src; } } auto f(int[] a) { return Foo!(int)(a.ptr); } auto f(in int[] a) { return Foo!(const(int))(a.ptr); } void main() {} --------------------
Comment #1 by dfj1esp02 — 2018-03-09T11:45:29Z
Looks like it can be solved by smart enough container constructors. See this quick PoC: --- struct Container(T) { T value; inout(T) get() inout { return value; } } /// Smart constructor auto makeContainer(T)(T arg) { alias E=typeof(cast()arg[0]); static if(is(T==inout(E)[])) { return inout(Container!(E[]))(arg); } else { return Container!T(arg); } } auto f(inout int[] a) { return makeContainer(a); } void g(immutable int[] a) { auto b=f(a); immutable Container!(int[]) c=b; immutable int[] d=c.get; immutable int[] e=b.get; //static assert(false,typeof(b).stringof); } void g(int[] a) { auto b=f(a); Container!(int[]) c=b; int[] d=c.get; int[] e=b.get; //static assert(false,typeof(b).stringof); } ---
Comment #2 by schveiguy — 2018-03-13T10:26:44Z
I actually went over this in my inout talk a few years ago. a couple of points here: 1. The OP's request is invalid. There is no way for f to know what the mutability qualifier is, as inout is not a template parameter, it's a qualifier. 2. inout members should be allowed inside structs, they will work just fine. I wish they hadn't been disallowed. The only thing you wouldn't be able to do is call a function that returns a struct with inout members with a different mutability qualifier than inout. e.g. this should work: inout int[] x; auto foo = f(x); // OK, returns Foo!(inout(int)) But this shouldn't: int[] x; auto foo = f(x); // Error, cannot convert struct with inout members to proper mutability. There is no way for the compiler to know that it could potentially convert the return value to mutable T, even when it knows that Foo is a template. We should either close this bug as invalid, or repurpose to request support for structs with inout members.
Comment #3 by dfj1esp02 — 2021-03-19T17:23:24Z
*** Issue 21733 has been marked as a duplicate of this issue. ***
Comment #4 by robert.schadek — 2024-12-13T18:06:21Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18569 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB