Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 24, 2012 [Issue 7355] New: inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
http://d.puremagic.com/issues/show_bug.cgi?id=7355 Summary: inout incorrectly resolved if the same type has both mutable and immutable parts Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nobody@puremagic.com ReportedBy: timon.gehr@gmx.ch --- Comment #0 from timon.gehr@gmx.ch 2012-01-23 16:41:58 PST --- DMD 2.058head inout(int*)* foo(inout(int*)* x){return x;} immutable(int)** x; static assert(is(typeof(foo(x))==const(int*)*)); Error: static assert (is(typeof(foo((__error))) == const(int*)*)) is false The assertion should pass. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> 2012-01-26 04:30:30 PST --- My understanding is, each inout deduction from a function argument just like pattern matching. Parameter type: inout( int *)* Argument type: mutable(immutable(int)*)* // mutable(...) is pseudo modifier --> 'inout' is deduced to 'mutable'. I think if we allow this kind of deduction, there is an ambiguous case: inout(int) foo(inout(int**) x){ return 0; } void main() { immutable(int*)* x; foo(x); // inout is deduced to imuutable or const? Both conversions // immutable(int*)* to immutable(int**) // immutable(int*)* to const(int**) // are valid, so it is ambiguous. } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 Steven Schveighoffer <schveiguy@yahoo.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |schveiguy@yahoo.com --- Comment #2 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-01-26 07:56:53 PST --- (In reply to comment #1) > My understanding is, each inout deduction from a function argument just like pattern matching. > > Parameter type: inout( int *)* > Argument type: mutable(immutable(int)*)* // mutable(...) is pseudo modifier > --> 'inout' is deduced to 'mutable'. The compiler should either fail to match, since inout wildcard is not applying to the immutable, or if it does match, it should treat foo as: int** foo(int **x) { return x; } This should fail to be able to be called with immutable(int)**. The assert should fail because the typeof should resolve to Error. I think this bug is invalid. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #3 from timon.gehr@gmx.ch 2012-01-26 09:07:23 PST --- (In reply to comment #2) > (In reply to comment #1) > > My understanding is, each inout deduction from a function argument just like pattern matching. > > > > Parameter type: inout( int *)* > > Argument type: mutable(immutable(int)*)* // mutable(...) is pseudo modifier > > --> 'inout' is deduced to 'mutable'. > > The compiler should either fail to match, since inout wildcard is not applying to the immutable, or if it does match, it should treat foo as: > > int** foo(int **x) { return x; } > > This should fail to be able to be called with immutable(int)**. > > The assert should fail because the typeof should resolve to Error. > > I think this bug is invalid. The typeof resolves to error because inout resolves to immutable. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #4 from timon.gehr@gmx.ch 2012-01-26 09:20:32 PST --- (In reply to comment #1) > My understanding is, each inout deduction from a function argument just like pattern matching. > > Parameter type: inout( int *)* > Argument type: mutable(immutable(int)*)* // mutable(...) is pseudo modifier > --> 'inout' is deduced to 'mutable'. > The compiler deduces inout to _immutable_ in this case. Other than that, it does not make much sense to talk about a mutable pseudo modifier: inout is transitive, but such a pseudo modifier cannot be transitive. > I think if we allow this kind of deduction, there is an ambiguous case: > > inout(int) foo(inout(int**) x){ return 0; } > void main() > { > immutable(int*)* x; > foo(x); > // inout is deduced to imuutable or const? Both conversions > // immutable(int*)* to immutable(int**) > // immutable(int*)* to const(int**) > // are valid, so it is ambiguous. > } The same ambiguity is already resolved at other points in the compiler: inout(int) foo(inout(int) x, inout(int)* y){ return 0; } void main(){ immutable(int)* y; foo(1, y); } inout is resolved to const, even though immutable would be a far better choice. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #5 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-01-26 09:36:01 PST --- (In reply to comment #3) > The typeof resolves to error because inout resolves to immutable. As I said, it should fail to match or match mutable and fail to call. I'm not sure which is correct, but I feel either way that the assert should fail. If it's resolving to immutable, I think it's a bug, not because it's not passing, but because it's failing for the wrong reason. I think your expectations would be a violation of const. Let's assume inout did resolve to const for foo, and the function could be called: immutable int x = 5; immutable(int)* xp = &x; immutable(int)** xpp = &xp; const(int *)* y = foo(xpp); int z = 2; *y = &z; // this should pass, since I can assign int* to const(int*). assert(*xp == 2); z = 3; assert(*xp == 3); // oops! changed data perceived as immutable! Is there an error in my example? I think it comes down to this: immutable(int *)* foo(immutable(int *)* x) // inout == immutable const(int *)* foo( const(int *)* x) // inout == const int ** foo( int ** x) // inout == mutable none of these can be called with immutable(int)** because there is no implicit cast to the parameter. I don't think const(immutable(int)*)* reduces to const(int *)*. This does take some mental effort, so I may have made a mistake :) I hate double pointers... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #6 from timon.gehr@gmx.ch 2012-01-26 09:55:37 PST --- (In reply to comment #5) > (In reply to comment #3) > > > The typeof resolves to error because inout resolves to immutable. > > As I said, it should fail to match or match mutable and fail to call. I'm not sure which is correct, but I feel either way that the assert should fail. If it's resolving to immutable, I think it's a bug, not because it's not passing, but because it's failing for the wrong reason. > > I think your expectations would be a violation of const. No. > Let's assume inout > did resolve to const for foo, and the function could be called: > > immutable int x = 5; > immutable(int)* xp = &x; > immutable(int)** xpp = &xp; > > const(int *)* y = foo(xpp); > > int z = 2; > > *y = &z; // this should pass, since I can assign int* to const(int*). You cannot assign anything to const(int*), that is the point of const. > > assert(*xp == 2); > z = 3; > assert(*xp == 3); // oops! changed data perceived as immutable! > > Is there an error in my example? I think it comes down to this: > > immutable(int *)* foo(immutable(int *)* x) // inout == immutable > const(int *)* foo( const(int *)* x) // inout == const > int ** foo( int ** x) // inout == mutable > > none of these can be called with immutable(int)** because there is no implicit > cast to the parameter. I don't think const(immutable(int)*)* reduces to > const(int *)*. It does. The second version is callable with immutable(int)**. Not fixing this would mean there are cases where code duplication is more expressive than inout. > > This does take some mental effort, so I may have made a mistake :) I hate double pointers... We have: immutable(T) is a subtype of const(T). => immutable(int) :< const(int) const(T*) :< const(S*) iff const(T) :< const(S) => const(immutable(int)*) :< const(int*) const(T)* :< const(S)* iff const(T) :< const(S) => const(immutable(int)*)* : const(int*)* qed -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 26, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #7 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-01-26 10:21:28 PST --- (In reply to comment #6) > (In reply to comment #5) > > Let's assume inout > > did resolve to const for foo, and the function could be called: > > > > immutable int x = 5; > > immutable(int)* xp = &x; > > immutable(int)** xpp = &xp; > > > > const(int *)* y = foo(xpp); > > > > int z = 2; > > > > *y = &z; // this should pass, since I can assign int* to const(int*). > > You cannot assign anything to const(int*), that is the point of const. Oh yeah :) Stupid me, for some reason in my head this made sense because there was a mutable part. > > > > immutable(int *)* foo(immutable(int *)* x) // inout == immutable > > const(int *)* foo( const(int *)* x) // inout == const > > int ** foo( int ** x) // inout == mutable > > > > none of these can be called with immutable(int)** because there is no implicit > > cast to the parameter. I don't think const(immutable(int)*)* reduces to > > const(int *)*. > > It does. The second version is callable with immutable(int)**. Not fixing this would mean there are cases where code duplication is more expressive than inout. You are right. So we need to come up with some rules for inout as to how it matches. What about this idea? for each inout parameter, we try as a substitute in order: mutable, immutable, inout, const. See if the argument can be implicitly converted to the substituted parameter. If none of the possible substitutes can be implicitly converted to for a single parameter, the function fails to be called, and an error is generated "inout cannot be resolved [for parameter x]" If substitutes can be found for all of the inout parameters, and they all match (i.e. all mutable, all immutable, all inout or all const), then that is used as the substitute and the function is called. If substitutes are different (e.g. one is mutable, but another is immutable), then const is used as the substitute. The parameters are then re-checked to see that they all implicitly convert to the substituted const type. If this is not possible, an error is generated "common inout substitute cannot be found". I think this should be as capable as duplicate functions. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
January 27, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #8 from timon.gehr@gmx.ch 2012-01-27 14:44:19 PST --- This rule should work satisfactory: - The compiler is required to resolve inout such that the behavior is as if there were four (five, with inout(const(T)) enhancement in place) separate overloads. This could be implemented similar to how you propose it, by adding all of the versions to the overload set, or by using some insights to speed up the process (not very hard) - If there would be an ambiguity between the different pseudo overloads: -- If one of the remaining multiple possibilities is the const version, drop it -- If one of the possibilities is the inout version, drop it (-- If one of the remaining multiple possibilities is the inout const version, drop it) -- If mutable and immutable are remaining possible matches for inout, resolve inout to mutable. -- otherwise resolve inout to what is left. - Allow direct conversion of the return type to any of the versions of inout that still match after implicit conversions of the arguments in place. - An inout function is considered to be less specialized than a corresponding non-inout one. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
February 02, 2012 [Issue 7355] inout incorrectly resolved if the same type has both mutable and immutable parts | ||||
---|---|---|---|---|
| ||||
Posted in reply to timon.gehr@gmx.ch | http://d.puremagic.com/issues/show_bug.cgi?id=7355 --- Comment #9 from Steven Schveighoffer <schveiguy@yahoo.com> 2012-02-02 12:07:29 PST --- (In reply to comment #8) > This rule should work satisfactory: > > - The compiler is required to resolve inout such that the behavior is as if > there were four (five, with inout(const(T)) enhancement in place) separate > overloads. This could be implemented similar to how you propose it, by adding > all of the versions to the overload set, or by using some insights to speed up > the process (not very hard) This sounds fine. However, inout(const(T)) is not a substitute for inout(T), so it should be four. inout(const(T)) is special in what can implicitly convert to it. But the inout is the only wildcard there. The rest is not necessary. The normal overload rules already should handle which one is chosen. Since inout, mutable, and immutable do not implicitly convert to each other, it's not possible for there to be an ambiguity, is there? immutable and mutable (and by extension inout) should be preferred over const. It's important to note that the inout overload we are talking about is not the wildcard inout, but the local const-like inout. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
Copyright © 1999-2021 by the D Language Foundation