Esempio n. 1
0
        private NamedTypeSymbol ApplyGenericArguments(NamedTypeSymbol symbol, Type[] typeArguments, ref int currentTypeArgument, bool includeReferences)
        {
            int remainingTypeArguments = typeArguments.Length - currentTypeArgument;

            // in case we are specializing a nested generic definition we might have more arguments than the current symbol:
            Debug.Assert(remainingTypeArguments >= symbol.Arity);

            if (remainingTypeArguments == 0)
            {
                return(symbol);
            }

            TypeSymbol[] typeArgumentSymbols = new TypeSymbol[symbol.TypeArgumentsNoUseSiteDiagnostics.Length];
            for (int i = 0; i < typeArgumentSymbols.Length; i++)
            {
                var argSymbol = GetTypeByReflectionType(typeArguments[currentTypeArgument++], includeReferences);
                if ((object)argSymbol == null)
                {
                    return(null);
                }
                typeArgumentSymbols[i] = argSymbol;
            }

            return(symbol.ConstructIfGeneric(typeArgumentSymbols.AsImmutableOrNull()));
        }
Esempio n. 2
0
        /// <summary>
        /// SubstType, but for NamedTypeSymbols only.  This is used for concrete types, so no alpha substitution appears in the result.
        /// </summary>
        internal NamedTypeSymbol SubstituteNamedType(NamedTypeSymbol previous)
        {
            if (ReferenceEquals(previous, null))
            {
                return(null);
            }

            if (previous.IsUnboundGenericType)
            {
                return(previous);
            }

            if (previous.IsAnonymousType)
            {
                ImmutableArray <TypeSymbol> oldFieldTypes = AnonymousTypeManager.GetAnonymousTypePropertyTypes(previous);
                ImmutableArray <TypeSymbol> newFieldTypes = SubstituteTypes(oldFieldTypes);
                return((oldFieldTypes == newFieldTypes) ? previous : AnonymousTypeManager.ConstructAnonymousTypeSymbol(previous, newFieldTypes));
            }

            // TODO: we could construct the result's ConstructedFrom lazily by using a "deep"
            // construct operation here (as VB does), thereby avoiding alpha renaming in most cases.
            // Aleksey has shown that would reduce GC pressure if substitutions of deeply nested generics are common.
            NamedTypeSymbol oldConstructedFrom = previous.ConstructedFrom;
            NamedTypeSymbol newConstructedFrom = SubstituteMemberType(oldConstructedFrom);

            ImmutableArray <TypeSymbol> oldTypeArguments = previous.TypeArgumentsNoUseSiteDiagnostics;
            ImmutableArray <TypeSymbol> newTypeArguments = SubstituteTypes(oldTypeArguments);

            if (ReferenceEquals(oldConstructedFrom, newConstructedFrom) && oldTypeArguments == newTypeArguments)
            {
                return(previous);
            }

            return(newConstructedFrom.ConstructIfGeneric(newTypeArguments));
        }
Esempio n. 3
0
        /// <summary>
        /// SubstType, but for NamedTypeSymbols only.  This is used for concrete types, so no alpha substitution appears in the result.
        /// </summary>
        internal NamedTypeSymbol SubstituteNamedType(NamedTypeSymbol previous)
        {
            if (ReferenceEquals(previous, null))
            {
                return(null);
            }

            if (previous.IsUnboundGenericType)
            {
                return(previous);
            }

            if (previous.IsAnonymousType)
            {
                ImmutableArray <TypeSymbol> oldFieldTypes = AnonymousTypeManager.GetAnonymousTypePropertyTypes(previous);
                ImmutableArray <TypeSymbol> newFieldTypes = SubstituteTypesWithoutModifiers(oldFieldTypes);
                return((oldFieldTypes == newFieldTypes) ? previous : AnonymousTypeManager.ConstructAnonymousTypeSymbol(previous, newFieldTypes));
            }

            if (previous.IsTupleType)
            {
                var             previousTuple     = (TupleTypeSymbol)previous;
                NamedTypeSymbol oldUnderlyingType = previousTuple.TupleUnderlyingType;
                NamedTypeSymbol newUnderlyingType = (NamedTypeSymbol)SubstituteType(oldUnderlyingType).Type;

                return(((object)newUnderlyingType == (object)oldUnderlyingType) ? previous : previousTuple.WithUnderlyingType(newUnderlyingType));
            }

            // TODO: we could construct the result's ConstructedFrom lazily by using a "deep"
            // construct operation here (as VB does), thereby avoiding alpha renaming in most cases.
            // Aleksey has shown that would reduce GC pressure if substitutions of deeply nested generics are common.
            NamedTypeSymbol oldConstructedFrom = previous.ConstructedFrom;
            NamedTypeSymbol newConstructedFrom = SubstituteMemberType(oldConstructedFrom);

            ImmutableArray <TypeSymbol> oldTypeArguments = previous.TypeArgumentsNoUseSiteDiagnostics;
            bool changed          = !ReferenceEquals(oldConstructedFrom, newConstructedFrom);
            bool hasModifiers     = previous.HasTypeArgumentsCustomModifiers;
            var  newTypeArguments = ArrayBuilder <TypeWithModifiers> .GetInstance(oldTypeArguments.Length);

            for (int i = 0; i < oldTypeArguments.Length; i++)
            {
                var oldArgument = hasModifiers ? new TypeWithModifiers(oldTypeArguments[i], previous.GetTypeArgumentCustomModifiers(i)) : new TypeWithModifiers(oldTypeArguments[i]);
                var newArgument = oldArgument.SubstituteTypeWithTupleUnification(this);

                if (!changed && oldArgument != newArgument)
                {
                    changed = true;
                }

                newTypeArguments.Add(newArgument);
            }

            if (!changed)
            {
                newTypeArguments.Free();
                return(previous);
            }

            return(newConstructedFrom.ConstructIfGeneric(newTypeArguments.ToImmutableAndFree()));
        }
Esempio n. 4
0
        private NamedTypeSymbol ApplyGenericArguments(NamedTypeSymbol symbol, Type[] typeArguments, ref int currentTypeArgument, bool includeReferences)
        {
            int remainingTypeArguments = typeArguments.Length - currentTypeArgument;

            // in case we are specializing a nested generic definition we might have more arguments than the current symbol:
            Debug.Assert(remainingTypeArguments >= symbol.Arity);

            if (remainingTypeArguments == 0)
            {
                return(symbol);
            }

            var length = symbol.TypeArgumentsNoUseSiteDiagnostics.Length;
            var typeArgumentSymbols = ArrayBuilder <TypeSymbolWithAnnotations> .GetInstance(length);

            for (int i = 0; i < length; i++)
            {
                var argSymbol = GetTypeByReflectionType(typeArguments[currentTypeArgument++], includeReferences);
                if ((object)argSymbol == null)
                {
                    return(null);
                }
                typeArgumentSymbols.Add(TypeSymbolWithAnnotations.Create(argSymbol));
            }

            return(symbol.ConstructIfGeneric(typeArgumentSymbols.ToImmutableAndFree()));
        }
Esempio n. 5
0
        internal NamedTypeSymbol SubstituteNamedType(NamedTypeSymbol previous)
        {
            if (ReferenceEquals(previous, null))
            {
                return(null);
            }

            if (previous.IsUnboundGenericType)
            {
                return(previous);
            }

            if (previous.IsAnonymousType)
            {
                ImmutableArray <TypeWithAnnotations> oldFieldTypes =
                    AnonymousTypeManager.GetAnonymousTypePropertyTypesWithAnnotations(previous);
                ImmutableArray <TypeWithAnnotations> newFieldTypes = SubstituteTypes(oldFieldTypes);
                return((oldFieldTypes == newFieldTypes)
                  ? previous
                  : AnonymousTypeManager.ConstructAnonymousTypeSymbol(previous, newFieldTypes));
            }

            // TODO: we could construct the result's ConstructedFrom lazily by using a "deep"
            // construct operation here (as VB does), thereby avoiding alpha renaming in most cases.
            // Aleksey has shown that would reduce GC pressure if substitutions of deeply nested generics are common.
            NamedTypeSymbol oldConstructedFrom = previous.ConstructedFrom;
            NamedTypeSymbol newConstructedFrom = SubstituteTypeDeclaration(oldConstructedFrom);

            ImmutableArray <TypeWithAnnotations> oldTypeArguments =
                previous.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;
            bool changed          = !ReferenceEquals(oldConstructedFrom, newConstructedFrom);
            var  newTypeArguments = ArrayBuilder <TypeWithAnnotations> .GetInstance(
                oldTypeArguments.Length
                );

            for (int i = 0; i < oldTypeArguments.Length; i++)
            {
                var oldArgument = oldTypeArguments[i];
                var newArgument = oldArgument.SubstituteType(this);

                if (!changed && !oldArgument.IsSameAs(newArgument))
                {
                    changed = true;
                }

                newTypeArguments.Add(newArgument);
            }

            if (!changed)
            {
                newTypeArguments.Free();
                return(previous);
            }

            return(newConstructedFrom
                   .ConstructIfGeneric(newTypeArguments.ToImmutableAndFree())
                   .WithTupleDataFrom(previous));
        }
        /// <summary>
        /// Constructs this implicit method, undoing the encoding of the
        /// concept parameters and instance in the process and retrieving
        /// a synthesised witness symbol.
        /// </summary>
        /// <param name="typeArguments">
        /// The full set of type arguments supplied for constructing
        /// this symbol, which map in order to the method parameters,
        /// concept parameters, and concept instance respectively.
        /// </param>
        /// <returns>
        /// A symbol representing the original implicit method, but with
        /// the concept-level and method-level inferences applied, and the
        /// inferred witness attached for later use in lowering.
        /// </returns>
        internal MethodSymbol ConstructAndRetarget(ImmutableArray <TypeSymbol> typeArguments)
        {
            Debug.Assert(!typeArguments.IsDefaultOrEmpty, "expected a valid type argument array to construct with");
            Debug.Assert(typeArguments.Length == Arity, "arity mismatch on type arguments");

            (var methodArgs, var recvArgs) = PartitionTypeArgs(typeArguments);
            var constructedReceiver = _originalReceiver.ConstructIfGeneric(recvArgs);

            MethodSymbol substituted = SubstituteForConstructAndRetarget(constructedReceiver);
            MethodSymbol constructed = ConstructForConstructAndRetarget(methodArgs, substituted);

            var instance = _originalReceiver.IsConcept ? typeArguments[Arity - 1] : constructedReceiver;

            Debug.Assert(instance != null, "type inference should have given us a non-null instance");
            Debug.Assert(instance.IsInstanceType() || instance.IsConceptWitness, "type inference should have made the last argument a concept instance");

            return(new SynthesizedWitnessMethodSymbol(constructed, instance));
        }
Esempio n. 7
0
        private NamedTypeSymbol TransformNamedType(NamedTypeSymbol namedType, bool isContaining = false)
        {
            // Native compiler encodes a bool for the given namedType, but none for its containing types.
            if (!isContaining)
            {
                var flag = ConsumeFlag();
                Debug.Assert(!flag);
            }

            NamedTypeSymbol containingType = namedType.ContainingType;
            NamedTypeSymbol newContainingType;
            if ((object)containingType != null && containingType.IsGenericType)
            {
                newContainingType = TransformNamedType(namedType.ContainingType, isContaining: true);
                if ((object)newContainingType == null)
                {
                    return null;
                }

                Debug.Assert(newContainingType.IsGenericType);
            }
            else
            {
                newContainingType = containingType;
            }

            // Native compiler encodes bools for each type argument, starting from type arguments for the outermost containing type to those for the given namedType.
            ImmutableArray<TypeSymbol> typeArguments = namedType.TypeArgumentsNoUseSiteDiagnostics;
            ImmutableArray<TypeSymbol> transformedTypeArguments = TransformTypeArguments(typeArguments);

            if (transformedTypeArguments.IsDefault)
            {
                return null;
            }

            // Construct a new namedType, if required.
            if (newContainingType != containingType)
            {
                namedType = namedType.OriginalDefinition.AsMember(newContainingType);
                return namedType.ConstructIfGeneric(transformedTypeArguments);
            }
            else if (transformedTypeArguments != typeArguments)
            {
                return namedType.ConstructedFrom.Construct(transformedTypeArguments);
            }
            else
            {
                return namedType;
            }
        }
Esempio n. 8
0
        private NamedTypeSymbol TransformNamedType(NamedTypeSymbol namedType, bool isContaining = false)
        {
            // Native compiler encodes a bool for the given namedType, but none for its containing types.
            if (!isContaining)
            {
                var flag = ConsumeFlag();
                Debug.Assert(!flag);
            }

            NamedTypeSymbol containingType = namedType.ContainingType;
            NamedTypeSymbol newContainingType;
            if ((object)containingType != null && containingType.IsGenericType)
            {
                newContainingType = TransformNamedType(namedType.ContainingType, isContaining: true);
                if ((object)newContainingType == null)
                {
                    return null;
                }

                Debug.Assert(newContainingType.IsGenericType);
            }
            else
            {
                newContainingType = containingType;
            }

            // Native compiler encodes bools for each type argument, starting from type arguments for the outermost containing type to those for the given namedType.
            ImmutableArray<TypeSymbol> typeArguments = namedType.TypeArgumentsNoUseSiteDiagnostics;
            var customModifiers = namedType.HasTypeArgumentsCustomModifiers ? namedType.TypeArgumentsCustomModifiers : default(ImmutableArray<ImmutableArray<CustomModifier>>);

            ImmutableArray<TypeSymbol> transformedTypeArguments = TransformTypeArguments(typeArguments); // Note, modifiers are not involved, this is behavior of the native compiler.

            if (transformedTypeArguments.IsDefault)
            {
                return null;
            }

            // Construct a new namedType, if required.
            bool containerIsChanged = (newContainingType != containingType);

            if (containerIsChanged || transformedTypeArguments != typeArguments)
            {
                var newTypeArguments = customModifiers.IsDefault ?
                                       transformedTypeArguments.SelectAsArray(TypeMap.TypeSymbolAsTypeWithModifiers) :
                                       transformedTypeArguments.Zip(customModifiers, (t, m) => new TypeWithModifiers(t, m)).AsImmutable();

                if (containerIsChanged)
                {
                    namedType = namedType.OriginalDefinition.AsMember(newContainingType);
                    return namedType.ConstructIfGeneric(newTypeArguments);
                }

                return namedType.ConstructedFrom.Construct(newTypeArguments, unbound: false);
            }
            else
            {
                return namedType;
            }
        }