/// <summary>
        /// Provided two composite types, determine if they "overlap". Two composite
        /// types overlap when the Sets of possible concrete types for each intersect.
        ///
        /// This is often used to determine if a fragment of a given type could possibly
        /// be visited in a context of another type.
        ///
        /// This function is commutative.
        /// </summary>
        public static bool DoTypesOverlap(this ISchema schema, IGraphType typeA, IGraphType typeB)
        {
            if (typeA.Equals(typeB))
            {
                return(true);
            }

            var a = typeA as IAbstractGraphType;
            var b = typeB as IAbstractGraphType;

            if (a != null)
            {
                if (b != null)
                {
                    return(a.PossibleTypes.Any(type => b.IsPossibleType(type)));
                }

                return(a.IsPossibleType(typeB));
            }

            if (b != null)
            {
                return(b.IsPossibleType(typeA));
            }

            return(false);
        }
        private bool DoTypesConflict(IGraphType type1, IGraphType type2)
        {
            if (type1 is ListGraphType type1List)
            {
                return(type2 is ListGraphType type2List?DoTypesConflict(type1List.ResolvedType, type2List.ResolvedType) : true);
            }

            if (type2 is ListGraphType)
            {
                return(true);
            }

            if (type1 is NonNullGraphType type1NonNull)
            {
                return(type2 is NonNullGraphType type2NonNull?DoTypesConflict(type1NonNull.ResolvedType, type2NonNull.ResolvedType) : true);
            }

            if (type2 is NonNullGraphType)
            {
                return(true);
            }

            if (type1.IsLeafType() || type2.IsLeafType())
            {
                return(!type1.Equals(type2));
            }

            return(false);
        }
        /// <summary>
        /// Provided a type and a super type, return true if the first type is either
        /// equal or a subset of the second super type (covariant).
        /// </summary>
        public static bool IsSubtypeOf(this IGraphType maybeSubType, IGraphType superType, ISchema schema)
        {
            if (maybeSubType.Equals(superType))
            {
                return(true);
            }

            // If superType is non-null, maybeSubType must also be nullable.
            if (superType is NonNullGraphType)
            {
                if (maybeSubType is NonNullGraphType)
                {
                    var sub = (NonNullGraphType)maybeSubType;
                    var sup = (NonNullGraphType)superType;
                    return(IsSubtypeOf(sub.ResolvedType, sup.ResolvedType, schema));
                }

                return(false);
            }
            else if (maybeSubType is NonNullGraphType)
            {
                var sub = (NonNullGraphType)maybeSubType;
                return(IsSubtypeOf(sub.ResolvedType, superType, schema));
            }

            // If superType type is a list, maybeSubType type must also be a list.
            if (superType is ListGraphType)
            {
                if (maybeSubType is ListGraphType)
                {
                    var sub = (ListGraphType)maybeSubType;
                    var sup = (ListGraphType)superType;
                    return(IsSubtypeOf(sub.ResolvedType, sup.ResolvedType, schema));
                }

                return(false);
            }
            else if (maybeSubType is ListGraphType)
            {
                // If superType is not a list, maybeSubType must also be not a list.
                return(false);
            }

            // If superType type is an abstract type, maybeSubType type may be a currently
            // possible object type.
            if (superType is IAbstractGraphType &&
                maybeSubType is IObjectGraphType)
            {
                return(((IAbstractGraphType)superType).IsPossibleType(maybeSubType));
            }

            return(false);
        }