You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When looking for compatible implicit extensions and we’re dealing with generic extensions, we need to find a type substitution before we can use the extension.
The current spec says that if a type substitution exists it is unique. But that’s incorrect.
The substitution is unique modulo small differences, such as dynamic vs. object, tuple name differences, etc.
Example
string s = C<object, dynamic>.f; // could use either `E<object>.f` or `E<dynamic>.f` or an error
class C<T ,U> { }
implicit extension E<T> for C<T ,T>
{
public static string f = "hi";
}
Proposal
Although I couldn’t find how it is spec’ed, we have an existing mechanism to resolve such differences (MergeEquivalentTypes, used in best type and in method type inference amongst other places).
We can just use that mechanism to uniquely resolve to E<dynamic>.f in that example (dynamic is preferred over object).
Variance will also come into play in some way (details TBD):
Given implicit extension E<T> for IIn<T ,T>, IIn<object, object?> would be found compatible with E<object>.
Whereas given implicit extension E<T> for IOut<T ,T>, IOut<object, object?> would be found compatible with E<object?>.
Alternatively, we could choose to make some such differences to be errors. But since nullability differences should not yield errors, we'll have to at least deal with merging those differences.
Description of the problem
When looking for compatible implicit extensions and we’re dealing with generic extensions, we need to find a type substitution before we can use the extension.
The current spec says that if a type substitution exists it is unique. But that’s incorrect.
The substitution is unique modulo small differences, such as
dynamic
vs.object
, tuple name differences, etc.Example
Proposal
Although I couldn’t find how it is spec’ed, we have an existing mechanism to resolve such differences (
MergeEquivalentTypes
, used in best type and in method type inference amongst other places).We can just use that mechanism to uniquely resolve to
E<dynamic>.f
in that example (dynamic
is preferred overobject
).Variance will also come into play in some way (details TBD):
Given
implicit extension E<T> for IIn<T ,T>
,IIn<object, object?>
would be found compatible withE<object>
.Whereas given
implicit extension E<T> for IOut<T ,T>
,IOut<object, object?>
would be found compatible withE<object?>
.Alternatively, we could choose to make some such differences to be errors. But since nullability differences should not yield errors, we'll have to at least deal with merging those differences.
Relates to championed issue #5497 (extensions)
Relates to test plan dotnet/roslyn#66722
The text was updated successfully, but these errors were encountered: