コード例 #1
0
ファイル: EmbeddedTypeParameter.cs プロジェクト: belav/roslyn
 public EmbeddedTypeParameter(
     EmbeddedMethod containingMethod,
     TypeParameterSymbolAdapter underlyingTypeParameter
     ) : base(containingMethod, underlyingTypeParameter)
 {
     Debug.Assert(underlyingTypeParameter.AdaptedTypeParameterSymbol.IsDefinition);
 }
コード例 #2
0
        public RetargetingTypeParameterSymbol(RetargetingModuleSymbol retargetingModule, TypeParameterSymbol underlyingTypeParameter)
            : base(underlyingTypeParameter)
        {
            Debug.Assert((object)retargetingModule != null);
            Debug.Assert(!(underlyingTypeParameter is RetargetingTypeParameterSymbol));

            _retargetingModule = retargetingModule;
        }
コード例 #3
0
        public static bool DependsOn(this TypeParameterSymbol typeParameter1, TypeParameterSymbol typeParameter2)
        {
            Debug.Assert((object)typeParameter1 != null);
            Debug.Assert((object)typeParameter2 != null);

            Func<TypeParameterSymbol, IEnumerable<TypeParameterSymbol>> dependencies = x => x.ConstraintTypesNoUseSiteDiagnostics.OfType<TypeParameterSymbol>();
            return dependencies.TransitiveClosure(typeParameter1).Contains(typeParameter2);
        }
コード例 #4
0
 internal SubstitutedTypeParameterSymbol(Symbol newContainer, TypeMap map, TypeParameterSymbol substitutedFrom)
 {
     _container = newContainer;
     // it is important that we don't use the map here in the constructor, as the map is still being filled
     // in by TypeMap.WithAlphaRename.  Instead, we can use the map lazily when yielding the constraints.
     _map = map;
     _substitutedFrom = substitutedFrom;
 }
コード例 #5
0
        public RetargetingTypeParameterSymbol(RetargetingModuleSymbol retargetingModule, TypeParameterSymbol underlyingTypeParameter)
        {
            Debug.Assert((object)retargetingModule != null);
            Debug.Assert((object)underlyingTypeParameter != null);
            Debug.Assert(!(underlyingTypeParameter is RetargetingTypeParameterSymbol));

            this.retargetingModule = retargetingModule;
            this.underlyingTypeParameter = underlyingTypeParameter;
        }
コード例 #6
0
        protected sealed override TypeWithModifiers SubstituteTypeParameter(TypeParameterSymbol typeParameter)
        {
            // It might need to be substituted directly.
            TypeWithModifiers result;
            if (Mapping.TryGetValue(typeParameter, out result))
            {
                return result;
            }

            return new TypeWithModifiers(typeParameter);
        }
コード例 #7
0
        protected sealed override TypeSymbol SubstituteTypeParameter(TypeParameterSymbol typeParameter)
        {
            // It might need to be substituted directly.
            TypeSymbol result;
            if (Mapping.TryGetValue(typeParameter, out result))
            {
                return result;
            }

            return typeParameter;
        }
コード例 #8
0
 public EETypeParameterSymbol(
     Symbol container,
     TypeParameterSymbol sourceTypeParameter,
     int ordinal,
     Func<TypeMap> getTypeMap)
 {
     Debug.Assert((container.Kind == SymbolKind.NamedType) || (container.Kind == SymbolKind.Method));
     _container = container;
     _sourceTypeParameter = sourceTypeParameter;
     _ordinal = ordinal;
     _getTypeMap = getTypeMap;
 }
コード例 #9
0
        internal SubstitutedTypeParameterSymbol(Symbol newContainer, TypeMap map, TypeParameterSymbol substitutedFrom, int ordinal)
        {
            _container = newContainer;
            // it is important that we don't use the map here in the constructor, as the map is still being filled
            // in by TypeMap.WithAlphaRename.  Instead, we can use the map lazily when yielding the constraints.
            _map = map;
            _substitutedFrom = substitutedFrom;
            _ordinal = ordinal;
#if DEBUG_ALPHA
            _mySequence = _nextSequence++;
#endif
        }
コード例 #10
0
        protected sealed override TypeWithModifiers SubstituteTypeParameter(TypeParameterSymbol typeParameter)
        {
            // It might need to be substituted directly.
            TypeWithModifiers result;
            if (Mapping.TryGetValue(typeParameter, out result))
            {
                if (typeParameter.NullabilityPreservation == CodeAnalysis.Symbols.NullabilityPreservationKind.None && result.Type.Kind == SymbolKind.NonNullableReference)
                {
                    return new TypeWithModifiers(((NonNullableReferenceTypeSymbol)result.Type).UnderlyingType);
                }
                return result;
            }

            return new TypeWithModifiers(typeParameter);
        }
コード例 #11
0
        /// <summary>
        /// Used for <see cref="SynthesizedDelegateSymbol"/> construction.
        /// </summary>
        protected SynthesizedContainer(NamespaceOrTypeSymbol containingSymbol, string name, int parameterCount, bool returnsVoid)
        {
            var typeParameters = new TypeParameterSymbol[parameterCount + (returnsVoid ? 0 : 1)];
            for (int i = 0; i < parameterCount; i++)
            {
                typeParameters[i] = new AnonymousTypeManager.AnonymousTypeParameterSymbol(this, i, "T" + (i + 1));
            }

            if (!returnsVoid)
            {
                typeParameters[parameterCount] = new AnonymousTypeManager.AnonymousTypeParameterSymbol(this, parameterCount, "TResult");
            }

            this.containingSymbol = containingSymbol;
            this.name = name;
            this.TypeMap = TypeMap.Empty;
            this.typeParameters = typeParameters.AsImmutableOrNull();
        }
コード例 #12
0
        private static void GrowPool(int count)
        {
            var initialPool = s_parameterPool;
            while (count > initialPool.Length)
            {
                var newPoolSize = ((count + 0x0F) & ~0xF); // grow in increments of 16
                var newPool = new TypeParameterSymbol[newPoolSize];

                Array.Copy(initialPool, newPool, initialPool.Length);

                for (int i = initialPool.Length; i < newPool.Length; i++)
                {
                    newPool[i] = new IndexedTypeParameterSymbol(i);
                }

                Interlocked.CompareExchange(ref s_parameterPool, newPool, initialPool);

                // repeat if race condition occurred and someone else resized the pool before us
                // and the new pool is still too small
                initialPool = s_parameterPool;
            }
        }
コード例 #13
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        // Input types
        //
        private static bool DoesInputTypeContain(BoundExpression argument, TypeSymbol formalParameterType, TypeParameterSymbol typeParameter)
        {
            // SPEC: If E is a method group or an anonymous function and T is a delegate
            // SPEC: type or expression tree type then all the parameter types of T are
            // SPEC: input types of E with type T.

            var delegateType = formalParameterType.GetDelegateType();
            if ((object)delegateType == null)
            {
                return false; // No input types.
            }

            if (argument.Kind != BoundKind.UnboundLambda && argument.Kind != BoundKind.MethodGroup)
            {
                return false; // No input types.
            }

            var delegateParameters = delegateType.DelegateParameters();
            if (delegateParameters.IsDefaultOrEmpty)
            {
                return false;
            }

            foreach (var delegateParameter in delegateParameters)
            {
                if (delegateParameter.Type.ContainsTypeParameter(typeParameter))
                {
                    return true;
                }
            }

            return false;
        }
コード例 #14
0
            internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
            {
                AnonymousTypeManager      manager = ((AnonymousTypeTemplateSymbol)this.ContainingType).Manager;
                SyntheticBoundNodeFactory F       = this.CreateBoundNodeFactory(compilationState, diagnostics);

                //  Method body:
                //
                //  {
                //      $anonymous$ local = value as $anonymous$;
                //      return local != null
                //             && System.Collections.Generic.EqualityComparer<T_1>.Default.Equals(this.backingFld_1, local.backingFld_1)
                //             ...
                //             && System.Collections.Generic.EqualityComparer<T_N>.Default.Equals(this.backingFld_N, local.backingFld_N);
                //  }

                // Type and type expression
                AnonymousTypeTemplateSymbol anonymousType = (AnonymousTypeTemplateSymbol)this.ContainingType;

                //  local
                BoundAssignmentOperator assignmentToTemp;
                BoundLocal boundLocal = F.StoreToTemp(F.As(F.Parameter(this.parameters[0]), anonymousType), out assignmentToTemp);

                //  Generate: statement <= 'local = value as $anonymous$'
                BoundStatement assignment = F.ExpressionStatement(assignmentToTemp);

                //  Generate expression for return statement
                //      retExpression <= 'local != null'
                BoundExpression retExpression = F.Binary(BinaryOperatorKind.ObjectNotEqual,
                                                         manager.System_Boolean,
                                                         F.Convert(manager.System_Object, boundLocal),
                                                         F.Null(manager.System_Object));

                //  prepare symbols
                MethodSymbol    equalityComparer_Equals      = manager.System_Collections_Generic_EqualityComparer_T__Equals;
                MethodSymbol    equalityComparer_get_Default = manager.System_Collections_Generic_EqualityComparer_T__get_Default;
                NamedTypeSymbol equalityComparerType         = equalityComparer_Equals.ContainingType;

                // Compare fields
                for (int index = 0; index < anonymousType.Properties.Length; index++)
                {
                    // Prepare constructed symbols
                    TypeParameterSymbol typeParameter = anonymousType.TypeParameters[index];
                    FieldSymbol         fieldSymbol   = anonymousType.Properties[index].BackingField;
                    NamedTypeSymbol     constructedEqualityComparer = equalityComparerType.Construct(typeParameter);

                    // Generate 'retExpression' = 'retExpression && System.Collections.Generic.EqualityComparer<T_index>.
                    //                                                  Default.Equals(this.backingFld_index, local.backingFld_index)'
                    retExpression = F.LogicalAnd(retExpression,
                                                 F.Call(F.StaticCall(constructedEqualityComparer,
                                                                     equalityComparer_get_Default.AsMember(constructedEqualityComparer)),
                                                        equalityComparer_Equals.AsMember(constructedEqualityComparer),
                                                        F.Field(F.This(), fieldSymbol),
                                                        F.Field(boundLocal, fieldSymbol)));
                }

                // Final return statement
                BoundStatement retStatement = F.Return(retExpression);

                // Create a bound block
                F.CloseMethod(F.Block(ImmutableArray.Create <LocalSymbol>(boundLocal.LocalSymbol), assignment, retStatement));
            }
コード例 #15
0
ファイル: AbstractTypeMap.cs プロジェクト: noahfalk/roslyn
 protected virtual TypeWithModifiers SubstituteTypeParameter(TypeParameterSymbol typeParameter)
 {
     return new TypeWithModifiers(typeParameter);
 }
コード例 #16
0
        // See TypeBind::CheckSingleConstraint.
        private static bool CheckConstraints(
            Symbol containingSymbol,
            ConversionsBase conversions,
            TypeMap substitution,
            TypeParameterSymbol typeParameter,
            TypeSymbol typeArgument,
            Compilation currentCompilation,
            ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder,
            ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder,
            HashSet<TypeParameterSymbol> ignoreTypeConstraintsDependentOnTypeParametersOpt)
        {
            Debug.Assert(substitution != null);
            // The type parameters must be original definitions of type parameters from the containing symbol.
            Debug.Assert(ReferenceEquals(typeParameter.ContainingSymbol, containingSymbol.OriginalDefinition));

            if (typeArgument.IsErrorType())
            {
                return true;
            }

            if (typeArgument.IsPointerType() || typeArgument.IsRestrictedType() || typeArgument.SpecialType == SpecialType.System_Void)
            {
                // "The type '{0}' may not be used as a type argument"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BadTypeArgument, typeArgument)));
                return false;
            }

            if (typeArgument.IsStatic)
            {
                // "'{0}': static types cannot be used as type arguments"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_GenericArgIsStaticClass, typeArgument)));
                return false;
            }

            if (typeParameter.HasReferenceTypeConstraint && !typeArgument.IsReferenceType)
            {
                // "The type '{2}' must be a reference type in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_RefConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return false;
            }

            if (typeParameter.HasValueTypeConstraint && !typeArgument.IsNonNullableValueType())
            {
                // "The type '{2}' must be a non-nullable value type in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ValConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return false;
            }

            // The type parameters for a constructed type/method are the type parameters of
            // the ConstructedFrom type/method, so the constraint types are not substituted.
            // For instance with "class C<T, U> where T : U", the type parameter for T in "C<object, int>"
            // has constraint "U", not "int". We need to substitute the constraints from the
            // original definition of the type parameters using the map from the constructed symbol.
            var constraintTypes = ArrayBuilder<TypeSymbol>.GetInstance();
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            substitution.SubstituteTypesDistinctWithoutModifiers(typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), constraintTypes, 
                                                                 ignoreTypeConstraintsDependentOnTypeParametersOpt);

            bool hasError = false;

            foreach (var constraintType in constraintTypes)
            {
                if (SatisfiesConstraintType(conversions, typeArgument, constraintType, ref useSiteDiagnostics))
                {
                    continue;
                }

                ErrorCode errorCode;
                if (typeArgument.IsReferenceType)
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType;
                }
                else if (typeArgument.IsNullableType())
                {
                    errorCode = constraintType.IsInterfaceType() ? ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface : ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum;
                }
                else if (typeArgument.TypeKind == TypeKind.TypeParameter)
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar;
                }
                else
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedValType;
                }

                SymbolDistinguisher distinguisher = new SymbolDistinguisher(currentCompilation, constraintType, typeArgument);
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(errorCode, containingSymbol.ConstructedFrom(), distinguisher.First, typeParameter, distinguisher.Second)));
                hasError = true;
            }

            if (AppendUseSiteDiagnostics(useSiteDiagnostics, typeParameter, ref useSiteDiagnosticsBuilder))
            {
                hasError = true;
            }

            constraintTypes.Free();

            // Check the constructor constraint.
            if (typeParameter.HasConstructorConstraint && !SatisfiesConstructorConstraint(typeArgument))
            {
                // "'{2}' must be a non-abstract type with a public parameterless constructor in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_NewConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return false;
            }

            return !hasError;
        }
コード例 #17
0
ファイル: TypeUnification.cs プロジェクト: GuilhermeSa/roslyn
        private static void AddSubstitution(ref MutableTypeMap substitution, TypeParameterSymbol tp1, TypeWithModifiers t2)
        {
            if (substitution == null)
            {
                substitution = new MutableTypeMap();
            }

            // MutableTypeMap.Add will throw if the key has already been added.  However,
            // if t1 was already in the substitution, it would have been substituted at the
            // start of CanUnifyHelper and we wouldn't be here.
            substitution.Add(tp1, t2);
        }
コード例 #18
0
 internal void Add(TypeParameterSymbol key, TypeSymbol value)
 {
     this.Mapping.Add(key, value);
 }
        public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
        {
            if ((object)reducedFromTypeParameter == null)
            {
                throw new System.ArgumentNullException();
            }

            if (reducedFromTypeParameter.ContainingSymbol != this.reducedFrom)
            {
                throw new System.ArgumentException();
            }

            return null;
        }
コード例 #20
0
ファイル: MutableTypeMap.cs プロジェクト: khm1600/CJing
 internal void Add(TypeParameterSymbol key, TypeWithModifiers value)
 {
     this.Mapping.Add(key, value);
 }
コード例 #21
0
ファイル: AbstractTypeMap.cs プロジェクト: shibutamang/roslyn
 protected virtual TypeSymbolWithAnnotations SubstituteTypeParameter(TypeParameterSymbol typeParameter)
 {
     return(TypeSymbolWithAnnotations.Create(typeParameter));
 }
コード例 #22
0
 protected virtual TypeWithModifiers SubstituteTypeParameter(TypeParameterSymbol typeParameter)
 {
     return(new TypeWithModifiers(typeParameter));
 }
コード例 #23
0
        /// <summary>
        /// (null TypeParameterSymbol "parameter"): Checks if the given type is a type parameter
        /// or its referent type is a type parameter (array/pointer) or contains a type parameter (aggregate type)
        /// (non-null TypeParameterSymbol "parameter"): above + also checks if the type parameter
        /// is the same as "parameter"
        /// </summary>
        public static bool ContainsTypeParameter(this TypeSymbol type, TypeParameterSymbol parameter = null)
        {
            var result = type.VisitType(ContainsTypeParameterPredicate, parameter);

            return((object)result != null);
        }
コード例 #24
0
 public static bool IsMethodTypeParameter(this TypeParameterSymbol p)
 {
     return(p.ContainingSymbol.Kind == SymbolKind.Method);
 }
コード例 #25
0
ファイル: VarianceSafety.cs プロジェクト: belav/roslyn
        private static void AddVarianceError <T>(
            this BindingDiagnosticBag diagnostics,
            TypeParameterSymbol unsafeTypeParameter,
            Symbol context,
            LocationProvider <T> locationProvider,
            T locationArg,
            MessageID expectedVariance
            ) where T : Symbol
        {
            MessageID actualVariance;

            switch (unsafeTypeParameter.Variance)
            {
            case VarianceKind.In:
                actualVariance = MessageID.IDS_Contravariant;
                break;

            case VarianceKind.Out:
                actualVariance = MessageID.IDS_Covariant;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(unsafeTypeParameter.Variance);
            }

            // Get a location that roughly represents the unsafe type parameter use.
            // (Typically, the locationProvider will return the location of the entire type
            // reference rather than the specific type parameter, for instance, returning
            // "C<T>[]" for "interface I<in T> { C<T>[] F(); }" rather than the type parameter
            // in "C<T>[]", but that is better than returning the location of T within "I<in T>".
            var location = locationProvider(locationArg) ?? unsafeTypeParameter.Locations[0];

            // CONSIDER: instead of using the same error code for all variance errors, we could use different codes for "requires input-safe",
            // "requires output-safe", and "requires input-safe and output-safe".  This would make the error codes much easier to document and
            // much more actionable.
            // UNDONE: related location for use is much more useful
            if (!(context is TypeSymbol) && context.IsStatic)
            {
                diagnostics.Add(
                    ErrorCode.ERR_UnexpectedVarianceStaticMember,
                    location,
                    context,
                    unsafeTypeParameter,
                    actualVariance.Localize(),
                    expectedVariance.Localize(),
                    new CSharpRequiredLanguageVersion(
                        MessageID.IDS_FeatureVarianceSafetyForStaticInterfaceMembers.RequiredVersion()
                        )
                    );
            }
            else
            {
                diagnostics.Add(
                    ErrorCode.ERR_UnexpectedVariance,
                    location,
                    context,
                    unsafeTypeParameter,
                    actualVariance.Localize(),
                    expectedVariance.Localize()
                    );
            }
        }
コード例 #26
0
        public static bool HaveSameConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2)
        {
            // Spec 13.4.3: Implementation of generic methods.

            if ((typeParameter1.HasConstructorConstraint != typeParameter2.HasConstructorConstraint) ||
                (typeParameter1.HasReferenceTypeConstraint != typeParameter2.HasReferenceTypeConstraint) ||
                (typeParameter1.HasValueTypeConstraint != typeParameter2.HasValueTypeConstraint) ||
                (typeParameter1.HasUnmanagedTypeConstraint != typeParameter2.HasUnmanagedTypeConstraint) ||
                (typeParameter1.Variance != typeParameter2.Variance))
            {
                return(false);
            }

            return(HaveSameTypeConstraints(typeParameter1, typeMap1, typeParameter2, typeMap2, TypeSymbol.EqualsIgnoringDynamicTupleNamesAndNullabilityComparer));
        }
コード例 #27
0
        private IEnumerable<ISymbol> LookupTypeParameterMembers(string types, string constraints, string memberName, out TypeParameterSymbol typeParameter)
        {
            var template = @"
{0}
 
public class C<T> where T : {1}
{{
    void M()
    {{
        System.Console.WriteLine(/*<bind>*/default(T)/*</bind>*/);
    }}
}}
";

            var tree = Parse(string.Format(template, types, constraints));
            var comp = CreateCompilationWithMscorlibAndSystemCore(new[] { tree });
            comp.VerifyDiagnostics();
            var model = comp.GetSemanticModel(tree);

            var classC = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
            typeParameter = classC.TypeParameters.Single();

            var exprSyntaxToBind = GetExprSyntaxForBinding(GetExprSyntaxList(tree));
            Assert.Equal(SyntaxKind.DefaultExpression, exprSyntaxToBind.Kind());

            return model.LookupSymbols(exprSyntaxToBind.SpanStart, typeParameter, memberName);
        }
コード例 #28
0
        private static bool HaveSameTypeConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2, EqualityComparer <TypeSymbol> comparer)
        {
            // Check that constraintTypes1 is a subset of constraintTypes2 and
            // also that constraintTypes2 is a subset of constraintTypes1
            // (see SymbolPreparer::CheckImplicitImplConstraints).

            var constraintTypes1 = typeParameter1.ConstraintTypesNoUseSiteDiagnostics;
            var constraintTypes2 = typeParameter2.ConstraintTypesNoUseSiteDiagnostics;

            // The two sets of constraints may differ in size but still be considered
            // the same (duplicated constraints, ignored "object" constraints), but
            // if both are zero size, the sets must be equal.
            if ((constraintTypes1.Length == 0) && (constraintTypes2.Length == 0))
            {
                return(true);
            }

            var substitutedTypes1 = new HashSet <TypeSymbol>(comparer);
            var substitutedTypes2 = new HashSet <TypeSymbol>(comparer);

            SubstituteConstraintTypes(constraintTypes1, typeMap1, substitutedTypes1);
            SubstituteConstraintTypes(constraintTypes2, typeMap2, substitutedTypes2);

            return(AreConstraintTypesSubset(substitutedTypes1, substitutedTypes2, typeParameter2) &&
                   AreConstraintTypesSubset(substitutedTypes2, substitutedTypes1, typeParameter1));
        }
コード例 #29
0
 public TypeParameterDiagnosticInfo(TypeParameterSymbol typeParameter, DiagnosticInfo diagnosticInfo)
 {
     this.TypeParameter = typeParameter;
     this.DiagnosticInfo = diagnosticInfo;
 }
コード例 #30
0
        public static bool HaveSameNullabilityInConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2)
        {
            if (!typeParameter1.IsValueType)
            {
                bool?isNotNullable1 = typeParameter1.IsNotNullable;
                bool?isNotNullable2 = typeParameter2.IsNotNullable;
                if (isNotNullable1.HasValue && isNotNullable2.HasValue &&
                    isNotNullable1.GetValueOrDefault() != isNotNullable2.GetValueOrDefault())
                {
                    return(false);
                }
            }

            return(HaveSameTypeConstraints(typeParameter1, typeMap1, typeParameter2, typeMap2, TypeSymbol.EqualsAllIgnoreOptionsPlusNullableWithUnknownMatchesAnyComparer));
        }
コード例 #31
0
 private static bool IsValueType(TypeParameterSymbol typeParameter, ImmutableArray<TypeSymbol> constraintTypes)
 {
     return typeParameter.HasValueTypeConstraint || TypeParameterSymbol.IsValueTypeFromConstraintTypes(constraintTypes);
 }
コード例 #32
0
 internal bool Equals(TypeParameterSymbol other)
 {
     return(Equals(other, TypeCompareKind.ConsiderEverything));
 }
コード例 #33
0
 public virtual void VisitTypeParameter(TypeParameterSymbol symbol)
 {
     DefaultVisit(symbol);
 }
コード例 #34
0
ファイル: TypeMap.cs プロジェクト: fjsnogueira/roslyn-1
 public ImmutableArray <CustomModifier> GetTypeArgumentsCustomModifiersFor(TypeParameterSymbol originalDefinition)
 {
     Debug.Assert((object)originalDefinition != null);
     Debug.Assert(originalDefinition.IsDefinition);
     return(SubstituteTypeParameter(originalDefinition).CustomModifiers);
 }
コード例 #35
0
            internal AnonymousTypeTemplateSymbol(AnonymousTypeManager manager, AnonymousTypeDescriptor typeDescr)
            {
                this.Manager = manager;
                this.TypeDescriptorKey = typeDescr.Key;
                _smallestLocation = typeDescr.Location;

                // Will be set when the type's metadata is ready to be emitted, 
                // <anonymous-type>.Name will throw exception if requested
                // before that moment.
                _nameAndIndex = null;

                int fieldsCount = typeDescr.Fields.Length;

                // members
                Symbol[] members = new Symbol[fieldsCount * 3 + 1];
                int memberIndex = 0;

                // The array storing property symbols to be used in 
                // generation of constructor and other methods
                if (fieldsCount > 0)
                {
                    AnonymousTypePropertySymbol[] propertiesArray = new AnonymousTypePropertySymbol[fieldsCount];
                    TypeParameterSymbol[] typeParametersArray = new TypeParameterSymbol[fieldsCount];

                    // Process fields
                    for (int fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex++)
                    {
                        AnonymousTypeField field = typeDescr.Fields[fieldIndex];

                        // Add a type parameter
                        AnonymousTypeParameterSymbol typeParameter =
                            new AnonymousTypeParameterSymbol(this, fieldIndex, GeneratedNames.MakeAnonymousTypeParameterName(field.Name));
                        typeParametersArray[fieldIndex] = typeParameter;

                        // Add a property
                        AnonymousTypePropertySymbol property = new AnonymousTypePropertySymbol(this, field, typeParameter);
                        propertiesArray[fieldIndex] = property;

                        // Property related symbols
                        members[memberIndex++] = property;
                        members[memberIndex++] = property.BackingField;
                        members[memberIndex++] = property.GetMethod;
                    }

                    _typeParameters = typeParametersArray.AsImmutable();
                    this.Properties = propertiesArray.AsImmutable();
                }
                else
                {
                    _typeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
                    this.Properties = ImmutableArray<AnonymousTypePropertySymbol>.Empty;
                }

                // Add a constructor
                members[memberIndex++] = new AnonymousTypeConstructorSymbol(this, this.Properties);
                _members = members.AsImmutable();

                Debug.Assert(memberIndex == _members.Length);

                // fill nameToSymbols map
                foreach (var symbol in _members)
                {
                    _nameToSymbols.Add(symbol.Name, symbol);
                }

                // special members: Equals, GetHashCode, ToString
                MethodSymbol[] specialMembers = new MethodSymbol[3];
                specialMembers[0] = new AnonymousTypeEqualsMethodSymbol(this);
                specialMembers[1] = new AnonymousTypeGetHashCodeMethodSymbol(this);
                specialMembers[2] = new AnonymousTypeToStringMethodSymbol(this);
                this.SpecialMembers = specialMembers.AsImmutable();
            }
コード例 #36
0
ファイル: ConstraintsHelper.cs プロジェクト: shashinh/roslyn
        // See TypeBind::CheckSingleConstraint.
        private static bool CheckConstraints(
            Symbol containingSymbol,
            ConversionsBase conversions,
            TypeMap substitution,
            TypeParameterSymbol typeParameter,
            TypeSymbol typeArgument,
            Compilation currentCompilation,
            ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder,
            ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder)
        {
            Debug.Assert(substitution != null);
            // The type parameters must be original definitions of type parameters from the containing symbol.
            Debug.Assert(ReferenceEquals(typeParameter.ContainingSymbol, containingSymbol.OriginalDefinition));

            if (typeArgument.IsErrorType())
            {
                return(true);
            }

            if (typeArgument.IsPointerType() || typeArgument.IsRestrictedType() || typeArgument.SpecialType == SpecialType.System_Void)
            {
                // "The type '{0}' may not be used as a type argument"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BadTypeArgument, typeArgument)));
                return(false);
            }

            if (typeArgument.IsStatic)
            {
                // "'{0}': static types cannot be used as type arguments"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_GenericArgIsStaticClass, typeArgument)));
                return(false);
            }

            if (typeParameter.HasReferenceTypeConstraint && !typeArgument.IsReferenceType)
            {
                // "The type '{2}' must be a reference type in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_RefConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return(false);
            }

            if (typeParameter.HasValueTypeConstraint && !typeArgument.IsNonNullableValueType())
            {
                // "The type '{2}' must be a non-nullable value type in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ValConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return(false);
            }

            // The type parameters for a constructed type/method are the type parameters of
            // the ConstructedFrom type/method, so the constraint types are not substituted.
            // For instance with "class C<T, U> where T : U", the type parameter for T in "C<object, int>"
            // has constraint "U", not "int". We need to substitute the constraints from the
            // original definition of the type parameters using the map from the constructed symbol.
            var constraintTypes = ArrayBuilder <TypeSymbol> .GetInstance();

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            substitution.SubstituteTypesDistinctWithoutModifiers(typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), constraintTypes);

            bool hasError = false;

            foreach (var constraintType in constraintTypes)
            {
                if (SatisfiesConstraintType(conversions, typeArgument, constraintType, ref useSiteDiagnostics))
                {
                    continue;
                }

                ErrorCode errorCode;
                if (typeArgument.IsReferenceType)
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType;
                }
                else if (typeArgument.IsNullableType())
                {
                    errorCode = constraintType.IsInterfaceType() ? ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface : ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum;
                }
                else if (typeArgument.TypeKind == TypeKind.TypeParameter)
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar;
                }
                else
                {
                    errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedValType;
                }

                SymbolDistinguisher distinguisher = new SymbolDistinguisher(currentCompilation, constraintType, typeArgument);
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(errorCode, containingSymbol.ConstructedFrom(), distinguisher.First, typeParameter, distinguisher.Second)));
                hasError = true;
            }

            if (AppendUseSiteDiagnostics(useSiteDiagnostics, typeParameter, ref useSiteDiagnosticsBuilder))
            {
                hasError = true;
            }

            constraintTypes.Free();

            // Check the constructor constraint.
            if (typeParameter.HasConstructorConstraint && !SatisfiesConstructorConstraint(typeArgument))
            {
                // "'{2}' must be a non-abstract type with a public parameterless constructor in order to use it as parameter '{1}' in the generic type or method '{0}'"
                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_NewConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument)));
                return(false);
            }

            return(!hasError);
        }
コード例 #37
0
 internal bool Equals(TypeParameterSymbol other)
 {
     return(Equals(other, false, false));
 }
コード例 #38
0
ファイル: ConstraintsHelper.cs プロジェクト: shashinh/roslyn
 private static bool IsValueType(TypeParameterSymbol typeParameter, ImmutableArray <TypeSymbol> constraintTypes)
 {
     return(typeParameter.HasValueTypeConstraint || TypeParameterSymbol.IsValueTypeFromConstraintTypes(constraintTypes));
 }
コード例 #39
0
        private void AddExactBound(TypeParameterSymbol methodTypeParameter, TypeSymbol exactBound)
        {
            Debug.Assert(IsUnfixedTypeParameter(methodTypeParameter));
            int methodTypeParameterIndex = methodTypeParameter.Ordinal;
            if (_exactBounds[methodTypeParameterIndex] == null)
            {
                _exactBounds[methodTypeParameterIndex] = new HashSet<TypeSymbol>();
            }

            _exactBounds[methodTypeParameterIndex].Add(exactBound);
        }
コード例 #40
0
ファイル: ConstraintsHelper.cs プロジェクト: shashinh/roslyn
 private static TypeParameterDiagnosticInfo GenerateConflictingConstraintsError(TypeParameterSymbol typeParameter, TypeSymbol deducedBase, bool classConflict)
 {
     // "Type parameter '{0}' inherits conflicting constraints '{1}' and '{2}'"
     return(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BaseConstraintConflict, typeParameter, deducedBase, classConflict ? "class" : "struct")));
 }
コード例 #41
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        // Output types
        //
        private static bool DoesOutputTypeContain(BoundExpression argument, TypeSymbol formalParameterType,
            TypeParameterSymbol typeParameter)
        {
            // SPEC: If E is a method group or an anonymous function and T is a delegate
            // SPEC: type or expression tree type then the return type of T is an output type
            // SPEC: of E with type T.

            var delegateType = formalParameterType.GetDelegateType();
            if ((object)delegateType == null)
            {
                return false;
            }

            if (argument.Kind != BoundKind.UnboundLambda && argument.Kind != BoundKind.MethodGroup)
            {
                return false;
            }

            MethodSymbol delegateInvoke = delegateType.DelegateInvokeMethod;
            if ((object)delegateInvoke == null || delegateInvoke.HasUseSiteError)
            {
                return false;
            }

            var delegateReturnType = delegateInvoke.ReturnType;
            if ((object)delegateReturnType == null)
            {
                return false;
            }

            return delegateReturnType.ContainsTypeParameter(typeParameter);
        }
コード例 #42
0
ファイル: ConstraintsHelper.cs プロジェクト: shashinh/roslyn
        // Based on SymbolLoader::ResolveBounds.
        public static TypeParameterBounds ResolveBounds(
            this TypeParameterSymbol typeParameter,
            AssemblySymbol corLibrary,
            ConsList <TypeParameterSymbol> inProgress,
            ImmutableArray <TypeSymbol> constraintTypes,
            bool inherited,
            CSharpCompilation currentCompilation,
            ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder,
            ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder)
        {
            Debug.Assert(currentCompilation == null || typeParameter.IsFromCompilation(currentCompilation));

            ImmutableArray <NamedTypeSymbol> interfaces;

            NamedTypeSymbol   effectiveBaseClass = corLibrary.GetSpecialType(typeParameter.HasValueTypeConstraint ? SpecialType.System_ValueType : SpecialType.System_Object);
            TypeSymbol        deducedBaseType    = effectiveBaseClass;
            DynamicTypeEraser dynamicEraser      = null;

            if (constraintTypes.Length == 0)
            {
                interfaces = ImmutableArray <NamedTypeSymbol> .Empty;
            }
            else
            {
                var constraintTypesBuilder = ArrayBuilder <TypeSymbol> .GetInstance();

                var interfacesBuilder = ArrayBuilder <NamedTypeSymbol> .GetInstance();

                var conversions = new TypeConversions(corLibrary);
                HashSet <DiagnosticInfo> useSiteDiagnostics = null;

                // Resolve base types, determine the effective base class and
                // interfaces, and filter out any constraint types that cause cycles.
                foreach (var constraintType in constraintTypes)
                {
                    NamedTypeSymbol constraintEffectiveBase;
                    TypeSymbol      constraintDeducedBase;

                    switch (constraintType.TypeKind)
                    {
                    case TypeKind.Dynamic:
                        Debug.Assert(inherited || currentCompilation == null);
                        continue;

                    case TypeKind.TypeParameter:
                    {
                        var containingSymbol        = typeParameter.ContainingSymbol;
                        var constraintTypeParameter = (TypeParameterSymbol)constraintType;
                        ConsList <TypeParameterSymbol> constraintsInProgress;

                        if (constraintTypeParameter.ContainingSymbol == containingSymbol)
                        {
                            // The constraint type parameter is from the same containing type or method.
                            if (inProgress.ContainsReference(constraintTypeParameter))
                            {
                                // "Circular constraint dependency involving '{0}' and '{1}'"
                                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(constraintTypeParameter, new CSDiagnosticInfo(ErrorCode.ERR_CircularConstraint, constraintTypeParameter, typeParameter)));
                                continue;
                            }

                            constraintsInProgress = inProgress;
                        }
                        else
                        {
                            // The constraint type parameter is from a different containing symbol so no cycle.
                            constraintsInProgress = ConsList <TypeParameterSymbol> .Empty;
                        }

                        // Use the calculated bounds from the constraint type parameter.
                        constraintEffectiveBase = constraintTypeParameter.GetEffectiveBaseClass(constraintsInProgress);
                        constraintDeducedBase   = constraintTypeParameter.GetDeducedBaseType(constraintsInProgress);
                        AddInterfaces(interfacesBuilder, constraintTypeParameter.GetInterfaces(constraintsInProgress));

                        if (constraintTypeParameter.HasValueTypeConstraint && !inherited && currentCompilation != null && constraintTypeParameter.IsFromCompilation(currentCompilation))
                        {
                            // "Type parameter '{1}' has the 'struct' constraint so '{1}' cannot be used as a constraint for '{0}'"
                            diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ConWithValCon, typeParameter, constraintTypeParameter)));
                            continue;
                        }
                    }
                    break;

                    case TypeKind.Interface:
                    case TypeKind.Class:
                    case TypeKind.Delegate:
                        NamedTypeSymbol erasedConstraintType;

                        if (inherited || currentCompilation == null)
                        {
                            // only inherited constraints may contain dynamic
                            if (dynamicEraser == null)
                            {
                                dynamicEraser = new DynamicTypeEraser(corLibrary.GetSpecialType(SpecialType.System_Object));
                            }

                            erasedConstraintType = (NamedTypeSymbol)dynamicEraser.EraseDynamic(constraintType);
                        }
                        else
                        {
                            Debug.Assert(!constraintType.ContainsDynamic());
                            Debug.Assert(constraintType.TypeKind != TypeKind.Delegate);

                            erasedConstraintType = (NamedTypeSymbol)constraintType;
                        }

                        if (constraintType.IsInterfaceType())
                        {
                            AddInterface(interfacesBuilder, erasedConstraintType);
                            constraintTypesBuilder.Add(constraintType);
                            continue;
                        }
                        else
                        {
                            constraintEffectiveBase = erasedConstraintType;
                            constraintDeducedBase   = constraintType;
                            break;
                        }

                    case TypeKind.Struct:
                        Debug.Assert(inherited || currentCompilation == null);
                        constraintEffectiveBase = corLibrary.GetSpecialType(SpecialType.System_ValueType);
                        constraintDeducedBase   = constraintType;
                        break;

                    case TypeKind.Enum:
                        Debug.Assert(inherited || currentCompilation == null);
                        constraintEffectiveBase = corLibrary.GetSpecialType(SpecialType.System_Enum);
                        constraintDeducedBase   = constraintType;
                        break;

                    case TypeKind.Array:
                        Debug.Assert(inherited || currentCompilation == null);
                        constraintEffectiveBase = corLibrary.GetSpecialType(SpecialType.System_Array);
                        constraintDeducedBase   = constraintType;
                        break;

                    case TypeKind.Error:
                        constraintEffectiveBase = (NamedTypeSymbol)constraintType;
                        constraintDeducedBase   = constraintType;
                        break;

                    case TypeKind.Submission:
                    default:
                        throw ExceptionUtilities.UnexpectedValue(constraintType.TypeKind);
                    }

                    CheckEffectiveAndDeducedBaseTypes(conversions, constraintEffectiveBase, constraintDeducedBase);

                    constraintTypesBuilder.Add(constraintType);

                    // Determine the more encompassed of the current effective base
                    // class and the previously computed effective base class.
                    if (!deducedBaseType.IsErrorType() && !constraintDeducedBase.IsErrorType())
                    {
                        if (!IsEncompassedBy(conversions, deducedBaseType, constraintDeducedBase, ref useSiteDiagnostics))
                        {
                            if (!IsEncompassedBy(conversions, constraintDeducedBase, deducedBaseType, ref useSiteDiagnostics))
                            {
                                // "Type parameter '{0}' inherits conflicting constraints '{1}' and '{2}'"
                                diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BaseConstraintConflict, typeParameter, constraintDeducedBase, deducedBaseType)));
                            }
                            else
                            {
                                deducedBaseType    = constraintDeducedBase;
                                effectiveBaseClass = constraintEffectiveBase;
                            }
                        }
                    }
                }

                AppendUseSiteDiagnostics(useSiteDiagnostics, typeParameter, ref useSiteDiagnosticsBuilder);

                CheckEffectiveAndDeducedBaseTypes(conversions, effectiveBaseClass, deducedBaseType);

                constraintTypes = constraintTypesBuilder.ToImmutableAndFree();
                interfaces      = interfacesBuilder.ToImmutableAndFree();
            }

            Debug.Assert((effectiveBaseClass.SpecialType == SpecialType.System_Object) || (deducedBaseType.SpecialType != SpecialType.System_Object));

            // Only create a TypeParameterBounds instance for this type
            // parameter if the bounds are not the default values.
            if ((constraintTypes.Length == 0) && (deducedBaseType.SpecialType == SpecialType.System_Object))
            {
                Debug.Assert(effectiveBaseClass.SpecialType == SpecialType.System_Object);
                Debug.Assert(interfaces.Length == 0);
                return(null);
            }

            var bounds = new TypeParameterBounds(constraintTypes, interfaces, effectiveBaseClass, deducedBaseType);

            // Additional constraint checks for overrides.
            if (inherited)
            {
                CheckOverrideConstraints(typeParameter, bounds, diagnosticsBuilder);
            }

            return(bounds);
        }
コード例 #43
0
 public EmbeddedTypeParameter(EmbeddedMethod containingMethod, TypeParameterSymbol underlyingTypeParameter) :
     base(containingMethod, underlyingTypeParameter)
 {
     Debug.Assert(underlyingTypeParameter.IsDefinition);
 }
コード例 #44
0
        public static bool HaveSameConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2)
        {
            // Spec 13.4.3: Implementation of generic methods.

            if ((typeParameter1.HasConstructorConstraint != typeParameter2.HasConstructorConstraint) ||
                (typeParameter1.HasReferenceTypeConstraint != typeParameter2.HasReferenceTypeConstraint) ||
                (typeParameter1.HasValueTypeConstraint != typeParameter2.HasValueTypeConstraint) ||
                (typeParameter1.HasUnmanagedTypeConstraint != typeParameter2.HasUnmanagedTypeConstraint) ||
                (typeParameter1.Variance != typeParameter2.Variance))
            {
                return(false);
            }

            // Check that constraintTypes1 is a subset of constraintTypes2 and
            // also that constraintTypes2 is a subset of constraintTypes1
            // (see SymbolPreparer::CheckImplicitImplConstraints).

            var constraintTypes1 = typeParameter1.ConstraintTypesNoUseSiteDiagnostics;
            var constraintTypes2 = typeParameter2.ConstraintTypesNoUseSiteDiagnostics;

            // The two sets of constraints may differ in size but still be considered
            // the same (duplicated constraints, ignored "object" constraints), but
            // if both are zero size, the sets must be equal.
            if ((constraintTypes1.Length == 0) && (constraintTypes2.Length == 0))
            {
                return(true);
            }

            var substitutedTypes1 = new HashSet <TypeSymbol>(TypeSymbol.EqualsIgnoringDynamicAndTupleNamesComparer);
            var substitutedTypes2 = new HashSet <TypeSymbol>(TypeSymbol.EqualsIgnoringDynamicAndTupleNamesComparer);

            SubstituteConstraintTypes(constraintTypes1, typeMap1, substitutedTypes1);
            SubstituteConstraintTypes(constraintTypes2, typeMap2, substitutedTypes2);

            return(AreConstraintTypesSubset(substitutedTypes1, substitutedTypes2, typeParameter2) &&
                   AreConstraintTypesSubset(substitutedTypes2, substitutedTypes1, typeParameter1));
        }
コード例 #45
0
ファイル: VarianceSafety.cs プロジェクト: belav/roslyn
        private static bool IsVarianceUnsafe <T>(
            TypeSymbol type,
            bool requireOutputSafety,
            bool requireInputSafety,
            Symbol context,
            LocationProvider <T> locationProvider,
            T locationArg,
            BindingDiagnosticBag diagnostics
            ) where T : Symbol
        {
            Debug.Assert(requireOutputSafety || requireInputSafety);

            // A type T is "output-unsafe" ["input-unsafe"] if one of the following holds:
            switch (type.Kind)
            {
            case SymbolKind.TypeParameter:
                // 1) T is a contravariant [covariant] type parameter
                TypeParameterSymbol typeParam = (TypeParameterSymbol)type;
                if (
                    requireInputSafety &&
                    requireOutputSafety &&
                    typeParam.Variance != VarianceKind.None
                    )
                {
                    // This sub-case isn't mentioned in the spec, because it's not required for
                    // the definition.  It just allows us to give a better error message for
                    // type parameters that are both output-unsafe and input-unsafe.
                    diagnostics.AddVarianceError(
                        typeParam,
                        context,
                        locationProvider,
                        locationArg,
                        MessageID.IDS_Invariantly
                        );
                    return(true);
                }
                else if (requireOutputSafety && typeParam.Variance == VarianceKind.In)
                {
                    // The is output-unsafe case (1) from the spec.
                    diagnostics.AddVarianceError(
                        typeParam,
                        context,
                        locationProvider,
                        locationArg,
                        MessageID.IDS_Covariantly
                        );
                    return(true);
                }
                else if (requireInputSafety && typeParam.Variance == VarianceKind.Out)
                {
                    // The is input-unsafe case (1) from the spec.
                    diagnostics.AddVarianceError(
                        typeParam,
                        context,
                        locationProvider,
                        locationArg,
                        MessageID.IDS_Contravariantly
                        );
                    return(true);
                }
                else
                {
                    return(false);
                }

            case SymbolKind.ArrayType:
                // 2) T is an array type with an output-unsafe [input-unsafe] element type
                return(IsVarianceUnsafe(
                           ((ArrayTypeSymbol)type).ElementType,
                           requireOutputSafety,
                           requireInputSafety,
                           context,
                           locationProvider,
                           locationArg,
                           diagnostics
                           ));

            case SymbolKind.ErrorType:
            case SymbolKind.NamedType:
                var namedType = (NamedTypeSymbol)type;
                // 3) (see IsVarianceUnsafe(NamedTypeSymbol))
                return(IsVarianceUnsafe(
                           namedType,
                           requireOutputSafety,
                           requireInputSafety,
                           context,
                           locationProvider,
                           locationArg,
                           diagnostics
                           ));

            default:
                return(false);
            }
        }
コード例 #46
0
ファイル: VarianceSafety.cs プロジェクト: zuvys/roslyn
        /// <summary>
        /// 3) T is an interface, class, struct, enum, or delegate type <![CDATA[S<A_1, ..., A_k>]]> constructed
        /// from a generic type <![CDATA[S<X_1, ..., X_k>]]> where for at least one A_i one
        /// of the following holds:
        ///     a) X_i is covariant or invariant and A_i is output-unsafe [input-unsafe]
        ///     b) X_i is contravariant or invariant and A_i is input-unsafe [output-unsafe] (note: spec has "input-safe", but it's a typo)
        /// </summary>
        /// <remarks>
        /// Slight rewrite to make it more idiomatic for C#:
        ///     a) X_i is covariant and A_i is input-unsafe
        ///     b) X_i is contravariant and A_i is output-unsafe
        ///     c) X_i is invariant and A_i is input-unsafe or output-unsafe
        /// </remarks>
        private static bool IsVarianceUnsafe <T>(
            NamedTypeSymbol namedType,
            bool requireOutputSafety,
            bool requireInputSafety,
            Symbol context,
            LocationProvider <T> locationProvider,
            T locationArg,
            DiagnosticBag diagnostics)
            where T : Symbol
        {
            Debug.Assert(requireOutputSafety || requireInputSafety);

            switch (namedType.TypeKind)
            {
            case TypeKind.Class:
            case TypeKind.Struct:
            case TypeKind.Enum:     // Can't be generic, but can be nested in generic.
            case TypeKind.Interface:
            case TypeKind.Delegate:
            case TypeKind.Error:
                break;

            default:
                return(false);
            }

            while ((object)namedType != null)
            {
                for (int i = 0; i < namedType.Arity; i++)
                {
                    TypeParameterSymbol typeParam = namedType.TypeParameters[i];
                    TypeSymbol          typeArg   = namedType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[i].Type;

                    bool requireOut;
                    bool requireIn;

                    switch (typeParam.Variance)
                    {
                    case VarianceKind.Out:
                        // a) X_i is covariant and A_i is output-unsafe [input-unsafe]
                        requireOut = requireOutputSafety;
                        requireIn  = requireInputSafety;
                        break;

                    case VarianceKind.In:
                        // b) X_i is contravariant and A_i is input-unsafe [output-unsafe]
                        requireOut = requireInputSafety;
                        requireIn  = requireOutputSafety;
                        break;

                    case VarianceKind.None:
                        // c) X_i is invariant and A_i is output-unsafe or input-unsafe
                        requireIn  = true;
                        requireOut = true;
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(typeParam.Variance);
                    }

                    if (IsVarianceUnsafe(typeArg, requireOut, requireIn, context, locationProvider, locationArg, diagnostics))
                    {
                        return(true);
                    }
                }

                namedType = namedType.ContainingType;
            }

            return(false);
        }
コード例 #47
0
        public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
        {
            // This will throw if API shouldn't be supported or there is a problem with the argument.
            var notUsed = originalDefinition.GetTypeInferredDuringReduction(reducedFromTypeParameter);

            Debug.Assert((object)notUsed == null && (object)originalDefinition.ReducedFrom != null);
            return this.TypeArguments[reducedFromTypeParameter.Ordinal];
        }
コード例 #48
0
 protected virtual TypeSymbol SubstituteTypeParameter(TypeParameterSymbol typeParameter)
 {
     return(typeParameter);
 }
コード例 #49
0
        // Based on SymbolLoader::SetOverrideConstraints.
        private static void CheckOverrideConstraints(
            TypeParameterSymbol typeParameter,
            TypeParameterBounds bounds,
            ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder)
        {
            var deducedBase = bounds.DeducedBaseType;
            var constraintTypes = bounds.ConstraintTypes;

            if (IsValueType(typeParameter, constraintTypes) && IsReferenceType(typeParameter, constraintTypes))
            {
                Debug.Assert(!deducedBase.IsValueType || typeParameter.HasReferenceTypeConstraint);
                diagnosticsBuilder.Add(GenerateConflictingConstraintsError(typeParameter, deducedBase, classConflict: deducedBase.IsValueType));
            }
            else if (deducedBase.IsNullableType() && (typeParameter.HasValueTypeConstraint || typeParameter.HasReferenceTypeConstraint))
            {
                diagnosticsBuilder.Add(GenerateConflictingConstraintsError(typeParameter, deducedBase, classConflict: typeParameter.HasReferenceTypeConstraint));
            }
        }
コード例 #50
0
ファイル: ConstraintsHelper.cs プロジェクト: lmeyer3/roslyn
 public TypeParameterDiagnosticInfo(TypeParameterSymbol typeParameter, DiagnosticInfo diagnosticInfo)
 {
     this.TypeParameter  = typeParameter;
     this.DiagnosticInfo = diagnosticInfo;
 }
コード例 #51
0
        private static bool AppendUseSiteDiagnostics(
            HashSet<DiagnosticInfo> useSiteDiagnostics,
            TypeParameterSymbol typeParameter,
            ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder)
        {
            if (useSiteDiagnostics.IsNullOrEmpty())
            {
                return false;
            }

            if (useSiteDiagnosticsBuilder == null)
            {
                useSiteDiagnosticsBuilder = new ArrayBuilder<TypeParameterDiagnosticInfo>();
            }

            bool hasErrors = false;

            foreach (var info in useSiteDiagnostics)
            {
                if (info.Severity == DiagnosticSeverity.Error)
                {
                    hasErrors = true;
                }

                useSiteDiagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, info));
            }

            return hasErrors;
        }
コード例 #52
0
 public SynthesizedTypeParameterSymbol(Symbol owner, TypeMap map, TypeParameterSymbol substitutedFrom)
     : base(owner, map, substitutedFrom)
 {
 }
コード例 #53
0
 private static TypeParameterDiagnosticInfo GenerateConflictingConstraintsError(TypeParameterSymbol typeParameter, TypeSymbol deducedBase, bool classConflict)
 {
     // "Type parameter '{0}' inherits conflicting constraints '{1}' and '{2}'"
     return new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BaseConstraintConflict, typeParameter, deducedBase, classConflict ? "class" : "struct"));
 }
コード例 #54
0
            internal AnonymousTypeTemplateSymbol(AnonymousTypeManager manager, AnonymousTypeDescriptor typeDescr)
            {
                this.Manager           = manager;
                this.TypeDescriptorKey = typeDescr.Key;
                _smallestLocation      = typeDescr.Location;

                // Will be set when the type's metadata is ready to be emitted,
                // <anonymous-type>.Name will throw exception if requested
                // before that moment.
                _nameAndIndex = null;

                int fieldsCount = typeDescr.Fields.Length;

                // members
                Symbol[] members     = new Symbol[fieldsCount * 3 + 1];
                int      memberIndex = 0;

                // The array storing property symbols to be used in
                // generation of constructor and other methods
                if (fieldsCount > 0)
                {
                    AnonymousTypePropertySymbol[] propertiesArray     = new AnonymousTypePropertySymbol[fieldsCount];
                    TypeParameterSymbol[]         typeParametersArray = new TypeParameterSymbol[fieldsCount];

                    // Process fields
                    for (int fieldIndex = 0; fieldIndex < fieldsCount; fieldIndex++)
                    {
                        AnonymousTypeField field = typeDescr.Fields[fieldIndex];

                        // Add a type parameter
                        AnonymousTypeParameterSymbol typeParameter =
                            new AnonymousTypeParameterSymbol(this, fieldIndex, GeneratedNames.MakeAnonymousTypeParameterName(field.Name));
                        typeParametersArray[fieldIndex] = typeParameter;

                        // Add a property
                        AnonymousTypePropertySymbol property = new AnonymousTypePropertySymbol(this, field, typeParameter);
                        propertiesArray[fieldIndex] = property;

                        // Property related symbols
                        members[memberIndex++] = property;
                        members[memberIndex++] = property.BackingField;
                        members[memberIndex++] = property.GetMethod;
                    }

                    _typeParameters = typeParametersArray.AsImmutable();
                    this.Properties = propertiesArray.AsImmutable();
                }
                else
                {
                    _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty;
                    this.Properties = ImmutableArray <AnonymousTypePropertySymbol> .Empty;
                }

                // Add a constructor
                members[memberIndex++] = new AnonymousTypeConstructorSymbol(this, this.Properties);
                _members = members.AsImmutable();

                Debug.Assert(memberIndex == _members.Length);

                // fill nameToSymbols map
                foreach (var symbol in _members)
                {
                    _nameToSymbols.Add(symbol.Name, symbol);
                }

                // special members: Equals, GetHashCode, ToString
                MethodSymbol[] specialMembers = new MethodSymbol[3];
                specialMembers[0]   = new AnonymousTypeEqualsMethodSymbol(this);
                specialMembers[1]   = new AnonymousTypeGetHashCodeMethodSymbol(this);
                specialMembers[2]   = new AnonymousTypeToStringMethodSymbol(this);
                this.SpecialMembers = specialMembers.AsImmutable();
            }
コード例 #55
0
ファイル: TypeUnification.cs プロジェクト: GuilhermeSa/roslyn
        /// <summary>
        /// Return true if the given type contains the specified type parameter.
        /// </summary>
        private static bool Contains(TypeSymbol type, TypeParameterSymbol typeParam)
        {
            switch (type.Kind)
            {
                case SymbolKind.ArrayType:
                    return Contains(((ArrayTypeSymbol)type).ElementType, typeParam);
                case SymbolKind.PointerType:
                    return Contains(((PointerTypeSymbol)type).PointedAtType, typeParam);
                case SymbolKind.NamedType:
                case SymbolKind.ErrorType:
                    {
                        NamedTypeSymbol namedType = (NamedTypeSymbol)type;
                        while ((object)namedType != null)
                        {
                            ImmutableArray<TypeSymbol> typeParts = namedType.IsTupleType ? namedType.TupleElementTypes : namedType.TypeArgumentsNoUseSiteDiagnostics;
                            foreach (TypeSymbol typePart in typeParts)
                            {
                                if (Contains(typePart, typeParam))
                                {
                                    return true;
                                }
                            }
                            namedType = namedType.ContainingType;
                        }

                        return false;
                    }
                case SymbolKind.TypeParameter:
                    return type == typeParam;
                default:
                    return false;
            }
        }
コード例 #56
0
 public WrappedTypeParameterSymbol(TypeParameterSymbol underlyingTypeParameter)
 {
     Debug.Assert((object)underlyingTypeParameter != null);
     _underlyingTypeParameter = underlyingTypeParameter;
 }
コード例 #57
0
        /// <summary>
        /// Returns true if the first set of constraint types
        /// is a subset of the second set.
        /// </summary>
        private static bool AreConstraintTypesSubset(HashSet <TypeSymbol> constraintTypes1, HashSet <TypeSymbol> constraintTypes2, TypeParameterSymbol typeParameter2)
        {
            foreach (var constraintType in constraintTypes1)
            {
                // Skip object type (spec. 13.4.3).
                if (constraintType.SpecialType == SpecialType.System_Object)
                {
                    continue;
                }

                if (constraintTypes2.Contains(constraintType))
                {
                    continue;
                }

                // The struct constraint implies a System.ValueType constraint
                // type which may be explicit in the other type parameter
                // constraints (through type substitution in derived types).
                if ((constraintType.SpecialType == SpecialType.System_ValueType) &&
                    typeParameter2.HasValueTypeConstraint)
                {
                    continue;
                }

                return(false);
            }

            return(true);
        }
コード例 #58
0
            internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
            {
                AnonymousTypeManager      manager = ((AnonymousTypeTemplateSymbol)this.ContainingType).Manager;
                SyntheticBoundNodeFactory F       = this.CreateBoundNodeFactory(compilationState, diagnostics);

                //  Method body:
                //
                //  HASH_FACTOR = 0xa5555529;
                //  INIT_HASH = (...((0 * HASH_FACTOR) + backingFld_1.Name.GetHashCode()) * HASH_FACTOR
                //                                     + backingFld_2.Name.GetHashCode()) * HASH_FACTOR
                //                                     + ...
                //                                     + backingFld_N.Name.GetHashCode()
                //
                //  {
                //      return (...((INITIAL_HASH * HASH_FACTOR) + EqualityComparer<T_1>.Default.GetHashCode(this.backingFld_1)) * HASH_FACTOR
                //                                               + EqualityComparer<T_2>.Default.GetHashCode(this.backingFld_2)) * HASH_FACTOR
                //                                               ...
                //                                               + EqualityComparer<T_N>.Default.GetHashCode(this.backingFld_N)
                //  }

                const int HASH_FACTOR = -1521134295; // (int)0xa5555529

                // Type expression
                AnonymousTypeTemplateSymbol anonymousType = (AnonymousTypeTemplateSymbol)this.ContainingType;

                //  INIT_HASH
                int initHash = 0;

                foreach (var property in anonymousType.Properties)
                {
                    initHash = unchecked (initHash * HASH_FACTOR + property.BackingField.Name.GetHashCode());
                }

                //  Generate expression for return statement
                //      retExpression <= 'INITIAL_HASH'
                BoundExpression retExpression = F.Literal(initHash);

                //  prepare symbols
                MethodSymbol    equalityComparer_GetHashCode = manager.System_Collections_Generic_EqualityComparer_T__GetHashCode;
                MethodSymbol    equalityComparer_get_Default = manager.System_Collections_Generic_EqualityComparer_T__get_Default;
                NamedTypeSymbol equalityComparerType         = equalityComparer_GetHashCode.ContainingType;

                //  bound HASH_FACTOR
                BoundLiteral boundHashFactor = F.Literal(HASH_FACTOR);

                // Process fields
                for (int index = 0; index < anonymousType.Properties.Length; index++)
                {
                    // Prepare constructed symbols
                    TypeParameterSymbol typeParameter = anonymousType.TypeParameters[index];
                    NamedTypeSymbol     constructedEqualityComparer = equalityComparerType.Construct(typeParameter);

                    // Generate 'retExpression' <= 'retExpression * HASH_FACTOR
                    retExpression = F.Binary(BinaryOperatorKind.IntMultiplication, manager.System_Int32, retExpression, boundHashFactor);

                    // Generate 'retExpression' <= 'retExpression + EqualityComparer<T_index>.Default.GetHashCode(this.backingFld_index)'
                    retExpression = F.Binary(BinaryOperatorKind.IntAddition,
                                             manager.System_Int32,
                                             retExpression,
                                             F.Call(
                                                 F.StaticCall(constructedEqualityComparer,
                                                              equalityComparer_get_Default.AsMember(constructedEqualityComparer)),
                                                 equalityComparer_GetHashCode.AsMember(constructedEqualityComparer),
                                                 F.Field(F.This(), anonymousType.Properties[index].BackingField)));
                }

                // Create a bound block
                F.CloseMethod(F.Block(F.Return(retExpression)));
            }
コード例 #59
0
 private static void CheckConstraints(
     TypeParameterSymbol typeParameter,
     TypeParameterConstraintKind constraints,
     bool isValueType,
     bool isReferenceType,
     string effectiveBaseClassDescription,
     string deducedBaseTypeDescription,
     params string[] constraintTypeDescriptions)
 {
     Assert.Equal(constraints, Utils.GetTypeParameterConstraints(typeParameter));
     Assert.Equal(typeParameter.IsValueType, isValueType);
     Assert.Equal(typeParameter.IsReferenceType, isReferenceType);
     Assert.Null(typeParameter.BaseType);
     Assert.Equal(typeParameter.Interfaces.Length, 0);
     Utils.CheckSymbol(typeParameter.EffectiveBaseClassNoUseSiteDiagnostics, effectiveBaseClassDescription);
     Utils.CheckSymbol(typeParameter.DeducedBaseTypeNoUseSiteDiagnostics, deducedBaseTypeDescription);
     Utils.CheckSymbols(typeParameter.ConstraintTypes, constraintTypeDescriptions);
 }
コード例 #60
0
 /// <summary>
 /// If this method is a reduced extension method, returns a type inferred during reduction process for the type parameter.
 /// </summary>
 /// <param name="reducedFromTypeParameter">Type parameter of the corresponding <see cref="ReducedFrom"/> method.</param>
 /// <returns>Inferred type or Nothing if nothing was inferred.</returns>
 /// <exception cref="System.InvalidOperationException">If this is not a reduced extension method.</exception>
 /// <exception cref="System.ArgumentNullException">If <paramref name="reducedFromTypeParameter"/> is null.</exception>
 /// <exception cref="System.ArgumentException">If <paramref name="reducedFromTypeParameter"/> doesn't belong to the corresponding <see cref="ReducedFrom"/> method.</exception>
 public virtual TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
 {
     throw new InvalidOperationException();
 }