Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specially handle more scenarios for type parameters with 'allows ref struct' constraint #73111

Merged

Conversation

AlekseyTs
Copy link
Contributor

No description provided.

@AlekseyTs AlekseyTs requested review from jjonescz and cston April 19, 2024 22:12
@AlekseyTs AlekseyTs requested a review from a team as a code owner April 19, 2024 22:12
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Apr 19, 2024
@AlekseyTs
Copy link
Contributor Author

@cston, @jjonescz, @dotnet/roslyn-compiler Please review

@@ -2829,7 +2829,8 @@ public bool HasImplicitTypeParameterConversion(TypeParameterSymbol source, TypeS
return true;
}

if ((destination.TypeKind == TypeKind.TypeParameter) &&
if (destination is TypeParameterSymbol { AllowByRefLike: false } &&
!source.AllowByRefLike &&
Copy link
Member

@cston cston Apr 22, 2024

Choose a reason for hiding this comment

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

!source.AllowByRefLike &&

Are we testing this case? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are we testing this case?

I tried, but given the convoluted nature of the conversion classification algorithms, I was not able to find a scenario where we get here with source.AllowByRefLike equals true. Nevertheless, I am fairly comfortable making this change regardless of the fact.

@@ -2868,7 +2872,7 @@ private bool HasImplicitReferenceTypeParameterConversion(TypeParameterSymbol sou
}

// * From T to a type parameter U, provided T depends on U.
if ((destination.TypeKind == TypeKind.TypeParameter) &&
if (destination is TypeParameterSymbol { AllowByRefLike: false } &&
Copy link
Member

@cston cston Apr 22, 2024

Choose a reason for hiding this comment

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

if (destination is TypeParameterSymbol { AllowByRefLike: false } &&

Why is AllowByRefLike: false required? Isn't it sufficient to check source.AllowByRefLike (above) and source.DependsOn((TypeParameterSymbol)destination)? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is AllowByRefLike: false required? Isn't it sufficient to check source.AllowByRefLike (above) and source.DependsOn((TypeParameterSymbol)destination)?

Why do you think it should be sufficient? Dependency between type parameters says nothing about their AllowByRefLike property (dependent type parameters can have different values for it) and reference conversions do not exist for those that have AllowByRefLike: true.

@@ -3221,8 +3225,8 @@ private bool HasImplicitBoxingTypeParameterConversion(TypeParameterSymbol source
}

// SPEC: From T to a type parameter U, provided T depends on U
if ((destination.TypeKind == TypeKind.TypeParameter) &&
source.DependsOn((TypeParameterSymbol)destination))
if (destination is TypeParameterSymbol { AllowByRefLike: false } d &&
Copy link
Member

@cston cston Apr 22, 2024

Choose a reason for hiding this comment

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

AllowByRefLike: false

Why is AllowByRefLike: false required? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is AllowByRefLike: false required?

Same response as for the change on line 2875

// IL_0000: ldarg.0
// IL_0001: box ""U""
// IL_0006: unbox.any ""T""
// IL_000b: ret
}
}
Copy link
Member

@cston cston Apr 22, 2024

Choose a reason for hiding this comment

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

Consider testing:

    static U Test9<T, U>(T x)
        where T : class
        where U : T, allows ref struct
    {
        return x;
    }
    static U Test10<T, U>(T x)
        where T : class
        where U : T, allows ref struct
    {
        return (U)x;
    }
``` #Closed

}

[Fact]
public void IllegalBoxing_05()
Copy link
Member

@cston cston Apr 23, 2024

Choose a reason for hiding this comment

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

IllegalBoxing_05

Is this distinct from IllegalBoxing_02? #Resolved

Copy link
Contributor Author

@AlekseyTs AlekseyTs Apr 24, 2024

Choose a reason for hiding this comment

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

Is this distinct from IllegalBoxing_02?

It is true that some scenarios are duplicated (not all scenarios), but I do not mind and do not plan to make any changes because of that.

// => y.M;
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "M").WithArguments("M", "System.Action").WithLocation(12, 14)
);
}
Copy link
Member

@cston cston Apr 23, 2024

Choose a reason for hiding this comment

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

}

Are we testing the receiver for anonymous delegate types?

static void Test3(T x)
{
    var f = x.M;
}
``` #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are we testing the receiver for anonymous delegate types?

Adding a couple of tests for completeness.

// h2.M2(y);
Diagnostic(ErrorCode.ERR_BadDynamicMethodArg, "y").WithArguments("S").WithLocation(15, 15)
);
}
Copy link
Member

@cston cston Apr 23, 2024

Choose a reason for hiding this comment

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

}

Are we testing a ref struct receiver and dynamic argument?

class Helper1<T>
    where T : I1, allows ref struct
{
    static void Test1(T x, dynamic d)
    {
        x.M(d);
    }
}
interface I1
{
    void M<T>(T t);
}
``` #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are we testing a ref struct receiver and dynamic argument?

Adding DynamicAccess_03 for completeness.

@AlekseyTs AlekseyTs requested a review from cston April 24, 2024 19:50
@AlekseyTs
Copy link
Contributor Author

@jjonescz, @dotnet/roslyn-compiler For the second review

{
static void Test1()
{
_ = new T[] {};
Copy link
Member

Choose a reason for hiding this comment

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

Consider testing T[][]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Feature - RefStructInterfaces untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants