summaryrefslogtreecommitdiff
path: root/mcs/mcs/generic.cs
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/mcs/generic.cs')
-rw-r--r--mcs/mcs/generic.cs183
1 files changed, 101 insertions, 82 deletions
diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs
index 972e3a8b1c..e3bb7b0502 100644
--- a/mcs/mcs/generic.cs
+++ b/mcs/mcs/generic.cs
@@ -117,9 +117,9 @@ namespace Mono.CSharp {
//
public class Constraints
{
- SimpleMemberName tparam;
- List<FullNamedExpression> constraints;
- Location loc;
+ readonly SimpleMemberName tparam;
+ readonly List<FullNamedExpression> constraints;
+ readonly Location loc;
bool resolved;
bool resolving;
@@ -398,7 +398,7 @@ namespace Mono.CSharp {
//
public class TypeParameter : MemberCore, ITypeDefinition
{
- static readonly string[] attribute_target = new string [] { "type parameter" };
+ static readonly string[] attribute_target = { "type parameter" };
Constraints constraints;
GenericTypeParameterBuilder builder;
@@ -486,6 +486,12 @@ namespace Mono.CSharp {
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
public string Name {
get {
return MemberName.Name;
@@ -1787,7 +1793,7 @@ namespace Mono.CSharp {
return false;
}
- TypeParameterInflator CreateLocalInflator (IModuleContext context)
+ public TypeParameterInflator CreateLocalInflator (IModuleContext context)
{
TypeParameterSpec[] tparams_full;
TypeSpec[] targs_full = targs;
@@ -2140,7 +2146,7 @@ namespace Mono.CSharp {
public virtual bool Resolve (IMemberContext ec)
{
if (atypes != null)
- return atypes.Length != 0;
+ return true;
int count = args.Count;
bool ok = true;
@@ -2171,7 +2177,7 @@ namespace Mono.CSharp {
}
if (!ok)
- atypes = TypeSpec.EmptyTypes;
+ atypes = null;
return ok;
}
@@ -2849,7 +2855,7 @@ namespace Mono.CSharp {
var mi = Delegate.GetInvokeMethod (t_i);
TypeSpec rtype = mi.ReturnType;
- if (tic.IsReturnTypeNonDependent (ec, mi, rtype)) {
+ if (tic.IsReturnTypeNonDependent (mi, rtype)) {
// It can be null for default arguments
if (arguments[i] == null)
continue;
@@ -2906,7 +2912,6 @@ namespace Mono.CSharp {
readonly TypeSpec[] tp_args;
readonly TypeSpec[] fixed_types;
readonly List<BoundInfo>[] bounds;
- bool failed;
// TODO MemberCache: Could it be TypeParameterSpec[] ??
public TypeInferenceContext (TypeSpec[] typeArguments)
@@ -2948,15 +2953,20 @@ namespace Mono.CSharp {
public void AddCommonTypeBound (TypeSpec type)
{
- AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
+ AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, false);
+ }
+
+ public void AddCommonTypeBoundAsync (TypeSpec type)
+ {
+ AddToBounds (new BoundInfo (type, BoundKind.Lower), 0, true);
}
- void AddToBounds (BoundInfo bound, int index)
+ void AddToBounds (BoundInfo bound, int index, bool voidAllowed)
{
//
// Some types cannot be used as type arguments
//
- if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
+ if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod)
return;
@@ -3030,7 +3040,7 @@ namespace Mono.CSharp {
if (pos == -1)
return 0;
- AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
+ AddToBounds (new BoundInfo (u, BoundKind.Exact), pos, false);
return 1;
}
@@ -3120,9 +3130,6 @@ namespace Mono.CSharp {
if (fixed_types[i] != null)
throw new InternalErrorException ("Type argument has been already fixed");
- if (failed)
- return false;
-
var candidates = bounds [i];
if (candidates == null)
return false;
@@ -3137,87 +3144,100 @@ namespace Mono.CSharp {
}
//
- // Determines a unique type from which there is
- // a standard implicit conversion to all the other
- // candidate types.
+ // The set of candidate types Uj starts out as the set of
+ // all types in the set of bounds for Xi
//
- TypeSpec best_candidate = null;
- int cii;
- int candidates_count = candidates.Count;
- for (int ci = 0; ci < candidates_count; ++ci) {
- BoundInfo bound = candidates [ci];
- for (cii = 0; cii < candidates_count; ++cii) {
- if (cii == ci)
- continue;
+ var applicable = new bool [candidates.Count];
+ for (int ci = 0; ci < applicable.Length; ++ci)
+ applicable [ci] = true;
+
+ for (int ci = 0; ci < applicable.Length; ++ci) {
+ var bound = candidates [ci];
+ int cii = 0;
+
+ switch (bound.Kind) {
+ case BoundKind.Exact:
+ for (; cii != applicable.Length; ++cii) {
+ if (ci == cii)
+ continue;
- BoundInfo cbound = candidates[cii];
-
- // Same type parameters with different bounds
- if (cbound.Type == bound.Type) {
- if (bound.Kind != BoundKind.Exact)
- bound = cbound;
+ if (!applicable[cii])
+ break;
- continue;
+ //
+ // For each exact bound U of Xi all types Uj which are not identical
+ // to U are removed from the candidate set
+ //
+ if (candidates [cii].Type != bound.Type)
+ applicable[cii] = false;
}
- if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
- if (cbound.Kind == BoundKind.Lower) {
- if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
- break;
- }
-
+ break;
+ case BoundKind.Lower:
+ for (; cii != applicable.Length; ++cii) {
+ if (ci == cii)
continue;
- }
- if (cbound.Kind == BoundKind.Upper) {
- if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
- break;
- }
- continue;
+ if (!applicable[cii])
+ break;
+
+ //
+ // For each lower bound U of Xi all types Uj to which there is not an implicit conversion
+ // from U are removed from the candidate set
+ //
+ if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), candidates [cii].Type)) {
+ applicable[cii] = false;
}
-
- if (bound.Kind != BoundKind.Exact) {
- if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
- break;
- }
+ }
- bound = cbound;
+ break;
+
+ case BoundKind.Upper:
+ for (; cii != applicable.Length; ++cii) {
+ if (ci == cii)
continue;
- }
-
- break;
+
+ if (!applicable[cii])
+ break;
+
+ //
+ // For each upper bound U of Xi all types Uj from which there is not an implicit conversion
+ // to U are removed from the candidate set
+ //
+ if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+ applicable[cii] = false;
}
- if (bound.Kind == BoundKind.Lower) {
- if (cbound.Kind == BoundKind.Lower) {
- if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
- break;
- }
- } else {
- if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
- break;
- }
+ break;
+ }
+ }
- bound = cbound;
- }
+ TypeSpec best_candidate = null;
+ for (int ci = 0; ci < applicable.Length; ++ci) {
+ if (!applicable[ci])
+ continue;
+ var bound = candidates [ci];
+ if (bound.Type == best_candidate)
+ continue;
+
+ int cii = 0;
+ for (; cii < applicable.Length; ++cii) {
+ if (ci == cii)
continue;
- }
- if (bound.Kind == BoundKind.Upper) {
- if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
- break;
- }
- } else {
- throw new NotImplementedException ("variance conversion");
- }
+ if (!applicable[cii])
+ continue;
+
+ if (!Convert.ImplicitConversionExists (ec, candidates[cii].GetTypeExpression (), bound.Type))
+ break;
}
- if (cii != candidates_count)
+ if (cii != applicable.Length)
continue;
//
- // We already have the best candidate, break if thet are different
+ // We already have the best candidate, break if it's different (non-unique)
//
// Dynamic is never ambiguous as we prefer dynamic over other best candidate types
//
@@ -3296,7 +3316,7 @@ namespace Mono.CSharp {
// Tests whether all delegate input arguments are fixed and generic output type
// requires output type inference
//
- public bool IsReturnTypeNonDependent (ResolveContext ec, MethodSpec invoke, TypeSpec returnType)
+ public bool IsReturnTypeNonDependent (MethodSpec invoke, TypeSpec returnType)
{
AParametersCollection d_parameters = invoke.Parameters;
@@ -3361,7 +3381,7 @@ namespace Mono.CSharp {
// If V is one of the unfixed type arguments
int pos = IsUnfixed (v);
if (pos != -1) {
- AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
+ AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos, false);
return 1;
}
@@ -3433,10 +3453,9 @@ namespace Mono.CSharp {
}
//
- // This should always cause type inference failure
+ // Break when candidate arguments are ambiguous
//
- failed = true;
- return 1;
+ return 0;
}
//
@@ -3529,7 +3548,7 @@ namespace Mono.CSharp {
var invoke = Delegate.GetInvokeMethod (t);
TypeSpec rtype = invoke.ReturnType;
- if (!IsReturnTypeNonDependent (ec, invoke, rtype))
+ if (!IsReturnTypeNonDependent (invoke, rtype))
return 0;
// LAMESPEC: Standard does not specify that all methodgroup arguments