public CodeGenerationTypeParameterSymbol(
     INamedTypeSymbol containingType,
     ImmutableArray <AttributeData> attributes,
     VarianceKind varianceKind,
     string name,
     NullableAnnotation nullableAnnotation,
     ImmutableArray <ITypeSymbol> constraintTypes,
     bool hasConstructorConstraint,
     bool hasReferenceConstraint,
     bool hasValueConstraint,
     bool hasUnmanagedConstraint,
     bool hasNotNullConstraint,
     int ordinal
     )
     : base(
         containingType?.ContainingAssembly,
         containingType,
         attributes,
         Accessibility.NotApplicable,
         default,
         name,
         SpecialType.None,
         nullableAnnotation
         )
 {
     this.Variance                   = varianceKind;
     this.ConstraintTypes            = constraintTypes;
     this.Ordinal                    = ordinal;
     this.HasConstructorConstraint   = hasConstructorConstraint;
     this.HasReferenceTypeConstraint = hasReferenceConstraint;
     this.HasValueTypeConstraint     = hasValueConstraint;
     this.HasUnmanagedTypeConstraint = hasUnmanagedConstraint;
     this.HasNotNullConstraint       = hasNotNullConstraint;
 }
Пример #2
0
        internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind variance)
        {
            Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
            TypeWithAnnotations elementType = ElementTypeWithAnnotations.MergeNullability(((ArrayTypeSymbol)other).ElementTypeWithAnnotations, variance);

            return(WithElementType(elementType));
        }
Пример #3
0
        internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind variance, out bool hadNullabilityMismatch)
        {
            Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
            TypeSymbolWithAnnotations pointedAtType = PointedAtType.MergeNullability(((PointerTypeSymbol)other).PointedAtType, VarianceKind.None, out hadNullabilityMismatch);

            return(WithPointedAtType(pointedAtType));
        }
Пример #4
0
        private static bool CanTypeParameterBeVariant(
            ITypeParameterSymbol parameter,
            VarianceKind variance,
            ITypeSymbol type,
            bool requireOutputSafety,
            bool requireInputSafety,
            ISymbol context)
        {
            switch (type.Kind)
            {
            case SymbolKind.TypeParameter:
                var typeParam = (ITypeParameterSymbol)type;
                if (!typeParam.Equals(parameter))
                {
                    return(true);
                }

                return(!((requireInputSafety && requireOutputSafety && variance != VarianceKind.None) ||
                         (requireOutputSafety && variance == VarianceKind.In) ||
                         (requireInputSafety && variance == VarianceKind.Out)));

            case SymbolKind.ArrayType:
                return(CanTypeParameterBeVariant(parameter, variance, ((IArrayTypeSymbol)type).ElementType, requireOutputSafety, requireInputSafety, context));

            case SymbolKind.ErrorType:
            case SymbolKind.NamedType:
                return(CanTypeParameterBeVariant(parameter, variance, (INamedTypeSymbol)type, requireOutputSafety, requireInputSafety, context));

            default:
                return(true);
            }
        }
Пример #5
0
        internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
        {
            Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
            TypeWithAnnotations pointedAtType = PointedAtTypeWithAnnotations.MergeEquivalentTypes(((PointerTypeSymbol)other).PointedAtTypeWithAnnotations, VarianceKind.None);

            return(WithPointedAtType(pointedAtType));
        }
 /// <summary>
 /// Creates a type parameter symbol that can be used to describe a type parameter declaration.
 /// </summary>
 public static ITypeParameterSymbol CreateTypeParameter(
     ImmutableArray <AttributeData> attributes,
     VarianceKind varianceKind, string name,
     ImmutableArray <ITypeSymbol> constraintTypes,
     bool hasConstructorConstraint = false,
     bool hasReferenceConstraint   = false,
     bool hasValueConstraint       = false, int ordinal = 0)
 {
     return(new CodeGenerationTypeParameterSymbol(null, attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, ordinal));
 }
Пример #7
0
 internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
 {
     Debug.Assert(
         this.Equals(
             other,
             TypeCompareKind.IgnoreDynamicAndTupleNames
             | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes
             )
         );
     return(this);
 }
Пример #8
0
        internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
        {
            Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));

            var otherType    = (FunctionTypeSymbol)other;
            var delegateType = (NamedTypeSymbol)_delegateType.MergeEquivalentTypes(otherType._delegateType, variance);

            return((object)_delegateType == delegateType ?
                   this :
                   otherType.WithDelegateType(delegateType));
        }
Пример #9
0
 public SourceTypeParameterSymbol(
     SourceNamedTypeSymbol owner,
     string name,
     int ordinal,
     VarianceKind varianceKind,
     ImmutableArray <Location> locations,
     ImmutableArray <SyntaxReference> syntaxRefs
     ) : base(name, ordinal, locations, syntaxRefs)
 {
     _owner        = owner;
     _varianceKind = varianceKind;
 }
        internal override TypeSymbol MergeEquivalentTypes(TypeSymbol other, VarianceKind variance)
        {
            Debug.Assert(this.Equals(other, TypeCompareKind.AllIgnoreOptions));
            var mergedSignature = Signature.MergeEquivalentTypes(((FunctionPointerTypeSymbol)other).Signature, variance);

            if ((object)mergedSignature != Signature)
            {
                return(new FunctionPointerTypeSymbol(mergedSignature));
            }

            return(this);
        }
        private static bool CheckTypeParameter(ITypeParameterSymbol typeParameter, VarianceKind variance,
                                               INamedTypeSymbol interfaceType)
        {
            if (typeParameter.Variance != VarianceKind.None)
            {
                return(false);
            }

            foreach (INamedTypeSymbol baseInterface in interfaceType.AllInterfaces)
            {
                var canBeVariant = CanTypeParameterBeVariant(
                    typeParameter, variance,
                    baseInterface,
                    true,
                    false,
                    baseInterface);

                if (!canBeVariant)
                {
                    return(false);
                }
            }

            foreach (ISymbol member in interfaceType.GetMembers())
            {
                bool canBeVariant;
                switch (member.Kind)
                {
                case SymbolKind.Method:
                    canBeVariant = CheckTypeParameterInMethod(typeParameter, variance, (IMethodSymbol)member);
                    if (!canBeVariant)
                    {
                        return(false);
                    }
                    break;

                case SymbolKind.Event:
                    canBeVariant = CheckTypeParameterInEvent(typeParameter, variance, (IEventSymbol)member);
                    if (!canBeVariant)
                    {
                        return(false);
                    }
                    break;

                default:
                    break;
                }
            }

            return(true);
        }
Пример #12
0
        public static RefKindInfo ConvertToStructure(this VarianceKind variance)
        {
            switch (variance)
            {
            case VarianceKind.Out:
                return(RefKindInfo.Out);

            case VarianceKind.In:
                return(RefKindInfo.In);

            default:
                return(RefKindInfo.None);
            }
        }
 public CodeGenerationTypeParameterSymbol(
     INamedTypeSymbol containingType,
     IList <AttributeData> attributes,
     VarianceKind varianceKind,
     string name,
     ImmutableArray <ITypeSymbol> constraintTypes,
     bool hasConstructorConstraint,
     bool hasReferenceConstraint,
     bool hasValueConstraint,
     int ordinal)
     : base(containingType, attributes, Accessibility.NotApplicable, default(DeclarationModifiers), name, SpecialType.None)
 {
     this.Variance                   = varianceKind;
     this.ConstraintTypes            = constraintTypes;
     this.Ordinal                    = ordinal;
     this.HasConstructorConstraint   = hasConstructorConstraint;
     this.HasReferenceTypeConstraint = hasReferenceConstraint;
     this.HasValueTypeConstraint     = hasValueConstraint;
 }
        private static void ReportIssue(ITypeParameterSymbol typeParameter, VarianceKind variance, SyntaxNodeAnalysisContext context)
        {
            if (!typeParameter.DeclaringSyntaxReferences.Any())
            {
                return;
            }

            var location = typeParameter.DeclaringSyntaxReferences.First().GetSyntax().GetLocation();

            if (variance == VarianceKind.In)
            {
                context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, location, "in", typeParameter.Name, "contravariant"));
                return;
            }

            if (variance == VarianceKind.Out)
            {
                context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, location, "out", typeParameter.Name, "covariant"));
            }
        }
        private static bool CheckTypeParameter(ITypeParameterSymbol typeParameter, VarianceKind variance,
                                               ITypeSymbol returnType, ImmutableArray <IParameterSymbol> parameters)
        {
            var canBe = CheckTypeParameterContraintsInSymbol(typeParameter, variance);

            if (!canBe)
            {
                return(false);
            }

            canBe = CanTypeParameterBeVariant(typeParameter, variance, returnType,
                                              true, false);

            if (!canBe)
            {
                return(false);
            }

            canBe = CheckTypeParameterInParameters(typeParameter, variance, parameters);
            return(canBe);
        }
		public CodeGenerationTypeParameterSymbol(
			INamedTypeSymbol containingType,
			IList<AttributeData> attributes,
			VarianceKind varianceKind,
			string name,
			ImmutableArray<ITypeSymbol> constraintTypes,
			bool hasConstructorConstraint,
			bool hasReferenceConstraint,
			bool hasValueConstraint,
			int ordinal)
		{
			instance = Activator.CreateInstance (typeInfo, new object[] {
				containingType,
				attributes,
				varianceKind,
				name,
				constraintTypes,
				hasConstructorConstraint,
				hasReferenceConstraint,
				hasValueConstraint,
				ordinal
			});
		}
 public CodeGenerationTypeParameterSymbol(
     INamedTypeSymbol containingType,
     IList <AttributeData> attributes,
     VarianceKind varianceKind,
     string name,
     ImmutableArray <ITypeSymbol> constraintTypes,
     bool hasConstructorConstraint,
     bool hasReferenceConstraint,
     bool hasValueConstraint,
     int ordinal)
 {
     instance = Activator.CreateInstance(typeInfo, new object[] {
         containingType,
         attributes,
         varianceKind,
         name,
         constraintTypes,
         hasConstructorConstraint,
         hasReferenceConstraint,
         hasValueConstraint,
         ordinal
     });
 }
 /// <summary>
 /// Merges nullability.
 /// </summary>
 public static NullableAnnotation MergeNullableAnnotation(this NullableAnnotation a, NullableAnnotation b, VarianceKind variance)
 {
     return(variance switch
     {
         VarianceKind.In => a.Meet(b),
         VarianceKind.Out => a.Join(b),
         VarianceKind.None => a.EnsureCompatible(b),
         _ => throw ExceptionUtilities.UnexpectedValue(variance)
     });
        private static bool CanTypeParameterBeVariant(
            ITypeParameterSymbol parameter,
            VarianceKind variance,
            INamedTypeSymbol namedType,
            bool requireOutputSafety,
            bool requireInputSafety,
            ISymbol context)
        {

            switch (namedType.TypeKind)
            {
                case TypeKind.Class:
                case TypeKind.Struct:
                case TypeKind.Enum:
                case TypeKind.Interface:
                case TypeKind.Delegate:
                case TypeKind.Error:
                    break;
                default:
                    return true;
            }

            var currentNamedType = namedType;
            while (currentNamedType != null)
            {
                for (int i = 0; i < currentNamedType.Arity; i++)
                {
                    var typeParam = currentNamedType.TypeParameters[i];
                    var typeArg = currentNamedType.TypeArguments[i];

                    if (!typeArg.Equals(parameter))
                    {
                        return false;
                    }

                    var requireOut = false;
                    var requireIn = false;

                    switch (typeParam.Variance)
                    {
                        case VarianceKind.Out:
                            requireOut = requireOutputSafety;
                            requireIn = requireInputSafety;
                            break;
                        case VarianceKind.In:
                            requireOut = requireInputSafety;
                            requireIn = requireOutputSafety;
                            break;
                        case VarianceKind.None:
                            requireIn = true;
                            requireOut = true;
                            break;
                        default:
                            throw new NotSupportedException();
                    }

                    if (!CanTypeParameterBeVariant(parameter, variance, typeArg, requireOut, requireIn, context))
                    {
                        return false;
                    }
                }

                currentNamedType = currentNamedType.ContainingType;
            }

            return true;
        }
        private static bool CanTypeParameterBeVariant(
            ITypeParameterSymbol parameter,
            VarianceKind variance,
            ITypeSymbol type,
            bool requireOutputSafety,
            bool requireInputSafety,
            ISymbol context)
        {
            switch (type.Kind)
            {
                case SymbolKind.TypeParameter:
                    var typeParam = (ITypeParameterSymbol)type;
                    if (!typeParam.Equals(parameter))
                    {
                        return true;
                    }

                    return !((requireInputSafety && requireOutputSafety && variance != VarianceKind.None) ||
                        (requireOutputSafety && variance == VarianceKind.In) ||
                        (requireInputSafety && variance == VarianceKind.Out));
                case SymbolKind.ArrayType:
                    return CanTypeParameterBeVariant(parameter, variance, ((IArrayTypeSymbol)type).ElementType, requireOutputSafety, requireInputSafety, context);
                case SymbolKind.ErrorType:
                case SymbolKind.NamedType:
                    return CanTypeParameterBeVariant(parameter, variance, (INamedTypeSymbol)type, requireOutputSafety, requireInputSafety, context);
                default:
                    return true;
            }
        }
        private static bool CheckTypeParameterContraintsInSymbol(ITypeParameterSymbol typeParameter, VarianceKind variance,
            ISymbol context)
        {
            foreach (ITypeSymbol constraintType in typeParameter.ConstraintTypes)
            {
                var canBe = CanTypeParameterBeVariant(
                    typeParameter,
                    variance,
                    constraintType,
                    false,
                    true,
                    context);

                if (!canBe)
                {
                    return false;
                }
            }
            return true;
        }
Пример #22
0
 internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind variance, out bool hadNullabilityMismatch)
 {
     throw new NotSupportedException();
 }
 public SourceTypeParameterSymbol(SourceNamedTypeSymbol owner, string name, int ordinal, VarianceKind varianceKind, ImmutableArray<Location> locations, ImmutableArray<SyntaxReference> syntaxRefs)
     : base(name, ordinal, locations, syntaxRefs)
 {
     this.owner = owner;
     this.varianceKind = varianceKind;
 }
Пример #24
0
 /// <summary>
 /// Creates a type parameter symbol that can be used to describe a type parameter declaration.
 /// </summary>
 public static ITypeParameterSymbol CreateTypeParameter(IList<AttributeData> attributes, VarianceKind varianceKind, string name, ImmutableArray<ITypeSymbol> constraintTypes, bool hasConstructorConstraint = false, bool hasReferenceConstraint = false, bool hasValueConstraint = false, int ordinal = 0)
 {
     return new CodeGenerationTypeParameterSymbol(null, attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, ordinal);
 }
 private static bool CheckTypeParameterInEvent(ITypeParameterSymbol typeParameter, VarianceKind variance,
                                               IEventSymbol @event)
 {
     return(CanTypeParameterBeVariant(
                typeParameter, variance,
                @event.Type,
                false,
                true));
 }
		public static ITypeParameterSymbol CreateTypeParameter(IList<AttributeData> attributes, VarianceKind varianceKind, string name, ImmutableArray<ITypeSymbol> constraintTypes, bool hasConstructorConstraint = false, bool hasReferenceConstraint = false, bool hasValueConstraint = false, int ordinal = 0)
		{
			try {
				return (ITypeParameterSymbol)createTypeParameterMethod.Invoke (null, new object[] { attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, ordinal});
			} catch (TargetInvocationException ex) {
				ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
				return null;
			}
		}
Пример #27
0
		void AppendVariance (StringBuilder sb, VarianceKind variance)
		{
			if (variance == VarianceKind.In) {
				sb.Append (Highlight ("in ", colorStyle.KeywordParameter));
			} else if (variance == VarianceKind.Out) {
				sb.Append (Highlight ("out ", colorStyle.KeywordParameter));
			}
		}
 public static ITypeParameterSymbol CreateTypeParameter(IList <AttributeData> attributes, VarianceKind varianceKind, string name, ImmutableArray <ITypeSymbol> constraintTypes, bool hasConstructorConstraint = false, bool hasReferenceConstraint = false, bool hasValueConstraint = false, int ordinal = 0)
 {
     try {
         return((ITypeParameterSymbol)createTypeParameterMethod.Invoke(null, new object[] { attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, ordinal }));
     } catch (TargetInvocationException ex) {
         ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
         return(null);
     }
 }
Пример #29
0
 internal override TypeSymbol MergeNullability(TypeSymbol other, VarianceKind variance, out bool hadNullabilityMismatch)
 {
     Debug.Assert(this.Equals(other, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes));
     hadNullabilityMismatch = false;
     return(this);
 }
Пример #30
0
 /// <summary>
 /// Merges nullability.
 /// </summary>
 public static NullableAnnotation MergeNullableAnnotation(this NullableAnnotation a, NullableAnnotation b, VarianceKind variance) =>
 variance switch
 {
Пример #31
0
 public SourceTypeParameterSymbol(SourceNamedTypeSymbol owner, string name, int ordinal, VarianceKind varianceKind, NullabilityPreservationKind preservationKind, ImmutableArray<Location> locations, ImmutableArray<SyntaxReference> syntaxRefs)
     : base(name, ordinal, preservationKind, locations, syntaxRefs)
 {
     _owner = owner;
     _varianceKind = varianceKind;
 }
        private static bool CheckTypeParameterContraintsInSymbol(ITypeParameterSymbol typeParameter, VarianceKind variance)
        {
            foreach (var constraintType in typeParameter.ConstraintTypes)
            {
                var canBe = CanTypeParameterBeVariant(
                    typeParameter,
                    variance,
                    constraintType,
                    false,
                    true);

                if (!canBe)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #33
0
            internal void CreateTypeEdge(TypeWithNode source, TypeWithNode target, TypeSubstitution?targetSubstitution, VarianceKind variance, EdgeLabel label)
            {
#if DEBUG
                if (source.FlowLabel != null)
                {
                    label = new EdgeLabel($"{label}\n{source.FlowLabel}");
                }
#endif
                if (targetSubstitution != null && target.Type is ITypeParameterSymbol tp)
                {
                    // If calling `void SomeCall<T>(T x);` as `SomeCall<string>(null)`, then
                    // we need either `x: T?` or `T = string?`:
                    //   (source is nullable) implies (target is nullable || substitutedTarget is nullable)
                    // We can't represent such a choice in the graph, so we always substitute and prefer `string?`.

                    // However, if the variance causes us to create edges the other way around
                    // (e.g. an override-edge for `override void SomeCall(string x)`), we have:
                    //   (target is nullable || substitutedTarget is nullable) implies (source is nullable)
                    // This can be represented by using two edges.
                    if (variance == VarianceKind.In || variance == VarianceKind.None)
                    {
                        CreateEdge(target.Node, source.Node, label);
                    }

                    // Perform the substitution:
                    target             = targetSubstitution.Value[tp.TypeParameterKind, tp.FullOrdinal()];
                    targetSubstitution = null;
                }
                Debug.Assert(source.Type?.TypeKind == target.Type?.TypeKind, "Type kinds do not match");
                if (source.Type is INamedTypeSymbol namedType)
                {
                    if (!SymbolEqualityComparer.Default.Equals(source.Type?.OriginalDefinition, target.Type?.OriginalDefinition))
                    {
                        throw new InvalidOperationException($"Types don't match: {source.Type} vs. {target.Type}");
                    }
                    var namedTypeTypeParameters = namedType.FullTypeParameters().ToList();
                    Debug.Assert(source.TypeArguments.Count == namedTypeTypeParameters.Count);
                    Debug.Assert(target.TypeArguments.Count == namedTypeTypeParameters.Count);
                    for (int i = 0; i < namedTypeTypeParameters.Count; i++)
                    {
                        var sourceArg        = source.TypeArguments[i];
                        var targetArg        = target.TypeArguments[i];
                        var combinedVariance = (variance, namedTypeTypeParameters[i].Variance).Combine();
        private static bool CheckTypeParameter(ITypeParameterSymbol typeParameter, VarianceKind variance,
            INamedTypeSymbol interfaceType)
        {
            if (typeParameter.Variance != VarianceKind.None)
            {
                return false;
            }

            foreach (INamedTypeSymbol baseInterface in interfaceType.AllInterfaces)
            {
                var canBeVariant = CanTypeParameterBeVariant(
                    typeParameter, variance,
                    baseInterface,
                    true,
                    false,
                    baseInterface);

                if (!canBeVariant)
                {
                    return false;
                }
            }

            foreach (ISymbol member in interfaceType.GetMembers())
            {
                var canBeVariant = false;
                switch (member.Kind)
                {
                    case SymbolKind.Method:
                        canBeVariant = CheckTypeParameterInMethod(typeParameter, variance, (IMethodSymbol)member);
                        if (!canBeVariant)
                        {
                            return false;
                        }
                        break;
                    case SymbolKind.Event:
                        canBeVariant = CheckTypeParameterInEvent(typeParameter, variance, (IEventSymbol)member);
                        if (!canBeVariant)
                        {
                            return false;
                        }
                        break;
                    default:
                        break;
                }
            }

            return true;
        }
        private static void ReportIssue(ITypeParameterSymbol typeParameter, VarianceKind variance, SyntaxNodeAnalysisContext context)
        {
            if (!typeParameter.DeclaringSyntaxReferences.Any())
            {
                return;
            }

            var location = typeParameter.DeclaringSyntaxReferences.First().GetSyntax().GetLocation();

            if (variance == VarianceKind.In)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, location, "in", typeParameter.Name, "contravariant"));
                return;
            }

            if (variance == VarianceKind.Out)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, location, "out", typeParameter.Name, "covariant"));
                return;
            }
        }
        private static bool CheckTypeParameterInMethod(ITypeParameterSymbol typeParameter, VarianceKind variance,
                                                       IMethodSymbol method)
        {
            var canBe = CheckTypeParameterContraintsInSymbol(typeParameter, variance);

            if (!canBe)
            {
                return(false);
            }


            canBe = CanTypeParameterBeVariant(
                typeParameter, variance,
                method.ReturnType,
                true,
                false);

            if (!canBe)
            {
                return(false);
            }

            return(CheckTypeParameterInParameters(typeParameter, variance, method.Parameters));
        }
        private static bool CheckTypeParameterInMethod(ITypeParameterSymbol typeParameter, VarianceKind variance,
            IMethodSymbol method)
        {
            var canBe = CheckTypeParameterContraintsInSymbol(typeParameter, variance, method);
            if (!canBe)
            {
                return false;
            }

            canBe = CanTypeParameterBeVariant(
                typeParameter, variance,
                method.ReturnType,
                true,
                false,
                method);

            if (!canBe)
            {
                return false;
            }

            return CheckTypeParameterInParameters(typeParameter, variance, method.Parameters, method);
        }
        private static bool CheckTypeParameterInParameters(ITypeParameterSymbol typeParameter, VarianceKind variance,
                                                           ImmutableArray <IParameterSymbol> parameters)
        {
            foreach (var param in parameters)
            {
                var canBe = CanTypeParameterBeVariant(
                    typeParameter, variance,
                    param.Type,
                    param.RefKind != RefKind.None,
                    true);

                if (!canBe)
                {
                    return(false);
                }
            }
            return(true);
        }
 private static bool CheckTypeParameterInEvent(ITypeParameterSymbol typeParameter, VarianceKind variance,
     IEventSymbol @event)
 {
     return CanTypeParameterBeVariant(
         typeParameter, variance,
         @event.Type,
         false,
         true,
         @event);
 }
        private static bool CanTypeParameterBeVariant(
            ITypeParameterSymbol parameter,
            VarianceKind variance,
            INamedTypeSymbol namedType,
            bool requireOutputSafety,
            bool requireInputSafety)
        {
            switch (namedType.TypeKind)
            {
            case TypeKind.Class:
            case TypeKind.Struct:
            case TypeKind.Enum:
            case TypeKind.Interface:
            case TypeKind.Delegate:
            case TypeKind.Error:
                break;

            default:
                return(true);
            }

            if (namedType.IsTupleType())
            {
                return(false);
            }

            var currentNamedType = namedType;

            while (currentNamedType != null)
            {
                for (var i = 0; i < currentNamedType.Arity; i++)
                {
                    var typeParam = currentNamedType.TypeParameters[i];
                    var typeArg   = currentNamedType.TypeArguments[i];

                    if (!typeArg.Equals(parameter))
                    {
                        return(false);
                    }

                    bool requireOut;
                    bool requireIn;

                    switch (typeParam.Variance)
                    {
                    case VarianceKind.Out:
                        requireOut = requireOutputSafety;
                        requireIn  = requireInputSafety;
                        break;

                    case VarianceKind.In:
                        requireOut = requireInputSafety;
                        requireIn  = requireOutputSafety;
                        break;

                    case VarianceKind.None:
                        requireIn  = true;
                        requireOut = true;
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    if (!CanTypeParameterBeVariant(parameter, variance, typeArg, requireOut, requireIn))
                    {
                        return(false);
                    }
                }

                currentNamedType = currentNamedType.ContainingType;
            }

            return(true);
        }
        private static bool CheckTypeParameterInParameters(ITypeParameterSymbol typeParameter, VarianceKind variance,
            ImmutableArray<IParameterSymbol> parameters, ISymbol context)
        {
            foreach (IParameterSymbol param in parameters)
            {
                var canBe = CanTypeParameterBeVariant(
                    typeParameter, variance,
                    param.Type,
                    param.RefKind != RefKind.None,
                    true,
                    context);

                if (!canBe)
                {
                    return false;
                }
            }
            return true;
        }
        private static bool CheckTypeParameter(ITypeParameterSymbol typeParameter, VarianceKind variance,
            INamedTypeSymbol delegateType, ITypeSymbol returnType, ImmutableArray<IParameterSymbol> parameters)
        {
            var canBe = CheckTypeParameterContraintsInSymbol(typeParameter, variance, delegateType);
            if (!canBe)
            {
                return false;
            }

            canBe = CanTypeParameterBeVariant(typeParameter, variance, returnType,
                true, false, delegateType);

            if (!canBe)
            {
                return false;
            }

            canBe = CheckTypeParameterInParameters(typeParameter, variance, parameters, delegateType);
            return canBe;
        }
            internal NullabilityEdge?CreateTypeEdge(TypeWithNode source, TypeWithNode target, TypeSubstitution?targetSubstitution, VarianceKind variance)
            {
                if (targetSubstitution != null && target.Type is ITypeParameterSymbol tp)
                {
                    // Perform the substitution:
                    target             = targetSubstitution.Value[tp.TypeParameterKind, tp.FullOrdinal()];
                    targetSubstitution = null;
                }
                Debug.Assert(source.Type?.TypeKind == target.Type?.TypeKind);
                if (source.Type is INamedTypeSymbol namedType)
                {
                    if (!SymbolEqualityComparer.Default.Equals(source.Type?.OriginalDefinition, target.Type?.OriginalDefinition))
                    {
                        throw new InvalidOperationException($"Types don't match: {source.Type} vs. {target.Type}");
                    }
                    var namedTypeTypeParameters = namedType.FullTypeParameters().ToList();
                    Debug.Assert(source.TypeArguments.Count == namedTypeTypeParameters.Count);
                    Debug.Assert(target.TypeArguments.Count == namedTypeTypeParameters.Count);
                    for (int i = 0; i < namedTypeTypeParameters.Count; i++)
                    {
                        tp = namedTypeTypeParameters[i];
                        var sourceArg        = source.TypeArguments[i];
                        var targetArg        = target.TypeArguments[i];
                        var combinedVariance = (variance, tp.Variance).Combine();
                        CreateTypeEdge(sourceArg, targetArg, targetSubstitution, combinedVariance);
                    }
                }
                else if (source.Type is IArrayTypeSymbol || source.Type is IPointerTypeSymbol)
                {
                    CreateTypeEdge(source.TypeArguments.Single(), target.TypeArguments.Single(), targetSubstitution, variance);
                }
                NullabilityEdge?edge = null;

                if (variance == VarianceKind.In || variance == VarianceKind.None)
                {
                    edge = CreateEdge(target.Node, source.Node);
                }
                if (variance == VarianceKind.Out || variance == VarianceKind.None)
                {
                    edge = CreateEdge(source.Node, target.Node);
                }
                return(edge);
            }