if (resolved)
return true;
- iface_constraints = new ArrayList ();
+ iface_constraints = new ArrayList (2); // TODO: Too expensive allocation
type_param_constraints = new ArrayList ();
foreach (object obj in constraints) {
type_param_constraints.Add (expr);
else if (expr.IsInterface)
iface_constraints.Add (expr);
- else if (class_constraint != null) {
+ else if (class_constraint != null || iface_constraints.Count != 0) {
Report.Error (406, loc,
- "`{0}': the class constraint for `{1}' " +
- "must come before any other constraints.",
- expr.GetSignatureForError (), name);
+ "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 " +
else
effective_base_type = TypeManager.object_type;
+ if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
+
resolved = true;
return true;
}
- bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
+ bool CheckTypeParameterConstraints (TypeParameter tparam, ref TypeExpr prevConstraint, ArrayList seen)
{
- seen.Add (tparam, true);
+ seen.Add (tparam);
Constraints constraints = tparam.Constraints;
if (constraints == null)
return true;
if (constraints.HasValueTypeConstraint) {
- Report.Error (456, loc, "Type parameter `{0}' has " +
- "the `struct' constraint, so it cannot " +
- "be used as a constraint for `{1}'",
- tparam.Name, name);
+ Report.Error (456, loc,
+ "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
+ tparam.Name, name);
return false;
}
+ //
+ // Checks whether there are no conflicts between type parameter constraints
+ //
+ // class Foo<T, U>
+ // where T : A
+ // where U : A, B // A and B are not convertible
+ //
+ if (constraints.HasClassConstraint) {
+ if (prevConstraint != null) {
+ Type t2 = constraints.ClassConstraint;
+ TypeExpr e2 = constraints.class_constraint;
+
+ if (!Convert.ImplicitReferenceConversionExists (prevConstraint, t2) &&
+ !Convert.ImplicitReferenceConversionExists (e2, prevConstraint.Type)) {
+ Report.Error (455, loc,
+ "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
+ name, TypeManager.CSharpName (prevConstraint.Type), TypeManager.CSharpName (t2));
+ return false;
+ }
+ }
+
+ prevConstraint = constraints.class_constraint;
+ }
+
if (constraints.type_param_constraints == null)
return true;
return false;
}
- if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prevConstraint, seen))
return false;
}
return false;
}
- foreach (TypeParameterExpr expr in type_param_constraints) {
- Hashtable seen = new Hashtable ();
- if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
- return false;
+ if (type_param_constraints.Count != 0) {
+ ArrayList seen = new ArrayList ();
+ TypeExpr prev_constraint = class_constraint;
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, ref prev_constraint, seen))
+ return false;
+ seen.Clear ();
+ }
}
for (int i = 0; i < iface_constraints.Count; ++i) {
return true;
}
- /// <summary>
- /// Check whether there are no conflicts in our type parameter constraints.
- ///
- /// This is an example:
- ///
- /// class Foo<T,U>
- /// where T : class
- /// where U : T, struct
- /// </summary>
- public bool CheckDependencies ()
- {
- foreach (TypeParameterExpr expr in type_param_constraints) {
- if (!CheckDependencies (expr.TypeParameter))
- return false;
- }
-
- return true;
- }
-
- bool CheckDependencies (TypeParameter tparam)
- {
- Constraints constraints = tparam.Constraints;
- if (constraints == null)
- return true;
-
- if (HasValueTypeConstraint && constraints.HasClassConstraint) {
- Report.Error (455, loc, "Type parameter `{0}' inherits " +
- "conflicting constraints `{1}' and `{2}'",
- name, TypeManager.CSharpName (constraints.ClassConstraint),
- "System.ValueType");
- return false;
- }
-
- if (HasClassConstraint && constraints.HasClassConstraint) {
- Type t1 = ClassConstraint;
- TypeExpr e1 = class_constraint;
- Type t2 = constraints.ClassConstraint;
- TypeExpr e2 = constraints.class_constraint;
-
- if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
- !Convert.ImplicitReferenceConversionExists (e2, t1)) {
- Report.Error (455, loc,
- "Type parameter `{0}' inherits " +
- "conflicting constraints `{1}' and `{2}'",
- name, TypeManager.CSharpName (t1), TypeManager.CSharpName (t2));
- return false;
- }
- }
-
- if (constraints.type_param_constraints == null)
- return true;
-
- foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
- if (!CheckDependencies (expr.TypeParameter))
- return false;
- }
-
- return true;
- }
-
public override GenericParameterAttributes Attributes {
get { return attrs; }
}
if (gc == null)
return true;
- if (gc.HasClassConstraint)
- type.SetBaseTypeConstraint (gc.ClassConstraint);
+ if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
+ type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
type.SetInterfaceConstraints (gc.InterfaceConstraints);
type.SetGenericParameterAttributes (gc.Attributes);
return true;
}
- /// <summary>
- /// Check whether there are no conflicts in our type parameter constraints.
- ///
- /// This is an example:
- ///
- /// class Foo<T,U>
- /// where T : class
- /// where U : T, struct
- /// </summary>
- public bool CheckDependencies ()
- {
- if (constraints != null)
- return constraints.CheckDependencies ();
-
- return true;
- }
-
/// <summary>
/// This is called for each part of a partial generic type definition.
///
if (t == null)
return null;
if (t.IsGenericParameter)
- return dargs [t.GenericParameterPosition];
+ return t.GenericParameterPosition < dargs.Length ? dargs [t.GenericParameterPosition] : t;
if (t.IsGenericType) {
Type[] args = t.GetGenericArguments ();
Type[] inflated = new Type [args.Length];
return false;
}
- if (te.Type.IsPointer) {
- Report.Error (306, Location, "The type `{0}' may not be used " +
- "as a type argument", TypeManager.CSharpName (te.Type));
+ if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
+ Report.Error (306, Location,
+ "The type `{0}' may not be used as a type argument",
+ TypeManager.CSharpName (te.Type));
return false;
}
public override string GetSignatureForError ()
{
- return TypeManager.RemoveGenericArity (gt.FullName) + "<" + args.GetSignatureForError () + ">";
+ return TypeManager.CSharpName (type);
}
protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
if (Convert.ImplicitStandardConversionExists (expr, ctype))
return true;
- Error_TypeMustBeConvertible (expr.Type, ctype, ptype);
+ Report_SymbolRelatedToPreviousError ();
+ Report.SymbolRelatedToPreviousError (expr.Type);
+
+ if (TypeManager.IsNullableType (expr.Type) && ctype.IsInterface) {
+ Report.Error (313, loc,
+ "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. " +
+ "The nullable type `{0}' never satisfies interface constraint of type `{3}'",
+ TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ptype),
+ GetSignatureForError (), TypeManager.CSharpName (ctype));
+ } else {
+ Report.Error (309, loc,
+ "The type `{0}' must be convertible to `{1}' in order to " +
+ "use it as parameter `{2}' in the generic type or method `{3}'",
+ TypeManager.CSharpName (expr.Type), TypeManager.CSharpName (ctype),
+ TypeManager.CSharpName (ptype), GetSignatureForError ());
+ }
return false;
}
protected abstract string GetSignatureForError ();
protected abstract void Report_SymbolRelatedToPreviousError ();
- void Error_TypeMustBeConvertible (Type atype, Type gc, Type ptype)
- {
- Report_SymbolRelatedToPreviousError ();
- Report.SymbolRelatedToPreviousError (atype);
- Report.Error (309, loc,
- "The type `{0}' must be convertible to `{1}' in order to " +
- "use it as parameter `{2}' in the generic type or method `{3}'",
- TypeManager.CSharpName (atype), TypeManager.CSharpName (gc),
- TypeManager.CSharpName (ptype), GetSignatureForError ());
- }
-
public static bool CheckConstraints (EmitContext ec, MethodBase definition,
MethodBase instantiated, Location loc)
{
ec, mb, implementing, is_override))
return false;
- bool ok = true;
- foreach (Parameter p in parameters.FixedParameters){
- if (p.Resolve (ec) == null)
- ok = false;
- }
+ bool ok = parameters.Resolve (ec);
+
if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
ok = false;
OptAttributes.Emit ();
}
- public override bool DefineMembers ()
- {
- return true;
- }
-
public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
MemberFilter filter, object criteria)
{
} else {
params_arguments_start = arg_count;
}
+
+ Type [] ptypes = methodParameters.Types;
//
// The first inference phase
method_parameter = methodParameters.Types [params_arguments_start];
else
method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
+
+ ptypes = (Type[]) ptypes.Clone ();
+ ptypes [i] = method_parameter;
}
//
// we don't need to call it in cycle
//
bool fixed_any = false;
- if (!tic.FixIndependentTypeArguments (methodParameters, ref fixed_any))
+ if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
return false;
- return DoSecondPhase (ec, tic, methodParameters, !fixed_any);
+ return DoSecondPhase (ec, tic, ptypes, !fixed_any);
}
- bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters, bool fixDependent)
+ bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
{
bool fixed_any = false;
- if (fixDependent && !tic.FixDependentTypes (methodParameters, ref fixed_any))
+ if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
return false;
// If no further unfixed type variables exist, type inference succeeds
// contain unfixed type variables but the input types do not,
// an output type inference is made
for (int i = 0; i < arg_count; i++) {
- Type t_i = methodParameters.Types [i];
+
+ // Align params arguments
+ Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
+
if (!TypeManager.IsDelegateType (t_i)) {
if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
continue;
// a, There is at least one type variable Xj that depends on Xi
// b, Xi has a non-empty set of bounds
//
- public bool FixDependentTypes (AParametersCollection methodParameters, ref bool fixed_any)
+ public bool FixDependentTypes (ref bool fixed_any)
{
for (int i = 0; i < unfixed_types.Length; ++i) {
if (unfixed_types[i] == null)
//
// All unfixed type variables Xi which depend on no Xj are fixed
//
- public bool FixIndependentTypeArguments (AParametersCollection methodParameters, ref bool fixed_any)
+ public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
{
ArrayList types_to_fix = new ArrayList (unfixed_types);
- for (int i = 0; i < methodParameters.Types.Length; ++i) {
- Type t = methodParameters.Types [i];
+ for (int i = 0; i < methodParameters.Length; ++i) {
+ Type t = methodParameters[i];
if (t.IsGenericParameter)
continue;