diff options
author | Marek Safar <marek.safar@gmail.com> | 2015-09-07 17:08:58 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2015-09-07 17:11:59 +0300 |
commit | 5e81ed1e03581885585e819c3dc14e60455cf42d (patch) | |
tree | 2526f867e8add20c35289ee202473f5dc039ce8f /mcs | |
parent | 9dd35ce4a56b018ae83f0681d0b93e2ac1c00d42 (diff) |
[mcs] Consider whole hierarchy of inherited type arguments inflated via base type. Fixes #33669
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/mcs/generic.cs | 40 | ||||
-rw-r--r-- | mcs/tests/gtest-634.cs | 27 | ||||
-rw-r--r-- | mcs/tests/ver-il-net_4_x.xml | 31 |
3 files changed, 79 insertions, 19 deletions
diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index b4b98f067a8..e63e999dc79 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -649,10 +649,10 @@ namespace Mono.CSharp { var meta_constraints = new List<MetaType> (spec.TypeArguments.Length); foreach (var c in spec.TypeArguments) { // - // Inflated type parameters can collide with special constraint types, don't + // Inflated type parameters can collide with base type constraint, don't // emit any such type parameter. // - if (c.BuiltinType == BuiltinTypeSpec.Type.Object || c.BuiltinType == BuiltinTypeSpec.Type.ValueType) + if (c.IsClass && spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object) continue; meta_constraints.Add (c.GetMetaInfo ()); @@ -1334,12 +1334,26 @@ namespace Mono.CSharp { { cache = new MemberCache (); + if (targs != null) { + foreach (var ta in targs) { + var tps = ta as TypeParameterSpec; + var b_type = tps == null ? ta : tps.GetEffectiveBase (); + + // + // Find the most specific type when base type was inflated from base constraints + // + if (b_type != null && !b_type.IsStructOrEnum && TypeSpec.IsBaseClass (b_type, BaseType, false)) + BaseType = b_type; + } + } + // // For a type parameter the membercache is the union of the sets of members of the types // specified as a primary constraint or secondary constraint // - if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) + if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) { cache.AddBaseType (BaseType); + } if (InterfacesDefined != null) { foreach (var iface_type in InterfacesDefined) { @@ -1347,25 +1361,13 @@ namespace Mono.CSharp { } } + // + // Import interfaces after base type to match behavior from ordinary classes + // if (targs != null) { foreach (var ta in targs) { var tps = ta as TypeParameterSpec; - IList<TypeSpec> ifaces; - TypeSpec b_type; - if (tps != null) { - b_type = tps.GetEffectiveBase (); - ifaces = tps.InterfacesDefined; - } else { - b_type = ta; - ifaces = ta.Interfaces; - } - - // - // Don't add base type which was inflated from base constraints but it's not valid - // in C# context - // - if (b_type != null && b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType && !b_type.IsStructOrEnum) - cache.AddBaseType (b_type); + var ifaces = tps == null ? ta.Interfaces : tps.InterfacesDefined; if (ifaces != null) { foreach (var iface_type in ifaces) { diff --git a/mcs/tests/gtest-634.cs b/mcs/tests/gtest-634.cs new file mode 100644 index 00000000000..b078d28e6a1 --- /dev/null +++ b/mcs/tests/gtest-634.cs @@ -0,0 +1,27 @@ +using System; + +public abstract class ThingWithOrganizationId +{ + public Guid OrganizationId; +} + +public class Thing : ThingWithOrganizationId +{ +} + +public abstract class BaseService<TConstraint> +{ + public abstract void Save<T> (T newThing) where T : TConstraint; +} + +public class DerivedService:BaseService<Thing> +{ + public override void Save<TThing>(TThing newThing) + { + Console.WriteLine (newThing.OrganizationId); + } + + static void Main () + { + } +}
\ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml index 9cfd1240b1a..0ea541bffb6 100644 --- a/mcs/tests/ver-il-net_4_x.xml +++ b/mcs/tests/ver-il-net_4_x.xml @@ -19688,6 +19688,37 @@ </method> </type> </test> + <test name="gtest-634.cs"> + <type name="ThingWithOrganizationId"> + <method name="Void .ctor()" attrs="6276"> + <size>7</size> + </method> + </type> + <type name="Thing"> + <method name="Void .ctor()" attrs="6278"> + <size>7</size> + </method> + </type> + <type name="BaseService`1[TConstraint]"> + <method name="Void Save[T](T)" attrs="1478"> + <size>0</size> + </method> + <method name="Void .ctor()" attrs="6276"> + <size>7</size> + </method> + </type> + <type name="DerivedService"> + <method name="Void Save[TThing](TThing)" attrs="198"> + <size>23</size> + </method> + <method name="Void Main()" attrs="145"> + <size>2</size> + </method> + <method name="Void .ctor()" attrs="6278"> + <size>7</size> + </method> + </type> + </test> <test name="gtest-anontype-01.cs"> <type name="Test"> <method name="Int32 Main()" attrs="150"> |