digitalmars.D.bugs - Access rights of mixins
- Stewart Gordon <smjg_1998 yahoo.com> Mar 07 2005
- "Regan Heath" <regan netwin.co.nz> Mar 07 2005
- Stewart Gordon <smjg_1998 yahoo.com> Mar 07 2005
- "Regan Heath" <regan netwin.co.nz> Mar 07 2005
- Stewart Gordon <smjg_1998 yahoo.com> Mar 08 2005
- "Regan Heath" <regan netwin.co.nz> Mar 08 2005
- Stewart Gordon <smjg_1998 yahoo.com> Mar 09 2005
- "Regan Heath" <regan netwin.co.nz> Mar 09 2005
- Stewart Gordon <smjg_1998 yahoo.com> Mar 10 2005
- "Regan Heath" <regan netwin.co.nz> Mar 10 2005
- Stewart Gordon <smjg_1998 yahoo.com> Mar 11 2005
Should a mixin have the access rights of the scope where it's defined,
or of the scope where it's used?
The compiler's answer is only where it's used, which doesn't seem right.
I've ended up with some kludgy declarations of members as public to
get around this.
Take this:
----- mixin1.d -----
module mixin1;
private int qwert;
template Yuiop() {
int asdfg() { return qwert; }
int hjkl() { return zxcvb; }
}
----- mixin2.d -----
module mixin2;
import mixin1;
private int zxcvb;
mixin Yuiop;
----------
D:\My Documents\Programming\D\Tests\bugs\mixin2.d: module mixin2
mixin1.qwert is private
----------
So the mixin cannot access qwert, even though the mixin is defined in
the same module. OTOH, it can access zxcvb, which is private to another
module.
My thought is that a mixin should have full access to the scope in which
it is defined. It should also still have access to at least the
protected members of the scope where it is used, but I'm not sure if it
should be able to access the private and package members thereof.
The spec doesn't seem to clarify, though it does say:
"Unlike a template instantiation, a template mixin's body is evaluated
within the scope where the mixin appears, not where the template
declaration is defined."
Since "evaluated" need not coincide with "access-checked", this isn't a
sure sign of anything. Moreover, considering it is pointed out that
mixins aren't just like C preprocessor macros, is there any reason this
shouldn't join the repertoire of differences? (Where does
implementation ease fit into the equation, FTM?)
Notice also that the error is missing a line number. And gives the name
of the file where it's used - it ought be pinpointing where the mixin
member is defined.
Stewart.
--
My e-mail is valid but not my primary mailbox. Please keep replies on
the 'group where everyone may benefit.
Mar 07 2005
On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Should a mixin have the access rights of the scope where it's defined, or of the scope where it's used?
Used.The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.
How were you actually using this? As in, why did you design it this way? why does the mixin rely on a global var? I think I need these details to see where you're coming from. Regan
Mar 07 2005
Regan Heath wrote:On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:
The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.
How were you actually using this? As in, why did you design it this way?
Why not? As in, it's one way in which someone would expect mixins to be usable, intuitively following the principle that what is defined in a module has access to the module's private members, and correspondingly having its practical uses.why does the mixin rely on a global var?
The way I'm using it, it actually relies on would-be private members of a class defined in the mixin's module. But the argument would apply equally if a real-world application relied on a global var.I think I need these details to see where you're coming from.
I'm using it to implement MDI for SDWF 0.5. I have two classes, MDIFrameWindow and MDIClientPane, and a template MDIChildWindow that child windows mixin in order to do the special handling that MDI child windows need. OTTOMH, I think one of these would-be private members is the child window list on the SDWF side.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 07 2005
On Mon, 07 Mar 2005 11:52:09 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote:On Mon, 07 Mar 2005 10:52:29 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:
The compiler's answer is only where it's used, which doesn't seem right. I've ended up with some kludgy declarations of members as public to get around this.
way?
Why not? As in, it's one way in which someone would expect mixins to be usable, intuitively following the principle that what is defined in a module has access to the module's private members, and correspondingly having its practical uses.
I didn't expect this. Interestingly, template functions: [a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.why does the mixin rely on a global var?
The way I'm using it, it actually relies on would-be private members of a class defined in the mixin's module. But the argument would apply equally if a real-world application relied on a global var.I think I need these details to see where you're coming from.
I'm using it to implement MDI for SDWF 0.5. I have two classes, MDIFrameWindow and MDIClientPane, and a template MDIChildWindow that child windows mixin in order to do the special handling that MDI child windows need. OTTOMH, I think one of these would-be private members is the child window list on the SDWF side....
I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct? It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way. I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought. Regan
Mar 07 2005
Regan Heath wrote: <snip>[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.
Aren't module members public by default? <snip>I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?
Yes, though in this case it would be totally expected.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.
I certainly don't see any disadvantages.I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.
Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 08 2005
On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.
Aren't module members public by default?
It still works if I change it to: private int g = 5;<snip>I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?
Yes, though in this case it would be totally expected.
That's just it though, to me what you encountered was totally expected. Due to how I understood mixins to work, as if you were pasting the code.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.
I certainly don't see any disadvantages.
Is the mixin itself protected, or can anyone choose to mix it in and thus get access to your privates.I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.
Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
I see.. so the mixin code is a 'helper' for creating 'custom' windo classes? Regan
Mar 08 2005
Regan Heath wrote:On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.
Aren't module members public by default?
It still works if I change it to: private int g = 5;
As should be expected, since the template is in the module scope. But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used? I'd like to say a bit of both.<snip>I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?
Yes, though in this case it would be totally expected.
That's just it though, to me what you encountered was totally expected. Due to how I understood mixins to work, as if you were pasting the code.
Mixins already aren't just like pasting the code. http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.
I certainly don't see any disadvantages.
Is the mixin itself protected, or can anyone choose to mix it in and thus get access to your privates.
Anyone can mix it in. It's the way it works - one creates an MDI child class by mixing it into the application-specific subclass of Window or FrameWindow. Whether someone can abuse it to this extent, I'm not sure. An alternative would be to have ready-mixed child window classes corresponding to these, each of which mixes it in, and keep the template private. I wonder....I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.
Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
I see.. so the mixin code is a 'helper' for creating 'custom' windo classes?
Not quite. A 'necessity' for creating MDI child window classes. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 09 2005
On Wed, 09 Mar 2005 10:27:42 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote:On Tue, 08 Mar 2005 16:35:32 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>[a.d] module a; int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; void main() { A!(int)(2); } seem to do what you expected.
Aren't module members public by default?
private int g = 5;
As should be expected, since the template is in the module scope.
Indeed. And the mixin has it's own scope. Another example: [a.d] (same as before) module a; private int g = 5; template A(Type) { void A(Type a) { printf("%d\n",g); } } [b.d] module b; import a; mixin A!(int) fn; void main() { fn(2); } C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?
Currently, a mixin creates a new scope.I'd like to say a bit of both.
Perhaps. Is there a problem with collision resolution? eg. [a.d] module a; private int g = 5; template M(T) { void foo() { writef(g); } } [b.d] module b; class A { private int g = 2; mixin M!(int); } You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g. Assuming of course the real-life usage is more complex and cannot simply be re-written: template M(alias T) { void foo() { writef(T); } } mixin M!(g); i.e. pass the var you want to use.<snip>I see, that makes sense. If you weren't using a mixin, but pasting the code in yourself, it would suffer the same problem.. that the new child window had no access to the list, correct?
Yes, though in this case it would be totally expected.
expected. Due to how I understood mixins to work, as if you were pasting the code.
Mixins already aren't just like pasting the code. http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.
The important one (in this case) seems to be: "Mixins create a scope, macros do not."It seems you're trying to cross the module boundary with mixins. I can see why you thought it might work, but I dont know whether it's a good idea for it to work that way.
I certainly don't see any disadvantages.
thus get access to your privates.
Anyone can mix it in. It's the way it works - one creates an MDI child class by mixing it into the application-specific subclass of Window or FrameWindow. Whether someone can abuse it to this extent, I'm not sure.
I think it can potentially 'weaken' the protection on the 'private' int. Whether we want to allow that, or not, I don't know.An alternative would be to have ready-mixed child window classes corresponding to these, each of which mixes it in, and keep the template private. I wonder....
Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface. In D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}I can't think of another solution, except to move the child window into the same module as the list it's trying to access, so, I think this needs some thought.
Delete all words after "solution". When the list it's trying to access is in the library and child window classes are part of applications, obviously you can't merge them into one module.
classes?
Not quite. A 'necessity' for creating MDI child window classes.
Right. I think I follow now. :) Regan
Mar 09 2005
Regan Heath wrote: <snip>C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.
What's that to do with your snippet?But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?
Currently, a mixin creates a new scope.
Then the point becomes: what is this new scope a subscope of?I'd like to say a bit of both.
Perhaps. Is there a problem with collision resolution? eg.
You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g.
Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used. It doesn't seem to address the issue of access rights though. <snip>http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.
The important one (in this case) seems to be: "Mixins create a scope, macros do not."
Similarly, classes create a scope. So do functions. And yet classes have no trouble accessing private members in their modules, and functions have no trouble accessing private members in their classes. <snip>Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface.
But in Java you can't (directly at least) share implementation details between classes that implement an interface.In D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}
At the moment I have class Window : WindowBase { ... } class FrameWindow : Window { ... } class MDIFrameWindow : FrameWindow { ... } class MDIClientPane : WindowBase { ... } template MDIChildWindow() { ... } The application window is an MDIFrameWindow, which frames an MDIClientPane (the standard Windows control that holds the child windows). To create a child window class, one uses class ChildWindow : Window { mixin MDIChildWindow; ... } But I'm now thinking maybe I should predefine the ChildWindow and ChildFrameWindow classes, and have the lib user create subclasses of these. I can think of a few other benefits to this approach.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 10 2005
On Thu, 10 Mar 2005 11:58:22 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:Regan Heath wrote: <snip>C:\Library\D\src\temp>dmd b a b.d: module b a.g is private b.d(7): function expected before (), not 'void' So, using a mixin, defines a scope, using a template doesn't.
What's that to do with your snippet?
My first example, didn't use a mixin, and worked. This snippet, used a mixin, and didn't work. This snippet was more like your code than my first example. I was trying to show the difference between mixin template usage and standard template usage. Which is, I believe, that a mixin creates a scope where it's used.But therein lies the question - when you use it as a mixin, is it in the scope of the module where the template is defined, or the scope in which it is used?
Then the point becomes: what is this new scope a subscope of?
I believe it's a subscope of the scope in which it's used, i.e. where type 'mixin'.I'd like to say a bit of both.
You can't modify the template to read b.g, cos 'a' does not know about 'b', nor should it. So, it seems the only solution is to 'assume' writef(g) means the a.g, not b.g.
Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used.
That is how I understood it.It doesn't seem to address the issue of access rights though.
True. Perhaps it should be explicit about it all. i.e. "mixins create their own sub-scope within the scope there they are used, not where they are defined. This means they have private access to the module where they are used, not where they are defined" .. or something.<snip>http://www.digitalmars.com/d/pretod.html#mixins OK, so half of those differences are really about the syntactic fragility of C preprocessor macros, but there are a few actual semantic differences as I see it.
macros do not."
Similarly, classes create a scope. So do functions. And yet classes have no trouble accessing private members in their modules, and functions have no trouble accessing private members in their classes.
The question, as you said, is where does it create that scope. In the case of classes it's created where it's defined, in the case of mixins it's where it's used. It seems it needs to be explicit about this behaviour in the docs.<snip>Ahh.. yes, sort of like how in Java .. (bear with me I'm relatively new to Java) I seem to recall something like: interface foo {} class SimpleFoo implements foo {} You extend SimpleFoo, which provides the basic methods for you, and conforms to the interface.
But in Java you can't (directly at least) share implementation details between classes that implement an interface.
Not that implement the interface, no, but you can derive all the classes from SimpleFoo, which in effect contains the shared implementation details.In D you'd go: interface IWindow {} class ChildWindow : IWindow { mixin .. } .. class MyWindow : ChildWindow {}
At the moment I have class Window : WindowBase { ... } class FrameWindow : Window { ... } class MDIFrameWindow : FrameWindow { ... } class MDIClientPane : WindowBase { ... } template MDIChildWindow() { ... } The application window is an MDIFrameWindow, which frames an MDIClientPane (the standard Windows control that holds the child windows). To create a child window class, one uses class ChildWindow : Window { mixin MDIChildWindow; ... } But I'm now thinking maybe I should predefine the ChildWindow and ChildFrameWindow classes, and have the lib user create subclasses of these. I can think of a few other benefits to this approach....
Excellent.. so it seems it's a better approach all round. Regan
Mar 10 2005
Regan Heath wrote:On Thu, 10 Mar 2005 11:58:22 +0000, Stewart Gordon <smjg_1998 yahoo.com> wrote:
Good question. FWIW I've just taken another look at the mixins page of the spec, and it seems to the effect that a mixin is a subscope of the scope where it's used.
That is how I understood it.
I guess we've come to an agreement on this then.It doesn't seem to address the issue of access rights though.
True. Perhaps it should be explicit about it all. i.e. "mixins create their own sub-scope within the scope there they are used, not where they are defined. This means they have private access to the module where they are used, not where they are defined" .. or something.
The question, as you said, is where does it create that scope. In the case of classes it's created where it's defined, in the case of mixins it's where it's used. It seems it needs to be explicit about this behaviour in the docs.
Good idea. <snip>But in Java you can't (directly at least) share implementation details between classes that implement an interface.
Not that implement the interface, no, but you can derive all the classes from SimpleFoo, which in effect contains the shared implementation details.
But not if the classes may already be derived from different classes. This is where mixins become useful - as a way of creating shared implementation details that may be applied to a variety of classes. Kind of like a makeshift form of multiple inheritance.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 11 2005








Stewart Gordon <smjg_1998 yahoo.com>