Skip to content

Conversation

@jcouv
Copy link
Member

@jcouv jcouv commented Aug 28, 2025

The change in SynthesizedParameterSymbolBase affects return-targeted attributes.

The change in SynthesizedMethodBaseSymbol is for local function parameter attributes. It only supported propagating attributes from a SourceComplexParameterSymbolBase, but for a local function inside an extension we're dealing with a RewrittenMethodParameterSymbol which wraps one.
This required generalizing SynthesizedComplexParameterSymbol to accept a ParameterSymbol instead of just a SourceComplexParameterSymbolBase which caused the rest of the changes (moving DefaultValueFromAttributes up the symbol hierarchy, tweaks to SynthesizedComplexParameterSymbol.IsMetadataIn/Out).

Test PropagateAttributes_20 illustrates both of the changes. Before, we were not properly emitting attributes A and C on the closure method.

The change in CodeGenLocalFunctionTests.BaseParameterWithDifferentRefKind results from tightening expectations in SynthesizedComplexParameterSymbol (added assertion in constructor).

Fixes #80017 (return-targeted attributes not properly emitted)
Relates to test plan #76130

Possible interaction with #79880

Relates to #73920

@jcouv jcouv added Area-Compilers Feature - Extension Everything The extension everything feature labels Aug 28, 2025
@jcouv jcouv self-assigned this Aug 28, 2025
@jcouv jcouv force-pushed the extensions-return branch from b3ee966 to dde1b78 Compare August 28, 2025 19:26
@jcouv jcouv marked this pull request as ready for review August 29, 2025 07:52
@jcouv jcouv requested a review from a team as a code owner August 29, 2025 07:52
@jcouv jcouv requested a review from jjonescz August 29, 2025 07:52
/// for symbols from source or derived from source symbols.
/// Returns <see cref="ConstantValue.NotAvailable"/> when not applicable.
/// </summary>
internal abstract ConstantValue DefaultValueFromAttributes { get; }
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

I think this should return ConstantValue? (i.e., nullable) since ConstantValue.NotAvailable is null. Btw, I'm not sure why ConstantValue.NotAvailable is not marked as nullable (and it's surprising that there is no nullable warning at the declaration site, but that seems to be a known issue - #50580). #Resolved

return _originalMethod.GetAttributes();
}

public override ImmutableArray<CSharpAttributeData> GetReturnTypeAttributes()
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

Suggested change
public override ImmutableArray<CSharpAttributeData> GetReturnTypeAttributes()
public sealed override ImmutableArray<CSharpAttributeData> GetReturnTypeAttributes()
``` #Resolved

get { return null; }
}

internal override ConstantValue DefaultValueFromAttributes
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

Suggested change
internal override ConstantValue DefaultValueFromAttributes
internal sealed override ConstantValue DefaultValueFromAttributes
``` #Resolved

}
}

internal override ConstantValue DefaultValueFromAttributes => ConstantValue.NotAvailable;
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

Suggested change
internal override ConstantValue DefaultValueFromAttributes => ConstantValue.NotAvailable;
internal sealed override ConstantValue DefaultValueFromAttributes => ConstantValue.NotAvailable;
``` #Resolved

get { return _underlyingParameter.ExplicitDefaultConstantValue; }
}

internal override ConstantValue DefaultValueFromAttributes
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

Suggested change
internal override ConstantValue DefaultValueFromAttributes
internal sealed override ConstantValue DefaultValueFromAttributes
``` #Resolved

var synthesizedParam = SynthesizedParameterSymbol.Create(localFunction, param.TypeWithAnnotations, ordinal: 0, RefKind.Out, param.Name, baseParameterForAttributes: (SourceComplexParameterSymbolBase)param);
Assert.False(synthesizedParam.IsMetadataIn);
Assert.True(synthesizedParam.IsMetadataOut);
}
Copy link
Member

@jjonescz jjonescz Aug 29, 2025

Choose a reason for hiding this comment

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

Seems like this deleted block of code was important to the test - at least from the name BaseParameterWithDifferentRefKind and the linked issue. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed the test as we never need to synthesize a parameter where the refkind and the base parameter's refkind disagree.
The linked issue describes the scenario covered by InOutAttributes.
Tagging @RikkiGibson to confirm

@jcouv jcouv requested a review from RikkiGibson August 29, 2025 15:22
@jcouv
Copy link
Member Author

jcouv commented Aug 29, 2025

@RikkiGibson You'd be a good reviewer for this one, as you worked in this area before (propagating attributes on local functions, in #39830). Please take a look

Julien Couvreur added 2 commits August 29, 2025 08:39

42.M();
42.M2();
E.M(42);
Copy link
Member

@333fred 333fred Aug 29, 2025

Choose a reason for hiding this comment

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

Nit: I know you didn't make this test source in this test, but consider refactoring to just set a preprocessor symbol through options and avoid repeating the same source twice, that we then have to keep in sync. #Resolved

}

[Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/80017")]
public void PropagateAttributes_21(bool withPreserve)
Copy link
Member

@333fred 333fred Aug 29, 2025

Choose a reason for hiding this comment

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

Why is this test in this file? It's unrelated to extensions? #Resolved

Copy link
Member Author

@jcouv jcouv Aug 29, 2025

Choose a reason for hiding this comment

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

It's meant to establish baseline for the test above. I'll remove move it

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

Done review pass. I'd like that local function test moved to CodeGenLocalFunctionsTests please.

@jcouv jcouv requested a review from 333fred August 29, 2025 18:48
@jcouv jcouv merged commit 7a96051 into dotnet:main Aug 29, 2025
24 checks passed
@jcouv jcouv deleted the extensions-return branch August 29, 2025 20:32
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Aug 29, 2025
@akhera99 akhera99 modified the milestones: Next, 18.0 P1, 18.0 P2 Sep 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Feature - Extension Everything The extension everything feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"return" attributes on extension property accessors not emitted on implementation

4 participants