提交 cd68b0de 编写于 作者: A AlekseyTs 提交者: GitHub

Merge pull request #17549 from AlekseyTs/Bug377890

Ensure LocalRewriter doesn’t crash when it has to deal with ErrorMethodSymbol.
......@@ -123,7 +123,7 @@ public static BoundCall Synthesized(SyntaxNode syntax, BoundExpression receiverO
argsToParamsOpt: default(ImmutableArray<int>),
resultKind: LookupResultKind.Viable,
type: method.ReturnType,
hasErrors: false
hasErrors: method.OriginalDefinition is ErrorMethodSymbol
)
{ WasCompilerGenerated = true };
}
......
......@@ -296,7 +296,22 @@ private static BoundStatement BadStatement(BoundNode node)
private static BoundExpression BadExpression(BoundExpression node)
{
return new BoundBadExpression(node.Syntax, LookupResultKind.NotReferencable, ImmutableArray<Symbol>.Empty, ImmutableArray.Create<BoundNode>(node), node.Type);
return BadExpression(node.Syntax, node.Type, ImmutableArray.Create<BoundNode>(node));
}
private static BoundExpression BadExpression(SyntaxNode syntax, TypeSymbol resultType, BoundNode child)
{
return BadExpression(syntax, resultType, ImmutableArray.Create<BoundNode>(child));
}
private static BoundExpression BadExpression(SyntaxNode syntax, TypeSymbol resultType, BoundNode child1, BoundNode child2)
{
return BadExpression(syntax, resultType, ImmutableArray.Create<BoundNode>(child1, child2));
}
private static BoundExpression BadExpression(SyntaxNode syntax, TypeSymbol resultType, ImmutableArray<BoundNode> children)
{
return new BoundBadExpression(syntax, LookupResultKind.NotReferencable, ImmutableArray<Symbol>.Empty, children, resultType);
}
private bool TryGetWellKnownTypeMember<TSymbol>(SyntaxNode syntax, WellKnownMember member, out TSymbol symbol, bool isOptional = false) where TSymbol : Symbol
......@@ -305,10 +320,15 @@ private static BoundExpression BadExpression(BoundExpression node)
return ((object)symbol != null);
}
private MethodSymbol GetSpecialTypeMethod(SyntaxNode syntax, SpecialMember specialMember)
/// <summary>
/// This function provides a false sense of security, it is likely going to surprise you when the requested member is missing.
/// Recommendation: Do not use, use <see cref="TryGetSpecialTypeMethod"/> instead!
/// If used, a unit-test with a missing member is absolutely a must have.
/// </summary>
private MethodSymbol UnsafeGetSpecialTypeMethod(SyntaxNode syntax, SpecialMember specialMember)
{
MethodSymbol method;
if (Binder.TryGetSpecialTypeMember(_compilation, specialMember, syntax, _diagnostics, out method))
if (TryGetSpecialTypeMethod(syntax, specialMember, out method))
{
return method;
}
......@@ -322,6 +342,11 @@ private MethodSymbol GetSpecialTypeMethod(SyntaxNode syntax, SpecialMember speci
}
}
private bool TryGetSpecialTypeMethod(SyntaxNode syntax, SpecialMember specialMember, out MethodSymbol method)
{
return Binder.TryGetSpecialTypeMember(_compilation, specialMember, syntax, _diagnostics, out method);
}
public override BoundNode VisitTypeOfOperator(BoundTypeOfOperator node)
{
Debug.Assert((object)node.GetTypeFromHandle == null);
......
......@@ -814,7 +814,7 @@ private BoundExpression MakeOptimizedGetValueOrDefault(SyntaxNode syntax, BoundE
if (expression.Type.IsNullableType())
{
return BoundCall.Synthesized(syntax, expression, GetNullableMethod(syntax, expression.Type, SpecialMember.System_Nullable_T_GetValueOrDefault));
return BoundCall.Synthesized(syntax, expression, UnsafeGetNullableMethod(syntax, expression.Type, SpecialMember.System_Nullable_T_GetValueOrDefault));
}
return expression;
......@@ -839,7 +839,7 @@ private BoundExpression MakeOptimizedHasValue(SyntaxNode syntax, BoundExpression
private BoundExpression MakeNullableHasValue(SyntaxNode syntax, BoundExpression expression)
{
return BoundCall.Synthesized(syntax, expression, GetNullableMethod(syntax, expression.Type, SpecialMember.System_Nullable_T_get_HasValue));
return BoundCall.Synthesized(syntax, expression, UnsafeGetNullableMethod(syntax, expression.Type, SpecialMember.System_Nullable_T_get_HasValue));
}
private BoundExpression LowerLiftedBuiltInComparisonOperator(
......@@ -1194,7 +1194,7 @@ private BoundExpression MakeNullableHasValue(SyntaxNode syntax, BoundExpression
// new R?(tempX.GetValueOrDefault() OP tempY.GetValueOrDefault)
return new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
unliftedOp);
}
......@@ -1480,9 +1480,10 @@ private BoundExpression MakeNewNullableBoolean(SyntaxNode syntax, bool? value)
{
return new BoundDefaultOperator(syntax, null, nullableBoolType);
}
return new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, nullableBoolType, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, nullableBoolType, SpecialMember.System_Nullable_T__ctor),
MakeBooleanConstant(syntax, value.GetValueOrDefault()));
}
......@@ -1662,8 +1663,8 @@ private BoundExpression MakeNewNullableBoolean(SyntaxNode syntax, bool? value)
TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
MethodSymbol getValueOrDefaultX = GetNullableMethod(syntax, boundTempX.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefaultY = GetNullableMethod(syntax, boundTempY.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefaultX = UnsafeGetNullableMethod(syntax, boundTempX.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefaultY = UnsafeGetNullableMethod(syntax, boundTempY.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// tempx.GetValueOrDefault()
BoundExpression callX_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTempX, getValueOrDefaultX);
......@@ -1712,11 +1713,28 @@ private BoundExpression MakeNewNullableBoolean(SyntaxNode syntax, bool? value)
type: conditionalExpression.Type);
}
private MethodSymbol GetNullableMethod(SyntaxNode syntax, TypeSymbol nullableType, SpecialMember member)
/// <summary>
/// This function provides a false sense of security, it is likely going to surprise you when the requested member is missing.
/// Recommendation: Do not use, use <see cref="TryGetNullableMethod"/> instead!
/// If used, a unit-test with a missing member is absolutely a must have.
/// </summary>
private MethodSymbol UnsafeGetNullableMethod(SyntaxNode syntax, TypeSymbol nullableType, SpecialMember member)
{
var nullableType2 = nullableType as NamedTypeSymbol;
Debug.Assert((object)nullableType2 != null);
return GetSpecialTypeMethod(syntax, member).AsMember(nullableType2);
return UnsafeGetSpecialTypeMethod(syntax, member).AsMember(nullableType2);
}
private bool TryGetNullableMethod(SyntaxNode syntax, TypeSymbol nullableType, SpecialMember member, out MethodSymbol result)
{
var nullableType2 = (NamedTypeSymbol)nullableType;
if (TryGetSpecialTypeMethod(syntax, member, out result))
{
result = result.AsMember(nullableType2);
return true;
}
return false;
}
private BoundExpression RewriteNullableNullEquality(
......@@ -1816,7 +1834,7 @@ private BoundExpression RewriteStringEquality(BoundBinaryOperator oldNode, Synta
return oldNode.Update(operatorKind, loweredLeft, loweredRight, oldNode.ConstantValueOpt, oldNode.MethodOpt, oldNode.ResultKind, type);
}
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
......@@ -1839,7 +1857,7 @@ private BoundExpression RewriteDelegateOperation(SyntaxNode syntax, BinaryOperat
}
else
{
method = GetSpecialTypeMethod(syntax, member);
method = UnsafeGetSpecialTypeMethod(syntax, member);
}
Debug.Assert((object)method != null);
......@@ -1877,7 +1895,7 @@ private BoundExpression RewriteDecimalBinaryOperation(SyntaxNode syntax, BoundEx
}
// call Operator (left, right)
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
......
......@@ -911,7 +911,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
// wrap it in a nullable ctor.
defaultValue = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
defaultValue);
}
else
......@@ -1019,7 +1019,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
// Finally, wrap it in a nullable ctor.
defaultValue = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor),
defaultValue);
}
else if (defaultConstantValue.IsNull || defaultConstantValue.IsBad)
......
......@@ -147,7 +147,7 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
node.Syntax,
loweredReceiver,
receiverType.IsNullableType() ?
GetNullableMethod(node.Syntax, loweredReceiver.Type, SpecialMember.System_Nullable_T_get_HasValue) :
UnsafeGetNullableMethod(node.Syntax, loweredReceiver.Type, SpecialMember.System_Nullable_T_get_HasValue) :
null,
loweredAccessExpression,
null,
......
......@@ -739,7 +739,7 @@ private static BoundExpression NullableAlwaysHasValue(BoundExpression expression
// SPEC: by a wrapping from T to T?.
BoundExpression rewrittenConversion = MakeConversionNode(syntax, rewrittenOperand, conversion.UnderlyingConversions[0], rewrittenType.GetNullableUnderlyingType(), @checked);
MethodSymbol ctor = GetNullableMethod(syntax, rewrittenType, SpecialMember.System_Nullable_T__ctor);
MethodSymbol ctor = UnsafeGetNullableMethod(syntax, rewrittenType, SpecialMember.System_Nullable_T__ctor);
return new BoundObjectCreationExpression(syntax, ctor, rewrittenConversion);
}
else
......@@ -756,7 +756,7 @@ private static BoundExpression NullableAlwaysHasValue(BoundExpression expression
{
// (If the source is known to be possibly null then we need to keep the call to get Value
// in place so that it throws at runtime.)
MethodSymbol get_Value = GetNullableMethod(syntax, rewrittenOperandType, SpecialMember.System_Nullable_T_get_Value);
MethodSymbol get_Value = UnsafeGetNullableMethod(syntax, rewrittenOperandType, SpecialMember.System_Nullable_T_get_Value);
value = BoundCall.Synthesized(syntax, rewrittenOperand, get_Value);
}
......@@ -835,11 +835,17 @@ private static BoundExpression NullableAlwaysHasValue(BoundExpression expression
BoundAssignmentOperator tempAssignment;
var boundTemp = _factory.StoreToTemp(operand, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault;
if (!TryGetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault, out getValueOrDefault))
{
return BadExpression(syntax, type, operand);
}
BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);
BoundExpression consequence = new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
MakeConversionNode(
syntax,
BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault),
......@@ -914,7 +920,7 @@ private static BoundExpression NullableAlwaysHasValue(BoundExpression expression
{
return new BoundObjectCreationExpression(
syntax,
GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor),
MakeConversionNode(
syntax,
nonNullValue,
......@@ -1019,7 +1025,7 @@ private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall cal
if (call.Method.ReturnType.IsNonNullableValueType())
{
Debug.Assert(resultType.IsNullableType() && resultType.GetNullableUnderlyingType() == call.Method.ReturnType);
MethodSymbol ctor = GetNullableMethod(call.Syntax, resultType, SpecialMember.System_Nullable_T__ctor);
MethodSymbol ctor = UnsafeGetNullableMethod(call.Syntax, resultType, SpecialMember.System_Nullable_T__ctor);
return new BoundObjectCreationExpression(call.Syntax, ctor, call);
}
......@@ -1034,7 +1040,7 @@ private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall cal
{
if (_inExpressionLambda)
{
Conversion conv = MakeConversion(syntax, conversion, rewrittenOperand.Type, rewrittenType);
Conversion conv = TryMakeConversion(syntax, conversion, rewrittenOperand.Type, rewrittenType);
return BoundConversion.Synthesized(syntax, rewrittenOperand, conv, false, true, default(ConstantValue), rewrittenType);
}
......@@ -1068,7 +1074,7 @@ private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall cal
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(rewrittenOperand, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// temp.HasValue
BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);
......@@ -1121,7 +1127,13 @@ private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall cal
TypeSymbol target = rewrittenType;
SpecialMember member = GetIntPtrConversionMethod(source: rewrittenOperand.Type, target: rewrittenType);
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
{
return BadExpression(syntax, rewrittenType, rewrittenOperand);
}
Debug.Assert(!method.ReturnsVoid);
Debug.Assert(method.ParameterCount == 1);
......@@ -1339,7 +1351,10 @@ private BoundExpression RewriteDecimalConversion(SyntaxNode syntax, BoundExpress
}
}
private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, TypeSymbol fromType, TypeSymbol toType)
/// <summary>
/// Reports diagnostics and returns Conversion.NoConversion in case of missing runtime helpers.
/// </summary>
private Conversion TryMakeConversion(SyntaxNode syntax, Conversion conversion, TypeSymbol fromType, TypeSymbol toType)
{
switch (conversion.Kind)
{
......@@ -1347,8 +1362,18 @@ private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, Type
case ConversionKind.ImplicitUserDefined:
{
var meth = conversion.Method;
Conversion fromConversion = MakeConversion(syntax, conversion.UserDefinedFromConversion, fromType, meth.Parameters[0].Type);
Conversion toConversion = MakeConversion(syntax, conversion.UserDefinedToConversion, meth.ReturnType, toType);
Conversion fromConversion = TryMakeConversion(syntax, conversion.UserDefinedFromConversion, fromType, meth.Parameters[0].Type);
if (!fromConversion.Exists)
{
return Conversion.NoConversion;
}
Conversion toConversion = TryMakeConversion(syntax, conversion.UserDefinedToConversion, meth.ReturnType, toType);
if (!toConversion.Exists)
{
return Conversion.NoConversion;
}
if (fromConversion == conversion.UserDefinedFromConversion && toConversion == conversion.UserDefinedToConversion)
{
return conversion;
......@@ -1364,8 +1389,13 @@ private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, Type
case ConversionKind.IntPtr:
{
SpecialMember member = GetIntPtrConversionMethod(fromType, toType);
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
return MakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
{
return Conversion.NoConversion;
}
return TryMakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
}
case ConversionKind.ImplicitNumeric:
case ConversionKind.ExplicitNumeric:
......@@ -1373,8 +1403,13 @@ private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, Type
if (fromType.SpecialType == SpecialType.System_Decimal || toType.SpecialType == SpecialType.System_Decimal)
{
SpecialMember member = DecimalConversionMethod(fromType, toType);
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
return MakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
{
return Conversion.NoConversion;
}
return TryMakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
}
return conversion;
case ConversionKind.ImplicitEnumeration:
......@@ -1383,14 +1418,24 @@ private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, Type
if (fromType.SpecialType == SpecialType.System_Decimal)
{
SpecialMember member = DecimalConversionMethod(fromType, toType.GetEnumUnderlyingType());
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
return MakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
{
return Conversion.NoConversion;
}
return TryMakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
}
else if (toType.SpecialType == SpecialType.System_Decimal)
{
SpecialMember member = DecimalConversionMethod(fromType.GetEnumUnderlyingType(), toType);
MethodSymbol method = GetSpecialTypeMethod(syntax, member);
return MakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
{
return Conversion.NoConversion;
}
return TryMakeUserDefinedConversion(syntax, method, fromType, toType, conversion.IsImplicit);
}
return conversion;
default:
......@@ -1398,18 +1443,34 @@ private Conversion MakeConversion(SyntaxNode syntax, Conversion conversion, Type
}
}
private Conversion MakeConversion(SyntaxNode syntax, TypeSymbol fromType, TypeSymbol toType)
/// <summary>
/// Reports diagnostics and returns Conversion.NoConversion in case of missing runtime helpers.
/// </summary>
private Conversion TryMakeConversion(SyntaxNode syntax, TypeSymbol fromType, TypeSymbol toType)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
var result = MakeConversion(syntax, _compilation.Conversions.ClassifyConversionFromType(fromType, toType, ref useSiteDiagnostics), fromType, toType);
var result = TryMakeConversion(syntax, _compilation.Conversions.ClassifyConversionFromType(fromType, toType, ref useSiteDiagnostics), fromType, toType);
_diagnostics.Add(syntax, useSiteDiagnostics);
return result;
}
private Conversion MakeUserDefinedConversion(SyntaxNode syntax, MethodSymbol meth, TypeSymbol fromType, TypeSymbol toType, bool isImplicit = true)
/// <summary>
/// Reports diagnostics and returns Conversion.NoConversion in case of missing runtime helpers.
/// </summary>
private Conversion TryMakeUserDefinedConversion(SyntaxNode syntax, MethodSymbol meth, TypeSymbol fromType, TypeSymbol toType, bool isImplicit = true)
{
Conversion fromConversion = MakeConversion(syntax, fromType, meth.Parameters[0].Type);
Conversion toConversion = MakeConversion(syntax, meth.ReturnType, toType);
Conversion fromConversion = TryMakeConversion(syntax, fromType, meth.Parameters[0].Type);
if (!fromConversion.Exists)
{
return Conversion.NoConversion;
}
Conversion toConversion = TryMakeConversion(syntax, meth.ReturnType, toType);
if (!toConversion.Exists)
{
return Conversion.NoConversion;
}
// TODO: distinguish between normal and lifted conversions here
var analysis = UserDefinedConversionAnalysis.Normal(meth, fromConversion, toConversion, fromType, toType);
var result = UserDefinedConversionResult.Valid(ImmutableArray.Create<UserDefinedConversionAnalysis>(analysis), 0);
......
......@@ -412,7 +412,7 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
BoundStatement initializer = new BoundStatementList(forEachSyntax,
statements: ImmutableArray.Create<BoundStatement>(stringVarDecl, positionVariableDecl));
MethodSymbol method = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Length);
MethodSymbol method = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Length);
BoundExpression stringLength = BoundCall.Synthesized(
syntax: forEachSyntax,
receiverOpt: boundStringVar,
......@@ -436,7 +436,7 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
Debug.Assert(node.ElementConversion.IsValid);
// (V)s.Chars[p]
MethodSymbol chars = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Chars);
MethodSymbol chars = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Chars);
BoundExpression iterationVarInitValue = MakeConversionNode(
syntax: forEachSyntax,
rewrittenOperand: BoundCall.Synthesized(
......@@ -697,8 +697,8 @@ private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEach
TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);
// Values we'll use every iteration
MethodSymbol getLowerBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetLowerBound);
MethodSymbol getUpperBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetUpperBound);
MethodSymbol getLowerBoundMethod = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetLowerBound);
MethodSymbol getUpperBoundMethod = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetUpperBound);
BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);
......
......@@ -35,7 +35,12 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato
if (_inExpressionLambda)
{
TypeSymbol strippedLeftType = rewrittenLeft.Type.StrippedType();
Conversion rewrittenConversion = MakeConversion(syntax, leftConversion, strippedLeftType, rewrittenResultType);
Conversion rewrittenConversion = TryMakeConversion(syntax, leftConversion, strippedLeftType, rewrittenResultType);
if (!rewrittenConversion.Exists)
{
return BadExpression(syntax, rewrittenResultType, rewrittenLeft, rewrittenRight);
}
return new BoundNullCoalescingOperator(syntax, rewrittenLeft, rewrittenRight, rewrittenConversion, rewrittenResultType);
}
......@@ -116,7 +121,7 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato
// MakeConversion(temp, rewrittenResultType)
BoundExpression convertedLeft = GetConvertedLeftForNullCoalescingOperator(boundTemp, leftConversion, rewrittenResultType);
Debug.Assert(convertedLeft.Type.Equals(rewrittenResultType, TypeCompareKind.IgnoreDynamicAndTupleNames));
Debug.Assert(convertedLeft.HasErrors || convertedLeft.Type.Equals(rewrittenResultType, TypeCompareKind.IgnoreDynamicAndTupleNames));
// (temp != null) ? MakeConversion(temp, LeftConversion) : RightOperand
BoundExpression conditionalExpression = RewriteConditionalOperator(
......@@ -156,7 +161,7 @@ private BoundExpression GetConvertedLeftForNullCoalescingOperator(BoundExpressio
if (rewrittenLeftType != rewrittenResultType && rewrittenLeftType.IsNullableType())
{
TypeSymbol strippedLeftType = rewrittenLeftType.GetNullableUnderlyingType();
MethodSymbol getValueOrDefault = GetNullableMethod(rewrittenLeft.Syntax, rewrittenLeftType, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(rewrittenLeft.Syntax, rewrittenLeftType, SpecialMember.System_Nullable_T_GetValueOrDefault);
rewrittenLeft = BoundCall.Synthesized(rewrittenLeft.Syntax, rewrittenLeft, getValueOrDefault);
if (strippedLeftType == rewrittenResultType)
{
......
......@@ -501,7 +501,7 @@ private void LowerBasicSwitch(DecisionTree.ByValue byValue)
if (underlyingSwitchType.SpecialType == SpecialType.System_String)
{
_localRewriter.EnsureStringHashFunction(rewrittenSections, _factory.Syntax);
stringEquality = _localRewriter.GetSpecialTypeMethod(_factory.Syntax, SpecialMember.System_String__op_Equality);
stringEquality = _localRewriter.UnsafeGetSpecialTypeMethod(_factory.Syntax, SpecialMember.System_String__op_Equality);
}
// The BoundSwitchStatement requires a constant target when there are no sections, so we accomodate that here.
......
......@@ -179,9 +179,11 @@ BoundExpression MakeIsDeclarationPattern(SyntaxNode syntax, BoundExpression lowe
// t = e as T?;
// return t.HasValue;
// }
// At the moment this code path has no test coverage https://github.com/dotnet/roslyn/issues/17548.
return _factory.Call(
_factory.AssignmentExpression(loweredTarget, _factory.As(loweredInput, type)),
GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_get_HasValue));
UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_get_HasValue));
}
else if (type.IsValueType)
{
......@@ -207,7 +209,7 @@ BoundExpression MakeIsDeclarationPattern(SyntaxNode syntax, BoundExpression lowe
var asg1 = _factory.AssignmentExpression(_factory.Local(tmp), tmpType == loweredInput.Type ? loweredInput : _factory.As(loweredInput, tmpType));
var value = _factory.Call(
_factory.Local(tmp),
GetNullableMethod(syntax, tmpType, SpecialMember.System_Nullable_T_GetValueOrDefault));
UnsafeGetNullableMethod(syntax, tmpType, SpecialMember.System_Nullable_T_GetValueOrDefault));
var asg2 = _factory.AssignmentExpression(loweredTarget, value);
var result = MakeNullableHasValue(syntax, _factory.Local(tmp));
return _factory.MakeSequence(tmp, asg1, asg2, result);
......
......@@ -260,7 +260,7 @@ private BoundExpression RewriteStringConcatenationOneExpr(SyntaxNode syntax, Bou
return _factory.Coalesce(loweredOperand, _factory.Literal(""));
}
var method = GetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatObject);
var method = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__ConcatObject);
Debug.Assert((object)method != null);
return (BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredOperand);
......@@ -272,7 +272,7 @@ private BoundExpression RewriteStringConcatenationTwoExprs(SyntaxNode syntax, Bo
SpecialMember.System_String__ConcatStringString :
SpecialMember.System_String__ConcatObjectObject;
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return (BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredLeft, loweredRight);
......@@ -286,7 +286,7 @@ private BoundExpression RewriteStringConcatenationThreeExprs(SyntaxNode syntax,
SpecialMember.System_String__ConcatStringStringString :
SpecialMember.System_String__ConcatObjectObjectObject;
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return BoundCall.Synthesized(syntax, null, method, ImmutableArray.Create(loweredFirst, loweredSecond, loweredThird));
......@@ -295,7 +295,7 @@ private BoundExpression RewriteStringConcatenationThreeExprs(SyntaxNode syntax,
private BoundExpression RewriteStringConcatenationManyExprs(SyntaxNode syntax, ImmutableArray<BoundExpression> loweredArgs)
{
Debug.Assert(loweredArgs.Length > 3);
Debug.Assert(loweredArgs.All(a => a.Type.SpecialType == SpecialType.System_Object || a.Type.SpecialType == SpecialType.System_String));
Debug.Assert(loweredArgs.All(a => a.HasErrors || a.Type.SpecialType == SpecialType.System_Object || a.Type.SpecialType == SpecialType.System_String));
bool isObject = false;
TypeSymbol elementType = null;
......@@ -315,7 +315,7 @@ private BoundExpression RewriteStringConcatenationManyExprs(SyntaxNode syntax, I
if (!isObject && loweredArgs.Length == 4)
{
SpecialMember member = SpecialMember.System_String__ConcatStringStringStringString;
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return (BoundExpression)BoundCall.Synthesized(syntax, null, method, loweredArgs);
......@@ -326,7 +326,7 @@ private BoundExpression RewriteStringConcatenationManyExprs(SyntaxNode syntax, I
SpecialMember.System_String__ConcatObjectArray :
SpecialMember.System_String__ConcatStringArray;
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
var array = _factory.ArrayOrEmpty(elementType, loweredArgs);
......@@ -345,7 +345,7 @@ private BoundExpression RewriteStringConcatInExpressionLambda(SyntaxNode syntax,
SpecialMember.System_String__ConcatStringString :
SpecialMember.System_String__ConcatObjectObject;
var method = GetSpecialTypeMethod(syntax, member);
var method = UnsafeGetSpecialTypeMethod(syntax, member);
Debug.Assert((object)method != null);
return new BoundBinaryOperator(syntax, operatorKind, loweredLeft, loweredRight, default(ConstantValue), method, default(LookupResultKind), type);
......@@ -382,7 +382,7 @@ private BoundExpression ConvertConcatExprToStringIfPossible(SyntaxNode syntax, B
// If so, we can synthesize a ToString call to avoid boxing.
if (ConcatExprCanBeOptimizedWithToString(operand.Type))
{
var toString = GetSpecialTypeMethod(syntax, SpecialMember.System_Object__ToString);
var toString = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_Object__ToString);
var type = (NamedTypeSymbol)operand.Type;
var toStringMembers = type.GetMembers(toString.Name);
......
......@@ -104,7 +104,7 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node)
if (rewrittenExpression.Type.SpecialType == SpecialType.System_String)
{
EnsureStringHashFunction(rewrittenSections, syntax);
stringEquality = GetSpecialTypeMethod(syntax, SpecialMember.System_String__op_Equality);
stringEquality = UnsafeGetSpecialTypeMethod(syntax, SpecialMember.System_String__op_Equality);
}
return oldNode.Update(
......@@ -162,7 +162,7 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node)
// Rewrite the switch statement using nullable expression's underlying value as the switch expression.
// rewrittenExpression.GetValueOrDefault()
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, exprNullableType, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, exprNullableType, SpecialMember.System_Nullable_T_GetValueOrDefault);
BoundCall callGetValueOrDefault = BoundCall.Synthesized(exprSyntax, rewrittenExpression, getValueOrDefault);
rewrittenExpression = callGetValueOrDefault;
......
......@@ -187,7 +187,7 @@ public override BoundNode VisitUnaryOperator(BoundUnaryOperator node)
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(loweredOperand, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// temp.HasValue
BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);
......@@ -333,7 +333,7 @@ public override BoundNode VisitUnaryOperator(BoundUnaryOperator node)
private BoundExpression GetLiftedUnaryOperatorConsequence(UnaryOperatorKind kind, SyntaxNode syntax, MethodSymbol method, TypeSymbol type, BoundExpression nonNullOperand)
{
MethodSymbol ctor = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);
MethodSymbol ctor = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);
// OP(temp.GetValueOrDefault())
BoundExpression unliftedOp = MakeUnaryOperator(
......@@ -620,8 +620,8 @@ private BoundExpression MakeUserDefinedIncrementOperator(BoundIncrementOperator
BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp = _factory.StoreToTemp(rewrittenArgument, out tempAssignment);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = UnsafeGetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);
// temp.HasValue
BoundExpression condition = MakeNullableHasValue(node.Syntax, boundTemp);
......@@ -699,7 +699,7 @@ private BoundExpression MakeBuiltInIncrementOperator(BoundIncrementOperator node
if (binaryOperatorKind.IsLifted())
{
binaryOperandType = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(binaryOperandType);
MethodSymbol ctor = GetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
MethodSymbol ctor = UnsafeGetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
boundOne = new BoundObjectCreationExpression(node.Syntax, ctor, boundOne);
}
......@@ -790,8 +790,8 @@ private BoundExpression MakeLiftedDecimalIncDecOperator(SyntaxNode syntax, Binar
// This method assumes that operand is already a temporary and so there is no need to copy it again.
MethodSymbol method = GetDecimalIncDecOperator(oper);
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = GetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T__ctor);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol ctor = UnsafeGetNullableMethod(syntax, operand.Type, SpecialMember.System_Nullable_T__ctor);
// x.HasValue
BoundExpression condition = MakeNullableHasValue(syntax, operand);
......
......@@ -278,7 +278,7 @@ private BoundStatement RewriteUsingStatementTryFinally(SyntaxNode syntax, BoundB
if (isNullableValueType)
{
MethodSymbol getValueOrDefault = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
MethodSymbol getValueOrDefault = UnsafeGetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
// local.GetValueOrDefault()
disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
}
......
......@@ -637,7 +637,8 @@ public BoundCall Call(BoundExpression receiver, MethodSymbol method, ImmutableAr
return new BoundCall(
Syntax, receiver, method, args,
ImmutableArray<String>.Empty, ImmutableArray<RefKind>.Empty, false, false, false,
default(ImmutableArray<int>), LookupResultKind.Viable, method.ReturnType)
default(ImmutableArray<int>), LookupResultKind.Viable, method.ReturnType,
hasErrors:method.OriginalDefinition is ErrorMethodSymbol)
{ WasCompilerGenerated = true };
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册