Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge main to main-vs-deps #57390

Merged
merged 8 commits into from
Oct 26, 2021
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<MajorVersion>4</MajorVersion>
<MinorVersion>1</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseVersionLabel>1</PreReleaseVersionLabel>
<PreReleaseVersionLabel>2</PreReleaseVersionLabel>
<VersionPrefix>$(MajorVersion).$(MinorVersion).$(PatchVersion)</VersionPrefix>
<!--
By default the assembly version in official builds is "$(MajorVersion).$(MinorVersion).0.0".
Expand Down
16 changes: 14 additions & 2 deletions eng/config/PublishData.json
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,18 @@
"vsMajorVersion": 17,
"insertionTitlePrefix": "[d17.0]"
},
"release/dev17.1-vs-deps": {
"nugetKind": [
"Shipping",
"NonShipping"
],
"version": "4.1.*",
"packageFeeds": "default",
"channels": [],
"vsBranch": "main",
"vsMajorVersion": 17,
"insertionTitlePrefix": "[d17.1p1]"
},
"main-vs-deps": {
"nugetKind": [
"Shipping",
Expand All @@ -210,8 +222,8 @@
"channels": [],
"vsBranch": "main",
"vsMajorVersion": 17,
"insertionCreateDraftPR": false,
"insertionTitlePrefix": "[d17.1]"
"insertionCreateDraftPR": true,
"insertionTitlePrefix": "[d17.1p2]"
},
"main": {
"nugetKind": [
Expand Down
55 changes: 49 additions & 6 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,7 @@ BoundExpression createConversion(
}

// Obsolete diagnostics for method group are reported as part of creating the method group conversion.
ReportDiagnosticsIfObsolete(diagnostics, conversion, syntax, hasBaseReceiver: false);
if (conversion.Method is not null)
{
ReportUseSite(conversion.Method, diagnostics, syntax.Location);
}
CheckConstraintLanguageVersionAndRuntimeSupportForConversion(syntax, conversion, diagnostics);
reportUseSiteDiagnostics(conversion);

if (conversion.IsAnonymousFunction && source.Kind == BoundKind.UnboundLambda)
{
Expand Down Expand Up @@ -266,6 +261,8 @@ BoundExpression createConversion(
.WithSuppression(source.IsSuppressed);
}

reportUseSiteDiagnosticsForUnderlyingConversions(conversion);

return new BoundConversion(
syntax,
BindToNaturalType(source, diagnostics),
Expand All @@ -277,6 +274,46 @@ BoundExpression createConversion(
type: destination,
hasErrors: hasErrors)
{ WasCompilerGenerated = wasCompilerGenerated };

void reportUseSiteDiagnostics(Conversion conversion)
{
// Obsolete diagnostics for method group are reported as part of creating the method group conversion.
Debug.Assert(!conversion.IsMethodGroup);
ReportDiagnosticsIfObsolete(diagnostics, conversion, syntax, hasBaseReceiver: false);
if (conversion.Method is not null)
{
ReportUseSite(conversion.Method, diagnostics, syntax.Location);
}
CheckConstraintLanguageVersionAndRuntimeSupportForConversion(syntax, conversion, diagnostics);
}

void reportUseSiteDiagnosticsForUnderlyingConversions(Conversion conversion)
{
var underlyingConversions = conversion.UnderlyingConversions;

if (!underlyingConversions.IsDefaultOrEmpty)
{
foreach (var underlying in underlyingConversions)
{
reportUseSiteDiagnosticsForSelfAndUnderlyingConversions(underlying);

if (underlying.IsUserDefined)
{
reportUseSiteDiagnosticsForSelfAndUnderlyingConversions(underlying.UserDefinedFromConversion);
reportUseSiteDiagnosticsForSelfAndUnderlyingConversions(underlying.UserDefinedToConversion);
underlying.MarkUnderlyingConversionsChecked();
}
}

conversion.MarkUnderlyingConversionsChecked();
}

void reportUseSiteDiagnosticsForSelfAndUnderlyingConversions(Conversion conversion)
{
reportUseSiteDiagnostics(conversion);
reportUseSiteDiagnosticsForUnderlyingConversions(conversion);
}
}
}
}

Expand Down Expand Up @@ -311,6 +348,9 @@ private BoundExpression ConvertObjectCreationExpression(SyntaxNode syntax, Bound
// is actually identical to `S? x = new S();`.
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var conversion = Conversions.ClassifyStandardConversion(null, expr.Type, destination, ref useSiteInfo);
Debug.Assert(conversion.IsNullable);
Debug.Assert(conversion.UnderlyingConversions.Single().IsIdentity);
conversion.MarkUnderlyingConversionsChecked();
expr = new BoundConversion(
node.Syntax,
operand: expr,
Expand Down Expand Up @@ -443,6 +483,7 @@ private BoundExpression CreateUserDefinedConversion(
Debug.Assert(conversionGroup != null);
Debug.Assert(conversion.IsUserDefined);

conversion.MarkUnderlyingConversionsChecked();
if (!conversion.IsValid)
{
if (!hasErrors)
Expand Down Expand Up @@ -730,6 +771,7 @@ private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTup
{
destinationWithoutNullable = destination.GetNullableUnderlyingType();
conversionWithoutNullable = conversion.UnderlyingConversions[0];
conversion.MarkUnderlyingConversionsChecked();
}

Debug.Assert(conversionWithoutNullable.IsTupleLiteralConversion);
Expand Down Expand Up @@ -772,6 +814,7 @@ private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTup
var targetElementTypes = targetType.TupleElementTypesWithAnnotations;
Debug.Assert(targetElementTypes.Length == arguments.Length, "converting a tuple literal to incompatible type?");
var underlyingConversions = conversionWithoutNullable.UnderlyingConversions;
conversionWithoutNullable.MarkUnderlyingConversionsChecked();

for (int i = 0; i < arguments.Length; i++)
{
Expand Down
20 changes: 18 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private bool MakeDeconstructionConversion(
bool hasErrors = false;

int count = variables.Count;
var nestedConversions = ArrayBuilder<Conversion>.GetInstance(count);
var nestedConversions = ArrayBuilder<(BoundValuePlaceholder?, BoundExpression?)>.GetInstance(count);
for (int i = 0; i < count; i++)
{
var variable = variables[i];
Expand All @@ -306,11 +306,21 @@ private bool MakeDeconstructionConversion(

hasErrors |= !MakeDeconstructionConversion(tupleOrDeconstructedTypes[i], elementSyntax, rightSyntax, diagnostics,
variable.NestedVariables, out nestedConversion);

Debug.Assert(nestedConversion.Kind == ConversionKind.Deconstruction);
var operandPlaceholder = new BoundValuePlaceholder(syntax, ErrorTypeSymbol.UnknownResultType).MakeCompilerGenerated();
nestedConversions.Add((operandPlaceholder, new BoundConversion(syntax, operandPlaceholder, nestedConversion,
@checked: false, explicitCastInCode: false,
conversionGroupOpt: null, constantValueOpt: null,
#pragma warning disable format
type: ErrorTypeSymbol.UnknownResultType) { WasCompilerGenerated = true }));
#pragma warning restore format
}
else
{
var single = variable.Single;
Debug.Assert(single is object);
Debug.Assert(single.Type is not null);
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
nestedConversion = this.Conversions.ClassifyConversionFromType(tupleOrDeconstructedTypes[i], single.Type, ref useSiteInfo);
diagnostics.Add(single.Syntax, useSiteInfo);
Expand All @@ -319,9 +329,15 @@ private bool MakeDeconstructionConversion(
{
hasErrors = true;
GenerateImplicitConversionError(diagnostics, Compilation, single.Syntax, nestedConversion, tupleOrDeconstructedTypes[i], single.Type);
nestedConversions.Add((null, null));
}
else
{
var operandPlaceholder = new BoundValuePlaceholder(syntax, tupleOrDeconstructedTypes[i]).MakeCompilerGenerated();
nestedConversions.Add((operandPlaceholder, CreateConversion(syntax, operandPlaceholder,
nestedConversion, isCast: false, conversionGroupOpt: null, single.Type, diagnostics)));
}
}
nestedConversions.Add(nestedConversion);
}

conversion = new Conversion(ConversionKind.Deconstruction, deconstructMethod, nestedConversions.ToImmutableAndFree());
Expand Down
32 changes: 15 additions & 17 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2558,32 +2558,30 @@ private BoundExpression BindExplicitNullableCastFromNonNullable(ExpressionSyntax
try
{
var underlyingExpr = BindCastCore(node, operand, underlyingTargetTypeWithAnnotations, wasCompilerGenerated: false, diagnostics: bag);
if (underlyingExpr.HasErrors || bag.HasAnyErrors())
{
Error(diagnostics, ErrorCode.ERR_NoExplicitConv, node, operand.Type, targetTypeWithAnnotations.Type);

return new BoundConversion(
node,
operand,
Conversion.NoConversion,
@checked: CheckOverflowAtRuntime,
explicitCastInCode: true,
conversionGroupOpt: new ConversionGroup(Conversion.NoConversion, explicitType: targetTypeWithAnnotations),
constantValueOpt: ConstantValue.NotAvailable,
type: targetTypeWithAnnotations.Type,
hasErrors: true);
}

// It's possible for the S -> T conversion to produce a 'better' constant value. If this
// constant value is produced place it in the tree so that it gets emitted. This maintains
// parity with the native compiler which also evaluated the conversion at compile time.
if (underlyingExpr.ConstantValue != null)
if (underlyingExpr.ConstantValue != null &&
!underlyingExpr.HasErrors && !bag.HasAnyErrors())
{
underlyingExpr.WasCompilerGenerated = true;
diagnostics.AddRange(bag.DiagnosticBag);
return BindCastCore(node, underlyingExpr, targetTypeWithAnnotations, wasCompilerGenerated: operand.WasCompilerGenerated, diagnostics: diagnostics);
}

return BindCastCore(node, operand, targetTypeWithAnnotations, wasCompilerGenerated: operand.WasCompilerGenerated, diagnostics: diagnostics);
var bag2 = BindingDiagnosticBag.GetInstance(diagnostics);

var result = BindCastCore(node, operand, targetTypeWithAnnotations, wasCompilerGenerated: operand.WasCompilerGenerated, diagnostics: bag2);

if (bag2.AccumulatesDiagnostics && bag.HasAnyErrors() && !bag2.HasAnyErrors())
{
diagnostics.AddRange(bag.DiagnosticBag);
}

diagnostics.AddRange(bag2);
bag2.Free();
return result;
}
finally
{
Expand Down
29 changes: 22 additions & 7 deletions src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,7 @@ private BoundExpression BindDynamicBinaryOperator(
// We need to make sure left is either implicitly convertible to Boolean or has user defined truth operator.
// left && right is lowered to {op_False|op_Implicit}(left) ? left : And(left, right)
// left || right is lowered to {op_True|!op_Implicit}(left) ? left : Or(left, right)
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
if (!IsValidDynamicCondition(left, isNegative: kind == BinaryOperatorKind.LogicalAnd, useSiteInfo: ref useSiteInfo, userDefinedOperator: out userDefinedOperator))
if (!IsValidDynamicCondition(left, isNegative: kind == BinaryOperatorKind.LogicalAnd, diagnostics, userDefinedOperator: out userDefinedOperator))
{
// Dev11 reports ERR_MustHaveOpTF. The error was shared between this case and user-defined binary Boolean operators.
// We report two distinct more specific error messages.
Expand All @@ -404,8 +403,6 @@ private BoundExpression BindDynamicBinaryOperator(
Debug.Assert(left.Type is not TypeParameterSymbol);
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, userDefinedOperator, constrainedToTypeOpt: null, diagnostics);
}

diagnostics.Add(node, useSiteInfo);
}

return new BoundBinaryOperator(
Expand Down Expand Up @@ -990,7 +987,7 @@ private BoundExpression BindConditionalLogicalOperator(BinaryExpressionSyntax no
return new BoundBinaryOperator(node, kind, left, right, ConstantValue.NotAvailable, methodOpt: null, constrainedToTypeOpt: null, lookupResult, originalUserDefinedOperators, CreateErrorType(), true);
}

private bool IsValidDynamicCondition(BoundExpression left, bool isNegative, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, out MethodSymbol userDefinedOperator)
private bool IsValidDynamicCondition(BoundExpression left, bool isNegative, BindingDiagnosticBag diagnostics, out MethodSymbol userDefinedOperator)
{
userDefinedOperator = null;

Expand All @@ -1005,19 +1002,37 @@ private bool IsValidDynamicCondition(BoundExpression left, bool isNegative, ref
return true;
}

var implicitConversion = Conversions.ClassifyImplicitConversionFromExpression(left, Compilation.GetSpecialType(SpecialType.System_Boolean), ref useSiteInfo);
var booleanType = Compilation.GetSpecialType(SpecialType.System_Boolean);
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var implicitConversion = Conversions.ClassifyImplicitConversionFromExpression(left, booleanType, ref useSiteInfo);

if (implicitConversion.Exists)
{
if (left.Type is not null)
{
var operandPlaceholder = new BoundValuePlaceholder(left.Syntax, left.Type).MakeCompilerGenerated();
CreateConversion(left.Syntax, operandPlaceholder, implicitConversion, isCast: false, conversionGroupOpt: null, booleanType, diagnostics);
}
else
{
Debug.Assert(left.IsLiteralNull());
}

diagnostics.Add(left.Syntax, useSiteInfo);
return true;
}

if (type.Kind != SymbolKind.NamedType)
{
diagnostics.Add(left.Syntax, useSiteInfo);
return false;
}

var namedType = type as NamedTypeSymbol;
return HasApplicableBooleanOperator(namedType, isNegative ? WellKnownMemberNames.FalseOperatorName : WellKnownMemberNames.TrueOperatorName, type, ref useSiteInfo, out userDefinedOperator);
var result = HasApplicableBooleanOperator(namedType, isNegative ? WellKnownMemberNames.FalseOperatorName : WellKnownMemberNames.TrueOperatorName, type, ref useSiteInfo, out userDefinedOperator);
diagnostics.Add(left.Syntax, useSiteInfo);

return result;
}

private bool IsValidUserDefinedConditionalLogicalOperator(
Expand Down
10 changes: 6 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,19 +1192,19 @@ private ImmutableArray<BoundPropertySubpattern> BindPropertyPatternClause(
}
else
{
member = LookupMembersForPropertyPattern(inputType, expr, diagnostics, ref hasErrors);
member = LookupMembersForPropertyPattern(inputType, expr, diagnostics, ref inputValEscape, ref hasErrors);
memberType = member.Type;
}

BoundPattern boundPattern = BindPattern(pattern, memberType, GetValEscape(memberType, inputValEscape), permitDesignations, hasErrors, diagnostics);
BoundPattern boundPattern = BindPattern(pattern, memberType, inputValEscape, permitDesignations, hasErrors, diagnostics);
builder.Add(new BoundPropertySubpattern(p, member, boundPattern));
}

return builder.ToImmutableAndFree();
}

private BoundPropertySubpatternMember LookupMembersForPropertyPattern(
TypeSymbol inputType, ExpressionSyntax expr, BindingDiagnosticBag diagnostics, ref bool hasErrors)
TypeSymbol inputType, ExpressionSyntax expr, BindingDiagnosticBag diagnostics, ref uint inputValEscape, ref bool hasErrors)
{
BoundPropertySubpatternMember? receiver = null;
Symbol? symbol = null;
Expand All @@ -1214,7 +1214,7 @@ private BoundPropertySubpatternMember LookupMembersForPropertyPattern(
symbol = BindPropertyPatternMember(inputType, name, ref hasErrors, diagnostics);
break;
case MemberAccessExpressionSyntax { Name: IdentifierNameSyntax name } memberAccess when memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression):
receiver = LookupMembersForPropertyPattern(inputType, memberAccess.Expression, diagnostics, ref hasErrors);
receiver = LookupMembersForPropertyPattern(inputType, memberAccess.Expression, diagnostics, ref inputValEscape, ref hasErrors);
symbol = BindPropertyPatternMember(receiver.Type.StrippedType(), name, ref hasErrors, diagnostics);
break;
default:
Expand All @@ -1230,6 +1230,8 @@ private BoundPropertySubpatternMember LookupMembersForPropertyPattern(
_ => CreateErrorType()
};

// Note: since we're recursing on the receiver, the val escape correctly flows from inside out.
inputValEscape = GetValEscape(memberType, inputValEscape);
return new BoundPropertySubpatternMember(expr, receiver, symbol, type: memberType, hasErrors);
}

Expand Down
Loading