protected void GenerateImplicitConversionError( DiagnosticBag diagnostics, CSharpSyntaxNode syntax, Conversion conversion, BoundExpression operand, TypeSymbol targetType) { Debug.Assert(operand != null); Debug.Assert((object)targetType != null); if (targetType.TypeKind == TypeKind.Error) { return; } if (operand.Kind == BoundKind.BadExpression) { return; } if (operand.Kind == BoundKind.UnboundLambda) { GenerateAnonymousFunctionConversionError(diagnostics, syntax, (UnboundLambda)operand, targetType); return; } if (operand.Kind == BoundKind.TupleLiteral) { var tuple = (BoundTupleLiteral)operand; var targetElementTypes = default(ImmutableArray<TypeSymbol>); // If target is a tuple or compatible type with the same number of elements, // report errors for tuple arguments that failed to convert, which would be more useful. if (targetType.TryGetElementTypesIfTupleOrCompatible(out targetElementTypes) && targetElementTypes.Length == tuple.Arguments.Length) { GenerateImplicitConversionErrorsForTupleLiteralArguments(diagnostics, tuple.Arguments, targetElementTypes); return; } // target is not compatible with source and source does not have a type if ((object)tuple.Type == null) { Error(diagnostics, ErrorCode.ERR_ConversionNotTupleCompatible, syntax, tuple.Arguments.Length, targetType); return; } // Otherwise it is just a regular conversion failure from T1 to T2. } var sourceType = operand.Type; if ((object)sourceType != null) { GenerateImplicitConversionError(diagnostics, this.Compilation, syntax, conversion, sourceType, targetType, operand.ConstantValue); return; } if (operand.IsLiteralNull()) { if (targetType.TypeKind == TypeKind.TypeParameter) { Error(diagnostics, ErrorCode.ERR_TypeVarCantBeNull, syntax, targetType); return; } if (targetType.IsValueType) { Error(diagnostics, ErrorCode.ERR_ValueCantBeNull, syntax, targetType); return; } } if (operand.Kind == BoundKind.MethodGroup) { var methodGroup = (BoundMethodGroup)operand; if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, methodGroup, targetType, diagnostics)) { var nodeForSquiggle = syntax; while (nodeForSquiggle.Kind() == SyntaxKind.ParenthesizedExpression) { nodeForSquiggle = ((ParenthesizedExpressionSyntax)nodeForSquiggle).Expression; } if (nodeForSquiggle.Kind() == SyntaxKind.SimpleMemberAccessExpression || nodeForSquiggle.Kind() == SyntaxKind.PointerMemberAccessExpression) { nodeForSquiggle = ((MemberAccessExpressionSyntax)nodeForSquiggle).Name; } var location = nodeForSquiggle.Location; if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, targetType, location)) { return; } Error(diagnostics, targetType.IsDelegateType() ? ErrorCode.ERR_MethDelegateMismatch : ErrorCode.ERR_MethGrpToNonDel, location, methodGroup.Name, targetType); } return; } Debug.Assert(operand.HasAnyErrors && operand.Kind != BoundKind.UnboundLambda, "Missing a case in implicit conversion error reporting"); }
private bool LowerBoundTupleInference(TypeSymbol source, TypeSymbol target, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)target != null); // NOTE: we are losing tuple element names when unwrapping tuple types to underlying types. // that is ok, because we are inferring type parameters used in the matching elements, // This is not the situation where entire tuple type used to infer a single type param ImmutableArray<TypeSymbol> sourceTypes; ImmutableArray<TypeSymbol> targetTypes; if (!source.TryGetElementTypesIfTupleOrCompatible(out sourceTypes) || !target.TryGetElementTypesIfTupleOrCompatible(out targetTypes) || sourceTypes.Length != targetTypes.Length) { return false; } for (int i = 0; i < sourceTypes.Length; i++) { LowerBoundInference(sourceTypes[i], targetTypes[i], ref useSiteDiagnostics); } return true; }