Wiki

Ticket #130 (accepted defect)

Opened 9 years ago

Last modified 9 years ago

The compiler doesn't find the "closest" extension method

Reported by: Chuck Owned by: jonathandavid
Priority: major Milestone: Cobra 0.9
Component: Cobra Compiler Version: 0.8.0
Keywords: Cc:

Description

Test case:

# x-extend.cobra
class A

	pass


class B
	inherits A
	
	pass


class C
	inherits B
	
	pass


extend B

	def n as int
		return 2


extend C

	def n as int
		return 3


class P

	def main is shared
		b = B()
		assert b.n == 2
		c = C()
		assert c.n == 3

Cobra takes the first extension method it can find instead of the closest among all available.

Also, this bug is blocking further extensions being added to Cobra.Lang\ExtendIEnumerable.cobra

Change History

Changed 9 years ago by jonathandavid

  • owner set to jonathandavid
  • status changed from new to accepted

Changed 9 years ago by Chuck

If you find one or more good reference URLs for the C# rules on this, please include them on this ticket.

Changed 9 years ago by Chuck

Any progress on this?

Changed 9 years ago by Chuck

I have confirmed that C# takes the closest extension method, not just the first compatible one that appears in the code (as even MSDN docs seem to imply).

// C# 3.0 / VS 2008
using System;

class A {
}

class B : A {   
}

class C : B {
}

static class ExtendB {

    public static int N(this B b) {
        return 2;
    }

}

static class ExtendC {
    
    public static int N(this C c) {
        return 3;
    }

}

class P {

    static void Main() {
        var b = new B();
        Console.WriteLine("b.N() == {0}", b.N());
        var c = new C();
        Console.WriteLine("c.N() == {0}", c.N());
    }

}

That prints 2 and then 3. And to prove that ExtendB is compatible with instances of C, you can comment out ExtendC at which point the program will print 2 and then 2.

Changed 9 years ago by Chuck

Here is article on extension methods that gives a little more detail and a lot more hints about binding. However, it's about VB and it's not clear that the comments about binding apply to the C# compiler.

Changed 9 years ago by Chuck

The C# 3.0 Spec, section 7.5.5.2 "Extension method invocations" describes what's going on. Basically, all the candidates are located, then overload resolution is applied to the candidate set as described in section 7.4.3 with the first argument of any method being the type that is extended.

Cobra's overload resolution is found in Expr.cobra CallExpr?._computeBestOverload.

Note: See TracTickets for help on using tickets.