/// <summary> /// Resolve the constraints - but only resolve things into Expression's, not /// into actual types. /// </summary> public bool Resolve (MemberCore ec, TypeParameter tp, Report Report) { if (resolved) return true; if (ec == null) return false; iface_constraints = new ArrayList (2); // TODO: Too expensive allocation type_param_constraints = new ArrayList (); foreach (object obj in constraints) { if (HasConstructorConstraint) { Report.Error (401, loc, "The new() constraint must be the last constraint specified"); return false; } if (obj is SpecialConstraint) { SpecialConstraint sc = (SpecialConstraint) obj; if (sc == SpecialConstraint.Constructor) { if (!HasValueTypeConstraint) { attrs |= GenericParameterAttributes.DefaultConstructorConstraint; continue; } Report.Error (451, loc, "The `new()' constraint " + "cannot be used with the `struct' constraint"); return false; } if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) { Report.Error (449, loc, "The `class' or `struct' " + "constraint must be the first constraint specified"); return false; } if (sc == SpecialConstraint.ReferenceType) attrs |= GenericParameterAttributes.ReferenceTypeConstraint; else attrs |= GenericParameterAttributes.NotNullableValueTypeConstraint; continue; } int errors = Report.Errors; FullNamedExpression fn = ((Expression) obj).ResolveAsTypeStep (ec, false); if (fn == null) { if (errors != Report.Errors) return false; NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError (), Report); return false; } TypeExpr expr; GenericTypeExpr cexpr = fn as GenericTypeExpr; if (cexpr != null) { expr = cexpr.ResolveAsBaseTerminal (ec, false); } else expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false); if ((expr == null) || (expr.Type == null)) return false; if (!ec.IsAccessibleAs (fn.Type)) { Report.SymbolRelatedToPreviousError (fn.Type); Report.Error (703, loc, "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'", fn.GetSignatureForError (), ec.GetSignatureForError ()); return false; } if (TypeManager.IsGenericParameter (expr.Type)) type_param_constraints.Add (expr); else if (expr.IsInterface) iface_constraints.Add (expr); else if (class_constraint != null || iface_constraints.Count != 0) { Report.Error (406, loc, "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list", expr.GetSignatureForError ()); return false; } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) { Report.Error (450, loc, "`{0}': cannot specify both " + "a constraint class and the `class' " + "or `struct' constraint", expr.GetSignatureForError ()); return false; } else class_constraint = expr; // // Checks whether each generic method parameter constraint type // is valid with respect to T // if (tp != null && tp.Type.DeclaringMethod != null) { TypeManager.CheckTypeVariance (expr.Type, Variance.Contravariant, ec as MemberCore); } num_constraints++; } ArrayList list = new ArrayList (); foreach (TypeExpr iface_constraint in iface_constraints) { foreach (Type type in list) { if (!type.Equals (iface_constraint.Type)) continue; Report.Error (405, loc, "Duplicate constraint `{0}' for type " + "parameter `{1}'.", iface_constraint.GetSignatureForError (), name); return false; } list.Add (iface_constraint.Type); } foreach (TypeExpr expr in type_param_constraints) { foreach (Type type in list) { if (!type.Equals (expr.Type)) continue; Report.Error (405, loc, "Duplicate constraint `{0}' for type " + "parameter `{1}'.", expr.GetSignatureForError (), name); return false; } list.Add (expr.Type); } iface_constraint_types = new Type [list.Count]; list.CopyTo (iface_constraint_types, 0); if (class_constraint != null) { class_constraint_type = class_constraint.Type; if (class_constraint_type == null) return false; if (class_constraint_type.IsSealed) { if (class_constraint_type.IsAbstract) { Report.Error (717, loc, "`{0}' is not a valid constraint. Static classes cannot be used as constraints", TypeManager.CSharpName (class_constraint_type)); } else { Report.Error (701, loc, "`{0}' is not a valid constraint. A constraint must be an interface, " + "a non-sealed class or a type parameter", TypeManager.CSharpName(class_constraint_type)); } return false; } if ((class_constraint_type == TypeManager.array_type) || (class_constraint_type == TypeManager.delegate_type) || (class_constraint_type == TypeManager.enum_type) || (class_constraint_type == TypeManager.value_type) || (class_constraint_type == TypeManager.object_type) || class_constraint_type == TypeManager.multicast_delegate_type) { Report.Error (702, loc, "A constraint cannot be special class `{0}'", TypeManager.CSharpName (class_constraint_type)); return false; } if (TypeManager.IsDynamicType (class_constraint_type)) { Report.Error (1967, loc, "A constraint cannot be the dynamic type"); return false; } } if (class_constraint_type != null) effective_base_type = class_constraint_type; else if (HasValueTypeConstraint) effective_base_type = TypeManager.value_type; else effective_base_type = TypeManager.object_type; if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) attrs |= GenericParameterAttributes.DefaultConstructorConstraint; resolved = true; return true; }