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> /// Retrieves anonymous type properties types /// </summary> internal static ImmutableArray<TypeSymbol> GetAnonymousTypePropertyTypes(NamedTypeSymbol type) { Debug.Assert(type.IsAnonymousType); var anonymous = (AnonymousTypePublicSymbol)type; var fields = anonymous.TypeDescriptor.Fields; TypeSymbol[] types = new TypeSymbol[fields.Length]; for (int i = 0; i < fields.Length; i++) { types[i] = fields[i].Type; } return types.AsImmutableOrNull(); }
/// <summary> /// Retrieves anonymous type properties types /// </summary> internal static ImmutableArray <TypeSymbol> GetAnonymousTypePropertyTypes(NamedTypeSymbol type) { Debug.Assert(type.IsAnonymousType); var anonymous = (AnonymousTypePublicSymbol)type; var fields = anonymous.TypeDescriptor.Fields; TypeSymbol[] types = new TypeSymbol[fields.Length]; for (int i = 0; i < fields.Length; i++) { types[i] = fields[i].Type; } return(types.AsImmutableOrNull()); }
private MethodSymbol GetMethodWrapperForBaseNonVirtualCall(MethodSymbol methodBeingCalled, SyntaxNode syntax) { var newMethod = GetOrCreateBaseFunctionWrapper(methodBeingCalled, syntax); if (!newMethod.IsGenericMethod) { return newMethod; } // for generic methods we need to construct the method to be actually called Debug.Assert(methodBeingCalled.IsGenericMethod); var typeArgs = methodBeingCalled.TypeArguments; Debug.Assert(typeArgs.Length == newMethod.Arity); TypeSymbol[] visitedTypeArgs = new TypeSymbol[typeArgs.Length]; for (int i = 0; i < visitedTypeArgs.Length; i++) { visitedTypeArgs[i] = VisitType(typeArgs[i]); } return newMethod.Construct(visitedTypeArgs.AsImmutableOrNull()); }
/// <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); }
/// <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); }
/// <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)); }
/// <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)); }