mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 03:27:04 +09:00
Fix type parsing issues in ILLink and ILC (#104060)
- Fixes https://github.com/dotnet/runtime/issues/98955 We will now produce a warning when a non-assembly-qualified type flows into a string location annotated with DynamicallyAccessedMembers, and we don't try to look up or mark the type (since we don't know which assemblies will be searched at runtime by the Type.GetType call). - Fixes https://github.com/dotnet/runtime/issues/103906 The ILLink intrinsic handling for `Type.GetType` will now look in corelib for generic arguments, matching native AOT. This replaces the existing warning IL2105. This uses a new warning instead of repurposing IL2105, because we already documented IL2105 and older versions of ILLink will produce it. Best to avoid any confusion about them.
This commit is contained in:
parent
856a0a6f5e
commit
9407c9cfa8
30 changed files with 308 additions and 136 deletions
|
@ -1870,6 +1870,22 @@ void TestMethod()
|
|||
}
|
||||
```
|
||||
|
||||
#### `IL2122`: Type 'typeName' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
|
||||
|
||||
- The type name string passed to a location with `DynamicallyAccessedMembers` requirements was not assembly-qualified, so the trimmer cannot guarantee that the type is preserved. Consider using an assembly-qualified name instead.
|
||||
|
||||
```C#
|
||||
// warning IL2122: Type 'MyClass' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
|
||||
GetTypeWrapper("MyClass");
|
||||
|
||||
class MyClass { }
|
||||
|
||||
// May be defined in another assembly, so at runtime Type.GetType will look in that assembly for "MyClass".
|
||||
void GetTypeWrapper([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string typeName)
|
||||
{
|
||||
var type = Type.GetType(typeName);
|
||||
}
|
||||
```
|
||||
|
||||
## Single-File Warning Codes
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<!-- Suppress trimming warnings as these are tests -->
|
||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
|
||||
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
|
||||
|
||||
<!-- Reduce library test app size by trimming framework library features -->
|
||||
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
|
||||
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
|
||||
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
|
||||
<NoWarn>$(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
|
||||
<NoWarn>$(NoWarn);IL1005;IL2122;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
|
||||
<TrimMode>partial</TrimMode>
|
||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
|
|
|
@ -36,13 +36,18 @@ namespace Internal.TypeSystem
|
|||
}
|
||||
|
||||
public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
|
||||
TypeSystemContext context, List<ModuleDesc> referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
|
||||
TypeSystemContext context, List<ModuleDesc> referencedModules, bool needsAssemblyName, out bool failedBecauseNotFullyQualified)
|
||||
{
|
||||
typeWasNotFoundInAssemblyNorBaseLibrary = false;
|
||||
|
||||
failedBecauseNotFullyQualified = false;
|
||||
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
|
||||
return null;
|
||||
|
||||
if (needsAssemblyName && !IsFullyQualified(parsed))
|
||||
{
|
||||
failedBecauseNotFullyQualified = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
TypeNameResolver resolver = new()
|
||||
{
|
||||
_context = context,
|
||||
|
@ -52,8 +57,33 @@ namespace Internal.TypeSystem
|
|||
|
||||
TypeDesc type = resolver.Resolve(parsed);
|
||||
|
||||
typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary;
|
||||
return type;
|
||||
|
||||
static bool IsFullyQualified(TypeName typeName)
|
||||
{
|
||||
if (typeName.AssemblyName is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
|
||||
{
|
||||
return IsFullyQualified(typeName.GetElementType());
|
||||
}
|
||||
|
||||
if (typeName.IsConstructedGenericType)
|
||||
{
|
||||
foreach (var typeArgument in typeName.GetGenericArguments())
|
||||
{
|
||||
if (!IsFullyQualified(typeArgument))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private struct TypeNameResolver
|
||||
|
@ -64,7 +94,6 @@ namespace Internal.TypeSystem
|
|||
internal Func<ModuleDesc, string, MetadataType> _canonResolver;
|
||||
|
||||
internal List<ModuleDesc> _referencedModules;
|
||||
internal bool _typeWasNotFoundInAssemblyNorBaseLibrary;
|
||||
|
||||
internal TypeDesc Resolve(TypeName typeName)
|
||||
{
|
||||
|
@ -136,8 +165,6 @@ namespace Internal.TypeSystem
|
|||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
_typeWasNotFoundInAssemblyNorBaseLibrary = true;
|
||||
}
|
||||
|
||||
if (_throwIfNotFound)
|
||||
|
|
|
@ -89,12 +89,13 @@ namespace ILCompiler.Dataflow
|
|||
|
||||
List<ModuleDesc> referencedModules = new();
|
||||
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
|
||||
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
|
||||
referencedModules, needsAssemblyName, out bool failedBecauseNotFullyQualified);
|
||||
if (foundType == null)
|
||||
{
|
||||
if (needsAssemblyName && typeWasNotFoundInAssemblyNorBaseLibrary)
|
||||
diagnosticContext.AddDiagnostic(DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeName);
|
||||
|
||||
if (failedBecauseNotFullyQualified)
|
||||
{
|
||||
diagnosticContext.AddDiagnostic(DiagnosticId.TypeNameIsNotAssemblyQualified, typeName);
|
||||
}
|
||||
type = default;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using Internal.TypeSystem.Ecma;
|
|||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||
using Mono.Linker.Tests.Extensions;
|
||||
using Xunit;
|
||||
using MetadataType = Internal.TypeSystem.MetadataType;
|
||||
|
|
|
@ -14,7 +14,7 @@ class Program
|
|||
/// </summary>
|
||||
static int Main(string[] args)
|
||||
{
|
||||
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider");
|
||||
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider, project");
|
||||
if (!RunTest(attr))
|
||||
{
|
||||
return -1;
|
||||
|
|
|
@ -53,7 +53,7 @@ class Program
|
|||
}
|
||||
}
|
||||
|
||||
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")]
|
||||
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy, project")]
|
||||
public class MyClassWithProxyString
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
|
|
@ -113,8 +113,8 @@ class Program
|
|||
}
|
||||
}
|
||||
|
||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer")]
|
||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2", "Program+MyClassWithVisualizerStringVisualizerObjectSource")]
|
||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer, project")]
|
||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2, project", "Program+MyClassWithVisualizerStringVisualizerObjectSource, project")]
|
||||
public class MyClassWithVisualizerString
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true'">
|
||||
<!-- Suppress trimming warnings as these are tests -->
|
||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
|
||||
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This .targets file is also imported by the runtime Trimming tests, and we want to be able to manually configure trimming in them so this
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace ILLink.Shared
|
|||
_unused_RearrangedXmlWarning2 = 2021,
|
||||
XmlCouldNotFindMatchingConstructorForCustomAttribute = 2022,
|
||||
XmlMoreThanOneReturnElementForMethod = 2023,
|
||||
XmlMoreThanOneValyForParameterOfMethod = 2024,
|
||||
XmlMoreThanOneValueForParameterOfMethod = 2024,
|
||||
XmlDuplicatePreserveMember = 2025,
|
||||
RequiresUnreferencedCode = 2026,
|
||||
AttributeShouldOnlyBeUsedOnceOnMember = 2027,
|
||||
|
@ -169,7 +169,7 @@ namespace ILLink.Shared
|
|||
InvalidIsTrimmableValue = 2102,
|
||||
PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined = 2103,
|
||||
AssemblyProducedTrimWarnings = 2104,
|
||||
TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
|
||||
_unused_TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
|
||||
DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings = 2106,
|
||||
MethodsAreAssociatedWithStateMachine = 2107,
|
||||
InvalidScopeInUnconditionalSuppressMessage = 2108,
|
||||
|
@ -186,6 +186,7 @@ namespace ILLink.Shared
|
|||
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMember = 2119,
|
||||
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMemberOnBase = 2120,
|
||||
RedundantSuppression = 2121,
|
||||
TypeNameIsNotAssemblyQualified = 2122,
|
||||
|
||||
// Single-file diagnostic ids.
|
||||
AvoidAssemblyLocationInSingleFile = 3000,
|
||||
|
|
|
@ -525,10 +525,10 @@
|
|||
<data name="XmlMoreThanOneReturnElementForMethodMessage" xml:space="preserve">
|
||||
<value>There is more than one 'return' child element specified for method '{0}'.</value>
|
||||
</data>
|
||||
<data name="XmlMoreThanOneValyForParameterOfMethodTitle" xml:space="preserve">
|
||||
<data name="XmlMoreThanOneValueForParameterOfMethodTitle" xml:space="preserve">
|
||||
<value>Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter.</value>
|
||||
</data>
|
||||
<data name="XmlMoreThanOneValyForParameterOfMethodMessage" xml:space="preserve">
|
||||
<data name="XmlMoreThanOneValueForParameterOfMethodMessage" xml:space="preserve">
|
||||
<value>More than one value specified for parameter '{0}' of method '{1}'.</value>
|
||||
</data>
|
||||
<data name="XmlDuplicatePreserveMemberTitle" xml:space="preserve">
|
||||
|
@ -1209,4 +1209,10 @@
|
|||
<data name="InvalidFeatureGuardTitle" xml:space="preserve">
|
||||
<value>Invalid FeatureGuardAttribute.</value>
|
||||
</data>
|
||||
<data name="TypeNameIsNotAssemblyQualifiedMessage" xml:space="preserve">
|
||||
<value>Type '{0}' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.</value>
|
||||
</data>
|
||||
<data name="TypeNameIsNotAssemblyQualifiedTitle" xml:space="preserve">
|
||||
<value>Type name is not assembly qualified.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace ILLink.Shared.TrimAnalysis
|
|||
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
|
||||
MarkTypeForDynamicallyAccessedMembers (systemTypeValue.RepresentedType, targetValue.DynamicallyAccessedMemberTypes);
|
||||
} else if (uniqueValue is KnownStringValue knownStringValue) {
|
||||
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, true, out TypeProxy foundType)) {
|
||||
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, needsAssemblyName: true, out TypeProxy foundType)) {
|
||||
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
|
||||
} else {
|
||||
MarkTypeForDynamicallyAccessedMembers (foundType, targetValue.DynamicallyAccessedMemberTypes);
|
||||
|
|
|
@ -1509,6 +1509,12 @@
|
|||
<Left>ref/net9.0/illink.dll</Left>
|
||||
<Right>lib/net9.0/illink.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Mono.Linker.LinkContext.get_SystemModuleName</Target>
|
||||
<Left>ref/net9.0/illink.dll</Left>
|
||||
<Right>lib/net9.0/illink.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Mono.Linker.LinkContext.set_KeepComInterfaces(System.Boolean)</Target>
|
||||
|
@ -1521,6 +1527,12 @@
|
|||
<Left>ref/net9.0/illink.dll</Left>
|
||||
<Right>lib/net9.0/illink.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Mono.Linker.LinkContext.set_SystemModuleName(System.String)</Target>
|
||||
<Left>ref/net9.0/illink.dll</Left>
|
||||
<Right>lib/net9.0/illink.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0008</DiagnosticId>
|
||||
<Target>T:Mono.Linker.LinkContext</Target>
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace Mono.Linker.Steps
|
|||
continue;
|
||||
}
|
||||
|
||||
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType);
|
||||
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType, provider);
|
||||
if (customAttribute != null) {
|
||||
_context.LogMessage ($"Assigning external custom attribute '{FormatCustomAttribute (customAttribute)}' instance to '{provider}'.");
|
||||
customAttributesBuilder.Add (customAttribute);
|
||||
|
@ -153,9 +153,9 @@ namespace Mono.Linker.Steps
|
|||
return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td;
|
||||
}
|
||||
|
||||
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType)
|
||||
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType, ICustomAttributeProvider provider)
|
||||
{
|
||||
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, attributeType);
|
||||
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, provider);
|
||||
|
||||
MethodDefinition? constructor = FindBestMatchingConstructor (attributeType, arguments);
|
||||
if (constructor == null) {
|
||||
|
@ -223,12 +223,12 @@ namespace Mono.Linker.Steps
|
|||
}
|
||||
}
|
||||
|
||||
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, TypeDefinition attributeType)
|
||||
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||
{
|
||||
ArrayBuilder<CustomAttributeArgument> args = default;
|
||||
|
||||
foreach (XPathNavigator argumentNav in nav.SelectChildren ("argument", string.Empty)) {
|
||||
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, attributeType);
|
||||
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, provider);
|
||||
if (caa is not null)
|
||||
args.Add (caa.Value);
|
||||
}
|
||||
|
@ -236,9 +236,9 @@ namespace Mono.Linker.Steps
|
|||
return args.ToArray () ?? Array.Empty<CustomAttributeArgument> ();
|
||||
}
|
||||
|
||||
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, IMemberDefinition memberWithAttribute)
|
||||
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||
{
|
||||
TypeReference? typeref = ResolveArgumentType (nav, memberWithAttribute);
|
||||
TypeReference? typeref = ResolveArgumentType (nav, provider);
|
||||
if (typeref is null)
|
||||
return null;
|
||||
|
||||
|
@ -295,8 +295,8 @@ namespace Mono.Linker.Steps
|
|||
if (!typeref.IsTypeOf (WellKnownType.System_Type))
|
||||
goto default;
|
||||
|
||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
|
||||
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _)) {
|
||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
|
||||
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _, needsAssemblyName: false)) {
|
||||
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue);
|
||||
return null;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ namespace Mono.Linker.Steps
|
|||
var arrayArgumentIterator = nav.SelectChildren ("argument", string.Empty);
|
||||
ArrayBuilder<CustomAttributeArgument> elements = default;
|
||||
foreach (XPathNavigator elementNav in arrayArgumentIterator) {
|
||||
if (ReadCustomAttributeArgument (elementNav, memberWithAttribute) is CustomAttributeArgument arg) {
|
||||
if (ReadCustomAttributeArgument (elementNav, provider) is CustomAttributeArgument arg) {
|
||||
// To match Cecil, elements of a list that are subclasses of the list type must be boxed in the base type
|
||||
// e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
|
||||
if (arg.Type == elementType) {
|
||||
|
@ -338,14 +338,14 @@ namespace Mono.Linker.Steps
|
|||
return null;
|
||||
}
|
||||
|
||||
TypeReference? ResolveArgumentType (XPathNavigator nav, IMemberDefinition memberWithAttribute)
|
||||
TypeReference? ResolveArgumentType (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||
{
|
||||
string typeName = GetAttribute (nav, "type");
|
||||
if (string.IsNullOrEmpty (typeName))
|
||||
typeName = "System.String";
|
||||
|
||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
|
||||
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _)) {
|
||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
|
||||
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _, needsAssemblyName: false)) {
|
||||
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value);
|
||||
return null;
|
||||
}
|
||||
|
@ -501,7 +501,7 @@ namespace Mono.Linker.Steps
|
|||
foreach (ParameterDefinition parameter in method.Parameters) {
|
||||
if (paramName == parameter.Name) {
|
||||
if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey (parameter))
|
||||
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValyForParameterOfMethod, paramName, method.GetDisplayName ());
|
||||
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValueForParameterOfMethod, paramName, method.GetDisplayName ());
|
||||
_attributeInfo.AddCustomAttributes (parameter, attributes, origins);
|
||||
break;
|
||||
}
|
||||
|
@ -513,11 +513,15 @@ namespace Mono.Linker.Steps
|
|||
|
||||
void ProcessReturnParameters (MethodDefinition method, XPathNavigator nav)
|
||||
{
|
||||
Debug.Assert (_attributeInfo != null);
|
||||
bool firstAppearance = true;
|
||||
foreach (XPathNavigator returnNav in nav.SelectChildren ("return", string.Empty)) {
|
||||
if (firstAppearance) {
|
||||
firstAppearance = false;
|
||||
PopulateAttributeInfo (method.MethodReturnType, returnNav);
|
||||
var (attributes, origins) = ProcessAttributes (returnNav, method);
|
||||
if (attributes != null && origins != null) {
|
||||
_attributeInfo.AddCustomAttributes (method.MethodReturnType, attributes, origins);
|
||||
}
|
||||
} else {
|
||||
LogWarning (returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName ());
|
||||
}
|
||||
|
|
|
@ -45,10 +45,6 @@ using Mono.Cecil.Cil;
|
|||
using Mono.Collections.Generic;
|
||||
using Mono.Linker.Dataflow;
|
||||
|
||||
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
|
||||
using TypeName = System.Reflection.Metadata.TypeName;
|
||||
using TypeNameParseOptions = System.Reflection.Metadata.TypeNameParseOptions;
|
||||
|
||||
namespace Mono.Linker.Steps
|
||||
{
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace Mono.Linker
|
|||
int? _targetRuntime;
|
||||
|
||||
readonly AssemblyResolver _resolver;
|
||||
readonly TypeNameResolver _typeNameResolver;
|
||||
TypeNameResolver? _typeNameResolver;
|
||||
|
||||
readonly AnnotationStore _annotations;
|
||||
readonly CustomAttributeSource _customAttributes;
|
||||
|
@ -146,9 +146,8 @@ namespace Mono.Linker
|
|||
get { return _resolver; }
|
||||
}
|
||||
|
||||
internal TypeNameResolver TypeNameResolver {
|
||||
get { return _typeNameResolver; }
|
||||
}
|
||||
internal TypeNameResolver TypeNameResolver
|
||||
=> _typeNameResolver ??= new TypeNameResolver (this, this);
|
||||
|
||||
public ISymbolReaderProvider SymbolReaderProvider { get; set; }
|
||||
|
||||
|
@ -205,7 +204,6 @@ namespace Mono.Linker
|
|||
_logger = logger ?? throw new ArgumentNullException (nameof (logger));
|
||||
|
||||
_resolver = factory.CreateResolver (this);
|
||||
_typeNameResolver = new TypeNameResolver (this, this);
|
||||
_actions = new Dictionary<string, AssemblyAction> ();
|
||||
_parameters = new Dictionary<string, string> (StringComparer.Ordinal);
|
||||
_customAttributes = new CustomAttributeSource (this);
|
||||
|
@ -973,7 +971,7 @@ namespace Mono.Linker
|
|||
public TypeDefinition? TryResolve (AssemblyDefinition assembly, string typeNameString)
|
||||
{
|
||||
// It could be cached if it shows up on fast path
|
||||
return _typeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
|
||||
return TypeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
|
||||
? TryResolve (typeReference)
|
||||
: null;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,8 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using ILLink.Shared;
|
||||
using ILLink.Shared.TrimAnalysis;
|
||||
using Mono.Cecil;
|
||||
using Mono.Linker;
|
||||
|
||||
using TypeName = System.Reflection.Metadata.TypeName;
|
||||
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
|
||||
|
||||
namespace Mono.Linker
|
||||
{
|
||||
|
@ -21,7 +19,7 @@ namespace Mono.Linker
|
|||
in DiagnosticContext diagnosticContext,
|
||||
[NotNullWhen (true)] out TypeReference? typeReference,
|
||||
[NotNullWhen (true)] out List<TypeResolutionRecord>? typeResolutionRecords,
|
||||
bool needsAssemblyName = true)
|
||||
bool needsAssemblyName)
|
||||
{
|
||||
typeReference = null;
|
||||
typeResolutionRecords = null;
|
||||
|
@ -31,28 +29,16 @@ namespace Mono.Linker
|
|||
if (!TypeName.TryParse (typeNameString, out TypeName? parsedTypeName, s_typeNameParseOptions))
|
||||
return false;
|
||||
|
||||
typeResolutionRecords = new List<TypeResolutionRecord> ();
|
||||
AssemblyDefinition? typeAssembly;
|
||||
if (parsedTypeName.AssemblyName is AssemblyNameInfo assemblyName) {
|
||||
typeAssembly = _assemblyResolver.TryResolve (assemblyName.Name);
|
||||
if (typeAssembly is null) {
|
||||
typeResolutionRecords = null;
|
||||
if (needsAssemblyName && !IsFullyQualified (parsedTypeName)) {
|
||||
diagnosticContext.AddDiagnostic (DiagnosticId.TypeNameIsNotAssemblyQualified, typeNameString);
|
||||
return false;
|
||||
}
|
||||
|
||||
typeReference = ResolveTypeName (typeAssembly, parsedTypeName, typeResolutionRecords);
|
||||
if (typeReference == null) {
|
||||
typeResolutionRecords = null;
|
||||
}
|
||||
|
||||
return typeReference != null;
|
||||
}
|
||||
|
||||
// If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
|
||||
// search for the type in the calling object's assembly. If not found, look in the core
|
||||
// assembly.
|
||||
ICustomAttributeProvider? provider = diagnosticContext.Origin.Provider;
|
||||
typeAssembly = provider switch {
|
||||
AssemblyDefinition? referencingAssembly = provider switch {
|
||||
AssemblyDefinition asm => asm,
|
||||
TypeDefinition type => type.Module?.Assembly,
|
||||
IMemberDefinition member => member.DeclaringType.Module.Assembly,
|
||||
|
@ -60,30 +46,29 @@ namespace Mono.Linker
|
|||
_ => throw new NotSupportedException ()
|
||||
};
|
||||
|
||||
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
|
||||
return true;
|
||||
|
||||
// If type is not found in the caller's assembly, try in core assembly.
|
||||
typeAssembly = _assemblyResolver.TryResolve (PlatformAssemblies.CoreLib);
|
||||
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
|
||||
return true;
|
||||
|
||||
// It is common to use Type.GetType for looking if a type is available.
|
||||
// If no type was found only warn and return null.
|
||||
if (needsAssemblyName && provider != null)
|
||||
diagnosticContext.AddDiagnostic (DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeNameString);
|
||||
|
||||
typeResolutionRecords = null;
|
||||
if (referencingAssembly is null)
|
||||
return false;
|
||||
|
||||
bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName? typeName, [NotNullWhen (true)] out TypeReference? typeReference, List<TypeResolutionRecord> typeResolutionRecords)
|
||||
{
|
||||
typeReference = null;
|
||||
if (assemblyDefinition == null)
|
||||
return false;
|
||||
|
||||
typeReference = ResolveTypeName (assemblyDefinition, typeName, typeResolutionRecords);
|
||||
typeResolutionRecords = new List<TypeResolutionRecord> ();
|
||||
typeReference = ResolveTypeName (referencingAssembly, parsedTypeName, typeResolutionRecords);
|
||||
return typeReference != null;
|
||||
|
||||
static bool IsFullyQualified (TypeName typeName)
|
||||
{
|
||||
if (typeName.AssemblyName is null)
|
||||
return false;
|
||||
|
||||
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
|
||||
return IsFullyQualified (typeName.GetElementType ());
|
||||
|
||||
if (typeName.IsConstructedGenericType) {
|
||||
foreach (var typeArgument in typeName.GetGenericArguments ()) {
|
||||
if (!IsFullyQualified (typeArgument))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,6 +107,19 @@ namespace Mono.Linker
|
|||
return resolvedType;
|
||||
}
|
||||
|
||||
// If it didn't resolve and wasn't assembly-qualified, we also try core library
|
||||
var coreLibrary = _metadataResolver.TryResolve (originalAssembly.MainModule.TypeSystem.Object)?.Module.Assembly;
|
||||
if (coreLibrary is null)
|
||||
return null;
|
||||
|
||||
if (topLevelTypeName.AssemblyName == null && assembly != coreLibrary) {
|
||||
resolvedType = GetSimpleTypeFromModule (typeName, coreLibrary.MainModule);
|
||||
if (resolvedType != null) {
|
||||
typeResolutionRecords.Add (new (coreLibrary, resolvedType));
|
||||
return resolvedType;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
TypeDefinition? GetSimpleTypeFromModule (TypeName typeName, ModuleDefinition module)
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace Mono.Linker.Tests.Cases.ComponentModel
|
|||
[Kept]
|
||||
[KeptAttributeAttribute (typeof (TypeConverterAttribute))]
|
||||
[KeptBackingField]
|
||||
[ExpectedWarning ("IL2105",
|
||||
"Type 'NonExistentType' was not found in the caller assembly nor in the base library. " +
|
||||
[ExpectedWarning ("IL2122",
|
||||
"Type 'NonExistentType' is not assembly qualified. " +
|
||||
"Type name strings used for dynamically accessing a type should be assembly qualified.")]
|
||||
public string Bar { [Kept] get; set; }
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[Kept]
|
||||
static void TestFromStringContantWithAnnotation ()
|
||||
{
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType, test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
|
@ -188,10 +188,19 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[UnconditionalSuppressMessage("test", "IL3050", Justification = "The test applies DAM on System.Array, which contains CreateInstance method which has RDC on it.")]
|
||||
static void TestFromStringConstantWithGeneric ()
|
||||
{
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner]]");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner],Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo]");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,]]]");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,]");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
|
||||
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner, test]"
|
||||
+ "], test");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2["
|
||||
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1["
|
||||
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner, test]"
|
||||
+ "], test],"
|
||||
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo, test]"
|
||||
+ "], test");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
|
||||
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,], test]"
|
||||
+ "], test");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,], test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
|
@ -205,7 +214,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[Kept]
|
||||
static void TestFromStringConstantWithGenericAndAssemblyQualified ()
|
||||
{
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1[[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute,Mono.Linker.Tests.Cases.Expectations]]");
|
||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute, Mono.Linker.Tests.Cases.Expectations]"
|
||||
+ "], test");
|
||||
}
|
||||
|
||||
class InvalidAssemblyNameType
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
RequireNothing (type);
|
||||
}
|
||||
|
||||
[ExpectedWarning ("IL2105", "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[ExpectedWarning ("IL2122", "Type 'System.Invalid.TypeName' is not assembly qualified. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestUnqualifiedTypeNameWarns ()
|
||||
{
|
||||
RequirePublicConstructors ("System.Invalid.TypeName");
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
|
||||
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
|
||||
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
|
||||
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")]
|
||||
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods, test")]
|
||||
[KeepsPublicFields (null, null)]
|
||||
[TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
|
||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")]
|
||||
|
|
|
@ -40,9 +40,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
|
||||
[Kept]
|
||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||
// Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273
|
||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
|
||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods, test")]
|
||||
public static void TestKeepsPublicMethodsString ()
|
||||
{
|
||||
typeof (AttributeFieldDataflow).GetMethod (nameof (TestKeepsPublicMethodsString)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||
// Trimmer/NativeAot only for now
|
||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName")]
|
||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName, test")]
|
||||
public static void TestKeepsPublicMethodsByName ()
|
||||
{
|
||||
typeof (AttributesOnMethod).GetMethod (nameof (TestKeepsPublicMethodsByName)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||
|
@ -213,7 +213,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||
// Trimmer/NativeAot only for now
|
||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
|
||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
|
||||
public static void Test ()
|
||||
{
|
||||
typeof (AttributeWithConditionalExpression).GetMethod ("Test").GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||
|
@ -225,11 +225,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
[Kept]
|
||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
|
||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
|
||||
public static int field;
|
||||
|
||||
[Kept]
|
||||
class ClassWithKeptPublicMethods
|
||||
class ClassWithKeptPublicMethodsKeptByName
|
||||
{
|
||||
[Kept]
|
||||
[KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
|
||||
|
|
|
@ -1372,29 +1372,32 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
{
|
||||
static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { }
|
||||
|
||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void AnnotatedParameter ()
|
||||
{
|
||||
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
|
||||
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||
+ "]], test");
|
||||
}
|
||||
|
||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
||||
static string AnnotatedReturnValue ()
|
||||
{
|
||||
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
|
||||
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||
+ "]], test";
|
||||
}
|
||||
|
||||
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
||||
static string _annotatedField;
|
||||
|
||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void AnnotatedField ()
|
||||
{
|
||||
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
|
||||
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||
+ "]], test";
|
||||
}
|
||||
|
||||
public static void Test ()
|
||||
|
@ -1407,11 +1410,12 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
|||
|
||||
class TypeGetType
|
||||
{
|
||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void SpecificType ()
|
||||
{
|
||||
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
|
||||
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod"
|
||||
+ "]]");
|
||||
}
|
||||
|
||||
public static void Test ()
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
{
|
||||
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
|
||||
}
|
||||
.assembly 'library'
|
||||
.assembly 'EscapedTypeNames'
|
||||
{
|
||||
.hash algorithm 0x00008004
|
||||
.ver 1:0:0:0
|
||||
}
|
||||
.module library.dll
|
||||
.module EscapedTypeNames.dll
|
||||
|
||||
// =============== CLASS MEMBERS DECLARATION ===================
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Mono.Linker.Tests.Cases.Reflection.Dependencies
|
||||
{
|
||||
public class RequireHelper
|
||||
{
|
||||
public static Type RequireType ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string type) {
|
||||
return Type.GetType (type);
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeDefinedInSameAssemblyAsGetType {}
|
||||
}
|
|
@ -4,16 +4,19 @@ using System.Reflection;
|
|||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
||||
using Mono.Linker.Tests.Cases.Reflection.Dependencies;
|
||||
|
||||
namespace Mono.Linker.Tests.Cases.Reflection
|
||||
{
|
||||
[KeptMember (".cctor()")]
|
||||
[ExpectedNoWarnings ()]
|
||||
[Define ("IL_ASSEMBLY_AVAILABLE")]
|
||||
[SetupCompileBefore ("library.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
|
||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested")]
|
||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes\\\\ted")]
|
||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes/ted")]
|
||||
[SetupCompileBefore ("EscapedTypeNames.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
|
||||
[SetupCompileBefore ("RequireHelper.dll", new[] { "Dependencies/RequireHelper.cs" })]
|
||||
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested")]
|
||||
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes\\\\ted")]
|
||||
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes/ted")]
|
||||
[RemovedTypeInAssembly ("RequireHelper", typeof (TypeDefinedInSameAssemblyAsGetType))]
|
||||
[KeptDelegateCacheField ("0", nameof (AssemblyResolver))]
|
||||
[KeptDelegateCacheField ("1", nameof (GetTypeFromAssembly))]
|
||||
public class TypeUsedViaReflection
|
||||
|
@ -31,8 +34,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
|||
TestReference ();
|
||||
TestArray ();
|
||||
TestArrayOfArray ();
|
||||
TestGenericArray ();
|
||||
TestGenericArrayFullString ();
|
||||
TestGenericInstantiation ();
|
||||
TestGenericInstantiationFullString ();
|
||||
TestGenericInstantiationOverCoreLib ();
|
||||
TestMultiDimensionalArray ();
|
||||
TestMultiDimensionalArrayFullString ();
|
||||
TestMultiDimensionalArrayAsmName ();
|
||||
|
@ -55,6 +59,7 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
|||
|
||||
TestInvalidTypeCombination ();
|
||||
TestEscapedTypeName ();
|
||||
AssemblyTypeResolutionBehavior.Test ();
|
||||
}
|
||||
|
||||
[Kept]
|
||||
|
@ -92,30 +97,42 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
|||
}
|
||||
|
||||
[Kept]
|
||||
public class GenericArray<T> { }
|
||||
public class GenericInstantiation<T> { }
|
||||
|
||||
[Kept]
|
||||
public class GenericArgument { }
|
||||
|
||||
[Kept]
|
||||
public static void TestGenericArray ()
|
||||
public static void TestGenericInstantiation ()
|
||||
{
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArray`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiation`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
|
||||
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||
}
|
||||
|
||||
[Kept]
|
||||
public class GenericArrayFullString<T> { }
|
||||
public class GenericInstantiationFullString<T> { }
|
||||
|
||||
[Kept]
|
||||
public class GenericArgumentFullString { }
|
||||
|
||||
[Kept]
|
||||
public static void TestGenericArrayFullString ()
|
||||
public static void TestGenericInstantiationFullString ()
|
||||
{
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArrayFullString`1" +
|
||||
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
|
||||
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationFullString`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
|
||||
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||
}
|
||||
|
||||
[Kept]
|
||||
public class GenericInstantiationOverCoreLib<T> { }
|
||||
|
||||
[Kept]
|
||||
public static void TestGenericInstantiationOverCoreLib ()
|
||||
{
|
||||
// Note: the argument type should not be assembly-qualified for this test, which is checking that
|
||||
// we can resolve non-assembly-qualified generic argument types from corelib.
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationOverCoreLib`1[[System.String]], test";
|
||||
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||
}
|
||||
|
||||
|
@ -420,9 +437,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
|||
[Kept]
|
||||
static void TestGenericTypeWithAnnotations ()
|
||||
{
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1" +
|
||||
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
|
||||
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
|
||||
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||
Type.GetType (reflectionTypeKeptString);
|
||||
}
|
||||
|
||||
|
@ -475,9 +492,75 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
|||
[Kept]
|
||||
static void TestEscapedTypeName ()
|
||||
{
|
||||
var typeKept = Type.GetType ("Library.Not\\+Nested, library");
|
||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, library");
|
||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, library");
|
||||
var typeKept = Type.GetType ("Library.Not\\+Nested, EscapedTypeNames");
|
||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, EscapedTypeNames");
|
||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, EscapedTypeNames");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
class AssemblyTypeResolutionBehavior
|
||||
{
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeInSameAssemblyAsGetType () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.Dependencies.TypeDefinedInSameAssemblyAsGetType");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeInSameAssemblyAsCallToRequireType () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+TypeDefinedInSameAssemblyAsCallToRequireType");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeWithNonAssemblyQualifiedGenericArguments () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1[[System.Int32]], test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeWithNonAssemblyQualifiedArrayType () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ArrayElementGenericArgumentType]"
|
||||
+ "][], test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeWithNonAssemblyQualifiedPointerType () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+PointerElementGenericArgumentType]"
|
||||
+ "]*, test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||
static void TestRequireTypeWithNonAssemblyQualifiedByRefType () {
|
||||
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ByRefElementGenericArgumentType]"
|
||||
+ "]&, test");
|
||||
}
|
||||
|
||||
[Kept]
|
||||
public static void Test () {
|
||||
TestRequireTypeInSameAssemblyAsGetType ();
|
||||
TestRequireTypeInSameAssemblyAsCallToRequireType ();
|
||||
TestRequireTypeWithNonAssemblyQualifiedGenericArguments ();
|
||||
TestRequireTypeWithNonAssemblyQualifiedArrayType ();
|
||||
TestRequireTypeWithNonAssemblyQualifiedPointerType ();
|
||||
TestRequireTypeWithNonAssemblyQualifiedByRefType ();
|
||||
}
|
||||
|
||||
class TypeDefinedInSameAssemblyAsCallToRequireType {}
|
||||
|
||||
class Generic<T> {}
|
||||
|
||||
class ArrayElementGenericArgumentType {}
|
||||
|
||||
class PointerElementGenericArgumentType {}
|
||||
|
||||
class ByRefElementGenericArgumentType {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ using Mono.Cecil;
|
|||
using Mono.Cecil.Cil;
|
||||
using Mono.Linker;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
||||
using Mono.Linker.Tests.Extensions;
|
||||
using Mono.Linker.Tests.TestCasesRunner.ILVerification;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue