本文整理汇总了C#中Microsoft.CodeAnalysis.CSharp.BoundConversion类的典型用法代码示例。如果您正苦于以下问题:C# BoundConversion类的具体用法?C# BoundConversion怎么用?C# BoundConversion使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
BoundConversion类属于Microsoft.CodeAnalysis.CSharp命名空间,在下文中一共展示了BoundConversion类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: MakeFieldAccess
private BoundExpression MakeFieldAccess(
CSharpSyntaxNode syntax,
BoundExpression rewrittenReceiver,
FieldSymbol fieldSymbol,
ConstantValue constantValueOpt,
LookupResultKind resultKind,
TypeSymbol type,
BoundFieldAccess oldNodeOpt = null)
{
if (fieldSymbol.IsTupleField)
{
return MakeTupleFieldAccess(syntax, fieldSymbol, rewrittenReceiver, constantValueOpt, resultKind);
}
BoundExpression result = oldNodeOpt != null ?
oldNodeOpt.Update(rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type) :
new BoundFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type);
if (fieldSymbol.IsFixed)
{
// a reference to a fixed buffer is translated into its address
result = new BoundConversion(syntax,
new BoundAddressOfOperator(syntax, result, syntax != null && SyntaxFacts.IsFixedStatementExpression(syntax), type, false),
new Conversion(ConversionKind.PointerToPointer), false, false, default(ConstantValue), type, false);
}
return result;
}
示例2: VisitConversion
public override BoundNode VisitConversion(BoundConversion node)
{
var rewrittenType = VisitType(node.Type);
bool wasInExpressionLambda = inExpressionLambda;
if (node.ConversionKind == ConversionKind.AnonymousFunction && !wasInExpressionLambda && rewrittenType.IsExpressionTree()) inExpressionLambda = true;
var rewrittenOperand = VisitExpression(node.Operand);
inExpressionLambda = wasInExpressionLambda;
var result = MakeConversion(node, node.Syntax, rewrittenOperand, node.ConversionKind, node.SymbolOpt, node.Checked,
node.ExplicitCastInCode, node.IsExtensionMethod, node.IsArrayIndex, node.ConstantValue, rewrittenType);
var toType = node.Type;
Debug.Assert(result.Type == toType);
// 4.1.6 C# spec: To force a value of a floating point type to the exact precision of its type, an explicit cast can be used.
// It means that explicit casts to (double) or (float) should be preserved on the node.
// If original conversion has become something else with unknown precision, add an explicit identity cast.
if (!inExpressionLambda &&
node.ExplicitCastInCode &&
IsFloatPointExpressionOfUnknownPrecision(result))
{
result = MakeConversion(
node.Syntax,
result,
Conversion.Identity,
toType,
@checked: false,
explicitCastInCode: true,
constantValueOpt: result.ConstantValue);
}
return result;
}
示例3: VisitConversion
public override BoundNode VisitConversion(BoundConversion conversion)
{
if (conversion.ConversionKind == ConversionKind.MethodGroup &&
conversion.SymbolOpt?.MethodKind == MethodKind.LocalFunction)
{
BoundExpression receiver;
MethodSymbol method;
var arguments = default(ImmutableArray<BoundExpression>);
_lambdaRewriter.RemapLocalFunction(
conversion.Syntax, conversion.SymbolOpt, out receiver, out method, ref arguments);
return new BoundDelegateCreationExpression(
conversion.Syntax, receiver, method, isExtensionMethod: false, type: conversion.Type);
}
return base.VisitConversion(conversion);
}
示例4: VisitConversion
public override BoundNode VisitConversion(BoundConversion node)
{
var rewrittenType = VisitType(node.Type);
if (node.ConversionKind == ConversionKind.InterpolatedString)
{
return RewriteInterpolatedStringConversion(node);
}
bool wasInExpressionLambda = _inExpressionLambda;
_inExpressionLambda = _inExpressionLambda || (node.ConversionKind == ConversionKind.AnonymousFunction && !wasInExpressionLambda && rewrittenType.IsExpressionTree());
var rewrittenOperand = VisitExpression(node.Operand);
_inExpressionLambda = wasInExpressionLambda;
var result = MakeConversionNode(node, node.Syntax, rewrittenOperand, node.Conversion, node.Checked, node.ExplicitCastInCode, node.ConstantValue, rewrittenType);
var toType = node.Type;
Debug.Assert(result.Type.Equals(toType, TypeCompareKind.IgnoreDynamicAndTupleNames));
// 4.1.6 C# spec: To force a value of a floating point type to the exact precision of its type, an explicit cast can be used.
// It means that explicit casts to (double) or (float) should be preserved on the node.
// If original conversion has become something else with unknown precision, add an explicit identity cast.
if (!_inExpressionLambda &&
node.ExplicitCastInCode &&
IsFloatPointExpressionOfUnknownPrecision(result))
{
result = MakeConversionNode(
node.Syntax,
result,
Conversion.Identity,
toType,
@checked: false,
explicitCastInCode: true,
constantValueOpt: result.ConstantValue);
}
return result;
}
示例5: RewriteInterpolatedStringConversion
private BoundExpression RewriteInterpolatedStringConversion(BoundConversion conversion)
{
Debug.Assert(conversion.ConversionKind == ConversionKind.InterpolatedString);
BoundExpression format;
ArrayBuilder<BoundExpression> expressions;
MakeInterpolatedStringFormat((BoundInterpolatedString)conversion.Operand, out format, out expressions);
expressions.Insert(0, format);
var stringFactory = _factory.WellKnownType(WellKnownType.System_Runtime_CompilerServices_FormattableStringFactory);
// The normal pattern for lowering is to lower subtrees before the enclosing tree. However we cannot lower
// the arguments first in this situation because we do not know what conversions will be
// produced for the arguments until after we've done overload resolution. So we produce the invocation
// and then lower it along with its arguments.
var result = _factory.StaticCall(stringFactory, "Create", expressions.ToImmutableAndFree(),
allowUnexpandedForm: false // if an interpolation expression is the null literal, it should not match a params parameter.
);
if (!result.HasAnyErrors)
{
result = VisitExpression(result); // lower the arguments AND handle expanded form, argument conversions, etc.
result = MakeImplicitConversion(result, conversion.Type);
}
return result;
}
示例6: VisitConversion
public override BoundNode VisitConversion(BoundConversion node)
{
BoundExpression operand = (BoundExpression)this.Visit(node.Operand);
TypeSymbol type = this.VisitType(node.Type);
if (operand.Kind != BoundKind.SpillSequence)
{
return node.Update(operand, node.ConversionKind, node.SymbolOpt, node.Checked, node.ExplicitCastInCode, node.IsExtensionMethod, node.IsArrayIndex, node.ConstantValueOpt, node.ResultKind, type);
}
var spill = (BoundSpillSequence)operand;
return RewriteSpillSequence(spill,
node.Update(
spill.Value,
node.ConversionKind,
node.SymbolOpt,
node.Checked,
node.ExplicitCastInCode,
node.IsExtensionMethod,
node.IsArrayIndex,
node.ConstantValueOpt,
node.ResultKind,
type));
}
示例7: RewriteIntPtrConversion
private BoundExpression RewriteIntPtrConversion(
BoundConversion oldNode,
CSharpSyntaxNode syntax,
BoundExpression rewrittenOperand,
ConversionKind conversionKind,
MethodSymbol symbolOpt,
bool @checked,
bool explicitCastInCode,
bool isExtensionMethod,
bool isArrayIndex,
ConstantValue constantValueOpt,
TypeSymbol rewrittenType)
{
Debug.Assert(rewrittenOperand != null);
Debug.Assert((object)rewrittenType != null);
TypeSymbol source = rewrittenOperand.Type;
TypeSymbol target = rewrittenType;
TypeSymbol t0 = target.StrippedType();
TypeSymbol s0 = source.StrippedType();
if (t0 != target && s0 != source)
{
// UNDONE: RewriteLiftedIntPtrConversion
return oldNode != null ?
oldNode.Update(
rewrittenOperand,
conversionKind,
oldNode.ResultKind,
isBaseConversion: oldNode.IsBaseConversion,
symbolOpt: symbolOpt,
@checked: @checked,
explicitCastInCode: explicitCastInCode,
isExtensionMethod: isExtensionMethod,
isArrayIndex: isArrayIndex,
constantValueOpt: constantValueOpt,
type: rewrittenType) :
new BoundConversion(
syntax,
rewrittenOperand,
conversionKind,
LookupResultKind.Viable,
isBaseConversion: false,
symbolOpt: symbolOpt,
@checked: @checked,
explicitCastInCode: explicitCastInCode,
isExtensionMethod: isExtensionMethod,
isArrayIndex: isArrayIndex,
constantValueOpt: constantValueOpt,
type: rewrittenType);
}
SpecialMember member = GetIntPtrConversionMethod(source: rewrittenOperand.Type, target: rewrittenType);
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
Debug.Assert(!method.ReturnsVoid);
Debug.Assert(method.ParameterCount == 1);
rewrittenOperand = MakeConversion(rewrittenOperand, method.ParameterTypes[0], @checked);
var returnType = method.ReturnType;
Debug.Assert((object)returnType != null);
if (inExpressionLambda)
{
return BoundConversion.Synthesized(syntax, rewrittenOperand, new Conversion(conversionKind, method, false), @checked, explicitCastInCode, constantValueOpt, rewrittenType);
}
var rewrittenCall =
inExpressionLambda && oldNode != null
? new BoundConversion(syntax, rewrittenOperand, new Conversion(conversionKind, method, false), @checked, explicitCastInCode, constantValueOpt, returnType)
: MakeCall(
syntax: syntax,
rewrittenReceiver: null,
method: method,
rewrittenArguments: ImmutableArray.Create<BoundExpression>(rewrittenOperand),
type: returnType);
return MakeConversion(rewrittenCall, rewrittenType, @checked);
}
示例8: MakeConversion
/// <summary>
/// Helper method to generate a lowered conversion.
/// </summary>
private BoundExpression MakeConversion(
BoundConversion oldNode,
CSharpSyntaxNode syntax,
BoundExpression rewrittenOperand,
ConversionKind conversionKind,
MethodSymbol symbolOpt,
bool @checked,
bool explicitCastInCode,
bool isExtensionMethod,
bool isArrayIndex,
ConstantValue constantValueOpt,
TypeSymbol rewrittenType)
{
Debug.Assert(oldNode == null || oldNode.Syntax == syntax);
Debug.Assert((object)rewrittenType != null);
@checked = @checked &&
(inExpressionLambda && (explicitCastInCode || DistinctSpecialTypes(rewrittenOperand.Type, rewrittenType)) ||
NeedsChecked(rewrittenOperand.Type, rewrittenType));
switch (conversionKind)
{
case ConversionKind.Identity:
// Spec 6.1.1:
// An identity conversion converts from any type to the same type.
// This conversion exists such that an entity that already has a required type can be said to be convertible to that type.
// Because object and dynamic are considered equivalent there is an identity conversion between object and dynamic,
// and between constructed types that are the same when replacing all occurrences of dynamic with object.
// Why ignoreDynamic: false?
// Lowering phase treats object and dynamic as equivalent types. So we don't need to produce any conversion here,
// but we need to change the Type property on the resulting BoundExpression to match the rewrittenType.
// This is necessary so that subsequent lowering transformations see that the expression is dynamic.
if (inExpressionLambda || !rewrittenOperand.Type.Equals(rewrittenType, ignoreCustomModifiers: false, ignoreDynamic: false))
{
break;
}
// 4.1.6 C# spec: To force a value of a floating point type to the exact precision of its type, an explicit cast can be used.
// If this is not an identity conversion of a float with unknown precision, strip away the identity conversion.
if (!(explicitCastInCode && IsFloatPointExpressionOfUnknownPrecision(rewrittenOperand)))
{
return rewrittenOperand;
}
break;
case ConversionKind.ExplicitUserDefined:
case ConversionKind.ImplicitUserDefined:
return RewriteUserDefinedConversion(
syntax: syntax,
rewrittenOperand: rewrittenOperand,
method: symbolOpt,
rewrittenType: rewrittenType,
conversionKind: conversionKind);
case ConversionKind.IntPtr:
return RewriteIntPtrConversion(oldNode, syntax, rewrittenOperand, conversionKind, symbolOpt, @checked,
explicitCastInCode, isExtensionMethod, isArrayIndex, constantValueOpt, rewrittenType);
case ConversionKind.ImplicitNullable:
case ConversionKind.ExplicitNullable:
return RewriteNullableConversion(
syntax: syntax,
rewrittenOperand: rewrittenOperand,
conversionKind: conversionKind,
@checked: @checked,
explicitCastInCode: explicitCastInCode,
rewrittenType: rewrittenType);
case ConversionKind.Boxing:
if (!inExpressionLambda)
{
// We can perform some optimizations if we have a nullable value type
// as the operand and we know its nullability:
// * (object)new int?() is the same as (object)null
// * (object)new int?(123) is the same as (object)123
if (NullableNeverHasValue(rewrittenOperand))
{
return new BoundDefaultOperator(syntax, rewrittenType);
}
BoundExpression nullableValue = NullableAlwaysHasValue(rewrittenOperand);
if (nullableValue != null)
{
// Recurse, eliminating the unnecessary ctor.
return MakeConversion(oldNode, syntax, nullableValue, conversionKind,
symbolOpt, @checked, explicitCastInCode, isExtensionMethod, isArrayIndex,
constantValueOpt, rewrittenType);
}
}
break;
//.........这里部分代码省略.........
示例9: RewriteLiftedConversionInExpressionTree
private BoundExpression RewriteLiftedConversionInExpressionTree(
CSharpSyntaxNode syntax,
BoundExpression rewrittenOperand,
ConversionKind conversionKind,
bool @checked,
bool explicitCastInCode,
TypeSymbol rewrittenType)
{
Debug.Assert((object)rewrittenType != null);
TypeSymbol rewrittenOperandType = rewrittenOperand.Type;
Debug.Assert(rewrittenType.IsNullableType() || rewrittenOperandType.IsNullableType());
TypeSymbol typeFrom = rewrittenOperandType.StrippedType();
TypeSymbol typeTo = rewrittenType.StrippedType();
if (typeFrom != typeTo && (typeFrom.SpecialType == SpecialType.System_Decimal || typeTo.SpecialType == SpecialType.System_Decimal))
{
// take special care if the underlying conversion is a decimal conversion
TypeSymbol typeFromUnderlying = typeFrom;
TypeSymbol typeToUnderlying = typeTo;
// They can't both be enums, since one of them is decimal.
if (typeFrom.IsEnumType())
{
typeFromUnderlying = typeFrom.GetEnumUnderlyingType();
// NOTE: Dev10 converts enum? to underlying?, rather than directly to underlying.
rewrittenOperandType = rewrittenOperandType.IsNullableType() ? ((NamedTypeSymbol)rewrittenOperandType.OriginalDefinition).Construct(typeFromUnderlying) : typeFromUnderlying;
rewrittenOperand = BoundConversion.SynthesizedNonUserDefined(syntax, rewrittenOperand, ConversionKind.ImplicitEnumeration, rewrittenOperandType);
}
else if (typeTo.IsEnumType())
{
typeToUnderlying = typeTo.GetEnumUnderlyingType();
}
var method = (MethodSymbol)this.compilation.Assembly.GetSpecialTypeMember(DecimalConversionMethod(typeFromUnderlying, typeToUnderlying));
conversionKind = conversionKind.IsImplicitConversion() ? ConversionKind.ImplicitUserDefined : ConversionKind.ExplicitUserDefined;
var result = new BoundConversion(syntax, rewrittenOperand, new Conversion(conversionKind, method, false), @checked, explicitCastInCode, default(ConstantValue), rewrittenType);
return result;
}
else
{
return new BoundConversion(syntax, rewrittenOperand, new Conversion(conversionKind), @checked, explicitCastInCode, default(ConstantValue), rewrittenType);
}
}
示例10: VisitConversion
private BoundExpression VisitConversion(BoundConversion node)
{
switch (node.ConversionKind)
{
case ConversionKind.MethodGroup:
{
var mg = (BoundMethodGroup)node.Operand;
return DelegateCreation(mg.ReceiverOpt, node.SymbolOpt, node.Type, node.SymbolOpt.IsStatic && !node.IsExtensionMethod);
}
case ConversionKind.ExplicitUserDefined:
case ConversionKind.ImplicitUserDefined:
case ConversionKind.IntPtr:
{
var method = node.SymbolOpt;
var operandType = node.Operand.Type;
var strippedOperandType = operandType.StrippedType();
var conversionInputType = method.Parameters[0].Type;
var isLifted = operandType != conversionInputType && strippedOperandType == conversionInputType;
bool requireAdditionalCast =
strippedOperandType != ((node.ConversionKind == ConversionKind.ExplicitUserDefined) ? conversionInputType : conversionInputType.StrippedType());
var resultType = (isLifted && method.ReturnType.IsNonNullableValueType() && node.Type.IsNullableType()) ? _nullableType.Construct(method.ReturnType) : method.ReturnType;
var e1 = requireAdditionalCast
? Convert(Visit(node.Operand), node.Operand.Type, method.Parameters[0].Type, node.Checked, false)
: Visit(node.Operand);
var e2 = ExprFactory("Convert", e1, _bound.Typeof(resultType), _bound.MethodInfo(method));
return Convert(e2, resultType, node.Type, node.Checked, false);
}
case ConversionKind.ImplicitReference:
case ConversionKind.Identity:
{
var operand = Visit(node.Operand);
return node.ExplicitCastInCode ? Convert(operand, node.Type, false) : operand;
}
case ConversionKind.ImplicitNullable:
if (node.Operand.Type.IsNullableType())
{
return Convert(Visit(node.Operand), node.Operand.Type, node.Type, node.Checked, node.ExplicitCastInCode);
}
else
{
// the native compiler performs this conversion in two steps, so we follow suit
var nullable = (NamedTypeSymbol)node.Type;
var intermediate = nullable.TypeArgumentsNoUseSiteDiagnostics[0];
var e1 = Convert(Visit(node.Operand), node.Operand.Type, intermediate, node.Checked, false);
return Convert(e1, intermediate, node.Type, node.Checked, false);
}
case ConversionKind.NullLiteral:
return Convert(Constant(_bound.Null(_objectType)), _objectType, node.Type, false, node.ExplicitCastInCode);
default:
return Convert(Visit(node.Operand), node.Operand.Type, node.Type, node.Checked, node.ExplicitCastInCode);
}
}
示例11: CreateUserDefinedConversion
protected BoundExpression CreateUserDefinedConversion(CSharpSyntaxNode syntax, BoundExpression source, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
{
if (!conversion.IsValid)
{
GenerateImplicitConversionError(diagnostics, syntax, conversion, source, destination);
return new BoundConversion(
syntax,
source,
conversion,
CheckOverflowAtRuntime,
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: destination,
hasErrors: true)
{ WasCompilerGenerated = source.WasCompilerGenerated };
}
// Due to an oddity in the way we create a non-lifted user-defined conversion from A to D?
// (required backwards compatibility with the native compiler) we can end up in a situation
// where we have:
// a standard conversion from A to B?
// then a standard conversion from B? to B
// then a user-defined conversion from B to C
// then a standard conversion from C to C?
// then a standard conversion from C? to D?
//
// In that scenario, the "from type" of the conversion will be B? and the "from conversion" will be
// from A to B?. Similarly the "to type" of the conversion will be C? and the "to conversion"
// of the conversion will be from C? to D?.
//
// Therefore, we might need to introduce an extra conversion on the source side, from B? to B.
// Now, you might think we should also introduce an extra conversion on the destination side,
// from C to C?. But that then gives us the following bad situation: If we in fact bind this as
//
// (D?)(C?)(C)(B)(B?)(A)x
//
// then what we are in effect doing is saying "convert C? to D? by checking for null, unwrapping,
// converting C to D, and then wrapping". But we know that the C? will never be null. In this case
// we should actually generate
//
// (D?)(C)(B)(B?)(A)x
//
// And thereby skip the unnecessary nullable conversion.
// Original expression --> conversion's "from" type
BoundExpression convertedOperand = CreateConversion(
syntax: source.Syntax,
source: source,
conversion: conversion.UserDefinedFromConversion,
isCast: false,
wasCompilerGenerated: true,
destination: conversion.BestUserDefinedConversionAnalysis.FromType,
diagnostics: diagnostics);
TypeSymbol conversionParameterType = conversion.BestUserDefinedConversionAnalysis.Operator.ParameterTypes[0];
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
if (conversion.BestUserDefinedConversionAnalysis.Kind == UserDefinedConversionAnalysisKind.ApplicableInNormalForm &&
conversion.BestUserDefinedConversionAnalysis.FromType != conversionParameterType)
{
// Conversion's "from" type --> conversion method's parameter type.
convertedOperand = CreateConversion(
syntax: syntax,
source: convertedOperand,
conversion: Conversions.ClassifyStandardConversion(null, convertedOperand.Type, conversionParameterType, ref useSiteDiagnostics),
isCast: false,
wasCompilerGenerated: true,
destination: conversionParameterType,
diagnostics: diagnostics);
}
BoundExpression userDefinedConversion;
TypeSymbol conversionReturnType = conversion.BestUserDefinedConversionAnalysis.Operator.ReturnType;
TypeSymbol conversionToType = conversion.BestUserDefinedConversionAnalysis.ToType;
Conversion toConversion = conversion.UserDefinedToConversion;
if (conversion.BestUserDefinedConversionAnalysis.Kind == UserDefinedConversionAnalysisKind.ApplicableInNormalForm &&
conversionToType != conversionReturnType)
{
// Conversion method's parameter type --> conversion method's return type
// NB: not calling CreateConversion here because this is the recursive base case.
userDefinedConversion = new BoundConversion(
syntax,
convertedOperand,
conversion,
@checked: false, // There are no checked user-defined conversions, but the conversions on either side might be checked.
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: conversionReturnType)
{ WasCompilerGenerated = true };
if (conversionToType.IsNullableType() && conversionToType.GetNullableUnderlyingType() == conversionReturnType)
{
// Skip introducing the conversion from C to C?. The "to" conversion is now wrong though,
// because it will still assume converting C? to D?.
toConversion = Conversions.ClassifyConversion(conversionReturnType, destination, ref useSiteDiagnostics);
Debug.Assert(toConversion.Exists);
//.........这里部分代码省略.........
示例12: CheckCompoundAssignmentOperator
private void CheckCompoundAssignmentOperator(BoundCompoundAssignmentOperator node)
{
BoundExpression left = node.Left;
if (!node.Operator.Kind.IsDynamic() && !node.LeftConversion.IsIdentity && node.LeftConversion.Exists)
{
// Need to represent the implicit conversion as a node in order to be able to produce correct diagnostics.
left = new BoundConversion(left.Syntax, left, node.LeftConversion, node.Operator.Kind.IsChecked(),
explicitCastInCode: false, constantValueOpt: null, type: node.Operator.LeftType);
}
CheckForBitwiseOrSignExtend(node, node.Operator.Kind, left, node.Right);
CheckLiftedCompoundAssignment(node);
if (_inExpressionLambda)
{
Error(ErrorCode.ERR_ExpressionTreeContainsAssignment, node);
}
}
示例13: BindForEachPartsWorker
//.........这里部分代码省略.........
boundIterationVariableType,
this.IterationVariable,
collectionExpr,
body,
CheckOverflowAtRuntime,
this.BreakLabel,
this.ContinueLabel,
hasErrors);
}
hasErrors |= hasNameConflicts;
var foreachKeyword = _syntax.ForEachKeyword;
ReportDiagnosticsIfObsolete(diagnostics, builder.GetEnumeratorMethod, foreachKeyword, hasBaseReceiver: false);
ReportDiagnosticsIfObsolete(diagnostics, builder.MoveNextMethod, foreachKeyword, hasBaseReceiver: false);
ReportDiagnosticsIfObsolete(diagnostics, builder.CurrentPropertyGetter, foreachKeyword, hasBaseReceiver: false);
ReportDiagnosticsIfObsolete(diagnostics, builder.CurrentPropertyGetter.AssociatedSymbol, foreachKeyword, hasBaseReceiver: false);
// We want to convert from inferredType in the array/string case and builder.ElementType in the enumerator case,
// but it turns out that these are equivalent (when both are available).
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
Conversion elementConversion = this.Conversions.ClassifyConversionForCast(inferredType, iterationVariableType, ref useSiteDiagnostics);
if (!elementConversion.IsValid)
{
ImmutableArray<MethodSymbol> originalUserDefinedConversions = elementConversion.OriginalUserDefinedConversions;
if (originalUserDefinedConversions.Length > 1)
{
diagnostics.Add(ErrorCode.ERR_AmbigUDConv, _syntax.ForEachKeyword.GetLocation(), originalUserDefinedConversions[0], originalUserDefinedConversions[1], inferredType, iterationVariableType);
}
else
{
SymbolDistinguisher distinguisher = new SymbolDistinguisher(this.Compilation, inferredType, iterationVariableType);
diagnostics.Add(ErrorCode.ERR_NoExplicitConv, _syntax.ForEachKeyword.GetLocation(), distinguisher.First, distinguisher.Second);
}
hasErrors = true;
}
else
{
ReportDiagnosticsIfObsolete(diagnostics, elementConversion, _syntax.ForEachKeyword, hasBaseReceiver: false);
}
// Spec (§8.8.4):
// If the type X of expression is dynamic then there is an implicit conversion from >>expression<< (not the type of the expression)
// to the System.Collections.IEnumerable interface (§6.1.8).
builder.CollectionConversion = this.Conversions.ClassifyConversionFromExpression(collectionExpr, builder.CollectionType, ref useSiteDiagnostics);
builder.CurrentConversion = this.Conversions.ClassifyConversion(builder.CurrentPropertyGetter.ReturnType, builder.ElementType, ref useSiteDiagnostics);
builder.EnumeratorConversion = this.Conversions.ClassifyConversion(builder.GetEnumeratorMethod.ReturnType, GetSpecialType(SpecialType.System_Object, diagnostics, _syntax), ref useSiteDiagnostics);
diagnostics.Add(_syntax.ForEachKeyword.GetLocation(), useSiteDiagnostics);
// Due to the way we extracted the various types, these conversions should always be possible.
// CAVEAT: if we're iterating over an array of pointers, the current conversion will fail since we
// can't convert from object to a pointer type. Similarly, if we're iterating over an array of
// Nullable<Error>, the current conversion will fail because we don't know if an ErrorType is a
// value type. This doesn't matter in practice, since we won't actually use the enumerator pattern
// when we lower the loop.
Debug.Assert(builder.CollectionConversion.IsValid);
Debug.Assert(builder.CurrentConversion.IsValid ||
(builder.ElementType.IsPointerType() && collectionExpr.Type.IsArray()) ||
(builder.ElementType.IsNullableType() && builder.ElementType.GetMemberTypeArgumentsNoUseSiteDiagnostics().Single().IsErrorType() && collectionExpr.Type.IsArray()));
Debug.Assert(builder.EnumeratorConversion.IsValid ||
this.Compilation.GetSpecialType(SpecialType.System_Object).TypeKind == TypeKind.Error ||
!useSiteDiagnostics.IsNullOrEmpty(),
"Conversions to object succeed unless there's a problem with the object type or the source type");
// If user-defined conversions could occur here, we would need to check for ObsoleteAttribute.
Debug.Assert((object)builder.CollectionConversion.Method == null,
"Conversion from collection expression to collection type should not be user-defined");
Debug.Assert((object)builder.CurrentConversion.Method == null,
"Conversion from Current property type to element type should not be user-defined");
Debug.Assert((object)builder.EnumeratorConversion.Method == null,
"Conversion from GetEnumerator return type to System.Object should not be user-defined");
// We're wrapping the collection expression in a (non-synthesized) conversion so that its converted
// type (i.e. builder.CollectionType) will be available in the binding API.
BoundConversion convertedCollectionExpression = new BoundConversion(
collectionExpr.Syntax,
collectionExpr,
builder.CollectionConversion,
CheckOverflowAtRuntime,
false,
ConstantValue.NotAvailable,
builder.CollectionType);
return new BoundForEachStatement(
_syntax,
builder.Build(this.Flags),
elementConversion,
boundIterationVariableType,
this.IterationVariable,
convertedCollectionExpression,
body,
CheckOverflowAtRuntime,
this.BreakLabel,
this.ContinueLabel,
hasErrors);
}
示例14: CreateTupleLiteralConversion
private BoundExpression CreateTupleLiteralConversion(CSharpSyntaxNode syntax, BoundTupleLiteral sourceTuple, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
{
// We have a successful tuple conversion; rather than producing a separate conversion node
// which is a conversion on top of a tuple literal, tuple conversion is an element-wise conversion of arguments.
Debug.Assert(conversion.Kind == ConversionKind.ImplicitTupleLiteral || conversion.Kind == ConversionKind.ImplicitNullable);
Debug.Assert((conversion.Kind == ConversionKind.ImplicitNullable) == destination.IsNullableType());
TypeSymbol destinationWithoutNullable = conversion.Kind == ConversionKind.ImplicitNullable ?
destinationWithoutNullable = destination.GetNullableUnderlyingType() :
destination;
NamedTypeSymbol targetType = (NamedTypeSymbol)destinationWithoutNullable;
if (targetType.IsTupleType)
{
var destTupleType = (TupleTypeSymbol)targetType;
// do not lose the original element names in the literal if different from names in the target
// Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
}
var arguments = sourceTuple.Arguments;
var convertedArguments = ArrayBuilder<BoundExpression>.GetInstance(arguments.Length);
ImmutableArray<TypeSymbol> targetElementTypes = targetType.GetElementTypesOfTupleOrCompatible();
Debug.Assert(targetElementTypes.Length == arguments.Length, "converting a tuple literal to incompatible type?");
for (int i = 0; i < arguments.Length; i++)
{
var argument = arguments[i];
var destType = targetElementTypes[i];
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
Conversion elementConversion;
if (isCast)
{
elementConversion = this.Conversions.ClassifyConversionForCast(argument, destType, ref useSiteDiagnostics);
}
else
{
elementConversion = this.Conversions.ClassifyConversionFromExpression(argument, destType, ref useSiteDiagnostics);
}
diagnostics.Add(syntax, useSiteDiagnostics);
convertedArguments.Add(CreateConversion(argument.Syntax, argument, elementConversion, isCast, destType, diagnostics));
}
BoundExpression result = new BoundConvertedTupleLiteral(
sourceTuple.Syntax,
sourceTuple.Type,
convertedArguments.ToImmutableAndFree(),
targetType);
// We need to preserve any conversion that changes the type (even identity conversions),
// or that was explicitly written in code (so that GetSemanticInfo can find the syntax in the bound tree).
if (!isCast && targetType == destination)
{
return result;
}
// if we have a nullable cast combined with a name/dynamic cast
// name/dynamic cast must happen before converting to nullable
if (conversion.Kind == ConversionKind.ImplicitNullable &&
destinationWithoutNullable != targetType)
{
Debug.Assert(destinationWithoutNullable.Equals(targetType, ignoreDynamic: true));
result = new BoundConversion(
syntax,
result,
Conversion.Identity,
@checked: false,
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: destinationWithoutNullable)
{ WasCompilerGenerated = sourceTuple.WasCompilerGenerated };
}
return new BoundConversion(
syntax,
result,
conversion,
@checked: false,
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: destination)
{ WasCompilerGenerated = sourceTuple.WasCompilerGenerated };
}
示例15: CreateTupleLiteralConversion
private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTupleLiteral sourceTuple, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
{
// We have a successful tuple conversion; rather than producing a separate conversion node
// which is a conversion on top of a tuple literal, tuple conversion is an element-wise conversion of arguments.
Debug.Assert((conversion.Kind == ConversionKind.ImplicitNullable) == destination.IsNullableType());
var destinationWithoutNullable = destination;
var conversionWithoutNullable = conversion;
if (conversion.Kind == ConversionKind.ImplicitNullable)
{
destinationWithoutNullable = destination.GetNullableUnderlyingType();
conversionWithoutNullable = conversion.UnderlyingConversions[0];
}
Debug.Assert(conversionWithoutNullable.IsTupleLiteralConversion);
NamedTypeSymbol targetType = (NamedTypeSymbol)destinationWithoutNullable;
if (targetType.IsTupleType)
{
var destTupleType = (TupleTypeSymbol)targetType;
// do not lose the original element names in the literal if different from names in the target
TupleTypeSymbol.ReportNamesMismatchesIfAny(targetType, sourceTuple, diagnostics);
// Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
}
var arguments = sourceTuple.Arguments;
var convertedArguments = ArrayBuilder<BoundExpression>.GetInstance(arguments.Length);
ImmutableArray<TypeSymbol> targetElementTypes = targetType.GetElementTypesOfTupleOrCompatible();
Debug.Assert(targetElementTypes.Length == arguments.Length, "converting a tuple literal to incompatible type?");
var underlyingConversions = conversionWithoutNullable.UnderlyingConversions;
for (int i = 0; i < arguments.Length; i++)
{
var argument = arguments[i];
var destType = targetElementTypes[i];
var elementConversion = underlyingConversions[i];
convertedArguments.Add(CreateConversion(argument.Syntax, argument, elementConversion, isCast, destType, diagnostics));
}
BoundExpression result = new BoundConvertedTupleLiteral(
sourceTuple.Syntax,
sourceTuple.Type,
convertedArguments.ToImmutableAndFree(),
targetType);
if (sourceTuple.Type != destination)
{
// literal cast is applied to the literal
result = new BoundConversion(
sourceTuple.Syntax,
result,
conversion,
@checked: false,
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: destination);
}
// If we had a cast in the code, keep conversion in the tree.
// even though the literal is already converted to the target type.
if (isCast)
{
result = new BoundConversion(
syntax,
result,
Conversion.Identity,
@checked: false,
explicitCastInCode: isCast,
constantValueOpt: ConstantValue.NotAvailable,
type: destination);
}
return result;
}