Bug 319585 (MONO76762) - [GMCS] CS0508 not reported for generic property override causing looped unification
Summary: [GMCS] CS0508 not reported for generic property override causing looped unifi...
Status: RESOLVED FIXED
Alias: MONO76762
Product: Mono: Compilers
Classification: Mono
Component: C# (show other bugs)
Version: 1.0
Hardware: Other Other
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Mono Bugs
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-20 00:35 UTC by Kamil Skalski
Modified: 2010-05-18 18:34 UTC (History)
1 user (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 19:38:42 UTC


---- Reported by nazgul@omega.pl 2005-11-19 17:35:05 MST ----

Please fill in this template when reporting a bug, unless you know what you
are doing.
Description of Problem:
The example below is quite strange. It should be rejected by gmcs, just
like by csc, because B returned by B getT() is in full signature A<T>.B,
but T getT() from A<T> resolves to A<A<T>.B> getT(), so A<T>.B getT() is
not a correct override of A<A<T>.B> getT()

Steps to reproduce the problem:
1. Compile following program

abstract class A<T>
{
   public abstract T getT();

   class B : A<B>
   {
       public override B getT()
       {
           throw new System.Exception("The method or operation is not
implemented.");
       }
   }
}

Actual Results:
error No Main

Expected Results:
t.cs(7,26): error CS0508: 'A<T>.B.getT()': return type must be 'A<T>.B' to
match overridden member 'A<A<T>.B>.getT()'
t.cs(3,22): (Location of symbol related to previous error)



---- Additional Comments From rharinath@novell.com 2005-12-17 02:33:33 MST ----

Hmm, I'm not sure I follow.  I think these hold:

(a) A<T>.getT() has a return type T (from the text)
(a') A<A<T>.B>.getT() has return type A<T>.B (subtitution T -> A<T>.B)
(b) A<T>.B.getT() overrides A<A<T>.B>.getT() (base type of A<T>.B)
(c) A<T>.B.getT() has return type A<T>.B (from the text)

So, they should unify fine?

IIUC, you disagree with (a').  Also, IIUC, the CSC error message is
saying (c) doesn't hold.



---- Additional Comments From nazgul@omega.pl 2005-12-17 10:18:07 MST ----

I did a more detailed analysis playing with csc and now I know the
problem. It is illustrated with following snippet of code:

class A<T>
{
   public class B : A<B>
   {
       public void getTT()
       {
           System.Console.WriteLine(typeof (B));
           System.Console.WriteLine(this.GetType());
       }
   }
}

class M { 
	static void Main () { 
		A<int>.B b = new A<int>.B();
		b.getTT();
		System.Console.WriteLine (b.GetType());
	}
}


The core of the problem is how C# resolves visibility of types. In
above example B means different things depending on context:
- in class declaration signature class B : A <B> { }  both B's refere
to the current type B (that is A<T>.B)
- inside the class B no longer referes to current type, but to type
derived from base type (that is A<A<T>.B>.B)

So my original example expands to

abstract class A<T>
{
   public abstract T getT();

}

 class A<T>.B : A<A<T>.B>
 {
       public override A<A<T>.B>.B getT()
       {
           throw new System.Exception("The method or operation is not
implemented.");
       }
 }

Which we can now easily see why is rejected.



---- Additional Comments From rharinath@novell.com 2005-12-17 13:57:32 MST ----

Thanks for the analysis.  So, the deduction '(c)' above appears to be
wrong.

Essentially this is a horrible interaction between generics and the
type-lookup rules.  In non-generic code, I don't think this
distinction matters -- it'd be the same type however you slice it.

I'm stealing the bug from Martin :-)

I think we have to ensure that

(1) a type name is not injected into its contained declaration space

(2) a name lookup first travels the inheritance hierarchy before
looking at any enclosing declaration spaces

Together, this would match the behaviour you see.  I'm fairly sure
that (2) is implemented.  So, I'll have to track down where it's not
satisfying (1).


This bug depended on bug(s) 77403.

Unknown operating system unknown. Setting to default OS "Other".

Comment 2 Marek Safar 2007-11-05 11:46:28 UTC
Expected output

A`1+B[A`1+B[System.Int32]]
A`1+B[System.Int32]
A`1+B[System.Int32]
Comment 3 Raja Harinath 2008-05-01 04:11:39 UTC
> I think we have to ensure that
> 
> (1) a type name is not injected into its contained declaration space
>
> (2) a name lookup first travels the inheritance hierarchy before
> looking at any enclosing declaration spaces
> 
> Together, this would match the behaviour you see.  I'm fairly sure
> that (2) is implemented.  So, I'll have to track down where it's not
> satisfying (1).

Hmm, my two conditions above hide the subtle assumption that the name lookup inflates the result of the lookup, which we probably don't.  So, (2) is not correctly implemented.
Comment 4 Marek Safar 2010-05-18 18:34:08 UTC
Fixed in trunk.