private static bool VerifyGenericParamConstraint(InstantiationContext genericParamContext, GenericParameterDesc genericParam,
                                                         InstantiationContext instantiationParamContext, TypeDesc instantiationParam)
        {
            GenericConstraints constraints = genericParam.Constraints;

            // Check class constraint
            if ((constraints & GenericConstraints.ReferenceTypeConstraint) != 0)
            {
                if (!instantiationParam.IsGCPointer &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.ReferenceTypeConstraint))
                {
                    return(false);
                }
            }

            // Check default constructor constraint
            if ((constraints & GenericConstraints.DefaultConstructorConstraint) != 0)
            {
                if (!instantiationParam.HasExplicitOrImplicitDefaultConstructor() &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.DefaultConstructorConstraint))
                {
                    return(false);
                }
            }

            // Check struct constraint
            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                if ((!instantiationParam.IsValueType || instantiationParam.IsNullable) &&
                    !CheckGenericSpecialConstraint(instantiationParam, GenericConstraints.NotNullableValueTypeConstraint))
                {
                    return(false);
                }
            }

            var instantiatedConstraints = new ArrayBuilder <TypeDesc>();

            GetInstantiatedConstraintsRecursive(instantiationParamContext, instantiationParam, ref instantiatedConstraints);

            foreach (var constraintType in genericParam.TypeConstraints)
            {
                var instantiatedType = constraintType.InstantiateSignature(genericParamContext.TypeInstantiation, genericParamContext.MethodInstantiation);
                if (CanCastConstraint(ref instantiatedConstraints, instantiatedType))
                {
                    continue;
                }

                if (!instantiationParam.CanCastTo(instantiatedType))
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #2
0
        public override AstNode?VisitTypeParamConstraintList(TypeParamConstraintListContext context)
        {
            foreach (var constraintContext in context.typeParamConstraint())
            {
                if (Visit(constraintContext) is GenericConstraint constraint)
                {
                    _currentMessage !.GenericConstraints.Add(constraint);
                }
            }

            return(null);
        }
コード例 #3
0
        private static bool VerifyGenericParamConstraint(Instantiation typeInstantiation, Instantiation methodInstantiation, GenericParameterDesc genericParam, TypeDesc instantiationParam)
        {
            GenericConstraints constraints = genericParam.Constraints;

            // Check class constraint
            if ((constraints & GenericConstraints.ReferenceTypeConstraint) != 0)
            {
                if (!instantiationParam.IsGCPointer)
                {
                    return(false);
                }
            }

            // Check default constructor constraint
            if ((constraints & GenericConstraints.DefaultConstructorConstraint) != 0)
            {
                if (!instantiationParam.HasExplicitOrImplicitDefaultConstructor())
                {
                    return(false);
                }
            }

            // Check struct constraint
            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                if (!instantiationParam.IsValueType)
                {
                    return(false);
                }

                if (instantiationParam.IsNullable)
                {
                    return(false);
                }
            }

            foreach (var constraintType in genericParam.TypeConstraints)
            {
                var instantiatedType = constraintType.InstantiateSignature(typeInstantiation, methodInstantiation);
                if (!instantiationParam.CanCastTo(instantiatedType))
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #4
0
        private static TypeDesc GetTypeThatMeetsConstraints(GenericParameterDesc genericParam)
        {
            TypeSystemContext context = genericParam.Context;

            // Universal canon is the best option if it's supported
            if (context.SupportsUniversalCanon)
            {
                return(context.UniversalCanonType);
            }

            // Try normal canon next
            if (!context.SupportsCanon)
            {
                return(null);
            }

            // Not nullable type is the only thing where reference canon doesn't make sense.
            GenericConstraints constraints = genericParam.Constraints;

            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                return(null);
            }

            foreach (var c in genericParam.TypeConstraints)
            {
                // Could be e.g. "where T : U"
                // We could try to dig into the U and solve it, but that just opens us up to
                // recursion and it's just not worth it.
                if (c.IsSignatureVariable)
                {
                    return(null);
                }

                if (!c.IsGCPointer)
                {
                    return(null);
                }
            }

            return(genericParam.Context.CanonType);
        }
コード例 #5
0
        private static TypeDesc GetTypeThatMeetsConstraints(GenericParameterDesc genericParam, bool allowCanon)
        {
            TypeSystemContext context = genericParam.Context;

            // Universal canon is the best option if it's supported
            if (allowCanon && context.SupportsUniversalCanon)
            {
                return(context.UniversalCanonType);
            }

            // Not nullable type is the only thing where we can't substitute reference types
            GenericConstraints constraints = genericParam.Constraints;

            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                return(null);
            }

            // If canon is allowed, we can use that
            if (allowCanon && context.SupportsCanon)
            {
                foreach (var c in genericParam.TypeConstraints)
                {
                    // Could be e.g. "where T : U"
                    // We could try to dig into the U and solve it, but that just opens us up to
                    // recursion and it's just not worth it.
                    if (c.IsSignatureVariable)
                    {
                        return(null);
                    }

                    if (!c.IsGCPointer)
                    {
                        return(null);
                    }
                }

                return(genericParam.Context.CanonType);
            }

            // If canon is not allowed, we're limited in our choices.
            TypeDesc constrainedType = null;

            foreach (var c in genericParam.TypeConstraints)
            {
                // Can't do multiple constraints
                if (constrainedType != null)
                {
                    return(null);
                }

                // Could be e.g. "where T : IFoo<U>" or "where T : U"
                if (c.ContainsSignatureVariables())
                {
                    return(null);
                }

                constrainedType = c;
            }

            return(constrainedType ?? genericParam.Context.GetWellKnownType(WellKnownType.Object));
        }
コード例 #6
0
        // Used to determine whether a type parameter used to instantiate another type parameter with a specific special
        // constraint satisfies that constraint.
        private static bool CheckGenericSpecialConstraint(TypeDesc type, GenericConstraints specialConstraint)
        {
            if (!type.IsGenericParameter)
            {
                return(false);
            }

            var genericType = (GenericParameterDesc)type;

            GenericConstraints constraints = genericType.Constraints;

            // Check if type has specialConstraint on its own
            if ((constraints & specialConstraint) != 0)
            {
                return(true);
            }

            // Value type always has default constructor
            if (specialConstraint == GenericConstraints.DefaultConstructorConstraint && (constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                return(true);
            }

            // The special constraints did not match, check if there is a primary type constraint,
            // that would always satisfy the special constraint
            foreach (var constraint in genericType.TypeConstraints)
            {
                if (constraint.IsGenericParameter || constraint.IsInterface)
                {
                    continue;
                }

                switch (specialConstraint)
                {
                case GenericConstraints.NotNullableValueTypeConstraint:
                    if (constraint.IsValueType && !constraint.IsNullable)
                    {
                        return(true);
                    }
                    break;

                case GenericConstraints.ReferenceTypeConstraint:
                    if (!constraint.IsValueType)
                    {
                        return(true);
                    }
                    break;

                case GenericConstraints.DefaultConstructorConstraint:
                    // As constraint is only ancestor, can only be sure whether type has public default constructor if it is a value type
                    if (constraint.IsValueType)
                    {
                        return(true);
                    }
                    break;

                default:
                    Debug.Assert(false);
                    break;
                }
            }

            // type did not satisfy special constraint in any way
            return(false);
        }
コード例 #7
0
ファイル: TypeExtensions.cs プロジェクト: CarnaViire/runtime
        private static TypeDesc GetTypeThatMeetsConstraints(GenericParameterDesc genericParam, bool allowCanon)
        {
            TypeSystemContext context = genericParam.Context;

            // Universal canon is the best option if it's supported
            if (allowCanon && context.SupportsUniversalCanon)
            {
                return(context.UniversalCanonType);
            }

            // Not nullable type is the only thing where we can't substitute reference types
            GenericConstraints constraints = genericParam.Constraints;

            if ((constraints & GenericConstraints.NotNullableValueTypeConstraint) != 0)
            {
                return(null);
            }

            // If canon is allowed, we can use that
            if (allowCanon && context.SupportsCanon)
            {
                foreach (var c in genericParam.TypeConstraints)
                {
                    // Could be e.g. "where T : U"
                    // We could try to dig into the U and solve it, but that just opens us up to
                    // recursion and it's just not worth it.
                    if (c.IsSignatureVariable)
                    {
                        return(null);
                    }

                    if (!c.IsGCPointer)
                    {
                        return(null);
                    }
                }

                return(genericParam.Context.CanonType);
            }

            // If canon is not allowed, we're limited in our choices.
            TypeDesc constrainedType = null;

            foreach (var c in genericParam.TypeConstraints)
            {
                // Can't do multiple constraints
                if (constrainedType != null)
                {
                    return(null);
                }

                // Could be e.g. "where T : IFoo<U>" or "where T : U"
                if (c.ContainsSignatureVariables())
                {
                    return(null);
                }

                // If there's unimplemented static abstract methods, this is not a suitable instantiation.
                // We shortcut to look for any static virtuals. It matches what Roslyn does for error CS8920.
                // Once TypeSystemConstraintsHelpers is updated to check constraints around static virtuals,
                // we could dispatch there instead.
                if (c.IsInterface)
                {
                    if (HasStaticVirtualMethods(c))
                    {
                        return(null);
                    }

                    foreach (DefType intface in c.RuntimeInterfaces)
                    {
                        if (HasStaticVirtualMethods(intface))
                        {
                            return(null);
                        }
                    }