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

The first array type in a generic method doesn't work #18686

Closed
5 tasks done
InSb opened this issue Nov 30, 2022 · 8 comments · Fixed by #19205
Closed
5 tasks done

The first array type in a generic method doesn't work #18686

InSb opened this issue Nov 30, 2022 · 8 comments · Fixed by #19205
Labels
Resolution-Fixed The issue is fixed.

Comments

@InSb
Copy link

InSb commented Nov 30, 2022

Prerequisites

Steps to reproduce

When I try to flatten a two-dimensional array by Enumerable.SelectMany method with generic type arguments, the first type argument int[] may not be treated correctly.

[Linq.Enumerable]::SelectMany[int[], int](
  [int[][]] @((,2), (,4), (,6), (,8)),
  [Func[[int[]], int[]]] { param ($x); $x }
) | ConvertTo-Json -Compress

Expected behavior

[2,4,6,8]

Actual behavior

Unable to find type [int,int].

Error details

Exception             :
    Type        : System.Management.Automation.RuntimeException
    ErrorRecord :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Unable to find type [int,int].
            HResult : -2146233087
        TargetObject          : int,int
        CategoryInfo          : InvalidOperation: (int,int:TypeName) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : TypeNotFound
        InvocationInfo        :
            ScriptLineNumber : 2
            OffsetInLine     : 31
            HistoryId        : -1
            Line             : [Linq.Enumerable]::SelectMany[int[], int](

            PositionMessage  : At line:2 char:31
                               + [Linq.Enumerable]::SelectMany[int[], int](
                               +                               ~~~~~
            CommandOrigin    : Internal
        ScriptStackTrace      : at <ScriptBlock>, <No file>: line 2
    TargetSite  :
        Name          : ResolveTypeName
        DeclaringType : System.Management.Automation.TypeOps, System.Management.Automation, Version=7.3.0.500, Culture=
neutral, PublicKeyToken=31bf3856ad364e35
        MemberType    : Method
        Module        : System.Management.Automation.dll
    Message     : Unable to find type [int,int].
    Data        : System.Collections.ListDictionaryInternal
    Source      : System.Management.Automation
    HResult     : -2146233087
    StackTrace  :
   at System.Management.Automation.TypeOps.ResolveTypeName(ITypeName typeName, IScriptExtent errorPos)
   at System.Management.Automation.TypeOps.ResolveTypeName(ITypeName typeName, IScriptExtent errorPos)
   at System.Management.Automation.Adapter.ResolveGenericTypeParameters(Object[] genericTypeParameters)
   at System.Management.Automation.Adapter.FindBestMethodImpl(MethodInformation[] methods, PSMethodInvocationConstraint
s invocationConstraints, Boolean allowCastingToByRefLikeType, Object[] arguments, String& errorId, String& errorMsg, Bo
olean& expandParamsOnBest)
   at System.Management.Automation.Adapter.FindBestMethod(MethodInformation[] methods, PSMethodInvocationConstraints in
vocationConstraints, Boolean allowCastingToByRefLikeType, Object[] arguments, String& errorId, String& errorMsg, Boolea
n& expandParamsOnBest, Boolean& callNonVirtually)
   at System.Management.Automation.Language.PSInvokeMemberBinder.InvokeDotNetMethod(CallInfo callInfo, String name, PSM
ethodInvocationConstraints psMethodInvocationConstraints, MethodInvocationType methodInvocationType, DynamicMetaObject
target, DynamicMetaObject[] args, BindingRestrictions restrictions, MethodInformation[] mi, Type errorExceptionType)
   at System.Management.Automation.Language.PSInvokeMemberBinder.FallbackInvokeMember(DynamicMetaObject target, Dynamic
MetaObject[] args, DynamicMetaObject errorSuggestion)
   at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLab
el)
   at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   at System.Management.Automation.Interpreter.DynamicInstruction`4.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          : int,int
CategoryInfo          : InvalidOperation: (int,int:TypeName) [], RuntimeException
FullyQualifiedErrorId : TypeNotFound
InvocationInfo        :
    ScriptLineNumber : 2
    OffsetInLine     : 31
    HistoryId        : -1
    Line             : [Linq.Enumerable]::SelectMany[int[], int](

    PositionMessage  : At line:2 char:31
                       + [Linq.Enumerable]::SelectMany[int[], int](
                       +                               ~~~~~
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 2

Environment data

Name                           Value
----                           -----
PSVersion                      7.3.0
PSEdition                      Core
GitCommitId                    7.3.0
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

@InSb InSb added the Needs-Triage The issue is new and needs to be triaged by a work group. label Nov 30, 2022
@CarloToso
Copy link
Contributor

It should work like this:

[Linq.Enumerable]::SelectMany(
  [int[][]] @((,2), (,4), (,6), (,8)),
  [Func[[int[]], int[]]] { param ($x); $x }
) | ConvertTo-Json -Compress

Great reference for Linq in Powershell:
https://www.red-gate.com/simple-talk/sysadmin/powershell/high-performance-powershell-linq/

@mklement0
Copy link
Contributor

It looks like the list of the generic-method type arguments isn't recognized as such and instead (mis)interpreted as a type literal, and the problem seemingly only occurs when the first type in such a list is an array type ([]) (as you state).

A simpler repro (note that the call doesn't make sense, but the error message reveals wether type arguments where formally parsed as such):

# !! -> "InvalidOperation: Unable to find type [int,int]."
[char]::ToUpper[int[], int]()
# !!  Using the list as a (broken) type literal yields the same error.
[int[], int]

# (Formally) OK; -> "Could not find a suitable generic method overload for ..."
[char]::ToUpper[int, int[]]()

@SeeminglyScience
Copy link
Collaborator

I believe this is an existing problem with generic types that has just been made more common. I don't think I ever filed an issue, but I've hit this quite a few times with delegate types:

# Also throws
[Func[int[], int]]

Fortunately the work around is really easy for generic types, just surround the inner type in more square brackets:

[Func[[int[]], int]]

Unfortunately, this doesn't work with generic method args:

# Throws differently because we don't seem to be checking for brackets around generic args
[Linq.Enumerable]::SelectMany[[int[]], int](
  [int[][]] @((,2), (,4), (,6), (,8)),
  [Func[[int[]], int[]]] { param ($x); $x }
) | ConvertTo-Json -Compress

@SeeminglyScience
Copy link
Collaborator

/cc @daxian-dbw @vexx32 FYI

@vexx32
Copy link
Collaborator

vexx32 commented Nov 30, 2022

The latter you mention (double-bracketing) I think was at least semi-intentional, since $a.[[int[]]] is potentially valid array-access syntax (passing a type token as an array lookup). In fact I think @daxian-dbw did a patch after the initial PR to ensure weird stuff like that worked.

The initial issue here seems to be... hm. Not a parsing error directly perhaps, but definitely something strange.

This code path parser-wise at least is very messy due to the overloaded meaning for [] being used for both type tokens and for array indexing. Not simple to tease out :/

@MartinGC94
Copy link
Contributor

I believe this is an existing problem with generic types that has just been made more common. I don't think I ever filed an issue, but I've hit this quite a few times with delegate types:

Rob has reported it here: #9639

@SeeminglyScience
Copy link
Collaborator

I even already gave it a thumb! Good catch, thanks @MartinGC94!

@ghost ghost added the In-PR Indicates that a PR is out for the issue label Feb 23, 2023
@ghost ghost added Resolution-Fixed The issue is fixed. and removed In-PR Indicates that a PR is out for the issue labels May 8, 2023
@ghost ghost removed the Needs-Triage The issue is new and needs to be triaged by a work group. label May 8, 2023
@ghost
Copy link

ghost commented Jun 29, 2023

🎉This issue was addressed in #19205, which has now been successfully released as v7.4.0-preview.4.:tada:

Handy links:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution-Fixed The issue is fixed.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants