digitalmars.D - Prevention of UFCS hijacking
- Andrej Mitrovic (75/75) Aug 27 2013 I've run into a bit of an issue with UFCS today, take a look at the
- Maxim Fomin (11/66) Aug 27 2013 But commenting out "text" property is not order to compiler to
- H. S. Teoh (8/13) Aug 27 2013 If that can be called a design at all, it's a horrible design. It should
- Maxim Fomin (2/15) Aug 27 2013 It wasn't me who invented this :)
- Andrej Mitrovic (2/3) Aug 27 2013 You've just repeated everything I've already said.
- Maxim Fomin (3/6) Aug 27 2013 What should I tell except you are surprising of current state of
- Andrej Mitrovic (6/8) Aug 28 2013 I'm just raising awareness of the issue. And it's surprising when
- Andrej Mitrovic (2/4) Aug 27 2013 I would call it an accidental implementation detail at best! :)
- Jesse Phillips (5/10) Aug 27 2013 It was by design, then @property was added and now everyone is
- H. S. Teoh (10/16) Aug 27 2013 Let's call it an accidental feature. -- Larry Wall
- Jacob Carlborg (8/11) Aug 27 2013 I see no reasons for why this should be allowed. I say:
- H. S. Teoh (6/20) Aug 28 2013 [...]
I've run into a bit of an issue with UFCS today, take a look at the reduced test-case: ----- import std.conv; class Label { // property string text() { } // property void text(string nText) { } } void main() { auto label = new Label; label.text = "My label"; assert(label.text == "My label"); // fails at runtime } ----- Because of the UFCS feature std.conv.text is called even though I expected compilation to fail since I've commented out the .text properties in my class. This is a problem since some of my classes might have a .text field, while others might not. If the user imports std.conv he could easily end up calling std.conv.text by mistake when a class object doesn't implement such a property. Anyway, there is a cure. I can work around this using disabled fields in the base class. For example: ----- import std.conv; class Widget { disable string text; } class Label : Widget { property string text() { return "My label"; } property void text(string nText) { } } class Image : Widget { } void main() { auto frame = new Label; frame.text = "My label"; assert(frame.text == "My label"); auto image = new Image; image.text = "foobar"; // ok, fails to compile } ----- Note that I've specifically made the base class declare a public variable rather than a property, otherwise the derived class would have to override a virtual property function. Maybe this code might even become a case of accepts-invalid at some point, since the properties do actually shadow the base class variable. I'm not sure how long this workaround will work. Has anyone else run into this sort of issue? I'm wondering whether we should have some language support (through __traits, disable, or something else), to enable writing APIs which are safer to use, where you can't by mistake call a UFCS function like that if there's an equally named function introduced in another derived class. --- Btw, why exactly is the following allowed to compile?: ----- import std.conv; import std.stdio; struct S { } void main() { S s; writeln(s.text = "foo"); } ----- This translates into std.conv.text(s, "foo"). I'm not a fan, especially since 'text' is not a property. But we've already reached the consensus that all functions can be called like properties (for some reason..), so I guess it's too late to change this.
Aug 27 2013
On Tuesday, 27 August 2013 at 18:02:27 UTC, Andrej Mitrovic wrote:I've run into a bit of an issue with UFCS today, take a look at the reduced test-case: ----- import std.conv; class Label { // property string text() { } // property void text(string nText) { } } void main() { auto label = new Label; label.text = "My label"; assert(label.text == "My label"); // fails at runtime } ----- Because of the UFCS feature std.conv.text is called even though I expected compilation to fail since I've commented out the .text properties in my class.But commenting out "text" property is not order to compiler to ignore all UFCS involving "text". What commenting out has to do with UFCS?This is a problem since some of my classes might have a .text field, while others might not. If the user imports std.conv he could easily end up calling std.conv.text by mistake when a class object doesn't implement such a property.Then classes should implement member to disable UFCS hijacktion. If not, this is an allowance for such name hijacktion. This is by design.Has anyone else run into this sort of issue? I'm wondering whether we should have some language support (through __traits, disable, or something else), to enable writing APIs which are safer to use, where you can't by mistake call a UFCS function like that if there's an equally named function introduced in another derived class.disable is a way to block this feature--- Btw, why exactly is the following allowed to compile?: ----- import std.conv; import std.stdio; struct S { } void main() { S s; writeln(s.text = "foo"); } ----- This translates into std.conv.text(s, "foo"). I'm not a fan, especially since 'text' is not a property. But we've already reached the consensus that all functions can be called like properties (for some reason..), so I guess it's too late to change this.Let's start from basics: writeln = 42; and this is also by design.
Aug 27 2013
On Tue, Aug 27, 2013 at 08:40:16PM +0200, Maxim Fomin wrote: [...]Let's start from basics: writeln = 42; and this is also by design.If that can be called a design at all, it's a horrible design. It should be illegal, if it isn't already. It makes assignment syntax meaningless, and is useful only for obfuscated code contests. T -- Why have vacation when you can work?? -- EC
Aug 27 2013
On Tuesday, 27 August 2013 at 19:00:43 UTC, H. S. Teoh wrote:On Tue, Aug 27, 2013 at 08:40:16PM +0200, Maxim Fomin wrote: [...]It wasn't me who invented this :)Let's start from basics: writeln = 42; and this is also by design.If that can be called a design at all, it's a horrible design. It should be illegal, if it isn't already. It makes assignment syntax meaningless, and is useful only for obfuscated code contests. T
Aug 27 2013
On 8/27/13, Maxim Fomin <maxim maxim-fomin.ru> wrote:Let's start from basicsYou've just repeated everything I've already said.
Aug 27 2013
On Tuesday, 27 August 2013 at 19:39:34 UTC, Andrej Mitrovic wrote:On 8/27/13, Maxim Fomin <maxim maxim-fomin.ru> wrote:What should I tell except you are surprising of current state of things?Let's start from basicsYou've just repeated everything I've already said.
Aug 27 2013
On 8/27/13, Maxim Fomin <maxim maxim-fomin.ru> wrote:What should I tell except you are surprising of current state of things?I'm just raising awareness of the issue. And it's surprising when you're coding and not expecting it. Imagine adding an import to a 3rd party library and no longer getting errors at compile time when you assign to a field that doesn't exist. Anyone could be caught off-guard by this.
Aug 28 2013
On 8/27/13, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:I would call it an accidental implementation detail at best! :)and this is also by design.If that can be called a design at all, it's a horrible design.
Aug 27 2013
On Tuesday, 27 August 2013 at 19:41:08 UTC, Andrej Mitrovic wrote:On 8/27/13, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:It was by design, then property was added and now everyone is confused why it exists. Pretty sure the consensus was to require property for assignment, but parens were to be optional. At least it seemed to have the least disagreement.I would call it an accidental implementation detail at best! :)and this is also by design.If that can be called a design at all, it's a horrible design.
Aug 27 2013
On Tue, Aug 27, 2013 at 09:40:54PM +0200, Andrej Mitrovic wrote:On 8/27/13, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:Let's call it an accidental feature. -- Larry Wall :) That doesn't make it any less ugly, though. I still say we should make func=y syntax illegal for non- property functions. T -- Claiming that your operating system is the best in the world because more people use it is like saying McDonalds makes the best food in the world. -- Carl B. ConstantineI would call it an accidental implementation detail at best! :)and this is also by design.If that can be called a design at all, it's a horrible design.
Aug 27 2013
On 2013-08-27 20:40, Maxim Fomin wrote:Let's start from basics: writeln = 42; and this is also by design.I see no reasons for why this should be allowed. I say: * Getters marked with property: call without parentheses * Getters not marked with property: call with or without parentheses * Setters marked with property: require assignment syntax * Setters not marked with property: disallow assignment syntax -- /Jacob Carlborg
Aug 27 2013
On Wed, Aug 28, 2013 at 08:41:39AM +0200, Jacob Carlborg wrote:On 2013-08-27 20:40, Maxim Fomin wrote:[...] +1, I agree with all of the above. T -- Старый друг лучше новых двух.Let's start from basics: writeln = 42; and this is also by design.I see no reasons for why this should be allowed. I say: * Getters marked with property: call without parentheses * Getters not marked with property: call with or without parentheses * Setters marked with property: require assignment syntax * Setters not marked with property: disallow assignment syntax
Aug 28 2013