-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid use of incorrect instantation argumens when checking for constr…
…aint satisfaction (#47258) - The constraint processing logic in the runtime conflates the idea of constraint checking on open, closed over concrete types, and closed over non-concrete types - This change adds a tweak to avoid using an instantiation context that isn't related to the type variable being instantiated Fixes issue #45600 and adds a regression test from the customer.
- Loading branch information
1 parent
cea6fbd
commit 76954b4
Showing
3 changed files
with
125 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/tests/Loader/classloader/regressions/GitHub_45600/GitHub_45600.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<OutputType>Exe</OutputType> | ||
<CLRTestKind>BuildAndRun</CLRTestKind> | ||
<CLRTestPriority>0</CLRTestPriority> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="repro.cs" /> | ||
</ItemGroup> | ||
</Project> |
102 changes: 102 additions & 0 deletions
102
src/tests/Loader/classloader/regressions/GitHub_45600/repro.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
|
||
public abstract class A { } | ||
|
||
public class B : A { } | ||
|
||
public abstract class C { } | ||
|
||
public abstract class C<CTParam> : C where CTParam : A { } | ||
|
||
public class D : C<B> { } | ||
|
||
public abstract class E | ||
{ | ||
internal E() { } | ||
|
||
internal abstract Type NamedObjectType { get; } | ||
} | ||
|
||
public class E<ETParam> : E | ||
where ETParam : A | ||
{ | ||
private readonly F<C<ETParam>> components = | ||
new F<C<ETParam>>(); | ||
|
||
internal override Type NamedObjectType => typeof(ETParam); | ||
|
||
public void Register<ERegMethodParam>() | ||
where ERegMethodParam : C<ETParam>, new() | ||
{ | ||
components.Register<ERegMethodParam>(); | ||
} | ||
} | ||
|
||
public class F<FTParam> where FTParam : class | ||
{ | ||
private readonly HashSet<Type> componentTypes = new HashSet<Type>(); | ||
|
||
private readonly Dictionary<Type, Func<FTParam>> componentFactories = | ||
new Dictionary<Type, Func<FTParam>>(); | ||
|
||
public void Register<FRegMethodParamHaha>() // F<C<B>>.Register<D> | ||
where FRegMethodParamHaha : class, FTParam, new() | ||
{ | ||
} | ||
} | ||
|
||
public class G | ||
{ | ||
private readonly Dictionary<Type, E> subcontainersByNamedObjectType = | ||
new Dictionary<Type, E>(); | ||
|
||
private readonly Dictionary<Type, E> subcontainersByRegisteredType = | ||
new Dictionary<Type, E>(); | ||
|
||
public E<ETParam> RegisterNamedObjectType<ETParam>() | ||
where ETParam : A | ||
{ | ||
return RegisterSubcontainer(new E<ETParam>()); | ||
} | ||
|
||
public GRegMethodParam RegisterSubcontainer<GRegMethodParam>(GRegMethodParam subcontainer) | ||
where GRegMethodParam : E | ||
{ | ||
subcontainersByNamedObjectType.Add(subcontainer.NamedObjectType, subcontainer); | ||
subcontainersByRegisteredType.Add(typeof(GRegMethodParam), subcontainer); | ||
return subcontainer; | ||
} | ||
|
||
internal void Register<GRegMethodParam1, GRegMethodParam2>() | ||
where GRegMethodParam1 : A | ||
where GRegMethodParam2 : C<GRegMethodParam1>, new() | ||
{ | ||
GetSubcontainerFor<GRegMethodParam1>().Register<GRegMethodParam2>(); // E<B>.Reg<D> | ||
} | ||
|
||
public E<GGetSebMethodParam> GetSubcontainerFor<GGetSebMethodParam>() | ||
where GGetSebMethodParam : A | ||
{ | ||
return (E<GGetSebMethodParam>)GetSubcontainerFor(typeof(GGetSebMethodParam)); | ||
} | ||
|
||
public E GetSubcontainerFor(Type baseNamedObjectType) | ||
{ | ||
return subcontainersByNamedObjectType[baseNamedObjectType]; | ||
} | ||
} | ||
|
||
class Program | ||
{ | ||
static int Main(string[] args) | ||
{ | ||
var contaner = new G(); | ||
contaner.RegisterNamedObjectType<B>(); | ||
contaner.Register<B, D>(); | ||
return 100; | ||
} | ||
} |