private SubstitutedParameterSymbol(Symbol containingSymbol, TypeMap map, ParameterSymbol originalParameter) :
     base(originalParameter)
 {
     Debug.Assert(originalParameter.IsDefinition);
     _containingSymbol = containingSymbol;
     _mapOrType = map;
 }
Example #2
0
 protected SynthesizedContainer(string name, int parameterCount, bool returnsVoid)
 {
     Debug.Assert(name != null);
     this.name = name;
     this.typeMap = TypeMap.Empty;
     this.typeParameters = CreateTypeParameters(parameterCount, returnsVoid);
 }
Example #3
0
 internal SynthesizedContainer(MethodSymbol topLevelMethod, string name, TypeKind typeKind)
 {
     this.typeKind = typeKind;
     this.containingSymbol = topLevelMethod.ContainingType;
     this.name = name;
     this.TypeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out this.typeParameters);
 }
Example #4
0
        protected SynthesizedContainer(string name, MethodSymbol topLevelMethod)
        {
            Debug.Assert(name != null);
            Debug.Assert(topLevelMethod != null);

            this.name = name;
            this.typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out this.typeParameters);
        }
 protected SynthesizedContainer(string name, int parameterCount, bool returnsVoid)
 {
     Debug.Assert(name != null);
     _name = name;
     _typeMap = TypeMap.Empty;
     _typeParameters = CreateTypeParameters(parameterCount, returnsVoid);
     _constructedFromTypeParameters = default(ImmutableArray<TypeParameterSymbol>);
 }
Example #6
0
 internal SynthesizedContainer(NamedTypeSymbol containingType, string name, TypeKind typeKind)
 {
     this.typeKind = typeKind;
     this.containingSymbol = containingType;
     this.name = name;
     this.TypeMap = TypeMap.Empty;
     this.typeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
 }
 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;
 }
 protected void AssignTypeMapAndTypeParameters(TypeMap typeMap, ImmutableArray<TypeParameterSymbol> typeParameters)
 {
     Debug.Assert(typeMap != null);
     Debug.Assert(this.TypeMap == null);
     Debug.Assert(!typeParameters.IsDefault);
     Debug.Assert(_typeParameters.IsDefault);
     this.TypeMap = typeMap;
     _typeParameters = typeParameters;
 }
Example #9
0
 internal override DisplayClassInstance ToOtherMethod(MethodSymbol method, TypeMap typeMap)
 {
     Debug.Assert(method.IsStatic);
     var otherOrdinal = this.ContainingSymbol.IsStatic
         ? this.Parameter.Ordinal
         : (this.Parameter.Ordinal + 1);
     var otherParameter = method.Parameters[otherOrdinal];
     return new DisplayClassInstanceFromParameter(otherParameter);
 }
Example #10
0
        protected SynthesizedContainer(string name, ImmutableArray<TypeParameterSymbol> typeParameters, TypeMap typeMap)
        {
            Debug.Assert(name != null);
            Debug.Assert(!typeParameters.IsDefault);
            Debug.Assert(typeMap != null);

            Name = name;
            _typeParameters = typeParameters;
            TypeMap = typeMap;
        }
        private ExpressionLambdaRewriter(TypeCompilationState compilationState, TypeMap typeMap, CSharpSyntaxNode node, DiagnosticBag diagnostics)
        {
            Bound = new SyntheticBoundNodeFactory(null, null, node, compilationState, diagnostics);
            Int32Type = Bound.SpecialType(SpecialType.System_Int32);
            ObjectType = Bound.SpecialType(SpecialType.System_Object);
            NullableType = Bound.SpecialType(SpecialType.System_Nullable_T);
            IEnumerableType = Bound.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T);

            this.typeMap = typeMap;
        }
Example #12
0
 internal static LocalSymbol ToOtherMethod(this LocalSymbol local, MethodSymbol method, TypeMap typeMap)
 {
     var l = local as EELocalSymbolBase;
     if ((object)l != null)
     {
         return l.ToOtherMethod(method, typeMap);
     }
     var type = typeMap.SubstituteType(local.Type);
     return new EELocalSymbol(method, local.Locations, local.Name, -1, local.DeclarationKind, type.Type, local.RefKind, local.IsPinned, local.IsCompilerGenerated, local.CanScheduleToStack);
 }
        private static ConsList<FieldSymbol> SubstituteFields(ConsList<FieldSymbol> fields, TypeMap typeMap)
        {
            if (!fields.Any())
            {
                return ConsList<FieldSymbol>.Empty;
            }

            var head = SubstituteField(fields.Head, typeMap);
            var tail = SubstituteFields(fields.Tail, typeMap);
            return tail.Prepend(head);
        }
        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
        }
 protected SynthesizedContainer(string name, MethodSymbol containingMethod)
 {
     Debug.Assert(name != null);
     _name = name;
     if (containingMethod == null)
     {
         _typeMap = TypeMap.Empty;
         _typeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
     }
     else
     {
         _typeMap = TypeMap.Empty.WithConcatAlphaRename(containingMethod, this, out _typeParameters, out _constructedFromTypeParameters);
     }
 }
        protected SubstitutedNamedTypeSymbol(Symbol newContainer, TypeMap map, NamedTypeSymbol originalDefinition, NamedTypeSymbol constructedFrom = null, bool unbound = false)
        {
            Debug.Assert(originalDefinition.IsDefinition);
            _originalDefinition = originalDefinition;
            _newContainer = newContainer;
            _inputMap = map;
            _unbound = unbound;

            // if we're substituting to create a new unconstructed type as a member of a constructed type,
            // then we must alpha rename the type parameters.
            if ((object)constructedFrom != null)
            {
                Debug.Assert(ReferenceEquals(constructedFrom.ConstructedFrom, constructedFrom));
                _lazyTypeParameters = constructedFrom.TypeParameters;
                _lazyMap = map;
            }
        }
 protected SubstitutedMethodSymbol(NamedTypeSymbol containingSymbol, TypeMap map, MethodSymbol originalDefinition, MethodSymbol constructedFrom)
 {
     Debug.Assert(originalDefinition.IsDefinition);
     _containingType = containingSymbol;
     this.originalDefinition = originalDefinition;
     _inputMap = map;
     if ((object)constructedFrom != null)
     {
         _constructedFrom = constructedFrom;
         Debug.Assert(ReferenceEquals(constructedFrom.ConstructedFrom, constructedFrom));
         _lazyTypeParameters = constructedFrom.TypeParameters;
         _lazyMap = map;
     }
     else
     {
         _constructedFrom = this;
     }
 }
Example #18
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();
        }
Example #19
0
        public bool Equals(Symbol member1, Symbol member2)
        {
            if (ReferenceEquals(member1, member2))
            {
                return(true);
            }

            if ((object)member1 == null || (object)member2 == null || member1.Kind != member2.Kind)
            {
                return(false);
            }

            bool sawInterfaceInName1 = false;
            bool sawInterfaceInName2 = false;

            if (_considerName)
            {
                string name1 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member1.Name);
                string name2 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member2.Name);

                sawInterfaceInName1 = name1 != member1.Name;
                sawInterfaceInName2 = name2 != member2.Name;

                if (name1 != name2)
                {
                    return(false);
                }
            }

            // NB: up to, and including, this check, we have not actually forced the (type) parameters
            // to be expanded - we're only using the counts.
            int arity = member1.GetMemberArity();

            if ((arity != member2.GetMemberArity()) ||
                (member1.GetParameterCount() != member2.GetParameterCount()))
            {
                return(false);
            }

            TypeMap typeMap1 = GetTypeMap(member1);
            TypeMap typeMap2 = GetTypeMap(member2);

            if (_considerReturnType && !HaveSameReturnTypes(member1, typeMap1, member2, typeMap2, _typeComparison))
            {
                return(false);
            }

            if (member1.GetParameterCount() > 0 && !HaveSameParameterTypes(member1.GetParameters(), typeMap1, member2.GetParameters(), typeMap2,
                                                                           _considerRefKindDifferences, _typeComparison))
            {
                return(false);
            }

            if (_considerCallingConvention)
            {
                if (GetCallingConvention(member1) != GetCallingConvention(member2))
                {
                    return(false);
                }
            }
            else
            {
                if (IsVarargMethod(member1) != IsVarargMethod(member2))
                {
                    return(false);
                }
            }

            if (_considerExplicitlyImplementedInterfaces)
            {
                if (sawInterfaceInName1 != sawInterfaceInName2)
                {
                    return(false);
                }

                // The purpose of this check is to determine whether the interface parts of the member names agree,
                // but to do so using robust symbolic checks, rather than syntactic ones.  Therefore, if neither member
                // name contains an interface name, this check is not relevant.
                // Phrased differently, the explicitly implemented interface is not part of the signature unless it's
                // part of the name.
                if (sawInterfaceInName1)
                {
                    Debug.Assert(sawInterfaceInName2);

                    // May avoid realizing interface members.
                    if (member1.IsExplicitInterfaceImplementation() != member2.IsExplicitInterfaceImplementation())
                    {
                        return(false);
                    }

                    // By comparing symbols, rather than syntax, we gain the flexibility of ignoring whitespace
                    // and gracefully accepting multiple names for the same (or equivalent) types (e.g. "I<int>.M"
                    // vs "I<System.Int32>.M"), but we lose the connection with the name.  For example, in metadata,
                    // a method name "I.M" could have nothing to do with "I" but explicitly implement interface "I2".
                    // We will behave as if the method was really named "I2.M".  Furthermore, in metadata, a method
                    // can explicitly implement more than one interface method, in which case it doesn't really
                    // make sense to pretend that all of them are part of the signature.

                    var explicitInterfaceImplementations1 = member1.GetExplicitInterfaceImplementations();
                    var explicitInterfaceImplementations2 = member2.GetExplicitInterfaceImplementations();

                    if (!explicitInterfaceImplementations1.SetEquals(explicitInterfaceImplementations2, SymbolEqualityComparer.ConsiderEverything))
                    {
                        return(false);
                    }
                }
            }

            return(!_considerTypeConstraints || HaveSameConstraints(member1, typeMap1, member2, typeMap2));
        }
Example #20
0
 public SubstitutedNestedErrorTypeSymbol(NamedTypeSymbol containingSymbol, ErrorTypeSymbol originalDefinition) :
     base(originalDefinition)
 {
     this.containingSymbol = containingSymbol;
     this.map = containingSymbol.TypeSubstitution.WithAlphaRename(originalDefinition, this, out this.typeParameters);
 }
Example #21
0
 internal ImmutableArray <TypeWithAnnotations> GetTypeParametersAsTypeArguments()
 {
     return(TypeMap.TypeParametersAsTypeSymbolsWithAnnotations(TypeParameters));
 }
Example #22
0
        private static bool HaveSameConstraints(Symbol member1, TypeMap typeMap1, Symbol member2, TypeMap typeMap2)
        {
            Debug.Assert(member1.GetMemberArity() == member2.GetMemberArity());

            int arity = member1.GetMemberArity();

            if (arity == 0)
            {
                return(true);
            }

            var typeParameters1 = member1.GetMemberTypeParameters();
            var typeParameters2 = member2.GetMemberTypeParameters();

            return(HaveSameConstraints(typeParameters1, typeMap1, typeParameters2, typeMap2));
        }
Example #23
0
        // @t-mawind This is a hack...
        protected SynthesizedContainer(string name, Func <SynthesizedContainer, ImmutableArray <TypeParameterSymbol> > typeParametersF, TypeMap typeMap)
        {
            Debug.Assert(name != null);
            Debug.Assert(typeParametersF != null);
            Debug.Assert(typeMap != null);

            _name           = name;
            _typeParameters = typeParametersF(this);
            Debug.Assert(!_typeParameters.IsDefault);
            _typeMap = typeMap;
        }
        private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, CSharpCompilation compilation, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
        {
            Debug.Assert(method.IsExtensionMethod);
            Debug.Assert((object)thisType != null);

            if (!method.IsGenericMethod || method != method.ConstructedFrom)
            {
                return(method);
            }

            // We never resolve extension methods on a dynamic receiver.
            if (thisType.IsDynamic())
            {
                return(null);
            }

            var containingAssembly = method.ContainingAssembly;
            var errorNamespace     = containingAssembly.GlobalNamespace;
            var conversions        = new TypeConversions(containingAssembly.CorLibrary);

            // There is absolutely no plausible syntax/tree that we could use for these
            // synthesized literals.  We could be speculatively binding a call to a PE method.
            var syntaxTree = CSharpSyntaxTree.Dummy;
            var syntax     = (CSharpSyntaxNode)syntaxTree.GetRoot();

            // Create an argument value for the "this" argument of specific type,
            // and pass the same bad argument value for all other arguments.
            var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType)
            {
                WasCompilerGenerated = true
            };
            var otherArgumentType  = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false);
            var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType)
            {
                WasCompilerGenerated = true
            };

            var paramCount = method.ParameterCount;
            var arguments  = new BoundExpression[paramCount];

            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i] = argument;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                arguments.AsImmutable(),
                useSiteInfo: ref useSiteInfo);

            if (typeArgs.IsDefault)
            {
                return(null);
            }

            // For the purpose of constraint checks we use error type symbol in place of type arguments that we couldn't infer from the first argument.
            // This prevents constraint checking from failing for corresponding type parameters.
            int firstNullInTypeArgs       = -1;
            var notInferredTypeParameters = PooledHashSet <TypeParameterSymbol> .GetInstance();

            var typeParams = method.TypeParameters;
            var typeArgsForConstraintsCheck = typeArgs;

            for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++)
            {
                if (!typeArgsForConstraintsCheck[i].HasType)
                {
                    firstNullInTypeArgs = i;
                    var builder = ArrayBuilder <TypeWithAnnotations> .GetInstance();

                    builder.AddRange(typeArgsForConstraintsCheck, firstNullInTypeArgs);

                    for (; i < typeArgsForConstraintsCheck.Length; i++)
                    {
                        var typeArg = typeArgsForConstraintsCheck[i];
                        if (!typeArg.HasType)
                        {
                            notInferredTypeParameters.Add(typeParams[i]);
                            builder.Add(TypeWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType));
                        }
                        else
                        {
                            builder.Add(typeArg);
                        }
                    }

                    typeArgsForConstraintsCheck = builder.ToImmutableAndFree();
                    break;
                }
            }

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance();

            var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck);
            ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(new ConstraintsHelper.CheckConstraintsArgs(compilation, conversions, includeNullability: false, NoLocation.Singleton, diagnostics: null, template: new CompoundUseSiteInfo <AssemblySymbol>(useSiteInfo)),
                                                  substitution, typeParams, typeArgsForConstraintsCheck, diagnosticsBuilder, nullabilityDiagnosticsBuilderOpt: null,
                                                  ref useSiteDiagnosticsBuilder,
                                                  ignoreTypeConstraintsDependentOnTypeParametersOpt: notInferredTypeParameters.Count > 0 ? notInferredTypeParameters : null);

            diagnosticsBuilder.Free();
            notInferredTypeParameters.Free();

            if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0)
            {
                foreach (var diag in useSiteDiagnosticsBuilder)
                {
                    useSiteInfo.Add(diag.UseSiteInfo);
                }
            }

            if (!success)
            {
                return(null);
            }

            // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument.
            ImmutableArray <TypeWithAnnotations> typeArgsForConstruct = typeArgs;

            if (typeArgs.Any(t => !t.HasType))
            {
                typeArgsForConstruct = typeArgs.ZipAsArray(
                    method.TypeParameters,
                    (t, tp) => t.HasType ? t : TypeWithAnnotations.Create(tp));
            }

            return(method.Construct(typeArgsForConstruct));
        }
 private FieldSymbol VisitFieldSymbol(FieldSymbol field)
 {
     //  Property of a regular type
     return(((FieldSymbol)field.OriginalDefinition)
            .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(field.ContainingType).AsTypeSymbolOnly()));
 }
Example #26
0
 private static void SubstituteConstraintTypes(ImmutableArray <TypeWithAnnotations> types, TypeMap typeMap, HashSet <TypeSymbol> result)
 {
     foreach (var type in types)
     {
         result.Add(typeMap.SubstituteType(type).Type);
     }
 }
Example #27
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, SymbolEqualityComparer.AllIgnoreOptionsPlusNullableWithUnknownMatchesAny));
        }
Example #28
0
        private static bool HaveSameTypeConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2, IEqualityComparer <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));
        }
Example #29
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, SymbolEqualityComparer.IgnoringDynamicTupleNamesAndNullability));
        }
Example #30
0
        public static bool HaveSameConstraints(ImmutableArray <TypeParameterSymbol> typeParameters1, TypeMap typeMap1, ImmutableArray <TypeParameterSymbol> typeParameters2, TypeMap typeMap2)
        {
            Debug.Assert(typeParameters1.Length == typeParameters2.Length);

            int arity = typeParameters1.Length;

            for (int i = 0; i < arity; i++)
            {
                if (!HaveSameConstraints(typeParameters1[i], typeMap1, typeParameters2[i], typeMap2))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #31
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)
        {
            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())
            {
                // "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)
            {
                // Caller should have already reported ERR_GenericArgIsStaticClass.
                // (For consistency, consider moving that error reporting here.)
                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.SubstituteTypesDistinct(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);
        }
Example #32
0
        public static ImmutableArray <T> SubstituteExplicitInterfaceImplementations <T>(ImmutableArray <T> unsubstitutedExplicitInterfaceImplementations, TypeMap map) where T : Symbol
        {
            var builder = ArrayBuilder <T> .GetInstance();

            foreach (var unsubstitutedPropertyImplemented in unsubstitutedExplicitInterfaceImplementations)
            {
                var unsubstitutedInterfaceType = unsubstitutedPropertyImplemented.ContainingType;
                Debug.Assert((object)unsubstitutedInterfaceType != null);
                var explicitInterfaceType = map.SubstituteNamedType(unsubstitutedInterfaceType);
                Debug.Assert((object)explicitInterfaceType != null);
                var name = unsubstitutedPropertyImplemented.Name; //should already be unqualified

                T substitutedMemberImplemented = null;
                foreach (var candidateMember in explicitInterfaceType.GetMembers(name))
                {
                    if (candidateMember.OriginalDefinition == unsubstitutedPropertyImplemented.OriginalDefinition)
                    {
                        substitutedMemberImplemented = (T)candidateMember;
                        break;
                    }
                }
                Debug.Assert((object)substitutedMemberImplemented != null); //if it was an explicit implementation before the substitution, it should still be after
                builder.Add(substitutedMemberImplemented);
            }

            return(builder.ToImmutableAndFree());
        }
Example #33
0
        /// <summary>
        /// Returns true if the two partial methods have the same constraints.
        /// </summary>
        private static bool HaveSameConstraints(SourceMemberMethodSymbol part1, SourceMemberMethodSymbol part2)
        {
            Debug.Assert(!ReferenceEquals(part1, part2));
            Debug.Assert(part1.Arity == part2.Arity);

            var typeParameters1 = part1.TypeParameters;

            int arity = typeParameters1.Length;
            if (arity == 0)
            {
                return true;
            }

            var typeParameters2 = part2.TypeParameters;
            var indexedTypeParameters = IndexedTypeParameterSymbol.Take(arity);
            var typeMap1 = new TypeMap(typeParameters1, indexedTypeParameters, allowAlpha: true);
            var typeMap2 = new TypeMap(typeParameters2, indexedTypeParameters, allowAlpha: true);

            return MemberSignatureComparer.HaveSameConstraints(typeParameters1, typeMap1, typeParameters2, typeMap2);
        }
 public sealed override TypeSymbol?VisitType(TypeSymbol?type)
 {
     return(TypeMap.SubstituteType(type).Type);
 }
Example #35
0
        private static bool HaveSameConstraints(ImmutableArray<TypeParameterSymbol> candidateTypeParameters, ImmutableArray<TypeParameterSymbol> desiredTypeParameters)
        {
            int arity = candidateTypeParameters.Length;
            if (arity != desiredTypeParameters.Length)
            {
                return false;
            }
            else if (arity == 0)
            {
                return true;
            }

            var indexedTypeParameters = IndexedTypeParameterSymbol.Take(arity);
            var candidateTypeMap = new TypeMap(candidateTypeParameters, indexedTypeParameters, allowAlpha: true);
            var desiredTypeMap = new TypeMap(desiredTypeParameters, indexedTypeParameters, allowAlpha: true);

            return MemberSignatureComparer.HaveSameConstraints(candidateTypeParameters, candidateTypeMap, desiredTypeParameters, desiredTypeMap);
        }
Example #36
0
        public bool Equals(Symbol member1, Symbol member2)
        {
            if (ReferenceEquals(member1, member2))
            {
                return(true);
            }

            if ((object)member1 == null || (object)member2 == null || member1.Kind != member2.Kind)
            {
                return(false);
            }

            bool sawInterfaceInName1 = false;
            bool sawInterfaceInName2 = false;

            if (_considerName)
            {
                string name1 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member1.Name);
                string name2 = ExplicitInterfaceHelpers.GetMemberNameWithoutInterfaceName(member2.Name);

                sawInterfaceInName1 = name1 != member1.Name;
                sawInterfaceInName2 = name2 != member2.Name;

                if (name1 != name2)
                {
                    return(false);
                }
            }

            // NB: up to, and including, this check, we have not actually forced the (type) parameters
            // to be expanded - we're only using the counts.
            int arity = member1.GetMemberArity();

            if ((arity != member2.GetMemberArity()) ||
                (member1.GetParameterCount() != member2.GetParameterCount()))
            {
                return(false);
            }

            TypeMap typeMap1;
            TypeMap typeMap2;

            if (arity > 0 && _useSpecialHandlingForNullableTypes)
            {
                // We need this special handling in order to avoid forcing resolution of nullable types
                // in signature of an overriding member while we are looking for a matching overridden member.
                // Doing the resolution in the original signature can send us into an infinite cycle because
                // constraints must be inherited from the member we are looking for.
                // It is important to ensure that the fact whether an indexed type parameter we are about to use
                // is a reference type is inherited from the corresponding type parameter of the possibly overridden
                // member (which is member2 when _useSpecialHandlingForNullableTypes is true). This will ensure
                // proper resolution for nullable types in substituted signature of member1, ensuring proper
                // comparison of types across both members.
                ArrayBuilder <TypeParameterSymbol> builder = ArrayBuilder <TypeParameterSymbol> .GetInstance(arity);

                var typeParameters2 = member2.GetMemberTypeParameters();

                for (int i = arity - 1; i >= 0; i--)
                {
                    builder.Add(IndexedTypeParameterSymbolForOverriding.GetTypeParameter(i, typeParameters2[i].IsValueType));
                }

                var indexed = builder.ToImmutableAndFree();

                typeMap1 = new TypeMap(member1.GetMemberTypeParameters(), indexed, true);
                typeMap2 = new TypeMap(typeParameters2, indexed, true);
            }
            else
            {
                typeMap1 = GetTypeMap(member1);
                typeMap2 = GetTypeMap(member2);
            }

            if (_considerReturnType && !HaveSameReturnTypes(member1, typeMap1, member2, typeMap2, _typeComparison))
            {
                return(false);
            }

            if (member1.GetParameterCount() > 0 && !HaveSameParameterTypes(member1.GetParameters(), typeMap1, member2.GetParameters(), typeMap2,
                                                                           _considerRefKindDifferences, _typeComparison))
            {
                return(false);
            }

            if (_considerCallingConvention)
            {
                if (GetCallingConvention(member1) != GetCallingConvention(member2))
                {
                    return(false);
                }
            }
            else
            {
                if (IsVarargMethod(member1) != IsVarargMethod(member2))
                {
                    return(false);
                }
            }

            if (_considerExplicitlyImplementedInterfaces)
            {
                if (sawInterfaceInName1 != sawInterfaceInName2)
                {
                    return(false);
                }

                // The purpose of this check is to determine whether the interface parts of the member names agree,
                // but to do so using robust symbolic checks, rather than syntactic ones.  Therefore, if neither member
                // name contains an interface name, this check is not relevant.
                // Phrased differently, the explicitly implemented interface is not part of the signature unless it's
                // part of the name.
                if (sawInterfaceInName1)
                {
                    Debug.Assert(sawInterfaceInName2);

                    // May avoid realizing interface members.
                    if (member1.IsExplicitInterfaceImplementation() != member2.IsExplicitInterfaceImplementation())
                    {
                        return(false);
                    }

                    // By comparing symbols, rather than syntax, we gain the flexibility of ignoring whitespace
                    // and gracefully accepting multiple names for the same (or equivalent) types (e.g. "I<int>.M"
                    // vs "I<System.Int32>.M"), but we lose the connection with the name.  For example, in metadata,
                    // a method name "I.M" could have nothing to do with "I" but explicitly implement interface "I2".
                    // We will behave as if the method was really named "I2.M".  Furthermore, in metadata, a method
                    // can explicitly implement more than one interface method, in which case it doesn't really
                    // make sense to pretend that all of them are part of the signature.

                    var explicitInterfaceImplementations1 = member1.GetExplicitInterfaceImplementations();
                    var explicitInterfaceImplementations2 = member2.GetExplicitInterfaceImplementations();

                    if (!explicitInterfaceImplementations1.SetEquals(explicitInterfaceImplementations2, EqualityComparer <Symbol> .Default))
                    {
                        return(false);
                    }
                }
            }

            return(!_considerTypeConstraints || HaveSameConstraints(member1, typeMap1, member2, typeMap2));
        }
Example #37
0
 internal override DisplayClassInstance ToOtherMethod(MethodSymbol method, TypeMap typeMap)
 {
     var otherInstance = (EELocalSymbol)this.Local.ToOtherMethod(method, typeMap);
     return new DisplayClassInstanceFromLocal(otherInstance);
 }
Example #38
0
        /// <summary>
        /// Check type parameter constraints for the containing type or method symbol.
        /// </summary>
        /// <param name="containingSymbol">The generic type or method.</param>
        /// <param name="conversions">Conversions instance.</param>
        /// <param name="substitution">The map from type parameters to type arguments.</param>
        /// <param name="typeParameters">Containing symbol type parameters.</param>
        /// <param name="typeArguments">Containing symbol type arguments.</param>
        /// <param name="currentCompilation">Improves error message detail.</param>
        /// <param name="diagnosticsBuilder">Diagnostics.</param>
        /// <param name="skipParameters">Parameters to skip.</param>
        /// <param name="useSiteDiagnosticsBuilder"/>
        /// <param name="ignoreTypeConstraintsDependentOnTypeParametersOpt">If an original form of a type constraint 
        /// depends on a type parameter from this set, do not verify this type constraint.</param>
        /// <returns>True if the constraints were satisfied, false otherwise.</returns>
        public static bool CheckConstraints(
            this Symbol containingSymbol,
            ConversionsBase conversions,
            TypeMap substitution,
            ImmutableArray<TypeParameterSymbol> typeParameters,
            ImmutableArray<TypeSymbol> typeArguments,
            Compilation currentCompilation,
            ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder,
            ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder,
            BitVector skipParameters = default(BitVector),
            HashSet<TypeParameterSymbol> ignoreTypeConstraintsDependentOnTypeParametersOpt = null)
        {
            Debug.Assert(typeParameters.Length == typeArguments.Length);
            Debug.Assert(typeParameters.Length > 0);

            int n = typeParameters.Length;
            bool succeeded = true;

            for (int i = 0; i < n; i++)
            {
                if (skipParameters[i])
                {
                    continue;
                }

                var typeArgument = typeArguments[i];
                var typeParameter = typeParameters[i];

                if (!CheckConstraints(containingSymbol, conversions, substitution, typeParameter, typeArgument, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder,
                                      ignoreTypeConstraintsDependentOnTypeParametersOpt))
                {
                    succeeded = false;
                }
            }

            return succeeded;
        }
Example #39
0
        private static bool HaveSameReturnTypes(Symbol member1, TypeMap typeMap1, Symbol member2, TypeMap typeMap2, TypeCompareKind typeComparison)
        {
            RefKind                         refKind1;
            TypeWithAnnotations             unsubstitutedReturnType1;
            ImmutableArray <CustomModifier> refCustomModifiers1;

            member1.GetTypeOrReturnType(out refKind1, out unsubstitutedReturnType1, out refCustomModifiers1);

            RefKind                         refKind2;
            TypeWithAnnotations             unsubstitutedReturnType2;
            ImmutableArray <CustomModifier> refCustomModifiers2;

            member2.GetTypeOrReturnType(out refKind2, out unsubstitutedReturnType2, out refCustomModifiers2);

            // short-circuit type map building in the easiest cases
            if (refKind1 != refKind2)
            {
                return(false);
            }

            var isVoid1 = unsubstitutedReturnType1.IsVoidType();
            var isVoid2 = unsubstitutedReturnType2.IsVoidType();

            if (isVoid1 != isVoid2)
            {
                return(false);
            }

            if (isVoid1)
            {
                if ((typeComparison & TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds) != 0 ||
                    (unsubstitutedReturnType1.CustomModifiers.IsEmpty && unsubstitutedReturnType2.CustomModifiers.IsEmpty))
                {
                    return(true);
                }
            }

            var returnType1 = SubstituteType(typeMap1, unsubstitutedReturnType1);
            var returnType2 = SubstituteType(typeMap2, unsubstitutedReturnType2);

            if (!returnType1.Equals(returnType2, typeComparison))
            {
                return(false);
            }

            if (((typeComparison & TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds) == 0) &&
                !HaveSameCustomModifiers(refCustomModifiers1, typeMap1, refCustomModifiers2, typeMap2))
            {
                return(false);
            }

            return(true);
        }
Example #40
0
        /// <summary>
        /// If the extension method is applicable based on the "this" argument type, return
        /// the method constructed with the inferred type arguments. If the method is not an
        /// unconstructed generic method, type inference is skipped. If the method is not
        /// applicable, or if constraints when inferring type parameters from the "this" type
        /// are not satisfied, the return value is null.
        /// </summary>
        public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol method, TypeSymbol thisType, Compilation compilation, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(method.IsExtensionMethod);
            Debug.Assert((object)thisType != null);

            if (!method.IsGenericMethod || method != method.ConstructedFrom)
            {
                return method;
            }

            // We never resolve extension methods on a dynamic receiver.
            if (thisType.IsDynamic())
            {
                return null;
            }

            var containingAssembly = method.ContainingAssembly;
            var errorNamespace = containingAssembly.GlobalNamespace;
            var conversions = new TypeConversions(containingAssembly.CorLibrary);

            // There is absolutely no plausible syntax/tree that we could use for these
            // synthesized literals.  We could be speculatively binding a call to a PE method.
            var syntaxTree = CSharpSyntaxTree.Dummy;
            var syntax = (CSharpSyntaxNode)syntaxTree.GetRoot();

            // Create an argument value for the "this" argument of specific type,
            // and pass the same bad argument value for all other arguments.
            var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType) { WasCompilerGenerated = true };
            var otherArgumentType = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false);
            var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType) { WasCompilerGenerated = true };

            var paramCount = method.ParameterCount;
            var arguments = new BoundExpression[paramCount];
            var argumentTypes = new TypeSymbol[paramCount];
            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i] = argument;
                argumentTypes[i] = argument.Type;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                argumentTypes.AsImmutableOrNull(),
                arguments.AsImmutableOrNull(),
                ref useSiteDiagnostics);

            if (typeArgs.IsDefault)
            {
                return null;
            }

            int firstNullInTypeArgs = -1;

            // For the purpose of constraint checks we use error type symbol in place of type arguments that we couldn't infer from the first argument.
            // This prevents constraint checking from failing for corresponding type parameters. 
            var typeArgsForConstraintsCheck = typeArgs;
            for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++)
            {
                if ((object)typeArgsForConstraintsCheck[i] == null)
                {
                    firstNullInTypeArgs = i;
                    var builder = ArrayBuilder<TypeSymbol>.GetInstance();
                    builder.AddRange(typeArgs, firstNullInTypeArgs);

                    for (; i < typeArgsForConstraintsCheck.Length; i++)
                    {
                        builder.Add(typeArgsForConstraintsCheck[i] ?? ErrorTypeSymbol.UnknownResultType);
                    }

                    typeArgsForConstraintsCheck = builder.ToImmutableAndFree();
                    break;
                }
            }

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
            var typeParams = method.TypeParameters;
            var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck.SelectAsArray(TypeMap.TypeSymbolAsTypeWithModifiers));
            ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, typeParams, typeArgsForConstraintsCheck, compilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);
            diagnosticsBuilder.Free();

            if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0)
            {
                if (useSiteDiagnostics == null)
                {
                    useSiteDiagnostics = new HashSet<DiagnosticInfo>();
                }

                foreach (var diag in useSiteDiagnosticsBuilder)
                {
                    useSiteDiagnostics.Add(diag.DiagnosticInfo);
                }
            }

            if (!success)
            {
                return null;
            }

            // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument.
            var typeArgsForConstruct = typeArgs;
            if (firstNullInTypeArgs != -1)
            {
                var builder = ArrayBuilder<TypeSymbol>.GetInstance();
                builder.AddRange(typeArgs, firstNullInTypeArgs);

                for (int i = firstNullInTypeArgs; i < typeArgsForConstruct.Length; i++)
                {
                    builder.Add(typeArgsForConstruct[i] ?? typeParams[i]);
                }

                typeArgsForConstruct = builder.ToImmutableAndFree();
            }

            return method.Construct(typeArgsForConstruct);
        }
Example #41
0
        public static bool HaveSameConstraints(ImmutableArray <TypeParameterSymbol> typeParameters1, TypeMap typeMap1, ImmutableArray <TypeParameterSymbol> typeParameters2, TypeMap typeMap2, bool includingNullability = false)
        {
            Debug.Assert(typeParameters1.Length == typeParameters2.Length);

            int arity = typeParameters1.Length;

            for (int i = 0; i < arity; i++)
            {
                if (!HaveSameConstraints(typeParameters1[i], typeMap1, typeParameters2[i], typeMap2) ||
                    (includingNullability && !HaveSameNullabilityInConstraints(typeParameters1[i], typeMap1, typeParameters2[i], typeMap2, unknownNullabilityMatchesAny: false)))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #42
0
        private TypeMap WithAlphaRename(ImmutableArray<TypeParameterSymbol> oldTypeParameters, Symbol newOwner, out ImmutableArray<TypeParameterSymbol> newTypeParameters)
        {
            if (oldTypeParameters.Length == 0)
            {
                newTypeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
                return this;
            }

            // Note: the below assertion doesn't hold while rewriting async lambdas defined inside generic methods.
            // The async rewriter adds a synthesized struct inside the lambda frame and construct a typemap from
            // the lambda frame's substituted type parameters.
            // Debug.Assert(!oldTypeParameters.Any(tp => tp is SubstitutedTypeParameterSymbol));

            // warning: we expose result to the SubstitutedTypeParameterSymbol constructor, below, even before it's all filled in.
            TypeMap result = new TypeMap(this.Mapping);
            ArrayBuilder<TypeParameterSymbol> newTypeParametersBuilder = ArrayBuilder<TypeParameterSymbol>.GetInstance();

            // The case where it is "synthesized" is when we're creating type parameters for a synthesized (generic)
            // class or method for a lambda appearing in a generic method.
            bool synthesized = !ReferenceEquals(oldTypeParameters[0].ContainingSymbol.OriginalDefinition, newOwner.OriginalDefinition);

            int ordinal = 0;
            foreach (var tp in oldTypeParameters)
            {
                var newTp = synthesized ?
                    new SynthesizedSubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal) :
                    new SubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal);
                result.Mapping.Add(tp, new TypeWithModifiers(newTp));
                newTypeParametersBuilder.Add(newTp);
                ordinal++;
            }

            newTypeParameters = newTypeParametersBuilder.ToImmutableAndFree();
            return result;
        }
        private ExpressionLambdaRewriter(TypeCompilationState compilationState, TypeMap typeMap, CSharpSyntaxNode node, DiagnosticBag diagnostics)
        {
            _bound = new SyntheticBoundNodeFactory(null, compilationState.Type, node, compilationState, diagnostics);
            _ignoreAccessibility = compilationState.ModuleBuilderOpt.IgnoreAccessibility;
            _int32Type = _bound.SpecialType(SpecialType.System_Int32);
            _objectType = _bound.SpecialType(SpecialType.System_Object);
            _nullableType = _bound.SpecialType(SpecialType.System_Nullable_T);
            _IEnumerableType = _bound.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T);

            _typeMap = typeMap;
        }
Example #44
0
 internal abstract DisplayClassInstance ToOtherMethod(MethodSymbol method, TypeMap typeMap);
Example #45
0
        /// <summary>
        /// If the extension method is applicable based on the "this" argument type, return
        /// the method constructed with the inferred type arguments. If the method is not an
        /// unconstructed generic method, type inference is skipped. If the method is not
        /// applicable, or if constraints when inferring type parameters from the "this" type
        /// are not satisfied, the return value is null.
        /// </summary>
        public static MethodSymbol InferExtensionMethodTypeArguments(this MethodSymbol method, TypeSymbol thisType, Compilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(method.IsExtensionMethod);
            Debug.Assert((object)thisType != null);

            if (!method.IsGenericMethod || method != method.ConstructedFrom)
            {
                return(method);
            }

            // We never resolve extension methods on a dynamic receiver.
            if (thisType.IsDynamic())
            {
                return(null);
            }

            var containingAssembly = method.ContainingAssembly;
            var errorNamespace     = containingAssembly.GlobalNamespace;
            var conversions        = new TypeConversions(containingAssembly.CorLibrary);

            // There is absolutely no plausible syntax/tree that we could use for these
            // synthesized literals.  We could be speculatively binding a call to a PE method.
            var syntaxTree = CSharpSyntaxTree.Dummy;
            var syntax     = (CSharpSyntaxNode)syntaxTree.GetRoot();

            // Create an argument value for the "this" argument of specific type,
            // and pass the same bad argument value for all other arguments.
            var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType)
            {
                WasCompilerGenerated = true
            };
            var otherArgumentType  = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false);
            var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType)
            {
                WasCompilerGenerated = true
            };

            var paramCount    = method.ParameterCount;
            var arguments     = new BoundExpression[paramCount];
            var argumentTypes = new TypeSymbol[paramCount];

            for (int i = 0; i < paramCount; i++)
            {
                var argument = (i == 0) ? thisArgumentValue : otherArgumentValue;
                arguments[i]     = argument;
                argumentTypes[i] = argument.Type;
            }

            var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument(
                conversions,
                method,
                argumentTypes.AsImmutableOrNull(),
                arguments.AsImmutableOrNull(),
                ref useSiteDiagnostics);

            if (typeArgs.IsDefault)
            {
                return(null);
            }

            // Check constraints.
            var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance();

            var typeParams   = method.TypeParameters;
            var substitution = new TypeMap(typeParams, typeArgs);
            ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var success = method.CheckConstraints(conversions, substitution, method.TypeParameters, typeArgs, compilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);

            diagnosticsBuilder.Free();

            if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0)
            {
                if (useSiteDiagnostics == null)
                {
                    useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                }

                foreach (var diag in useSiteDiagnosticsBuilder)
                {
                    useSiteDiagnostics.Add(diag.DiagnosticInfo);
                }
            }

            if (!success)
            {
                return(null);
            }

            return(method.Construct(typeArgs));
        }
Example #46
0
        private static bool HaveSameParameterTypes(ImmutableArray <ParameterSymbol> params1, TypeMap typeMap1, ImmutableArray <ParameterSymbol> params2, TypeMap typeMap2,
                                                   bool considerRefKindDifferences, TypeCompareKind typeComparison)
        {
            Debug.Assert(params1.Length == params2.Length);

            var numParams = params1.Length;

            for (int i = 0; i < numParams; i++)
            {
                var param1 = params1[i];
                var param2 = params2[i];

                var type1 = SubstituteType(typeMap1, param1.TypeWithAnnotations);
                var type2 = SubstituteType(typeMap2, param2.TypeWithAnnotations);

                if (!type1.Equals(type2, typeComparison))
                {
                    return(false);
                }

                if ((typeComparison & TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds) == 0 &&
                    !HaveSameCustomModifiers(param1.RefCustomModifiers, typeMap1, param2.RefCustomModifiers, typeMap2))
                {
                    return(false);
                }

                var refKind1 = param1.RefKind;
                var refKind2 = param2.RefKind;

                // Metadata signatures don't distinguish ref/out, but C# does - even when comparing metadata method signatures.
                if (considerRefKindDifferences)
                {
                    if (refKind1 != refKind2)
                    {
                        return(false);
                    }
                }
                else
                {
                    if ((refKind1 == RefKind.None) != (refKind2 == RefKind.None))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #47
0
        public static bool HaveSameNullabilityInConstraints(TypeParameterSymbol typeParameter1, TypeMap typeMap1, TypeParameterSymbol typeParameter2, TypeMap typeMap2, bool unknownNullabilityMatchesAny = true)
        {
            if (!typeParameter1.IsValueType)
            {
                bool?isNotNullableIfReferenceType1 = typeParameter1.IsNotNullableIfReferenceType;
                bool?isNotNullableIfReferenceType2 = typeParameter2.IsNotNullableIfReferenceType;
                if (isNotNullableIfReferenceType1 != isNotNullableIfReferenceType2 &&
                    !(unknownNullabilityMatchesAny && (!isNotNullableIfReferenceType1.HasValue || !isNotNullableIfReferenceType2.HasValue)))
                {
                    return(false);
                }
            }

            return(HaveSameTypeConstraints(typeParameter1, typeMap1, typeParameter2, typeMap2,
                                           unknownNullabilityMatchesAny ?
                                           TypeSymbol.EqualsAllIgnoreOptionsPlusNullableWithUnknownMatchesAnyComparer :
                                           TypeSymbol.EqualsAllIgnoreOptionsPlusNullableComparer));
        }
        public void TypeMap()
        {
            var source = @"
struct S<T> where T : struct
{
}
";

            var comp = CreateCompilationWithMscorlib(source);
            comp.VerifyDiagnostics();

            var intType = comp.GetSpecialType(SpecialType.System_Int32);
            var customModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateOptional(intType));

            var structType = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("S");
            var typeParamType = structType.TypeParameters.Single();

            var pointerType = new PointerTypeSymbol(typeParamType, customModifiers); // NOTE: We're constructing this manually, since it's illegal.
            var arrayType = new ArrayTypeSymbol(comp.Assembly, typeParamType, customModifiers); // This is legal, but we're already manually constructing types.

            var typeMap = new TypeMap(ImmutableArray.Create(typeParamType), ImmutableArray.Create<TypeSymbol>(intType));

            var substitutedPointerType = (PointerTypeSymbol)typeMap.SubstituteType(pointerType);
            var substitutedArrayType = (ArrayTypeSymbol)typeMap.SubstituteType(arrayType);

            // The map changed the types.
            Assert.Equal(intType, substitutedPointerType.PointedAtType);
            Assert.Equal(intType, substitutedArrayType.ElementType);

            // The map preserved the custom modifiers.
            Assert.Equal(customModifiers, substitutedPointerType.CustomModifiers);
            Assert.Equal(customModifiers, substitutedArrayType.CustomModifiers);
        }
Example #49
0
 private static TypeWithAnnotations SubstituteType(TypeMap typeMap, TypeWithAnnotations typeSymbol)
 {
     return(typeMap == null ? typeSymbol : typeSymbol.SubstituteType(typeMap));
 }
Example #50
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;
        }
Example #51
0
 private static bool HaveSameCustomModifiers(ImmutableArray <CustomModifier> customModifiers1, TypeMap typeMap1, ImmutableArray <CustomModifier> customModifiers2, TypeMap typeMap2)
 {
     // the runtime compares custom modifiers using (effectively) SequenceEqual
     return(SubstituteModifiers(typeMap1, customModifiers1).SequenceEqual(SubstituteModifiers(typeMap2, customModifiers2)));
 }
Example #52
0
 private static ImmutableArray <CustomModifier> SubstituteModifiers(TypeMap typeMap, ImmutableArray <CustomModifier> customModifiers)
 {
     return(typeMap == null ? customModifiers : typeMap.SubstituteCustomModifiers(customModifiers));
 }
Example #53
0
 internal SubstitutedParameterSymbol(PropertySymbol containingSymbol, TypeMap map, ParameterSymbol originalParameter) :
     this((Symbol)containingSymbol, map, originalParameter)
 {
 }
 internal static BoundNode RewriteLambda(BoundLambda node, TypeCompilationState compilationState, TypeMap typeMap, DiagnosticBag diagnostics)
 {
     try
     {
         var r = new ExpressionLambdaRewriter(compilationState, typeMap, node.Syntax, diagnostics);
         var result = r.VisitLambdaInternal(node);
         if (node.Type != result.Type)
         {
             diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, node.Syntax.Location, r.ExpressionType, "Lambda");
         }
         return result;
     }
     catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
     {
         diagnostics.Add(ex.Diagnostic);
         return node;
     }
 }
Example #55
0
        protected SynthesizedContainer(string name, ImmutableArray <TypeParameterSymbol> typeParameters, TypeMap typeMap)
        {
            Debug.Assert(name != null);
            Debug.Assert(!typeParameters.IsDefault);
            Debug.Assert(typeMap != null);

            Name            = name;
            _typeParameters = typeParameters;
            TypeMap         = typeMap;
        }
 internal override EELocalSymbolBase ToOtherMethod(MethodSymbol method, TypeMap typeMap)
 {
     // Placeholders should be rewritten (as method calls)
     // rather than copied as locals to the target method.
     throw ExceptionUtilities.Unreachable;
 }
        protected MethodSymbol VisitMethodSymbol(MethodSymbol method)
        {
            if ((object)method == null)
            {
                return(null);
            }

            if (method.IsTupleMethod)
            {
                //  Method of a tuple type
                var oldType         = method.ContainingType;
                var constructedFrom = method.ConstructedFrom;
                Debug.Assert(oldType.IsTupleType);

                var newType = (NamedTypeSymbol)TypeMap.SubstituteType(oldType).AsTypeSymbolOnly();
                if ((object)newType == oldType)
                {
                    //  tuple type symbol was not rewritten
                    return(constructedFrom.ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)));
                }

                Debug.Assert(newType.IsTupleType);
                Debug.Assert(oldType.TupleElementTypes.Length == newType.TupleElementTypes.Length);

                //  get a new method by position
                var oldMembers = oldType.GetMembers();
                var newMembers = newType.GetMembers();
                Debug.Assert(oldMembers.Length == newMembers.Length);

                for (int i = 0; i < oldMembers.Length; i++)
                {
                    if ((object)constructedFrom == oldMembers[i])
                    {
                        return(((MethodSymbol)newMembers[i]).ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)));
                    }
                }

                throw ExceptionUtilities.Unreachable;
            }
            else if (method.ContainingType.IsAnonymousType)
            {
                //  Method of an anonymous type
                var newType = (NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly();
                if (ReferenceEquals(newType, method.ContainingType))
                {
                    //  Anonymous type symbol was not rewritten
                    return(method);
                }

                //  get a new method by name
                foreach (var member in newType.GetMembers(method.Name))
                {
                    if (member.Kind == SymbolKind.Method)
                    {
                        return((MethodSymbol)member);
                    }
                }

                throw ExceptionUtilities.Unreachable;
            }
            else
            {
                //  Method of a regular type
                return(((MethodSymbol)method.OriginalDefinition)
                       .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(method.ContainingType).AsTypeSymbolOnly())
                       .ConstructIfGeneric(TypeMap.SubstituteTypesWithoutModifiers(method.TypeArguments)));
            }
        }