[Mono-bugs] [Bug 591226] New: Using Reflection.Emit to generate a generic method may lead to invalid codegen
bugzilla_noreply at novell.com
bugzilla_noreply at novell.com
Thu Mar 25 15:18:38 EDT 2010
http://bugzilla.novell.com/show_bug.cgi?id=591226
http://bugzilla.novell.com/show_bug.cgi?id=591226#c0
Summary: Using Reflection.Emit to generate a generic method may
lead to invalid codegen
Classification: Mono
Product: Mono: Runtime
Version: 2.6.x
Platform: x86
OS/Version: All
Status: NEW
Severity: Normal
Priority: P5 - None
Component: generics
AssignedTo: mono-bugs at lists.ximian.com
ReportedBy: joe at noteven.org
QAContact: mono-bugs at lists.ximian.com
Found By: ---
Blocker: ---
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64;
Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;
Media Center PC 6.0; MS-RTC LM 8; InfoPath.2; .NET4.0C; .NET4.0E)
It looks like if two non-generic classes are emitted into a module, with one
containing a specialized call to a generic method defined in the other, there’s
a problem with the code generated for the specialized call.
Reproducible: Always
Steps to Reproduce:
1. Download the latest F# CTP
http://www.microsoft.com/downloads/details.aspx?FamilyID=b55f0532-ac3c-4106-918c-5586a953a7da&displaylang=en
2. Run FSI.exe through Mono
3. Enter the following code:
let myFunc x y =
if x > y then stdout.WriteLine("greater {0} {1}",x,y);
if x < y then stdout.WriteLine("less {0} {1}",x,y);
if x = y then stdout.WriteLine("equal {0} {1}",x,y);
myFunc 1 4;;
Actual Results:
The above will yield the following output using Mono 2.6.3 (tested on both
Windows 7 and Mac OS X 10.5.8/Intel):
greater 1 4
less 1 4
equal 1 4
val myFunc : 'a -> 'a -> unit when 'a : comparison
Expected Results:
The above is incorrect. The output should be:
less 1 4
val myFunc : 'a -> 'a -> unit when 'a : comparison
Copy and paste the following code fragment into fsi.exe:
let myFunc x y =
if x > y then stdout.WriteLine("greater {0} {1}",x,y);
if x < y then stdout.WriteLine("less {0} {1}",x,y);
if x = y then stdout.WriteLine("equal {0} {1}",x,y);
myFunc 1 4;;
The above will yield the following output using Mono 2.6.3 (tested on both
Windows 7 and Mac OS X 10.5.8/Intel):
greater 1 4
less 1 4
equal 1 4
val myFunc : 'a -> 'a -> unit when 'a : comparison
The above is incorrect. The output should be:
less 1 4
val myFunc : 'a -> 'a -> unit when 'a : comparison
On the Microsoft CLR, the correct output is generated.
It looks like if two non-generic classes are emitted into a module, with one
containing a specialized call to a generic method defined in the other, there’s
a problem with the code generated for the specialized call.
(To be clear, in the example above, fsi.exe will emit two classes - one with
myFunc defined as a static method, and another with a static “main” method that
calls “myFunc 1 4”. When the fragment is evaluated, the “main” method is
called.) Here’s a clearer example that will produce the same incorrect output:
type A() =
member a.Foo x y =
if x > y then stdout.WriteLine("greater {0} {1}",x,y);
if x < y then stdout.WriteLine("less {0} {1}",x,y);
if x = y then stdout.WriteLine("equal {0} {1}",x,y);
and B() =
member b.Bar x y = let a = A() in a.Foo x y
let _ = let b = B() in b.Bar 1 4
And one more sample, reported by a user:
let reduce gen =
match gen with
| [_; _] ->
printfn "path1"
1
| [_] ->
printfn "path2"
2
| _ ->
3
printfn "result = %A" (reduce [1;2])
In this case, the expression “reduce [1;2]” will evaluate to “path2”, where it
should evaluate to “path1”.
It’s important to note that in all of these cases, if the “call” method is
emitted separately from the generic method (that is, as two separate evaluated
expressions), the correct code will be generated. For example:
// evaluate the definition of myFunc
let myFunc x y =
if x > y then stdout.WriteLine("greater {0} {1}",x,y);
if x < y then stdout.WriteLine("less {0} {1}",x,y);
if x = y then stdout.WriteLine("equal {0} {1}",x,y);;
val myFunc : 'a -> 'a -> unit when 'a : comparison
// Ok, fsi.exe has evaluated it - now call it
less 1 4
val it : unit = ()
// correct!
--
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the mono-bugs
mailing list