Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
Original file line number Diff line number Diff line change
Expand Up @@ -7755,7 +7755,7 @@ private BoundExpression BindDynamicMemberAccess(
/// </summary>
/// <remarks>
/// If new checks are added to this method, they will also need to be added to
/// <see cref="MakeQueryInvocation(CSharpSyntaxNode, BoundExpression, bool, string, SeparatedSyntaxList{TypeSyntax}, ImmutableArray{TypeWithAnnotations}, ImmutableArray{BoundExpression}, BindingDiagnosticBag, string?)"/>.
/// <see cref="MakeQueryInvocation(CSharpSyntaxNode, BoundExpression, bool, string, SeparatedSyntaxList{TypeSyntax}, ImmutableArray{TypeWithAnnotations}, ImmutableArray{BoundExpression}, BindingDiagnosticBag, BindingDiagnosticBag, string?)"/>.
/// </remarks>
#else
/// <summary>
Expand Down
28 changes: 21 additions & 7 deletions src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,18 @@ private BoundExpression FinalTranslation(QueryTranslationState state, BindingDia

// this is the unoptimized form (when v is not the identifier x)
var d = BindingDiagnosticBag.GetInstance(diagnostics);
var checkValueDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics);
BoundExpression lambdaRight = MakeQueryUnboundLambda(state.RangeVariableMap(), x, v, diagnostics.AccumulatesDependencies);
result = MakeQueryInvocation(state.selectOrGroup, e, receiverIsCheckedForRValue: false, "GroupBy", ImmutableArray.Create(lambdaLeft, lambdaRight), d
result = MakeQueryInvocation(
state.selectOrGroup,
e,
receiverIsCheckedForRValue: false,
methodName: "GroupBy",
typeArgsSyntax: default,
typeArgs: default,
args: ImmutableArray.Create(lambdaLeft, lambdaRight),
diagnostics: d,
checkValueDiagnostics: checkValueDiagnostics
#if DEBUG
, state.nextInvokedMethodName
#endif
Expand All @@ -276,11 +286,13 @@ private BoundExpression FinalTranslation(QueryTranslationState state, BindingDia
{
// The optimized form. We store the unoptimized form for analysis
unoptimizedForm = result;
result = MakeQueryInvocation(state.selectOrGroup, e, receiverIsCheckedForRValue: false, "GroupBy", lambdaLeft, diagnostics
result = MakeQueryInvocation(state.selectOrGroup, e, receiverIsCheckedForRValue: true, "GroupBy", lambdaLeft, diagnostics

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This receiver (e) is checked on line 263. I've re-audited the rest of the call sites of MakeQueryInvocation and didn't see any others that need to be updated.

Comment thread
333fred marked this conversation as resolved.
Outdated
#if DEBUG
, state.nextInvokedMethodName
#endif
);

diagnostics.AddRange(checkValueDiagnostics);
#if DEBUG
state.nextInvokedMethodName = null;
#endif
Expand All @@ -289,9 +301,11 @@ private BoundExpression FinalTranslation(QueryTranslationState state, BindingDia
else
{
diagnostics.AddRange(d);
diagnostics.AddRange(checkValueDiagnostics);
}

d.Free();
checkValueDiagnostics.Free();
return MakeQueryClause(groupClause, result, queryInvocation: result, unoptimizedForm: unoptimizedForm);
}
default:
Expand Down Expand Up @@ -888,7 +902,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
#endif
)
{
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), ImmutableArray.Create(arg), diagnostics
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), ImmutableArray.Create(arg), diagnostics, checkValueDiagnostics: diagnostics
#if DEBUG
, expectedMethodName
#endif
Expand All @@ -901,7 +915,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
#endif
)
{
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), args, diagnostics
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), args, diagnostics, checkValueDiagnostics: diagnostics
#if DEBUG
, expectedMethodName
#endif
Expand All @@ -914,14 +928,14 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
#endif
)
{
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, new SeparatedSyntaxList<TypeSyntax>(new SyntaxNodeOrTokenList(typeArgSyntax, 0)), ImmutableArray.Create(typeArg), ImmutableArray<BoundExpression>.Empty, diagnostics
return MakeQueryInvocation(node, receiver, receiverIsCheckedForRValue, methodName, new SeparatedSyntaxList<TypeSyntax>(new SyntaxNodeOrTokenList(typeArgSyntax, 0)), ImmutableArray.Create(typeArg), ImmutableArray<BoundExpression>.Empty, diagnostics, checkValueDiagnostics: diagnostics
#if DEBUG
, expectedMethodName
#endif
);
}

protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression receiver, bool receiverIsCheckedForRValue, string methodName, SeparatedSyntaxList<TypeSyntax> typeArgsSyntax, ImmutableArray<TypeWithAnnotations> typeArgs, ImmutableArray<BoundExpression> args, BindingDiagnosticBag diagnostics
protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression receiver, bool receiverIsCheckedForRValue, string methodName, SeparatedSyntaxList<TypeSyntax> typeArgsSyntax, ImmutableArray<TypeWithAnnotations> typeArgs, ImmutableArray<BoundExpression> args, BindingDiagnosticBag diagnostics, BindingDiagnosticBag checkValueDiagnostics
Comment thread
333fred marked this conversation as resolved.
Outdated
#if DEBUG
, string? expectedMethodName
#endif
Expand Down Expand Up @@ -995,7 +1009,7 @@ protected BoundCall MakeQueryInvocation(CSharpSyntaxNode node, BoundExpression r
{
if (!receiverIsCheckedForRValue)
{
var checkedUltimateReceiver = CheckValue(ultimateReceiver, BindValueKind.RValue, diagnostics);
var checkedUltimateReceiver = CheckValue(ultimateReceiver, BindValueKind.RValue, checkValueDiagnostics);
if (checkedUltimateReceiver != ultimateReceiver)
{
receiver = updateUltimateReceiver(receiver, ultimateReceiver, checkedUltimateReceiver);
Expand Down
44 changes: 44 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/QueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4480,6 +4480,33 @@ public void SetOnlyProperty()
var test = from i in c.Prop
select i;

public class C {
public IEnumerable<int> Prop
{
set {}
}
}
", options: TestOptions.ReleaseExe);

comp.VerifyDiagnostics(
// (6,22): error CS0154: The property or indexer 'C.Prop' cannot be used in this context because it lacks the get accessor
// var test = from i in c.Prop
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "c.Prop").WithArguments("C.Prop").WithLocation(6, 22)
);
}

[Fact, WorkItem(50316, "https://github.com/dotnet/roslyn/issues/50316")]
public void SetOnlyProperty_GroupByContinuation()
{
var comp = CreateCompilation(@"
using System.Collections.Generic;
using System.Linq;

var c = new C();
var test = from i in c.Prop
group i by i into g
select g;

public class C {
public IEnumerable<int> Prop
{
Expand Down Expand Up @@ -4786,5 +4813,22 @@ public static class F
var comp = CreateCompilation(code);
CompileAndVerify(code, expectedOutput: "ran").VerifyDiagnostics();
}

[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/81709")]
public void PropertyAccess_AnonymousType_GroupBy()
{
var code = """
using System.Linq;

var x = new { A = new[] { new { B = 1 } } };

var y = from a in x.A
group a by a.B into g
select 1;
""";

var comp = CreateCompilation(code);
comp.VerifyDiagnostics();
}
}
}
Loading