Skip to content

Avoid duplicate misplaced 'partial' diagnostics - #85013

Merged
333fred merged 14 commits into
dotnet:mainfrom
CyrusNajmabadi:avoid-duplicate-misplaced-partial-diagnostics
Aug 27, 2026
Merged

Avoid duplicate misplaced 'partial' diagnostics#85013
333fred merged 14 commits into
dotnet:mainfrom
CyrusNajmabadi:avoid-duplicate-misplaced-partial-diagnostics

Conversation

@CyrusNajmabadi

@CyrusNajmabadi CyrusNajmabadi commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Report modifier-order diagnostics only when partial is valid for the declaration kind. This avoids reporting the same misplaced partial error from both modifier conversion and declaration-specific validation.

PR chain

This is a chain of three PRs. Merge them in this order:

Test plan

  • C# Syntax unit tests
  • C# Symbol unit tests
Microsoft Reviewers: Open in CodeFlow

Check partial ordering only for declarations that permit the modifier, leaving invalid declarations to the existing modifier check.
@CyrusNajmabadi
CyrusNajmabadi requested a review from a team as a code owner August 24, 2026 21:18
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service dotnet-policy-service Bot added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Aug 24, 2026
if (kind != DeclarationKind.Extension)
{
node.Modifiers.CheckPartialModifierOrder(diagnostics, isOrdinaryMethod: false);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

note: an alternative is to still have CheckPartialModifierOrder inside ToDeclarationModifiers, and then pass in a flag if you don't want them to be checked (because you know it would be be unhelpful with other errors you know will happen).

I'm fine with either approach.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

in this case, we'd have ToDeclarationModifiers(..., checkPartialModifierOrder: kind != DeclarationKind.Extension)

var result = modifiers.ToDeclarationModifiers(isForTypeDeclaration: false, diagnosticBag);
// There is no need to report an ordering error when 'partial' is not allowed.
// The invalid modifier is reported below.
if ((allowedModifiers & DeclarationModifiers.Partial) != 0)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

and here we'd do ToDeclarationModifiers(..., checkPartialModifierOrder: (allowedModifiers & DeclarationModifiers.Partial) != 0)

@CyrusNajmabadi

Copy link
Copy Markdown
Contributor Author

@333fred fixing that funky duplicate partial modifier issue.

@CyrusNajmabadi

Copy link
Copy Markdown
Contributor Author

@jjonescz ptal. Thanks!

Remove duplicate misplaced-partial expectations after modifier validation begins reporting each occurrence once.
Let modifier conversion validate both whether partial is allowed and whether it is ordered correctly, so later modifier checks do not report the same token again.
Comment thread src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs Outdated
// (1,8): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type.
// public partial delegate void M();
Diagnostic(ErrorCode.ERR_PartialMisplaced, "M").WithLocation(1, 30));
Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 8));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

note: these diagnostics are better. they're now on the partial modifier, not hte member.

Comment thread src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs
@333fred
333fred enabled auto-merge (squash) August 26, 2026 19:55
@333fred
333fred merged commit 9dd38bd into dotnet:main Aug 27, 2026
21 checks passed
@dotnet-policy-service dotnet-policy-service Bot added this to the Next milestone Aug 27, 2026
333fred pushed a commit that referenced this pull request Sep 4, 2026
## Summary
- Parse `partial` as a declaration modifier in any position when the
following tokens unambiguously identify a declaration.
- Build the intended declaration syntax tree instead of producing
cascading parser errors.
- Preserve the existing validity rules by reporting
`ERR_PartialMisplaced` from binding for every non-canonical position.
- Preserve the historical `partial async` ordinary-method behavior.
- Preserve the existing `CS0267` order-modifiers code fix; this PR does
not introduce or depend on a feature diagnostic.

This is a parser-recovery implementation fix. It does not change which
programs compile.

## PR chain

This is a chain of three PRs. Merge them in this order:

- #85013
- #84935
- #83216

## Test plan
- Added permutation and regression coverage for misplaced `partial` on
type and member declarations.
- Updated affected parser tests to verify declaration-shaped trees and
binding diagnostics.
- Verified the existing `OrderModifiersCompilerErrorTests` suite still
fixes `CS0267` by moving `partial` to its canonical position.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants