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())); }
/// <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)); }
/// <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())); }
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())); }
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)); }
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; } }
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; } }