void CheckCircular(TypeParameterSpec p, TypeParameterSpec baseType, ResolveContext rc, bool ignoreFirst = false, TypeParameterSpec parent = null)
        {
            if (p == baseType && !ignoreFirst)
            {
                rc.Report.Error(173, Location,
                                "Circular constraint dependency involving `{0}' and `{1}'",
                                p.Name, parent.Name);
                return;
            }



            foreach (var t in baseType.DirectBaseTypes.Where(x => x is TypeParameterSpec))
            {
                CheckCircular(p, t as TypeParameterSpec, rc, false, baseType);
            }
        }
        public bool DoResolve(Resolver.ResolveContext rc)
        {
            ResolvedTypeParameter = CreateResolvedTypeParameter(rc.CurrentTypeResolveContext);

            // check for conflicting constraints (struct & class)
            //    if(ResolvedTypeParameter.HasReferenceTypeConstraint && ResolvedTypeParameter.HasValueTypeConstraint )
            //        rc.Report.Error(174, Location,
            //"Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
            //name, "struct","class");



            // check direct base types
            List <IType> checked_types = new List <IType>();

            foreach (var type in ResolvedTypeParameter.DirectBaseTypes)
            {
                // check for duplicate constraints
                if (checked_types.Contains(type))
                {
                    rc.Report.Error(176, Location,
                                    "Duplicate constraint `{0}' for type parameter `{1}'", type.ToString(), name);
                    continue;
                }
                checked_types.Add(type);
                // check accessibility of type & constraint
                if (!ResolvedTypeParameter.Owner.IsAccessibleAs(type))
                {
                    rc.Report.Error(177, Location,
                                    "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'",
                                    type.ToString(), ResolvedTypeParameter.Owner.ToString());
                }


                if (type is TypeParameterSpec)
                {
                    TypeParameterSpec t = (type as TypeParameterSpec);
                    if (t.HasValueTypeConstraint)
                    {
                        rc.Report.Error(178, Location,
                                        "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
                                        t.Name, name);
                    }

                    // check for circular
                    CheckCircular(t, t, rc, true);


                    //
                    // Checks whether there are no conflicts between type parameter constraints
                    //
                    // class Foo<T, U>
                    //      where T : A
                    //      where U : B, T
                    //
                    // A and B are not convertible and only 1 class constraint is allowed
                    //TODO: Add Conversion check


                    // check for class type and (class or struct constraint)
                    if ((t.HasValueTypeConstraint && ResolvedTypeParameter.HasReferenceTypeConstraint) ||
                        (t.HasReferenceTypeConstraint && ResolvedTypeParameter.HasValueTypeConstraint))
                    {
                        rc.Report.Error(179, Location,
                                        "`{0}' and `{1}' : cannot specify both `class' and `struct' constraint",
                                        t.Name, Name);
                    }
                }
                else
                {
                    // check static or sealed
                    if ((type as IEntity).IsSealed)
                    {
                        rc.Report.Error(180, Location,
                                        "`{0}' A constraint must be an interface,  a type parameter or a non sealed/static class",
                                        type.ToString());
                    }
                }

                // primitive types check
                if (type.IsBuiltinType())
                {
                    rc.Report.Error(182, Location,
                                    "The type `{0}' cannot not be used as a base type for type parameter `{1}' in type or method `{2}'. ",
                                    type.ToString(), name, ResolvedTypeParameter.Owner.ToString());
                }
            }


            // constructor constraint
            if (ResolvedTypeParameter.HasDefaultConstructorConstraint && !ResolvedTypeParameter.EffectiveBaseClass.GetConstructors(x => x.Parameters.Count == 0).Any())
            {
                rc.Report.Error(181, Location,
                                "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'",
                                ResolvedTypeParameter.EffectiveBaseClass.ToString(), name, ResolvedTypeParameter.Owner.ToString());
            }


            return(true);
        }