if (constraints != null)
return spec.HasSameConstraintsDefinition (tp.Type);
- constraints = new_constraints;
+ // Copy constraint from resolved part to partial container
+ spec.SpecialConstraint = tp.spec.SpecialConstraint;
+ spec.InterfacesDefined = tp.spec.InterfacesDefined;
+ spec.TypeArguments = tp.spec.TypeArguments;
+ spec.BaseType = tp.spec.BaseType;
+
return true;
}
var tps = (TypeParameterSpec) MemberwiseClone ();
tps.BaseType = inflator.Inflate (BaseType);
if (ifaces != null) {
- tps.ifaces = new TypeSpec[ifaces.Count];
+ tps.ifaces = new List<TypeSpec> (ifaces.Count);
for (int i = 0; i < ifaces.Count; ++i)
- tps.ifaces[i] = inflator.Inflate (ifaces[i]);
+ tps.ifaces.Add (inflator.Inflate (ifaces[i]));
}
if (targs != null) {
tps.targs = new TypeSpec[targs.Length];
}
}
+ public bool IsConvertibleToInterface (TypeSpec iface)
+ {
+ if (Interfaces != null) {
+ foreach (var t in Interfaces) {
+ if (t == iface)
+ return true;
+ }
+ }
+
+ if (TypeArguments != null) {
+ foreach (var t in TypeArguments) {
+ if (((TypeParameterSpec) t).IsConvertibleToInterface (iface))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public override TypeSpec Mutate (TypeParameterMutator mutator)
{
return mutator.Mutate (this);
}
// Inflate generic type
- if (ts.IsGeneric)
+ if (ts.Arity > 0)
return InflateTypeParameters (ts);
return ts;
if (tparams [i] == tp)
return targs[i];
- // CECIL: This can happen when inflating nested types
+ // This can happen when inflating nested types
// without type arguments specified
return tp;
}
for (int i = 0; i < names.Length; i++) {
string type_argument_name = names[i].Name;
int idx = parameters.GetParameterIndexByName (type_argument_name);
+
if (idx >= 0) {
- Block b = m.Block;
+ var b = m.Block;
if (b == null)
- b = new Block (null);
+ b = new ToplevelBlock (Compiler, Location);
- b.Error_AlreadyDeclaredTypeParameter (Report, parameters [i].Location,
+ b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
type_argument_name, "method parameter");
}
+
+ if (m.Block != null) {
+ var ikv = m.Block.GetKnownVariable (type_argument_name);
+ if (ikv != null)
+ ikv.Block.Error_AlreadyDeclaredTypeParameter (ikv.Location, type_argument_name, "local variable");
+ }
snames[i] = type_argument_name;
}
}
//
- // Uses inferred types to inflate delegate type argument
+ // Uses inferred or partially infered types to inflate delegate type argument. Returns
+ // null when type parameter was not yet inferres
//
public TypeSpec InflateGenericArgument (TypeSpec parameter)
{
var tp = parameter as TypeParameterSpec;
if (tp != null) {
//
- // Inflate method generic argument (MVAR) only
+ // Type inference work on generic arguments (MVAR) only
//
if (!tp.IsMethodOwned)
return parameter;
- return fixed_types [tp.DeclaredPosition];
+ return fixed_types [tp.DeclaredPosition] ?? parameter;
}
var gt = parameter as InflatedTypeSpec;
if (gt != null) {
var inflated_targs = new TypeSpec [gt.TypeArguments.Length];
for (int ii = 0; ii < inflated_targs.Length; ++ii) {
- inflated_targs[ii] = InflateGenericArgument (gt.TypeArguments [ii]);
+ var inflated = InflateGenericArgument (gt.TypeArguments [ii]);
+ if (inflated == null)
+ return null;
+
+ inflated_targs[ii] = inflated;
}
return gt.GetDefinition ().MakeGenericType (inflated_targs);
// then a lower-bound inference is made from U for Tb.
//
if (e is MethodGroupExpr) {
- // TODO: Or expression tree
- if (!TypeManager.IsDelegateType (t))
- return 0;
+ if (!TypeManager.IsDelegateType (t)) {
+ if (TypeManager.expression_type == null || t.MemberDefinition != TypeManager.expression_type.MemberDefinition)
+ return 0;
+
+ t = TypeManager.GetTypeArguments (t)[0];
+ }
var invoke = Delegate.GetInvokeMethod (ec.Compiler, t);
TypeSpec rtype = invoke.ReturnType;
- if (!TypeManager.IsGenericType (rtype))
+ if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype))
return 0;
+ // LAMESPEC: Standard does not specify that all methodgroup arguments
+ // has to be fixed but it does not specify how to do recursive type inference
+ // either. We choose the simple option and infer return type only
+ // if all delegate generic arguments are fixed.
+ TypeSpec[] param_types = new TypeSpec [invoke.Parameters.Count];
+ for (int i = 0; i < param_types.Length; ++i) {
+ var inflated = InflateGenericArgument (invoke.Parameters.Types[i]);
+ if (inflated == null)
+ return 0;
+
+ param_types[i] = inflated;
+ }
+
MethodGroupExpr mg = (MethodGroupExpr) e;
- Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, e.Location);
+ Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, param_types, e.Location);
mg = mg.OverloadResolve (ec, ref args, true, e.Location);
if (mg == null)
return 0;
- // TODO: What should happen when return type is of generic type ?
- throw new NotImplementedException ();
-// return LowerBoundInference (null, rtype) + 1;
+ return LowerBoundInference (mg.BestCandidate.ReturnType, rtype) + 1;
}
//