Extensions: Address follow-ups related to collection expressions#79877
Extensions: Address follow-ups related to collection expressions#79877jcouv merged 4 commits intodotnet:mainfrom
Conversation
| { | ||
| if (member.TryGetCorrespondingExtensionImplementationMethod() is { } extensionImplementation) | ||
| { | ||
| member = extensionImplementation; |
There was a problem hiding this comment.
📝 since we swap the implementation method for the member here and reduce it below, I had to relax the assertion in TypeMap again (see PR)
An alternative would be to implement the logic for this method specially for new extension methods, instead of using the implementation method to leverage the existing handling
01c628c to
083fbaa
Compare
083fbaa to
03e8cbd
Compare
| { | ||
| // If the method is generic, skip it if the type arguments cannot be inferred. | ||
| var member = candidate.Member; | ||
| if (member.GetIsNewExtensionMember()) |
| builder: out var builder); | ||
| // Collection expression target types require instance method GetEnumerator. | ||
| if (result && builder.ViaExtensionMethod) // Tracked by https://github.com/dotnet/roslyn/issues/78960: Add test coverage for new extensions | ||
| if (result && builder.ViaExtensionMethod) |
There was a problem hiding this comment.
Yes, see getEnumeratorInfo
if (SatisfiesGetEnumeratorPattern(syntax, collectionSyntax, ref builder, collectionExpr, isAsync, viaExtensionMethod: true, diagnostics))
{
return createPatternBasedEnumeratorResult(ref builder, collectionExpr, isAsync, viaExtensionMethod: true, diagnostics);
}
The relevant test is CollectionExpression_09
| { | ||
| return ConsiderEverything; | ||
| } | ||
| else if (comparison == TypeCompareKind.AllIgnoreOptions) |
There was a problem hiding this comment.
I prefer to remove since not exercised
| { | ||
| // mapping contents are read-only hereafter | ||
| Debug.Assert(allowAlpha || !from.Any(static tp => tp is SubstitutedTypeParameterSymbol)); | ||
| Debug.Assert(allowAlpha || !from.Any(static tp => tp is SubstitutedTypeParameterSymbol && tp.ContainingSymbol is not SourceExtensionImplementationMethodSymbol)); |
There was a problem hiding this comment.
| (type, parameter, unused) => type.TypeKind == TypeKind.TypeParameter && (parameter is null || TypeSymbol.Equals(type, parameter, TypeCompareKind.ConsiderEverything2)); | ||
|
|
||
| public static bool ContainsTypeParameter(this TypeSymbol type, MethodSymbol parameterContainer) | ||
| public static bool ContainsTypeParameter(this TypeSymbol type, Symbol parameterContainer) |
| // (7,26): error CS1929: 'MyCollection<object>' does not contain a definition for 'Add' and the best extension method overload 'E.extension<T>(MyCollection<T>).Add(T)' requires a receiver of type 'MyCollection<T>' | ||
| // MyCollection<object> c = [oNull, oNotNull]; | ||
| Diagnostic(ErrorCode.ERR_BadInstanceArgType, "[oNull, oNotNull]").WithArguments("MyCollection<object>", "Add", "E.extension<T>(MyCollection<T>).Add(T)", "MyCollection<T>").WithLocation(7, 26)); | ||
| comp.VerifyEmitDiagnostics(); |
| } | ||
| } | ||
|
|
||
| public class D : System.Collections.IEnumerable |
| { | ||
| extension(C c) | ||
| { | ||
| public int Length => 2; |
|
Done with review pass (commit 2) |
| } | ||
| """; | ||
| var comp = CreateCompilationWithIL(src, ilSrc); | ||
| comp.VerifyEmitDiagnostics(); |
There was a problem hiding this comment.
Should we verify execution to check that E2 was used, not E? #Resolved
| """; | ||
| var comp = CreateCompilation(src); | ||
| comp.VerifyEmitDiagnostics( | ||
| // (1,7): error CS1921: The best overloaded method match for 'E.extension(C).Add(int)' has wrong signature for the initializer element. The initializable Add must be an accessible instance method. |
There was a problem hiding this comment.
This error wording seems inaccurate - the Add can be an instance or extension method. But I guess that's a pre-existing issue. #WontFix
There was a problem hiding this comment.
Yup. I'll leave as pre-existing issue
Closes #78960
The first commit addresses minor post-PR-merge follow-ups from last PR: #79702 (comment)
The design needs to be confirmed with LDM, it is outlined here and copied below:
Note: the last LDM decision regarding pattern-based constructs was to not let extension properties count as "countable properties" in any of the relevant scenarios (list-patterns and implicit indexers) so I kept that behavior here as well.
Relates to test plan #76130