Skip to content

Require all parameters on hidden model factory back-compat overloads - #11832

Open
Jorge Rangel (jorgerangel-msft) with Copilot wants to merge 7 commits into
mainfrom
copilot/fix-back-compat-factory-methods
Open

Require all parameters on hidden model factory back-compat overloads#11832
Jorge Rangel (jorgerangel-msft) with Copilot wants to merge 7 commits into
mainfrom
copilot/fix-back-compat-factory-methods

Conversation

Copilot AI commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

#11703 made model factory compatibility overloads preserve their published parameter optionality. The latest regen shows the result is inverted: the [EditorBrowsable(Never)] overload ended up fully optional while the newly generated overload became all-required. This flips it back — the hidden overload requires every parameter, and the generated overload keeps the optionality of the current model shape.

// Before
public static CompatibilityModel CompatibilityModel(string id, string description, string name) { }

[EditorBrowsable(EditorBrowsableState.Never)]
public static CompatibilityModel CompatibilityModel(string id, int? count = default) { }

// After
public static CompatibilityModel CompatibilityModel(string id = default, string description = default, string name = default) { }

[EditorBrowsable(EditorBrowsableState.Never)]
public static CompatibilityModel CompatibilityModel(string id, int? count) { }

An overload that receives an argument for every parameter is preferred over one that substitutes a default, so an all-required hidden overload serves exactly the published call sites it was compiled against and is unreachable by any shorter call — which is what lets the visible overload keep its defaults.

Changes

  • MethodSignatureHelper
    • BuildBackCompatMethodSignature skips the minimum-prefix computation when hideMethod is true and requires every parameter instead. The visible (reorder-replacement) path still computes the minimum required prefix.
    • New AreAmbiguous(signature, other): walks the shared parameter-type prefix and reports the argument counts where both overloads are applicable and in the same default-substitution state, i.e. where overload resolution has no tie-breaker. Signatures with ref/out/params are skipped.
  • ModelFactoryProvider
    • Newly generated overloads are no longer constrained against published signatures that are restored as compatibility overloads; those overloads either require every parameter or replace the generated one outright.
    • TryBuildCompatibleMethodForPreviousContract builds the signature once and rejects it when AreAmbiguous matches a custom overload (logged under ModelFactoryMethodSkipped). A rejected visible replacement falls back to the hidden all-required overload.
  • Tests — flipped the assertions and baselines that encoded the inverted behavior, renamed the tests whose names now describe the wrong rule (with their TestData directories), and added coverage for the ambiguity guard end-to-end plus unit tests for AreAmbiguous.

Note the trade-off this restores: a published call that omitted a trailing optional argument no longer binds to the compatibility overload. That is the pre-#11703 behavior and supersedes #11667.

@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.

Copilot AI linked an issue Sep 2, 2026 that may be closed by this pull request
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Sep 2, 2026
@pkg-pr-new

pkg-pr-new Bot commented Sep 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@11832

commit: e3e2841

Copilot AI changed the title [WIP] Fix back compat model factory methods to have all required properties Require all parameters on hidden model factory back-compat overloads Sep 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The ambiguity detector misses null-literal and named-argument ambiguity, allowing conflicting overloads to remain.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates C# model-factory back compatibility so hidden overloads require all parameters while current overloads retain their optionality.

Changes:

  • Requires every parameter on hidden compatibility overloads.
  • Adds custom-overload ambiguity detection and fallback behavior.
  • Updates unit tests and generated baselines.

Paths are relative to packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/.

File summaries
File Description
src/Shared/MethodSignatureHelper.cs Adds required-parameter and ambiguity logic.
src/Providers/ModelFactoryProvider.cs Applies ambiguity fallback during compatibility generation.
test/Shared/MethodSignatureHelperTests.cs Tests signature and ambiguity behavior.
test/Providers/ModelFactories/ModelFactoryProviderTests.cs Updates and expands provider tests.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_UnknownDiscriminatorReturnTypeOverloadIsGenerated.cs Updates hidden-overload baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ReorderedPartiallyOptionalParametersRequireAllParameters(Last)/SampleNamespaceModelFactory.cs Adds previous-contract fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ReorderedPartiallyOptionalParametersRequireAllParameters.cs Updates optionality baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ReorderedOverloadKeptWhenStillInLastContract.cs Updates compatibility baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ReorderedFullyOptionalParametersRequireAllParameters(Last)/SampleNamespaceModelFactory.cs Adds fully optional fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ReorderedFullyOptionalParametersRequireAllParameters.cs Updates required compatibility baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_PositionalPrefixOverloadRequiresAllParameters.cs Updates positional-prefix baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_NewOverloadKeepsOptionalityAgainstCompatibilityOverload(Last)/SampleNamespaceModelFactory.cs Adds previous-overload fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_MultiplePreviousOverloadsRequireAllParameters(Last)/SampleNamespaceModelFactory.cs Adds multiple-overload fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_MultiplePreviousOverloadsRequireAllParameters.cs Updates multiple-overload baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_LongPositionalPrefixOverloadKeepsGeneratedOptionality(Last)/SampleNamespaceModelFactory.cs Adds long-prefix fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_LongPositionalPrefixOverloadKeepsGeneratedOptionality.cs Updates generated optionality baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CustomOverloadsCoexistWithRequiredCompatibilityOverload(Last)/SampleNamespaceModelFactory.cs Adds published custom fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CustomOverloadsCoexistWithRequiredCompatibilityOverload(Custom)/SampleNamespaceModelFactory.cs Adds current customization fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CustomOverloadsCoexistWithRequiredCompatibilityOverload.cs Adds custom coexistence baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CustomOverloadConstrainsNewlyGeneratedOverload.cs Updates custom constraint baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CoexistingPreviousOverloadsRequireAllParametersReversed(Last)/SampleNamespaceModelFactory.cs Adds reversed-order fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CoexistingPreviousOverloadsRequireAllParametersReversed.cs Updates reversed-order baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CoexistingPreviousOverloadsRequireAllParameters(Last)/SampleNamespaceModelFactory.cs Adds coexisting-overload fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_CoexistingPreviousOverloadsRequireAllParameters.cs Updates coexistence baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ChangedCustomOptionalityConstrainsGeneratedOverload(Last)/SampleNamespaceModelFactory.cs Adds prior optionality fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_ChangedCustomOptionalityConstrainsGeneratedOverload(Custom)/SampleNamespaceModelFactory.cs Adds changed customization fixture.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_AmbiguousReorderedOverloadFallsBackToHiddenOverload(Last)/SampleNamespaceModelFactory.cs Adds ambiguous prior overload.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_AmbiguousReorderedOverloadFallsBackToHiddenOverload(Custom)/SampleNamespaceModelFactory.cs Adds conflicting custom overload.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_AmbiguousReorderedOverloadFallsBackToHiddenOverload.cs Adds ambiguity-fallback baseline.
test/Providers/ModelFactories/TestData/ModelFactoryProviderTests/BackCompatibility_AbstractReturnTypeOverloadIsGenerated.cs Updates abstract-return baseline.
Review details
  • Files reviewed: 19/30 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot why were so many testdata file renamed with no changes?

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Copilot why were so many testdata file renamed with no changes?

Those were renamed only because the test methods were renamed and the helpers default TestData lookup to the caller member name. In e4ac243e I moved the unchanged TestData back to the original names and made the renamed tests explicitly reference those existing asset names, so the cumulative PR diff no longer contains the no-content renames.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@jorgerangel-msft

Copy link
Copy Markdown
Contributor

Those were renamed only because the test methods were renamed and the helpers default TestData lookup to the caller member name. In e4ac243e I moved the unchanged TestData back to the original names and made the renamed tests explicitly reference those existing asset names, so the cumulative PR diff no longer contains the no-content renames.

Copilot in that case, we can revert back to what you had if and only if, the test method names changed

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Those were renamed only because the test methods were renamed and the helpers default TestData lookup to the caller member name. In e4ac243e I moved the unchanged TestData back to the original nam...

Done in 3062a913. Since the test method names did change, I reverted to matching TestData names and removed the explicit old asset-name overrides.

…y checks

AreAmbiguous treated IsNullable as significant for every type, but C# erases
reference type nullability from a signature. A pair such as
M(string?, string = default) and M(string, string = default, string = default)
was reported as unambiguous even though M("a") is CS0121. Nullability is now
only significant for value types, so int and int? stay distinguishable.

Also:
- Extract AreEquivalentParameterTypes and reuse it in
  GetMinimumRequiredParameterCount, which already relied on the same rule.
- Restore the published default values when a compatibility overload candidate
  is rejected for ambiguity. BuildBackCompatMethodSignature strips defaults in
  place, so a rejected candidate previously left the previous signature
  partially required for later attempts.
- Document that AreAmbiguous is sound but deliberately incomplete, and why
  ref/out/params pairs are reported as unambiguous.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 098ae4f6-52c2-41dc-a7aa-88f561b153e5
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

@jorgerangel-msft

Copy link
Copy Markdown
Contributor

Regen preview: Azure/azure-sdk-for-net#62661

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Generic custom overloads can be falsely classified as ambiguous, causing avoidable source compatibility breaks.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 19/30 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Back Compat Model Factory Methods to Have All Required Properties

3 participants