Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,16 @@ bool shouldTryUserDefinedInstanceOperator(AssignmentExpressionSyntax node, bool
if (isExtension)
{
Debug.Assert(method.ContainingType.ExtensionParameter is not null);

if (Compilation.SourceModule != method.ContainingModule)
{
// While this code path is reachable, its effect is not observable
// because instance operators are simply not considered when the target
// version is C#13 or earlier. Coincidentally the following line
// would produce diagnostics only for C#13 or earlier.
CheckFeatureAvailability(node, MessageID.IDS_FeatureExtensions, diagnostics);
}

Conversion conversion = overloadResolutionResult.ValidResult.Result.ConversionForArg(0);

if (conversion.Kind is not ConversionKind.Identity)
Expand Down Expand Up @@ -556,11 +566,6 @@ TypeSymbol getResultType(ExpressionSyntax node, TypeSymbol leftType, BindingDiag
staticResultKind = LookupResultKind.Empty;
staticOriginalUserDefinedOperators = [];

if (!this.Compilation.LanguageVersion.AllowNewExtensions())
{
return null;
}

var result = BinaryOperatorOverloadResolutionResult.GetInstance();
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var extensionDeclarationsInSingleScope = ArrayBuilder<NamedTypeSymbol>.GetInstance();
Expand Down Expand Up @@ -1944,8 +1949,7 @@ private BinaryOperatorAnalysisResult BinaryOperatorOverloadResolution(
resultKind = LookupResultKind.Empty;
originalUserDefinedOperators = [];

if ((left.Type is null && right.Type is null) ||
!this.Compilation.LanguageVersion.AllowNewExtensions())
if (left.Type is null && right.Type is null)
{
return null;
}
Expand Down Expand Up @@ -2218,8 +2222,7 @@ static bool isNuint(TypeSymbol type)
originalUserDefinedOperators = [];

if (operand.IsLiteralDefault() || // Reported not being able to target-type `default` elsewhere, so we can avoid doing more work
operand.Type is null || // GetUserDefinedOperators performs this check too, let's optimize early
!this.Compilation.LanguageVersion.AllowNewExtensions())
operand.Type is null) // GetUserDefinedOperators performs this check too, let's optimize early
{
return null;
}
Expand Down Expand Up @@ -3342,6 +3345,16 @@ InstanceUserDefinedIncrementUsageMode getInstanceUserDefinedIncrementUsageMode(
if (isExtension)
{
Debug.Assert(method.ContainingType.ExtensionParameter is not null);

if (Compilation.SourceModule != method.ContainingModule)
{
// While this code path is reachable, its effect is not observable
// because instance operators are simply not considered when the target
// version is C#13 or earlier. Coincidentally the following line
// would produce diagnostics only for C#13 or earlier.
CheckFeatureAvailability(node, MessageID.IDS_FeatureExtensions, diagnostics);
}

Conversion conversion = overloadResolutionResult.ValidResult.Result.ConversionForArg(0);

if (conversion.Kind is not ConversionKind.Identity)
Expand Down Expand Up @@ -3432,11 +3445,6 @@ TypeSymbol getResultType(ExpressionSyntax node, TypeSymbol operandType, Instance
staticResultKind = LookupResultKind.Empty;
staticOriginalUserDefinedOperators = [];

if (!this.Compilation.LanguageVersion.AllowNewExtensions())
{
return null;
}

var result = UnaryOperatorOverloadResolutionResult.GetInstance();
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var extensionDeclarationsInSingleScope = ArrayBuilder<NamedTypeSymbol>.GetInstance();
Expand Down Expand Up @@ -3758,6 +3766,10 @@ private bool CheckConstraintLanguageVersionAndRuntimeSupportForOperator(SyntaxNo
{
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureUnsignedRightShift, diagnostics);
}
else if (methodOpt.GetIsNewExtensionMember())
{
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureExtensions, diagnostics);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,13): error CS0023: Operator '+' cannot be applied to operand of type 'S1'
// (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// _ = +s1;
Diagnostic(ErrorCode.ERR_BadUnaryOp, "+s1").WithArguments("+", "S1").WithLocation(6, 13)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "+s1").WithArguments("extensions").WithLocation(6, 13)
);

var src3 = $$$"""
Expand Down Expand Up @@ -2083,9 +2083,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,13): error CS0029: Cannot implicitly convert type 'S1' to 'bool'
// (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// if (s1)
Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1", "bool").WithLocation(6, 13)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1").WithArguments("extensions").WithLocation(6, 13)
);

var src3 = $$$"""
Expand Down Expand Up @@ -2641,9 +2641,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,13): error CS0029: Cannot implicitly convert type 'S1' to 'bool'
// (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// if ((s1, 1) == (s1, 1))
Diagnostic(ErrorCode.ERR_NoImplicitConv, "(s1, 1) == (s1, 1)").WithArguments("S1", "bool").WithLocation(6, 13)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "(s1, 1) == (s1, 1)").WithArguments("extensions").WithLocation(6, 13)
);
}

Expand Down Expand Up @@ -3355,9 +3355,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,9): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
// (6,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// ++s1;
Diagnostic(ErrorCode.ERR_BadUnaryOp, "++s1").WithArguments("++", "S1").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "++s1").WithArguments("extensions").WithLocation(6, 9)
);

var src3 = $$$"""
Expand Down Expand Up @@ -6746,9 +6746,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,9): error CS0023: Operator '++' cannot be applied to operand of type 'S1'
// (6,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// s1++;
Diagnostic(ErrorCode.ERR_BadUnaryOp, "s1++").WithArguments("++", "S1").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1++").WithArguments("extensions").WithLocation(6, 9)
);
}

Expand Down Expand Up @@ -7897,9 +7897,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,13): error CS0019: Operator '+' cannot be applied to operands of type 'S1' and 'S1'
// (6,13): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// _ = s1 + s1;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 + s1").WithArguments("+", "S1", "S1").WithLocation(6, 13)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1 + s1").WithArguments("extensions").WithLocation(6, 13)
);

var src3 = $$$"""
Expand Down Expand Up @@ -9960,9 +9960,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,14): error CS0019: Operator '&&' cannot be applied to operands of type 'S1' and 'S1'
// (6,14): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// s1 = s1 && s1;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 " + op + " s1").WithArguments(op, "S1", "S1").WithLocation(6, 14)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1 " + op + " s1").WithArguments("extensions").WithLocation(6, 14)
);
}

Expand Down Expand Up @@ -12901,9 +12901,9 @@ static void Main()

comp2 = CreateCompilation(src2, references: [comp1Ref], options: TestOptions.DebugExe, parseOptions: TestOptions.Regular13);
comp2.VerifyEmitDiagnostics(
// (6,9): error CS0019: Operator '+=' cannot be applied to operands of type 'S1' and 'S1'
// (6,9): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// s1 += s1;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "s1 += s1").WithArguments("+=", "S1", "S1").WithLocation(6, 9)
Diagnostic(ErrorCode.ERR_FeatureInPreview, "s1 += s1").WithArguments("extensions").WithLocation(6, 9)
);

var src3 = $$$"""
Expand Down