diff options
Diffstat (limited to 'mcs/mcs/generic.cs')
-rw-r--r-- | mcs/mcs/generic.cs | 183 |
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 |