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

Generic Blazor component can't correctly infer it's type when type has an additional constraint #25588

Closed
MariovanZeist opened this issue Sep 3, 2020 · 13 comments
Assignees
Labels
affected-most This issue impacts most of the customers area-razor.compiler This issue is related to the Razor compiler (now external) bug This issue describes a behavior which is not expected - a bug. feature-razor.language Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Milestone

Comments

@MariovanZeist
Copy link
Contributor

MariovanZeist commented Sep 3, 2020

Describe the bug

When a generic Blazor component has a Generic Parameter with an additional constraint, it can't infer it's type correctly.

Example:

Define a basic class and interface

    public class MyClass : IMyInterface
    {
    }

    public interface IMyInterface
    {
    }

Say we have 2 components. (I will only show the code behind.)

    partial class InferComponent<T>
    {
        [Parameter] public IEnumerable<T> Items { get; set; }
    }

And

    partial class NotInferComponent<T>
      where T : IMyInterface
    {
        [Parameter] public IEnumerable<T> Items { get; set; }
    }

And then use these 2 classes

<InferComponent Items="new MyClass[] { new MyClass() }"></InferComponent>

<NotInferComponent Items="new MyClass[] { new MyClass() }"></NotInferComponent>

InferComponent will correctly infer that it's T is MyClass

But NotInferComponent will report an error:

(The type 'T' cannot be used as type parameter 'T' in the generic type or method 'NotInferComponent'. There is no boxing conversion or type parameter conversion from 'T' to 'BlazorApp1.IMyInterface'. BlazorApp1)

The problem lies in the autogenerated razor.g.cs classes, and especially where it tries to get its type by type inference.

Below is part of the generated code. I added a remark with what is missing.
I think the solution would be that whenever the Blazor component that it wants to construct has additional constraints, these constraints should be added to the CreateComponentName function as well.

namespace __Blazor.BlazorApp1.Pages.Index
{
    #line hidden
    internal static class TypeInference
    {
        public static void CreateInferComponent_0<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
        {
        __builder.OpenComponent<global::BlazorApp1.Components.InferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
        public static void CreateNotInferComponent_1<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder 
__builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
          //Where T : IMyInterface    <--- This is missing
        {
        __builder.OpenComponent<global::BlazorApp1.Components.NotInferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
    }
}

I don't think it's a duplicate of #8433, as the constraint on components itself works, it's the type inference that fails

Workaround

there is a workaround for this issue

add
T="MyClass"

as in

<NotInferComponent Items="new MyClass[] { new MyClass() }" T="MyClass"></NotInferComponent>

Will make it compile.

So we have a temporary solution for this issue, although I think it's confusing for the end-user to have to add T="MyClass" only when T has an additional constraint.

To Reproduce

Repro: https://github.com/MariovanZeist/BlazorTypeinference
(based on Simple Blazor server app template)

Further technical details

Aspnetcore 5 preview 8
.NET SDK (reflecting any global.json):
Version: 5.0.100-preview.8.20417.9
Commit: fc62663a35

Runtime Environment:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\5.0.100-preview.8.20417.9\

Host (useful for support):
Version: 5.0.0-preview.8.20407.11
Commit: bf456654f9

.NET SDKs installed:
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.201 [C:\Program Files\dotnet\sdk]
3.1.400-preview-015203 [C:\Program Files\dotnet\sdk]
3.1.401 [C:\Program Files\dotnet\sdk]
5.0.100-preview.8.20417.9 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-preview.8.20414.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0-preview.8.20407.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0-preview.8.20411.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

VS 2019 16.8 Preview 2.1

@javiercn javiercn added area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Sep 4, 2020
@javiercn javiercn added this to the Backlog milestone Sep 7, 2020
@ghost
Copy link

ghost commented Sep 7, 2020

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@SteveSandersonMS SteveSandersonMS added affected-most This issue impacts most of the customers severity-minor This label is used by an internal tool labels Oct 7, 2020 — with ASP.NET Core Issue Ranking
@Rauce
Copy link

Rauce commented Jan 5, 2021

Just came across this myself. Would be a great improvement if it could be fixed.

@javiercn javiercn added feature-razor.language area-razor.compiler This issue is related to the Razor compiler (now external) labels Apr 20, 2021
@chrisoverton91
Copy link

+1 for this! Thank you @MariovanZeist for the workaround!

@TanayParikh TanayParikh modified the milestones: Backlog, .NET 7 Planning Oct 19, 2021
@pranavkm pranavkm added Priority:1 Work that is critical for the release, but we could probably ship without k:1 and removed Priority:1 Work that is critical for the release, but we could probably ship without labels Nov 8, 2021
@mkArtakMSFT mkArtakMSFT added Priority:1 Work that is critical for the release, but we could probably ship without bug This issue describes a behavior which is not expected - a bug. triaged and removed enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Nov 11, 2021
@mkArtakMSFT mkArtakMSFT removed the area-blazor Includes: Blazor, Razor Components label Nov 30, 2021
@javiercn
Copy link
Member

javiercn commented Jan 24, 2022

I think this is fixed in 6.0.

@MariovanZeist can you check and if not, provide a minimal repro project? I did create the same components you did and things seem to be in order

Here is my Index.razor

<InferComponent Items="new MyClass[]{ new MyClass() }">
    <NotInferComponent Items="new MyClass[] {}"></NotInferComponent>
</InferComponent>

<NotInferComponent Items="new MyClass[] {}">
<InferComponent Items="new MyClass[]{ new MyClass() }">
</InferComponent>
</NotInferComponent>

<NotInferComponent Items="new MyClass[] {}">
</NotInferComponent>
<InferComponent Items="new MyClass[]{ new MyClass() }">
</InferComponent>
@typeparam T
<h3>InferComponent</h3>

@code {
    [Parameter] public IEnumerable<T> Items { get; set; }
}
@typeparam T where T : IMyInterface
<h3>NotInferComponent</h3>

@code {
    [Parameter] public IEnumerable<T> Items { get; set; }
}
#pragma checksum "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "b4e4c7aae7395f7fe3f026556c35f26bd5351a366110865aa6c567572c48eb29"
// <auto-generated/>
#pragma warning disable 1591
namespace BlazorApp66.Pages
{
    #line hidden
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components;
#nullable restore
#line 1 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using System.Net.Http;

#line default
#line hidden
#nullable disable
#nullable restore
#line 2 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Authorization;

#line default
#line hidden
#nullable disable
#nullable restore
#line 3 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Components.Authorization;

#line default
#line hidden
#nullable disable
#nullable restore
#line 4 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Components.Forms;

#line default
#line hidden
#nullable disable
#nullable restore
#line 5 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Components.Routing;

#line default
#line hidden
#nullable disable
#nullable restore
#line 6 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Components.Web;

#line default
#line hidden
#nullable disable
#nullable restore
#line 7 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.AspNetCore.Components.Web.Virtualization;

#line default
#line hidden
#nullable disable
#nullable restore
#line 8 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using Microsoft.JSInterop;

#line default
#line hidden
#nullable disable
#nullable restore
#line 9 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using BlazorApp66;

#line default
#line hidden
#nullable disable
#nullable restore
#line 10 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\_Imports.razor"
using BlazorApp66.Shared;

#line default
#line hidden
#nullable disable
    [Microsoft.AspNetCore.Components.RouteAttribute("/")]
    public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.OpenComponent<Microsoft.AspNetCore.Components.Web.PageTitle>(0);
            __builder.AddAttribute(1, "ChildContent", (Microsoft.AspNetCore.Components.RenderFragment)((__builder2) => {
                __builder2.AddContent(2, "Index");
            }
            ));
            __builder.CloseComponent();
            __builder.AddMarkupContent(3, "\r\n\r\n");
            __builder.AddMarkupContent(4, "<h1>Hello, world!</h1>\r\n\r\nWelcome to your new app.\r\n\r\n");
            __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateInferComponent_0(__builder, 5, 6, 
#nullable restore
#line 9 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                       new MyClass[]{ new MyClass() }

#line default
#line hidden
#nullable disable
            , 7, (__builder2) => {
                __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateNotInferComponent_1(__builder2, 8, 9, 
#nullable restore
#line 10 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                              new MyClass[] {}

#line default
#line hidden
#nullable disable
                );
            }
            );
            __builder.AddMarkupContent(10, "\r\n\r\n");
            __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateNotInferComponent_2(__builder, 11, 12, 
#nullable restore
#line 13 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                          new MyClass[] {}

#line default
#line hidden
#nullable disable
            , 13, (__builder2) => {
                __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateInferComponent_3(__builder2, 14, 15, 
#nullable restore
#line 14 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                       new MyClass[]{ new MyClass() }

#line default
#line hidden
#nullable disable
                );
            }
            );
            __builder.AddMarkupContent(16, "\r\n\r\n");
            __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateNotInferComponent_4(__builder, 17, 18, 
#nullable restore
#line 18 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                          new MyClass[] {}

#line default
#line hidden
#nullable disable
            );
            __builder.AddMarkupContent(19, "\r\n");
            __Blazor.BlazorApp66.Pages.Index.TypeInference.CreateInferComponent_5(__builder, 20, 21, 
#nullable restore
#line 20 "C:\Users\jacalvar\source\repos\BlazorApp66\BlazorApp66\Pages\Index.razor"
                       new MyClass[]{ new MyClass() }

#line default
#line hidden
#nullable disable
            );
            __builder.AddMarkupContent(22, "\r\n\r\n");
            __builder.OpenComponent<BlazorApp66.Shared.SurveyPrompt>(23);
            __builder.AddAttribute(24, "Title", "How is Blazor working for you?");
            __builder.CloseComponent();
        }
        #pragma warning restore 1998
    }
}
namespace __Blazor.BlazorApp66.Pages.Index
{
    #line hidden
    internal static class TypeInference
    {
        public static void CreateInferComponent_0<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1)
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.InferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.AddAttribute(__seq1, "ChildContent", __arg1);
        __builder.CloseComponent();
        }
        public static void CreateNotInferComponent_1<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
            where T : IMyInterface
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.NotInferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
        public static void CreateNotInferComponent_2<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0, int __seq1, Microsoft.AspNetCore.Components.RenderFragment __arg1)
            where T : IMyInterface
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.NotInferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.AddAttribute(__seq1, "ChildContent", __arg1);
        __builder.CloseComponent();
        }
        public static void CreateInferComponent_3<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.InferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
        public static void CreateNotInferComponent_4<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
            where T : IMyInterface
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.NotInferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
        public static void CreateInferComponent_5<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
        {
        __builder.OpenComponent<global::BlazorApp66.Pages.InferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
    }
}
#pragma warning restore 1591

Let me know if you still find this issue (and please provide a repro for it)

@javiercn javiercn modified the milestones: 7.0-preview2, .NET 6.0 Jan 24, 2022
@MariovanZeist
Copy link
Contributor Author

@javiercn
Sorry for opening it again,
I am getting an error when I try it.
Repo: https://github.com/MariovanZeist/BlazorConstraint

It cannot find IMyInterface, I am wondering if it has to do with the generated namespace. __Blazor.BlazorConstraint.Pages.Index, (And the lack of referring to IMyInterface using the global definition global::BlazorConstraint.IMyInterface

Below you find the generated source: (I added some comments)

#pragma checksum "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\Pages\Index.razor" "{8829d00f-11b8-4213-878b-770e8597ac16}" "54544ab82b3c41f78c37f12044b089c044acda30a0e2b79840203630c301649e"
// <auto-generated/>
#pragma warning disable 1591
namespace BlazorConstraint.Pages
{
    #line hidden
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Components;
#nullable restore
#line 1 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using System.Net.Http;

#line default
#line hidden
#nullable disable
#nullable restore
#line 2 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using System.Net.Http.Json;

#line default
#line hidden
#nullable disable
#nullable restore
#line 3 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.AspNetCore.Components.Forms;

#line default
#line hidden
#nullable disable
#nullable restore
#line 4 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.AspNetCore.Components.Routing;

#line default
#line hidden
#nullable disable
#nullable restore
#line 5 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.AspNetCore.Components.Web;

#line default
#line hidden
#nullable disable
#nullable restore
#line 6 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.AspNetCore.Components.Web.Virtualization;

#line default
#line hidden
#nullable disable
#nullable restore
#line 7 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.AspNetCore.Components.WebAssembly.Http;

#line default
#line hidden
#nullable disable
#nullable restore
#line 8 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using Microsoft.JSInterop;

#line default
#line hidden
#nullable disable
#nullable restore
#line 9 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using BlazorConstraint;

#line default
#line hidden
#nullable disable
#nullable restore
#line 10 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using BlazorConstraint.Components;

#line default
#line hidden
#nullable disable
#nullable restore
#line 11 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\_Imports.razor"
using BlazorConstraint.Shared;

#line default
#line hidden
#nullable disable
    [Microsoft.AspNetCore.Components.RouteAttribute("/")]
    public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
    {
        #pragma warning disable 1998
        protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __Blazor.BlazorConstraint.Pages.Index.TypeInference.CreateInferComponent_0(__builder, 0, 1, 
#nullable restore
#line 3 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\Pages\Index.razor"
                      SimpleData.List

#line default
#line hidden
#nullable disable
            );
            __builder.AddMarkupContent(2, "\r\n");
            __Blazor.BlazorConstraint.Pages.Index.TypeInference.CreateNonInferComponent_1(__builder, 3, 4, 
#nullable restore
#line 4 "D:\My Projects\Reference Projects\BlazorConstraint\BlazorConstraint\Pages\Index.razor"
                         SimpleData.List

#line default
#line hidden
#nullable disable
            );
        }
        #pragma warning restore 1998
    }
}
//The below namespace is auto-generated, and no usings are included, so this might be the reason why it fails:

namespace __Blazor.BlazorConstraint.Pages.Index
{
    #line hidden
    internal static class TypeInference
    {
        public static void CreateInferComponent_0<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
        {
        __builder.OpenComponent<global::BlazorConstraint.Components.InferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
        public static void CreateNonInferComponent_1<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
            where T : IMyInterface  //<- how should the compiler locate the Interface
                                    //All other objects in this namespace are prefixed with their global namespace
        {
        __builder.OpenComponent<global::BlazorConstraint.Components.NonInferComponent<T>>(seq);
        __builder.AddAttribute(__seq0, "Items", __arg0);
        __builder.CloseComponent();
        }
    }
}
#pragma warning restore 1591

All the other referenced objects in the TypeInference class are prefixed and include their global namespace, so if IMyInterface would be changed to global::BlazorConstraint.IMyInterface it should work.

@javiercn javiercn reopened this Jan 24, 2022
@javiercn
Copy link
Member

@MariovanZeist No problem, I was not able to repro and that makes it hard/impossible for me to determine what's goin on.

I do see now this issue, and I think I'm reproing it (found the same issue by chance authoring another test).

I believe the issue here is that we don't add the usings inside the type inference namespace and because of that, it's not able to find the types.

@MariovanZeist
Copy link
Contributor Author

It's either adding usings to the namespace or refering to objects using their global namespace notation.
Although adding the global namespace notation seems more consistent with the rest of the generated file.

@MariovanZeist
Copy link
Contributor Author

@javiercn There is another (tightly) related issue
Checking the generated source file (although it doesn't compile I can still see the problem)
Is that the following constraint is supported:

@typeparam T where T : IMyInterface

But the following constraint is not: (a.k.a. Generic Constraints)

@typeparam T where T : IMyInterface<T>

The generated sourcecode in both examples are

 public static void CreateNonInferComponent_1<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
            where T : IMyInterface

Should I create a separate issue for this?

@javiercn
Copy link
Member

@MariovanZeist thanks for pointing that out.

I don't think we need an extra issue for that, I'll tackle it as part of the work we are currently doing

@Pilchie
Copy link
Member

Pilchie commented Jan 24, 2022

@javiercn - This probably needs a new milestone

@javiercn javiercn modified the milestones: .NET 6.0, 7.0-preview2 Jan 24, 2022
@javiercn
Copy link
Member

@Pilchie good point. I updated it

@javiercn
Copy link
Member

Fixed by dotnet/razor-compiler#44 (Including the generic type constraint in the type parameter described here)

@rtfleg
Copy link

rtfleg commented Feb 19, 2022

Is it possible if we'll see this fix in upcoming .NET 6 update?

@ghost ghost locked as resolved and limited conversation to collaborators Mar 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-most This issue impacts most of the customers area-razor.compiler This issue is related to the Razor compiler (now external) bug This issue describes a behavior which is not expected - a bug. feature-razor.language Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Projects
None yet
Development

No branches or pull requests

10 participants