[nem-bug] [Nemerle 0000776]: Can't Define virtual & override
methods (in macro)
feedback at nemerle.org
feedback at nemerle.org
Sun Oct 8 16:43:41 CEST 2006
A NOTE has been added to this issue.
======================================================================
<http://nemerle.org/bugs/view.php?id=776>
======================================================================
Reported By: VladD2
Assigned To:
======================================================================
Project: Nemerle
Issue ID: 776
Category: Compiler (type engine)
Reproducibility: always
Severity: block
Priority: urgent
Status: new
======================================================================
Date Submitted: 10-05-2006 01:59 CEST
Last Modified: 10-08-2006 16:43 CEST
======================================================================
Summary: Can't Define virtual & override methods (in macro)
Description:
Macro code:
----------------------------------------------------------------------------
using Nemerle.Compiler;
[Nemerle.MacroUsage (Nemerle.MacroPhase.WithTypedMembers,
Nemerle.MacroTargets.Class)]
macro AddVirtualTestImpl (tb : TypeBuilder)
{
tb.Define (<[ decl:
internal virtual TestImpl () : void
{
}
]>);
}
[Nemerle.MacroUsage (Nemerle.MacroPhase.WithTypedMembers,
Nemerle.MacroTargets.Class)]
macro AddOverrideTestImpl (tb : TypeBuilder)
{
tb.Define (<[ decl:
internal override TestImpl () : void
{
}
]>);
}
----------------------------------------------------------------------------
Code use macro:
----------------------------------------------------------------------------
[AddVirtualTestImpl]
class A { }
[AddOverrideTestImpl]
class B : A { }
----------------------------------------------------------------------------
Error message:
----------------------------------------------------------------------------
Main.n(4,2,4,21): error : `override' specified on method B.TestImpl() :
void, but there is no such member in parent to override
======================================================================
----------------------------------------------------------------------
malekith - 10-05-06 07:46
----------------------------------------------------------------------
It's by design.
You need to add virtual memebers in the BeforeInheritance stage, not
WithTypedMembers. Otherwise they are not visible in derived class.
We can maybe turn this issue into feature request to allow this also at
later stages. Is BeforeInheritenance a problem for you?
----------------------------------------------------------------------
nazgul - 10-08-06 15:51
----------------------------------------------------------------------
I agree, we do not allow adding virtual members during WithTypedMembers
stage. Changing this would require lots of refactoring of "override" and
virtual methods handling.
And the solution is quite simple - just add virtual members in
BeforeTypedMembers stage.
----------------------------------------------------------------------
VladD2 - 10-08-06 15:55
----------------------------------------------------------------------
I cannot add methods at stage BeforeInheritance. I need use
TypeBuilder.GetFields() method to determinate what classes require
methods.
What problem add methods into TypeInfo.member_map (of subtypes) during
adding it in supertype?
----------------------------------------------------------------------
VladD2 - 10-08-06 16:03
----------------------------------------------------------------------
If I simply comment this lines:
| None =>
//when (mem.Attributes %&& NemerleAttributes.Override)
//{
// Message.Error ($"`override' specified on $mem, "
// "but there is no such member in parent to
override");
//}
...then my code compile successfully. May be add in this point simple hack
(add member to member_map if it exists in one of supertype)?
----------------------------------------------------------------------
nazgul - 10-08-06 16:05
----------------------------------------------------------------------
Adding methods in given class changes the way how interfaces are
implemented in derived classes and how all the checks are performed for
overriding methods - we would need to re-process all existing methods in
subclasses to validate that everything is still ok. Not mentioning such
problems, like finding all deriving classes from given one.
Can you use parsed version of fields, instead of list of FieldBuilders
from GetFields? In BeforeTypedMembers you can simply analyze the parse
tree of class.
----------------------------------------------------------------------
nazgul - 10-08-06 16:11
----------------------------------------------------------------------
I would rather add some kind of checking for situation like:
- class B : A has already processed its members
- somebody adds any non private member to class A
In this situation compiler will be not able to easily reject incorrect
code - for example you could add abstract method, which is not overriden
in derived class or new interface member, which is not implemented in all
the necessary places.
----------------------------------------------------------------------
VladD2 - 10-08-06 16:22
----------------------------------------------------------------------
> Adding methods in given class changes the way how interfaces are
implemented in derived classes ...
Hm... But, I without problems can add a method which implements a
interface. Current design not prevent this! And I without problems can add
a override method if suprtype contains it virtual version. But I can't add
virtual-method into supertype and override-methods into subtypes.
> Can you use parsed version of fields, instead of list of FieldBuilders
from GetFields? In BeforeTypedMembers you can simply analyze the parse
tree of class.
I need find all class in which exists fields which type refer to Location.
It may be "field : Location", "field : Compiler.Location", "field :
list[Location]", ...
It's not simple.
----------------------------------------------------------------------
nazgul - 10-08-06 16:38
----------------------------------------------------------------------
Well, consider following scenario:
interface A { b(): void; }
class B : A { public b() : void { } }
and now:
1. interface A is processed and we have typed member in it
2. class B is processed and it is validated that it correctly implements
interface A
3. you call builderOfA.Define (<[ decl: c(): void; ]>)
4. program is compiled and invalid assembly is generated
What we would need here is to add quite expansive and hard implementation
after step 3 - to traverse all classes, which imlements A, remove their
members, add them once again and perform all validity checks.
As far as there are no classes deriving from one you are adding some new
methods it is safe, for example you can add new method to builderOfB.
I'm not saying it is completely impossible to support such scenarios, but
it would require a lot of changes... :(
So unfortunately the best way is to change the way you are trying to use
the API. Could you give some more details on your idea? I think you could
add the methods in two steps: first define the virtual method and its
override in desired classes in BeforeTypedMembers stage and then in
WithTypedMembers stage you could fill the bodies of those methods. This
should work unless you decide to add or not to add those methods basing on
the gathered typed members.
----------------------------------------------------------------------
VladD2 - 10-08-06 16:41
----------------------------------------------------------------------
> I would rather add some kind of checking for situation like:
> - class B : A has already processed its members
> - somebody adds any non private member to class A
Excellent! Then try to compile the following:
----------------------------------------------------------------------------
Macro-project
----------------------------------------------------------------------------
using Nemerle.Compiler;
[Nemerle.MacroUsage (Nemerle.MacroPhase.WithTypedMembers,
Nemerle.MacroTargets.Class)]
macro AddVirtualTestImpl (tb : TypeBuilder)
{
tb.Define (<[ decl:
public abstract TestImpl () : void
]>);
}
----------------------------------------------------------------------------
Code use macro
----------------------------------------------------------------------------
[AddVirtualTestImpl]
public abstract class A { }
public class B : A { }
System.Console.WriteLine(B());
----------------------------------------------------------------------------
It code compile successfully, but throw exception if try run it:
----------------------------------------------------------------------------
Unhandled Exception: System.TypeLoadException: Method 'TestImpl' in type
'B' from assembly 'ConsoleApplication1,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an
implementation.
at _N_AutoModule.Main()
----------------------------------------------------------------------------
But code:
----------------------------------------------------------------------------
public abstract class A
{
public abstract TestImpl () : void
}
public class B : A { }
System.Console.WriteLine(B());
----------------------------------------------------------------------------
...report error during compilation:
----------------------------------------------------------------------------
Main.n(6,1,6,23): error : method A.TestImpl() : void must be overriden,
because it is abstract
----------------------------------------------------------------------------
Then it's a bug in design of compiler and it will needs fix.
----------------------------------------------------------------------
nazgul - 10-08-06 16:43
----------------------------------------------------------------------
Yes, compiler is not currently resistant on such usage patterns, otherwise
you would get the error during addition of virtual method, not in addition
of override method. It should be checked as I said in note 0001473
Issue History
Date Modified Username Field Change
======================================================================
10-05-06 01:59 VladD2 New Issue
10-05-06 07:46 malekith Note Added: 0001467
10-08-06 15:51 nazgul Note Added: 0001469
10-08-06 15:55 VladD2 Note Added: 0001470
10-08-06 16:03 VladD2 Note Added: 0001471
10-08-06 16:05 nazgul Note Added: 0001472
10-08-06 16:11 nazgul Note Added: 0001473
10-08-06 16:22 VladD2 Note Added: 0001474
10-08-06 16:38 nazgul Note Added: 0001475
10-08-06 16:39 VladD2 Note Added: 0001476
10-08-06 16:41 VladD2 Note Edited: 0001476
10-08-06 16:43 nazgul Note Added: 0001477
======================================================================
More information about the bugs
mailing list