diff options
author | Sven Boemer <sbomer@gmail.com> | 2021-10-19 21:42:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-19 21:42:12 +0300 |
commit | 4c9de67922b2381aed29c6dff2c892ff6467f114 (patch) | |
tree | 6ba7c46cab304cae9a2a2107b3e0b050b16613f7 /src | |
parent | c75a5240bd253e2e407438cbaa14c9d1bf714343 (diff) |
Nullable annotations part 4 (final) (#2300)
* Nullable annotations part 4 (final)
* PR feedback
- Clean up extra variables introduced as
nullable versions of existing variables.
* Fix a few annotations
- TryGetMethodStubValue may return null when true
- GetReturnType and GetParameterType may return null in some cases
* More annotations and PR feedback
- Don't resolve a generic typeref that should already be a typedef
- Remove some redundant null checks
- Turn on nullable annotations for ref assembly
- Remove #nullable disable section
* Clean up GetInflatedDeclaringType
- Remove null check
- Replace TryResolve call with an assert
- Add comment and asserts justifying null-forgiving operator
* Replace exception with assert in accessors
* PR feedback
- Add parens to improve readability
- Throw on diagnostic without message
- Remove unnecessary string.empty
* Undo DiagnosticString change
- Some DiagnosticIds intentionally have no fixed format strings because
we generate different strings in different circumstances.
Diffstat (limited to 'src')
73 files changed, 957 insertions, 793 deletions
diff --git a/src/ILLink.Shared/DiagnosticString.cs b/src/ILLink.Shared/DiagnosticString.cs index ba7599c2d..e01cc9b5b 100644 --- a/src/ILLink.Shared/DiagnosticString.cs +++ b/src/ILLink.Shared/DiagnosticString.cs @@ -1,4 +1,6 @@ -namespace ILLink.Shared +using System; + +namespace ILLink.Shared { public readonly struct DiagnosticString { @@ -8,15 +10,15 @@ public DiagnosticString (DiagnosticId diagnosticId) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString ($"{diagnosticId}Title"); - _messageFormat = resourceManager.GetString ($"{diagnosticId}Message"); + _titleFormat = resourceManager.GetString ($"{diagnosticId}Title") ?? string.Empty; + _messageFormat = resourceManager.GetString ($"{diagnosticId}Message") ?? string.Empty; } public DiagnosticString (string diagnosticResourceStringName) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString ($"{diagnosticResourceStringName}Title"); - _messageFormat = resourceManager.GetString ($"{diagnosticResourceStringName}Message"); + _titleFormat = resourceManager.GetString ($"{diagnosticResourceStringName}Title") ?? string.Empty; + _messageFormat = resourceManager.GetString ($"{diagnosticResourceStringName}Message") ?? string.Empty; } public string GetMessage (params string[] args) => diff --git a/src/ILLink.Shared/MessageFormat.cs b/src/ILLink.Shared/MessageFormat.cs index e8ae020f7..58ac52d14 100644 --- a/src/ILLink.Shared/MessageFormat.cs +++ b/src/ILLink.Shared/MessageFormat.cs @@ -1,6 +1,4 @@ -#nullable enable - -namespace ILLink.Shared +namespace ILLink.Shared { internal static class MessageFormat { diff --git a/src/linker/Linker.Dataflow/DiagnosticUtilities.cs b/src/linker/Linker.Dataflow/DiagnosticUtilities.cs index 4651bb7da..9aef3fde6 100644 --- a/src/linker/Linker.Dataflow/DiagnosticUtilities.cs +++ b/src/linker/Linker.Dataflow/DiagnosticUtilities.cs @@ -1,6 +1,7 @@ // 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 Mono.Cecil; namespace Mono.Linker.Dataflow @@ -21,7 +22,7 @@ namespace Mono.Linker.Dataflow if (declaredParameterIndex >= 0 && declaredParameterIndex < method.Parameters.Count) return method.Parameters[declaredParameterIndex]; - return null; + throw new InvalidOperationException (); } internal static string GetParameterNameForErrorMessage (ParameterDefinition parameterDefinition) => @@ -33,6 +34,6 @@ namespace Mono.Linker.Dataflow genericParameter.DeclaringType.GetDisplayName (); internal static string GetMethodSignatureDisplayName (IMethodSignature methodSignature) => - (methodSignature is MethodReference method) ? method.GetDisplayName () : methodSignature.ToString (); + (methodSignature is MethodReference method) ? method.GetDisplayName () : (methodSignature.ToString () ?? string.Empty); } } diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs index 66b6d17e2..b44dd1cd1 100644 --- a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs @@ -7,8 +7,6 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using Mono.Cecil; -#nullable enable - namespace Mono.Linker { // Temporary workaround - should be removed once linker can be upgraded to build against diff --git a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersTypeHierarchy.cs b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersTypeHierarchy.cs index 2658d7435..f75825871 100644 --- a/src/linker/Linker.Dataflow/DynamicallyAccessedMembersTypeHierarchy.cs +++ b/src/linker/Linker.Dataflow/DynamicallyAccessedMembersTypeHierarchy.cs @@ -65,7 +65,7 @@ namespace Mono.Linker.Dataflow // Base should already be marked (since we're marking its derived type now) // so we should already have its cached values filled. - TypeDefinition baseType = _context.TryResolve (type.BaseType); + TypeDefinition? baseType = _context.TryResolve (type.BaseType); Debug.Assert (baseType == null || _context.Annotations.IsMarked (baseType)); if (baseType != null && _typesInDynamicallyAccessedMembersHierarchy.TryGetValue (baseType, out var baseValue)) { annotation |= baseValue.annotation; @@ -195,7 +195,7 @@ namespace Mono.Linker.Dataflow if (applied) return true; - TypeDefinition baseType = _context.TryResolve (type.BaseType); + TypeDefinition? baseType = _context.TryResolve (type.BaseType); if (baseType != null) applied = ApplyDynamicallyAccessedMembersToTypeHierarchyInner (reflectionMethodBodyScanner, baseType); diff --git a/src/linker/Linker.Dataflow/FlowAnnotations.cs b/src/linker/Linker.Dataflow/FlowAnnotations.cs index 839fed525..4f4a50dae 100644 --- a/src/linker/Linker.Dataflow/FlowAnnotations.cs +++ b/src/linker/Linker.Dataflow/FlowAnnotations.cs @@ -8,8 +8,6 @@ using System.Diagnostics.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; -#nullable enable - namespace Mono.Linker.Dataflow { class FlowAnnotations @@ -588,15 +586,15 @@ namespace Mono.Linker.Dataflow { readonly TypeDefinition _type; readonly DynamicallyAccessedMemberTypes _typeAnnotation; - readonly MethodAnnotations[] _annotatedMethods; - readonly FieldAnnotation[] _annotatedFields; + readonly MethodAnnotations[]? _annotatedMethods; + readonly FieldAnnotation[]? _annotatedFields; readonly DynamicallyAccessedMemberTypes[]? _genericParameterAnnotations; public TypeAnnotations ( TypeDefinition type, DynamicallyAccessedMemberTypes typeAnnotation, - MethodAnnotations[] annotatedMethods, - FieldAnnotation[] annotatedFields, + MethodAnnotations[]? annotatedMethods, + FieldAnnotation[]? annotatedFields, DynamicallyAccessedMemberTypes[]? genericParameterAnnotations) => (_type, _typeAnnotation, _annotatedMethods, _annotatedFields, _genericParameterAnnotations) = (type, typeAnnotation, annotatedMethods, annotatedFields, genericParameterAnnotations); diff --git a/src/linker/Linker.Dataflow/MethodBodyScanner.cs b/src/linker/Linker.Dataflow/MethodBodyScanner.cs index 84b0b9785..f3cce6d4b 100644 --- a/src/linker/Linker.Dataflow/MethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/MethodBodyScanner.cs @@ -8,8 +8,6 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; -#nullable enable - namespace Mono.Linker.Dataflow { /// <summary> diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 8790e1663..a523de225 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -13,8 +13,6 @@ using Mono.Linker.Steps; using BindingFlags = System.Reflection.BindingFlags; -#nullable enable - namespace Mono.Linker.Dataflow { class ReflectionMethodBodyScanner : MethodBodyScanner @@ -893,8 +891,7 @@ namespace Mono.Linker.Dataflow // We have one of the accessors for the property. The Expression.Property will in this case search // for the matching PropertyInfo and store that. So to be perfectly correct we need to mark the // respective PropertyInfo as "accessed via reflection". - var propertyDefinition = methodBaseValue.MethodRepresented.GetProperty (); - if (propertyDefinition != null) { + if (methodBaseValue.MethodRepresented.TryGetProperty (out PropertyDefinition? propertyDefinition)) { MarkProperty (ref reflectionContext, propertyDefinition); continue; } @@ -1050,9 +1047,8 @@ namespace Mono.Linker.Dataflow } foreach (var typeNameValue in methodParams[0].UniqueValues ()) { if (typeNameValue is KnownStringValue knownStringValue) { - TypeReference foundTypeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, callingMethodDefinition, out AssemblyDefinition typeAssembly, false); - TypeDefinition? foundType = ResolveToTypeDefinition (foundTypeRef); - if (foundType == null) { + if (!_context.TypeNameResolver.TryResolveTypeName (knownStringValue.Contents, callingMethodDefinition, out TypeReference? foundTypeRef, out AssemblyDefinition? typeAssembly, false) + || ResolveToTypeDefinition (foundTypeRef) is not TypeDefinition foundType) { // Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back. reflectionContext.RecordHandledPattern (); } else { @@ -1199,7 +1195,7 @@ namespace Mono.Linker.Dataflow // We have chosen not to populate the methodReturnValue for now RequireDynamicallyAccessedMembers (ref reflectionContext, DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes, value, calledMethodDefinition); else { - TypeDefinition[] matchingNestedTypes = MarkNestedTypesOnType (ref reflectionContext, systemTypeValue.TypeRepresented, m => m.Name == stringValue.Contents, bindingFlags); + TypeDefinition[]? matchingNestedTypes = MarkNestedTypesOnType (ref reflectionContext, systemTypeValue.TypeRepresented, m => m.Name == stringValue.Contents, bindingFlags); if (matchingNestedTypes != null) { for (int i = 0; i < matchingNestedTypes.Length; i++) @@ -1935,9 +1931,9 @@ namespace Mono.Linker.Dataflow continue; } - var typeRef = _context.TypeNameResolver.ResolveTypeName (resolvedAssembly, typeNameStringValue.Contents); - var resolvedType = _context.TryResolve (typeRef); - if (resolvedType == null || typeRef is ArrayType) { + if (!_context.TypeNameResolver.TryResolveTypeName (resolvedAssembly, typeNameStringValue.Contents, out TypeReference? typeRef) + || _context.TryResolve (typeRef) is not TypeDefinition resolvedType + || typeRef is ArrayType) { // It's not wrong to have a reference to non-existing type - the code may well expect to get an exception in this case // Note that we did find the assembly, so it's not a linker config problem, it's either intentional, or wrong versions of assemblies // but linker can't know that. In case a user tries to create an array using System.Activator we should simply ignore it, the user @@ -2231,9 +2227,8 @@ namespace Mono.Linker.Dataflow } else if (uniqueValue is SystemTypeValue systemTypeValue) { MarkTypeForDynamicallyAccessedMembers (ref reflectionContext, systemTypeValue.TypeRepresented, requiredMemberTypes, DependencyKind.DynamicallyAccessedMember); } else if (uniqueValue is KnownStringValue knownStringValue) { - TypeReference typeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, reflectionContext.Source, out AssemblyDefinition typeAssembly); - TypeDefinition? foundType = ResolveToTypeDefinition (typeRef); - if (foundType == null) { + if (!_context.TypeNameResolver.TryResolveTypeName (knownStringValue.Contents, reflectionContext.Source, out TypeReference? typeRef, out AssemblyDefinition? typeAssembly) + || ResolveToTypeDefinition (typeRef) is not TypeDefinition foundType) { // Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back. reflectionContext.RecordHandledPattern (); } else { @@ -2386,7 +2381,7 @@ namespace Mono.Linker.Dataflow MarkField (ref reflectionContext, field); } - TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func<TypeDefinition, bool> filter, BindingFlags? bindingFlags = BindingFlags.Default) + TypeDefinition[]? MarkNestedTypesOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func<TypeDefinition, bool> filter, BindingFlags? bindingFlags = BindingFlags.Default) { var result = new ArrayBuilder<TypeDefinition> (); diff --git a/src/linker/Linker.Dataflow/ReflectionPatternContext.cs b/src/linker/Linker.Dataflow/ReflectionPatternContext.cs index fd2c11cab..1cd64ce43 100644 --- a/src/linker/Linker.Dataflow/ReflectionPatternContext.cs +++ b/src/linker/Linker.Dataflow/ReflectionPatternContext.cs @@ -25,9 +25,9 @@ namespace Mono.Linker.Dataflow #endif public MessageOrigin Origin { get; init; } - public ICustomAttributeProvider Source { get => Origin.Provider; } + public ICustomAttributeProvider? Source { get => Origin.Provider; } public IMetadataTokenProvider MemberWithRequirements { get; init; } - public Instruction Instruction { get; init; } + public Instruction? Instruction { get; init; } public bool ReportingEnabled { get; init; } public ReflectionPatternContext ( @@ -35,7 +35,7 @@ namespace Mono.Linker.Dataflow bool reportingEnabled, in MessageOrigin origin, IMetadataTokenProvider memberWithRequirements, - Instruction instruction = null) + Instruction? instruction = null) { _context = context; ReportingEnabled = reportingEnabled; diff --git a/src/linker/Linker.Dataflow/ValueNode.cs b/src/linker/Linker.Dataflow/ValueNode.cs index ce2887aff..5e3349db6 100644 --- a/src/linker/Linker.Dataflow/ValueNode.cs +++ b/src/linker/Linker.Dataflow/ValueNode.cs @@ -12,8 +12,6 @@ using FieldDefinition = Mono.Cecil.FieldDefinition; using GenericParameter = Mono.Cecil.GenericParameter; using TypeDefinition = Mono.Cecil.TypeDefinition; -#nullable enable - namespace Mono.Linker.Dataflow { public enum ValueNodeKind diff --git a/src/linker/Linker.Steps/AddBypassNGenStep.cs b/src/linker/Linker.Steps/AddBypassNGenStep.cs index baf492fdd..bbe4e6507 100644 --- a/src/linker/Linker.Steps/AddBypassNGenStep.cs +++ b/src/linker/Linker.Steps/AddBypassNGenStep.cs @@ -4,6 +4,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; @@ -14,13 +15,15 @@ namespace Mono.Linker.Steps public class AddBypassNGenStep : BaseStep { - AssemblyDefinition coreLibAssembly; - CustomAttribute bypassNGenAttribute; + AssemblyDefinition? coreLibAssembly; + CustomAttribute? bypassNGenAttribute; protected override void ProcessAssembly (AssemblyDefinition assembly) { if (Annotations.GetAction (assembly) == AssemblyAction.AddBypassNGen) { coreLibAssembly = Context.Resolve (assembly.MainModule.TypeSystem.CoreLibrary); + if (coreLibAssembly == null) + return; bypassNGenAttribute = null; if (assembly == coreLibAssembly) { EnsureBypassNGenAttribute (assembly.MainModule); @@ -59,13 +62,14 @@ namespace Mono.Linker.Steps private void EnsureBypassNGenAttribute (ModuleDefinition targetModule) { + Debug.Assert (coreLibAssembly != null); if (bypassNGenAttribute != null) { return; } ModuleDefinition corelibMainModule = coreLibAssembly.MainModule; TypeReference bypassNGenAttributeRef = new TypeReference ("System.Runtime", "BypassNGenAttribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary); TypeDefinition bypassNGenAttributeDef = corelibMainModule.MetadataResolver.Resolve (bypassNGenAttributeRef); - MethodDefinition bypassNGenAttributeDefaultConstructor = null; + MethodDefinition? bypassNGenAttributeDefaultConstructor = null; if (bypassNGenAttributeDef == null) { // System.Runtime.BypassNGenAttribute is not found in corelib. Add it. diff --git a/src/linker/Linker.Steps/BaseStep.cs b/src/linker/Linker.Steps/BaseStep.cs index eabffedb7..cedd2e5de 100644 --- a/src/linker/Linker.Steps/BaseStep.cs +++ b/src/linker/Linker.Steps/BaseStep.cs @@ -27,6 +27,7 @@ // using System; +using System.Diagnostics; using Mono.Cecil; namespace Mono.Linker.Steps @@ -35,21 +36,24 @@ namespace Mono.Linker.Steps public abstract class BaseStep : IStep { - private LinkContext _context; + private LinkContext? _context; public LinkContext Context { - get { return _context; } + get { + Debug.Assert (_context != null); + return _context; + } } public AnnotationStore Annotations { - get { return _context.Annotations; } + get { return Context.Annotations; } } public Tracer Tracer { - get { return _context.Tracer; } + get { return Context.Tracer; } } - public MarkingHelpers MarkingHelpers => _context.MarkingHelpers; + public MarkingHelpers MarkingHelpers => Context.MarkingHelpers; public void Process (LinkContext context) { diff --git a/src/linker/Linker.Steps/BaseSubStep.cs b/src/linker/Linker.Steps/BaseSubStep.cs index 9a3aa250a..4826c7014 100644 --- a/src/linker/Linker.Steps/BaseSubStep.cs +++ b/src/linker/Linker.Steps/BaseSubStep.cs @@ -1,6 +1,8 @@ // 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.Diagnostics; using Mono.Cecil; namespace Mono.Linker.Steps @@ -9,13 +11,19 @@ namespace Mono.Linker.Steps { protected AnnotationStore Annotations => Context.Annotations; - protected LinkContext Context { get; private set; } + LinkContext? _context { get; set; } + protected LinkContext Context { + get { + Debug.Assert (_context != null); + return _context; + } + } public abstract SubStepTargets Targets { get; } public virtual void Initialize (LinkContext context) { - Context = context; + _context = context; } public virtual bool IsActiveFor (AssemblyDefinition assembly) => true; diff --git a/src/linker/Linker.Steps/BodySubstitutionParser.cs b/src/linker/Linker.Steps/BodySubstitutionParser.cs index f79b34da3..bccf3e093 100644 --- a/src/linker/Linker.Steps/BodySubstitutionParser.cs +++ b/src/linker/Linker.Steps/BodySubstitutionParser.cs @@ -5,8 +5,6 @@ using System.Linq; using System.Xml.XPath; using Mono.Cecil; -#nullable enable - namespace Mono.Linker.Steps { public class BodySubstitutionParser : ProcessLinkerXmlBase @@ -137,7 +135,7 @@ namespace Mono.Linker.Steps continue; } - EmbeddedResource resource = assembly.FindEmbeddedResource (name); + EmbeddedResource? resource = assembly.FindEmbeddedResource (name); if (resource == null) { LogWarning ($"Could not find embedded resource '{name}' to remove in assembly '{assembly.Name.Name}'.", 2040, resourceNav); continue; diff --git a/src/linker/Linker.Steps/CleanStep.cs b/src/linker/Linker.Steps/CleanStep.cs index 7285b7e5d..4736be28f 100644 --- a/src/linker/Linker.Steps/CleanStep.cs +++ b/src/linker/Linker.Steps/CleanStep.cs @@ -58,7 +58,7 @@ namespace Mono.Linker.Steps CleanType (nested); } - static MethodDefinition CheckMethod (TypeDefinition type, MethodDefinition method) + static MethodDefinition? CheckMethod (TypeDefinition type, MethodDefinition method) { if (method == null) return null; diff --git a/src/linker/Linker.Steps/CodeRewriterStep.cs b/src/linker/Linker.Steps/CodeRewriterStep.cs index 9b9f17010..93d2a933d 100644 --- a/src/linker/Linker.Steps/CodeRewriterStep.cs +++ b/src/linker/Linker.Steps/CodeRewriterStep.cs @@ -8,7 +8,13 @@ namespace Mono.Linker.Steps { public class CodeRewriterStep : BaseStep { - AssemblyDefinition assembly; + AssemblyDefinition? assembly; + AssemblyDefinition Assembly { + get { + Debug.Assert (assembly != null); + return assembly; + } + } protected override void ProcessAssembly (AssemblyDefinition assembly) { @@ -47,7 +53,7 @@ namespace Mono.Linker.Steps var method = new MethodDefinition (".cctor", MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig, - assembly.MainModule.TypeSystem.Void); + Assembly.MainModule.TypeSystem.Void); type.Methods.Add (method); @@ -76,7 +82,7 @@ namespace Mono.Linker.Steps if (!Annotations.HasSubstitutedInit (field)) continue; - Context.Annotations.TryGetFieldUserValue (field, out object value); + Context.Annotations.TryGetFieldUserValue (field, out object? value); var valueInstr = CreateConstantResultInstruction (Context, field.FieldType, value); if (valueInstr == null) @@ -123,11 +129,11 @@ namespace Mono.Linker.Steps { var body = new MethodBody (method); var il = body.GetLinkerILProcessor (); - MethodReference ctor; + MethodReference? ctor; // Makes the body verifiable if (method.IsConstructor && !method.DeclaringType.IsValueType) { - ctor = assembly.MainModule.ImportReference (Context.MarkedKnownMembers.ObjectCtor); + ctor = Assembly.MainModule.ImportReference (Context.MarkedKnownMembers.ObjectCtor); il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Call, ctor); @@ -135,7 +141,7 @@ namespace Mono.Linker.Steps // import the method into the current assembly ctor = Context.MarkedKnownMembers.NotSupportedExceptionCtorString; - ctor = assembly.MainModule.ImportReference (ctor); + ctor = Assembly.MainModule.ImportReference (ctor); il.Emit (OpCodes.Ldstr, "Linked away"); il.Emit (OpCodes.Newobj, ctor); @@ -161,7 +167,7 @@ namespace Mono.Linker.Steps if (base_ctor == null) throw new NotSupportedException ($"Cannot replace constructor for '{method.DeclaringType}' when no base default constructor exists"); - base_ctor = assembly.MainModule.ImportReference (base_ctor); + base_ctor = Assembly.MainModule.ImportReference (base_ctor); il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Call, base_ctor); @@ -208,14 +214,15 @@ namespace Mono.Linker.Steps throw new NotImplementedException (method.FullName); } - public static Instruction CreateConstantResultInstruction (LinkContext context, MethodDefinition method) + public static Instruction? CreateConstantResultInstruction (LinkContext context, MethodDefinition method) { - context.Annotations.TryGetMethodStubValue (method, out object value); + context.Annotations.TryGetMethodStubValue (method, out object? value); return CreateConstantResultInstruction (context, method.ReturnType, value); } - public static Instruction CreateConstantResultInstruction (LinkContext context, TypeReference rtype, object value = null) + public static Instruction? CreateConstantResultInstruction (LinkContext context, TypeReference inputRtype, object? value = null) { + TypeReference? rtype = inputRtype; switch (rtype.MetadataType) { case MetadataType.ValueType: var definition = context.TryResolve (rtype); diff --git a/src/linker/Linker.Steps/DescriptorMarker.cs b/src/linker/Linker.Steps/DescriptorMarker.cs index 2930a5445..e99708f5e 100644 --- a/src/linker/Linker.Steps/DescriptorMarker.cs +++ b/src/linker/Linker.Steps/DescriptorMarker.cs @@ -9,8 +9,6 @@ using System.Xml.XPath; using Mono.Cecil; -#nullable enable - namespace Mono.Linker.Steps { public class DescriptorMarker : ProcessLinkerXmlBase diff --git a/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs b/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs index 3cb0e98bb..8497a61ea 100644 --- a/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs +++ b/src/linker/Linker.Steps/DiscoverCustomOperatorsHandler.cs @@ -1,6 +1,7 @@ // 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; using System.Diagnostics; using Mono.Cecil; @@ -9,10 +10,17 @@ namespace Mono.Linker.Steps { public class DiscoverOperatorsHandler : IMarkHandler { - LinkContext _context; + LinkContext? _context; + LinkContext Context { + get { + Debug.Assert (_context != null); + return _context; + } + } + bool _seenLinqExpressions; readonly HashSet<TypeDefinition> _trackedTypesWithOperators; - Dictionary<TypeDefinition, List<MethodDefinition>> _pendingOperatorsForType; + Dictionary<TypeDefinition, List<MethodDefinition>>? _pendingOperatorsForType; Dictionary<TypeDefinition, List<MethodDefinition>> PendingOperatorsForType { get { @@ -74,7 +82,7 @@ namespace Mono.Linker.Steps void MarkOperator (MethodDefinition method) { - _context.Annotations.Mark (method, new DependencyInfo (DependencyKind.PreservedOperator, method.DeclaringType)); + Context.Annotations.Mark (method, new DependencyInfo (DependencyKind.PreservedOperator, method.DeclaringType)); } bool ProcessCustomOperators (TypeDefinition type, bool mark) @@ -93,7 +101,7 @@ namespace Mono.Linker.Steps Debug.Assert (_seenLinqExpressions); hasCustomOperators = true; - if (otherType == null || _context.Annotations.IsMarked (otherType)) { + if (otherType == null || Context.Annotations.IsMarked (otherType)) { MarkOperator (method); continue; } @@ -108,18 +116,18 @@ namespace Mono.Linker.Steps return hasCustomOperators; } - TypeDefinition _nullableOfT; - TypeDefinition NullableOfT { + TypeDefinition? _nullableOfT; + TypeDefinition? NullableOfT { get { if (_nullableOfT == null) - _nullableOfT = BCL.FindPredefinedType ("System", "Nullable`1", _context); + _nullableOfT = BCL.FindPredefinedType ("System", "Nullable`1", Context); return _nullableOfT; } } - TypeDefinition NonNullableType (TypeReference type) + TypeDefinition? NonNullableType (TypeReference type) { - var typeDef = _context.TryResolve (type); + var typeDef = Context.TryResolve (type); if (typeDef == null) return null; @@ -134,10 +142,10 @@ namespace Mono.Linker.Steps type = ((TypeSpecification) type).ElementType; var nullableType = type as GenericInstanceType; Debug.Assert (nullableType != null && nullableType.HasGenericArguments && nullableType.GenericArguments.Count == 1); - return _context.TryResolve (nullableType.GenericArguments[0]); + return Context.TryResolve (nullableType.GenericArguments[0]); } - bool IsOperator (MethodDefinition method, out TypeDefinition otherType) + bool IsOperator (MethodDefinition method, out TypeDefinition? otherType) { otherType = null; diff --git a/src/linker/Linker.Steps/DiscoverSerializationHandler.cs b/src/linker/Linker.Steps/DiscoverSerializationHandler.cs index 644fd33eb..0b30d6ea4 100644 --- a/src/linker/Linker.Steps/DiscoverSerializationHandler.cs +++ b/src/linker/Linker.Steps/DiscoverSerializationHandler.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Mono.Cecil; using Mono.Linker.Dataflow; @@ -16,7 +17,13 @@ namespace Mono.Linker.Steps // - this will discover types in non-"link" assemblies as well public class DiscoverSerializationHandler : IMarkHandler { - LinkContext _context; + LinkContext? _context; + LinkContext Context { + get { + Debug.Assert (_context != null); + return _context; + } + } public void Initialize (LinkContext context, MarkContext markContext) { @@ -29,20 +36,20 @@ namespace Mono.Linker.Steps { var type = method.DeclaringType; - if (!_context.SerializationMarker.IsActive (SerializerKind.DataContractSerializer) && + if (!Context.SerializationMarker.IsActive (SerializerKind.DataContractSerializer) && method.IsConstructor && !method.IsStatic && ((type.Namespace == "System.Runtime.Serialization" && type.Name == "DataContractSerializer") || (type.Namespace == "System.Runtime.Serialization.Json" && type.Name == "DataContractJsonSerializer"))) { - _context.SerializationMarker.Activate (SerializerKind.DataContractSerializer); + Context.SerializationMarker.Activate (SerializerKind.DataContractSerializer); } - if (!_context.SerializationMarker.IsActive (SerializerKind.XmlSerializer) && + if (!Context.SerializationMarker.IsActive (SerializerKind.XmlSerializer) && method.IsConstructor && !method.IsStatic && type.Namespace == "System.Xml.Serialization" && type.Name == "XmlSerializer") { - _context.SerializationMarker.Activate (SerializerKind.XmlSerializer); + Context.SerializationMarker.Activate (SerializerKind.XmlSerializer); } } @@ -88,9 +95,9 @@ namespace Mono.Linker.Steps return; if (serializedFor.HasFlag (SerializerKind.DataContractSerializer)) - _context.SerializationMarker.TrackForSerialization (provider, SerializerKind.DataContractSerializer); + Context.SerializationMarker.TrackForSerialization (provider, SerializerKind.DataContractSerializer); if (serializedFor.HasFlag (SerializerKind.XmlSerializer)) - _context.SerializationMarker.TrackForSerialization (provider, SerializerKind.XmlSerializer); + Context.SerializationMarker.TrackForSerialization (provider, SerializerKind.XmlSerializer); } static bool IsPreservedSerializationAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out SerializerKind serializerKind) diff --git a/src/linker/Linker.Steps/LinkAttributesParser.cs b/src/linker/Linker.Steps/LinkAttributesParser.cs index df4189e8d..b3d64a05e 100644 --- a/src/linker/Linker.Steps/LinkAttributesParser.cs +++ b/src/linker/Linker.Steps/LinkAttributesParser.cs @@ -10,8 +10,6 @@ using System.Text; using System.Xml.XPath; using Mono.Cecil; -#nullable enable - namespace Mono.Linker.Steps { public class LinkAttributesParser : ProcessLinkerXmlBase @@ -35,7 +33,7 @@ namespace Mono.Linker.Steps ProcessXml (stripLinkAttributes, _context.IgnoreLinkAttributes); } - CustomAttribute[] ProcessAttributes (XPathNavigator nav, ICustomAttributeProvider provider) + CustomAttribute[]? ProcessAttributes (XPathNavigator nav, ICustomAttributeProvider provider) { var builder = new ArrayBuilder<CustomAttribute> (); foreach (XPathNavigator argumentNav in nav.SelectChildren ("attribute", string.Empty)) { @@ -278,8 +276,7 @@ namespace Mono.Linker.Steps if (!typeref.IsTypeOf ("System", "Type")) goto default; - TypeReference type = _context.TypeNameResolver.ResolveTypeName (svalue, memberWithAttribute, out _); - if (type == null) { + if (!_context.TypeNameResolver.TryResolveTypeName (svalue, memberWithAttribute, out TypeReference? type, out _)) { _context.LogError ($"Could not resolve custom attribute type value '{svalue}'.", 1044, origin: GetMessageOriginForPosition (nav)); return null; } @@ -297,8 +294,7 @@ namespace Mono.Linker.Steps if (string.IsNullOrEmpty (typeName)) typeName = "System.String"; - TypeReference typeref = _context.TypeNameResolver.ResolveTypeName (typeName, memberWithAttribute, out _); - if (typeref == null) { + if (!_context.TypeNameResolver.TryResolveTypeName (typeName, memberWithAttribute, out TypeReference? typeref, out _)) { _context.LogError ($"The type '{typeName}' used with attribute value '{nav.Value}' could not be found.", 1041, origin: GetMessageOriginForPosition (nav)); return null; } @@ -368,7 +364,7 @@ namespace Mono.Linker.Steps if (string.IsNullOrEmpty (assemblyName)) { attributeType = _context.GetType (attributeFullName); } else { - AssemblyDefinition assembly; + AssemblyDefinition? assembly; try { assembly = _context.TryResolve (AssemblyNameReference.Parse (assemblyName)); if (assembly == null) { diff --git a/src/linker/Linker.Steps/MarkScopeStack.cs b/src/linker/Linker.Steps/MarkScopeStack.cs index 11d8f5d5b..60ff98722 100644 --- a/src/linker/Linker.Steps/MarkScopeStack.cs +++ b/src/linker/Linker.Steps/MarkScopeStack.cs @@ -40,7 +40,7 @@ namespace Mono.Linker.Steps // we will store the suppression context in the SuppressionContextMember. // For code which is not compiler generated the suppression context // is the same as the message's origin member. - IMemberDefinition suppressionContextMember = _scopeStack.GetSuppressionContext (origin.Provider); + IMemberDefinition? suppressionContextMember = _scopeStack.GetSuppressionContext (origin.Provider); _scopeStack.Push (new Scope (new MessageOrigin (origin, suppressionContextMember))); } @@ -137,7 +137,7 @@ namespace Mono.Linker.Steps [Conditional ("DEBUG")] public void AssertIsEmpty () => Debug.Assert (_scopeStack.Count == 0); - IMemberDefinition GetSuppressionContext (ICustomAttributeProvider provider) + IMemberDefinition? GetSuppressionContext (ICustomAttributeProvider? provider) { if (provider is not IMemberDefinition sourceMember) return null; diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs index dec6fd1e3..524c9195e 100644 --- a/src/linker/Linker.Steps/MarkStep.cs +++ b/src/linker/Linker.Steps/MarkStep.cs @@ -45,7 +45,14 @@ namespace Mono.Linker.Steps public partial class MarkStep : IStep { - protected LinkContext _context; + LinkContext? _context; + protected LinkContext Context { + get { + Debug.Assert (_context != null); + return _context; + } + } + protected Queue<(MethodDefinition, DependencyInfo, MarkScopeStack.Scope)> _methods; protected List<(MethodDefinition, MarkScopeStack.Scope)> _virtual_methods; protected Queue<AttributeProviderPair> _assemblyLevelAttributes; @@ -57,14 +64,35 @@ namespace Mono.Linker.Steps protected List<(MethodBody, MarkScopeStack.Scope)> _unreachableBodies; readonly List<(TypeDefinition Type, MethodBody Body, Instruction Instr)> _pending_isinst_instr; - UnreachableBlocksOptimizer _unreachableBlocksOptimizer; - MarkStepContext _markContext; + UnreachableBlocksOptimizer? _unreachableBlocksOptimizer; + UnreachableBlocksOptimizer UnreachableBlocksOptimizer { + get { + Debug.Assert (_unreachableBlocksOptimizer != null); + return _unreachableBlocksOptimizer; + } + } + MarkStepContext? _markContext; + MarkStepContext MarkContext { + get { + Debug.Assert (_markContext != null); + return _markContext; + } + } readonly HashSet<TypeDefinition> _entireTypesMarked; - DynamicallyAccessedMembersTypeHierarchy _dynamicallyAccessedMembersTypeHierarchy; - MarkScopeStack _scopeStack; + DynamicallyAccessedMembersTypeHierarchy? _dynamicallyAccessedMembersTypeHierarchy; + MarkScopeStack? _scopeStack; + MarkScopeStack ScopeStack { + get { + Debug.Assert (_scopeStack != null); + return _scopeStack; + } + } internal DynamicallyAccessedMembersTypeHierarchy DynamicallyAccessedMembersTypeHierarchy { - get => _dynamicallyAccessedMembersTypeHierarchy; + get { + Debug.Assert (_dynamicallyAccessedMembersTypeHierarchy != null); + return _dynamicallyAccessedMembersTypeHierarchy; + } } #if DEBUG @@ -197,9 +225,9 @@ namespace Mono.Linker.Steps _entireTypesMarked = new HashSet<TypeDefinition> (); } - public AnnotationStore Annotations => _context.Annotations; - public MarkingHelpers MarkingHelpers => _context.MarkingHelpers; - public Tracer Tracer => _context.Tracer; + public AnnotationStore Annotations => Context.Annotations; + public MarkingHelpers MarkingHelpers => Context.MarkingHelpers; + public Tracer Tracer => Context.Tracer; public virtual void Process (LinkContext context) { @@ -217,7 +245,7 @@ namespace Mono.Linker.Steps void Initialize () { InitializeCorelibAttributeXml (); - _context.Pipeline.InitializeMarkHandlers (_context, _markContext); + Context.Pipeline.InitializeMarkHandlers (Context, MarkContext); ProcessMarkedPending (); } @@ -228,18 +256,18 @@ namespace Mono.Linker.Steps // corelib attribute XML can contain modifications to other assemblies. // We could just mark it here, but the attribute processing isn't necessarily tied to marking, // so this would rely on implementation details of corelib. - var coreLib = _context.TryResolve (PlatformAssemblies.CoreLib); + var coreLib = Context.TryResolve (PlatformAssemblies.CoreLib); if (coreLib == null) return; - var xmlInfo = EmbeddedXmlInfo.ProcessAttributes (coreLib, _context); + var xmlInfo = EmbeddedXmlInfo.ProcessAttributes (coreLib, Context); if (xmlInfo == null) return; // Because the attribute XML can reference other assemblies, they must go in the global store, // instead of the per-assembly stores. foreach (var (provider, annotations) in xmlInfo.CustomAttributes) - _context.CustomAttributes.PrimaryAttributeInfo.AddCustomAttributes (provider, annotations); + Context.CustomAttributes.PrimaryAttributeInfo.AddCustomAttributes (provider, annotations); } void Complete () @@ -258,7 +286,7 @@ namespace Mono.Linker.Steps Debug.Assert (attr.Provider is ModuleDefinition or AssemblyDefinition); var assembly = (provider is ModuleDefinition module) ? module.Assembly : provider as AssemblyDefinition; - using var assemblyScope = _scopeStack.PushScope (new MessageOrigin (assembly)); + using var assemblyScope = ScopeStack.PushScope (new MessageOrigin (assembly)); if (!Annotations.IsMarked (attr.Attribute) && IsInternalsVisibleAttributeAssemblyMarked (attr.Attribute)) { MarkCustomAttribute (attr.Attribute, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, attr.Provider)); @@ -277,7 +305,7 @@ namespace Mono.Linker.Steps return false; } - var assembly = _context.GetLoadedAssembly (an.Name!); + var assembly = Context.GetLoadedAssembly (an.Name!); if (assembly == null) return false; @@ -323,7 +351,7 @@ namespace Mono.Linker.Steps // Prevent cases where there's nothing on the stack (can happen when marking entire assemblies) // In which case we would generate warnings with no source (hard to debug) - using var _ = _scopeStack.CurrentScope.Origin.Provider == null ? _scopeStack.PushScope (new MessageOrigin (type)) : null; + using var _ = ScopeStack.CurrentScope.Origin.Provider == null ? ScopeStack.PushScope (new MessageOrigin (type)) : null; if (!_entireTypesMarked.Add (type)) return; @@ -389,33 +417,33 @@ namespace Mono.Linker.Steps // Fully mark any assemblies with copy/save action. // Unresolved references could get the copy/save action if this is the default action. - bool scanReferences = IsFullyPreservedAction (_context.TrimAction) || IsFullyPreservedAction (_context.DefaultAction); + bool scanReferences = IsFullyPreservedAction (Context.TrimAction) || IsFullyPreservedAction (Context.DefaultAction); if (!scanReferences) { // Unresolved references could get the copy/save action if it was set explicitly // for some referenced assembly that has not been resolved yet - foreach (var (assemblyName, action) in _context.Actions) { + foreach (var (assemblyName, action) in Context.Actions) { if (!IsFullyPreservedAction (action)) continue; - var assembly = _context.GetLoadedAssembly (assemblyName); + var assembly = Context.GetLoadedAssembly (assemblyName); if (assembly == null) { scanReferences = true; break; } // The action should not change from the explicit command-line action - Debug.Assert (_context.Annotations.GetAction (assembly) == action); + Debug.Assert (Context.Annotations.GetAction (assembly) == action); } } // Beware: this works on loaded assemblies, not marked assemblies, so it should not be tied to marking. // We could further optimize this to only iterate through assemblies if the last mark iteration loaded // a new assembly, since this is the only way that the set we need to consider could have changed. - var assembliesToCheck = scanReferences ? _context.GetReferencedAssemblies ().ToArray () : _context.GetAssemblies (); + var assembliesToCheck = scanReferences ? Context.GetReferencedAssemblies ().ToArray () : Context.GetAssemblies (); bool markedNewAssembly = false; foreach (var assembly in assembliesToCheck) { - var action = _context.Annotations.GetAction (assembly); + var action = Context.Annotations.GetAction (assembly); if (!IsFullyPreservedAction (action)) continue; if (!Annotations.IsProcessed (assembly)) @@ -444,7 +472,7 @@ namespace Mono.Linker.Steps bool ProcessMarkedPending () { - using var emptyScope = _scopeStack.PushScope (new MessageOrigin (null as ICustomAttributeProvider)); + using var emptyScope = ScopeStack.PushScope (new MessageOrigin (null as ICustomAttributeProvider)); bool marked = false; foreach (var pending in Annotations.GetMarkedPending ()) { @@ -501,7 +529,7 @@ namespace Mono.Linker.Steps Instruction new_instr = Instruction.Create (OpCodes.Pop); ilProcessor.Replace (instr, new_instr); - _context.LogMessage ($"Removing typecheck of '{type.FullName}' inside '{item.Body.Method.GetDisplayName ()}' method."); + Context.LogMessage ($"Removing typecheck of '{type.FullName}' inside '{item.Body.Method.GetDisplayName ()}' method."); } } @@ -532,7 +560,7 @@ namespace Mono.Linker.Steps void ProcessVirtualMethods () { foreach ((MethodDefinition method, MarkScopeStack.Scope scope) in _virtual_methods) { - using (_scopeStack.PushScope (scope)) + using (ScopeStack.PushScope (scope)) ProcessVirtualMethod (method); } } @@ -551,7 +579,7 @@ namespace Mono.Linker.Steps if (!Annotations.IsInstantiated (type) && !Annotations.IsRelevantToVariantCasting (type)) continue; - using (_scopeStack.PushScope (scope)) + using (ScopeStack.PushScope (scope)) MarkInterfaceImplementations (type); } } @@ -559,7 +587,7 @@ namespace Mono.Linker.Steps void DiscoverDynamicCastableImplementationInterfaces () { // We could potentially avoid loading all references here: https://github.com/dotnet/linker/issues/1788 - foreach (var assembly in _context.GetReferencedAssemblies ().ToArray ()) { + foreach (var assembly in Context.GetReferencedAssemblies ().ToArray ()) { switch (Annotations.GetAction (assembly)) { // We only need to search assemblies where we don't mark everything // Assemblies that are fully marked already mark these types. @@ -610,7 +638,7 @@ namespace Mono.Linker.Steps if (Annotations.IsMarked (iface.InterfaceType)) { // We only need to mark the type definition because the linker will ensure that all marked implemented interfaces and used method implementations // will be marked on this type as well. - MarkType (type, new DependencyInfo (DependencyKind.DynamicInterfaceCastableImplementation, iface.InterfaceType), new MessageOrigin (_context.TryResolve (iface.InterfaceType))); + MarkType (type, new DependencyInfo (DependencyKind.DynamicInterfaceCastableImplementation, iface.InterfaceType), new MessageOrigin (Context.TryResolve (iface.InterfaceType))); _dynamicInterfaceCastableImplementationTypes.RemoveAt (i--); break; @@ -624,7 +652,7 @@ namespace Mono.Linker.Steps for (int i = 0; i < _unreachableBodies.Count; i++) { (var body, var scope) = _unreachableBodies[i]; if (Annotations.IsInstantiated (body.Method.DeclaringType)) { - using (_scopeStack.PushScope (scope)) + using (ScopeStack.PushScope (scope)) MarkMethodBody (body); _unreachableBodies.RemoveAt (i--); @@ -634,7 +662,7 @@ namespace Mono.Linker.Steps void ProcessVirtualMethod (MethodDefinition method) { - _context.Annotations.EnqueueVirtualMethod (method); + Context.Annotations.EnqueueVirtualMethod (method); var overrides = Annotations.GetOverrides (method); if (overrides != null) { @@ -671,16 +699,16 @@ namespace Mono.Linker.Steps return; // Interface static veitual methods will be abstract and will also by pass this check to get marked - if (!isInstantiated && !@base.IsAbstract && _context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method)) + if (!isInstantiated && !@base.IsAbstract && Context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method)) return; // Only track instantiations if override removal is enabled and the type is instantiated. // If it's disabled, all overrides are kept, so there's no instantiation site to blame. - if (_context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method) && isInstantiated) { + if (Context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method) && isInstantiated) { MarkMethod (method, new DependencyInfo (DependencyKind.OverrideOnInstantiatedType, method.DeclaringType)); } else { // If the optimization is disabled or it's an abstract type, we just mark it as a normal override. - Debug.Assert (!_context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method) || @base.IsAbstract); + Debug.Assert (!Context.IsOptimizationEnabled (CodeOptimizations.OverrideRemoval, method) || @base.IsAbstract); MarkMethod (method, new DependencyInfo (DependencyKind.Override, @base)); } @@ -703,7 +731,7 @@ namespace Mono.Linker.Steps var interfaceType = overrideInformation.InterfaceType; var overrideDeclaringType = overrideInformation.Override.DeclaringType; - if (!IsInterfaceImplementationMarkedRecursively (overrideDeclaringType, interfaceType)) + if (interfaceType == null || !IsInterfaceImplementationMarkedRecursively (overrideDeclaringType, interfaceType)) return true; return false; @@ -713,7 +741,7 @@ namespace Mono.Linker.Steps { if (type.HasInterfaces) { foreach (var intf in type.Interfaces) { - TypeDefinition resolvedInterface = _context.Resolve (intf.InterfaceType); + TypeDefinition? resolvedInterface = Context.Resolve (intf.InterfaceType); if (resolvedInterface == null) continue; @@ -732,7 +760,7 @@ namespace Mono.Linker.Steps if (typeToExamine.HasInterfaces) { foreach (var iface in typeToExamine.Interfaces) { - var resolved = _context.TryResolve (iface.InterfaceType); + var resolved = Context.TryResolve (iface.InterfaceType); if (resolved == null) continue; @@ -759,7 +787,7 @@ namespace Mono.Linker.Steps if (spec.MarshalInfo is CustomMarshalInfo marshaler) { MarkType (marshaler.ManagedType, reason); - TypeDefinition type = _context.Resolve (marshaler.ManagedType); + TypeDefinition? type = Context.Resolve (marshaler.ManagedType); if (type != null) { MarkICustomMarshalerMethods (type, in reason); MarkCustomMarshalerGetInstance (type, in reason); @@ -771,18 +799,18 @@ namespace Mono.Linker.Steps { if (provider.HasCustomAttributes) { bool providerInLinkedAssembly = Annotations.GetAction (CustomAttributeSource.GetAssemblyFromCustomAttributeProvider (provider)) == AssemblyAction.Link; - bool markOnUse = _context.KeepUsedAttributeTypesOnly && providerInLinkedAssembly; + bool markOnUse = Context.KeepUsedAttributeTypesOnly && providerInLinkedAssembly; foreach (CustomAttribute ca in provider.CustomAttributes) { if (ProcessLinkerSpecialAttribute (ca, provider, reason)) continue; if (markOnUse) { - _lateMarkedAttributes.Enqueue ((new AttributeProviderPair (ca, provider), reason, _scopeStack.CurrentScope)); + _lateMarkedAttributes.Enqueue ((new AttributeProviderPair (ca, provider), reason, ScopeStack.CurrentScope)); continue; } - var resolvedAttributeType = _context.Resolve (ca.AttributeType); + var resolvedAttributeType = Context.Resolve (ca.AttributeType); if (resolvedAttributeType == null) { continue; } @@ -799,14 +827,14 @@ namespace Mono.Linker.Steps return; IMemberDefinition providerMember = (IMemberDefinition) provider; ; - using (_scopeStack.PushScope (new MessageOrigin (providerMember))) - foreach (var dynamicDependency in _context.Annotations.GetLinkerAttributes<DynamicDependency> (providerMember)) + using (ScopeStack.PushScope (new MessageOrigin (providerMember))) + foreach (var dynamicDependency in Context.Annotations.GetLinkerAttributes<DynamicDependency> (providerMember)) MarkDynamicDependency (dynamicDependency, providerMember); } bool IsAttributeRemoved (CustomAttribute ca, TypeDefinition attributeType) { - foreach (var attr in _context.Annotations.GetLinkerAttributes<RemoveAttributeInstancesAttribute> (attributeType)) { + foreach (var attr in Context.Annotations.GetLinkerAttributes<RemoveAttributeInstancesAttribute> (attributeType)) { var args = attr.Arguments; if (args.Length == 0) return true; @@ -850,7 +878,7 @@ namespace Mono.Linker.Steps if (isPreserveDependency) MarkUserDependency (member, ca); - if (_context.CanApplyOptimization (CodeOptimizations.RemoveDynamicDependencyAttribute, member.DeclaringType.Module.Assembly)) { + if (Context.CanApplyOptimization (CodeOptimizations.RemoveDynamicDependencyAttribute, member.DeclaringType.Module.Assembly)) { // Record the custom attribute so that it has a reason, without actually marking it. Tracer.AddDirectDependency (ca, reason, marked: false); } else { @@ -863,11 +891,11 @@ namespace Mono.Linker.Steps void MarkDynamicDependency (DynamicDependency dynamicDependency, IMemberDefinition context) { Debug.Assert (context is MethodDefinition || context is FieldDefinition); - AssemblyDefinition assembly; + AssemblyDefinition? assembly; if (dynamicDependency.AssemblyName != null) { - assembly = _context.TryResolve (dynamicDependency.AssemblyName); + assembly = Context.TryResolve (dynamicDependency.AssemblyName); if (assembly == null) { - _context.LogWarning ($"Unresolved assembly '{dynamicDependency.AssemblyName}' in 'DynamicDependencyAttribute'.", 2035, _scopeStack.CurrentScope.Origin); + Context.LogWarning ($"Unresolved assembly '{dynamicDependency.AssemblyName}' in 'DynamicDependencyAttribute'.", 2035, ScopeStack.CurrentScope.Origin); return; } } else { @@ -875,41 +903,41 @@ namespace Mono.Linker.Steps Debug.Assert (assembly != null); } - TypeDefinition type; + TypeDefinition? type; if (dynamicDependency.TypeName is string typeName) { - type = DocumentationSignatureParser.GetTypeByDocumentationSignature (assembly, typeName, _context); + type = DocumentationSignatureParser.GetTypeByDocumentationSignature (assembly, typeName, Context); if (type == null) { - _context.LogWarning ($"Unresolved type '{typeName}' in 'DynamicDependencyAttribute'.", 2036, _scopeStack.CurrentScope.Origin); + Context.LogWarning ($"Unresolved type '{typeName}' in 'DynamicDependencyAttribute'.", 2036, ScopeStack.CurrentScope.Origin); return; } MarkingHelpers.MarkMatchingExportedType (type, assembly, new DependencyInfo (DependencyKind.DynamicDependency, type)); } else if (dynamicDependency.Type is TypeReference typeReference) { - type = _context.TryResolve (typeReference); + type = Context.TryResolve (typeReference); if (type == null) { - _context.LogWarning ($"Unresolved type '{typeReference}' in 'DynamicDependencyAtribute'.", 2036, _scopeStack.CurrentScope.Origin); + Context.LogWarning ($"Unresolved type '{typeReference}' in 'DynamicDependencyAtribute'.", 2036, ScopeStack.CurrentScope.Origin); return; } } else { - type = _context.TryResolve (context.DeclaringType); + type = Context.TryResolve (context.DeclaringType); if (type == null) { - _context.LogWarning ($"Unresolved type '{context.DeclaringType}' in 'DynamicDependencyAttribute'.", 2036, context); + Context.LogWarning ($"Unresolved type '{context.DeclaringType}' in 'DynamicDependencyAttribute'.", 2036, context); return; } } IEnumerable<IMetadataTokenProvider> members; if (dynamicDependency.MemberSignature is string memberSignature) { - members = DocumentationSignatureParser.GetMembersByDocumentationSignature (type, memberSignature, _context, acceptName: true); + members = DocumentationSignatureParser.GetMembersByDocumentationSignature (type, memberSignature, Context, acceptName: true); if (!members.Any ()) { - _context.LogWarning ($"No members were resolved for '{memberSignature}'.", 2037, _scopeStack.CurrentScope.Origin); + Context.LogWarning ($"No members were resolved for '{memberSignature}'.", 2037, ScopeStack.CurrentScope.Origin); return; } } else { var memberTypes = dynamicDependency.MemberTypes; - members = type.GetDynamicallyAccessedMembers (_context, memberTypes); + members = type.GetDynamicallyAccessedMembers (Context, memberTypes); if (!members.Any ()) { - _context.LogWarning ($"No members were resolved for '{memberTypes}'.", 2037, _scopeStack.CurrentScope.Origin); + Context.LogWarning ($"No members were resolved for '{memberTypes}'.", 2037, ScopeStack.CurrentScope.Origin); return; } } @@ -950,17 +978,17 @@ namespace Mono.Linker.Steps protected virtual void MarkUserDependency (IMemberDefinition context, CustomAttribute ca) { - _context.LogWarning ($"'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead.", 2033, context); + Context.LogWarning ($"'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead.", 2033, context); - if (!DynamicDependency.ShouldProcess (_context, ca)) + if (!DynamicDependency.ShouldProcess (Context, ca)) return; - AssemblyDefinition assembly; + AssemblyDefinition? assembly; var args = ca.ConstructorArguments; if (args.Count >= 3 && args[2].Value is string assemblyName) { - assembly = _context.TryResolve (assemblyName); + assembly = Context.TryResolve (assemblyName); if (assembly == null) { - _context.LogWarning ( + Context.LogWarning ( $"Could not resolve dependency assembly '{assemblyName}' specified in a 'PreserveDependency' attribute.", 2003, context); return; } @@ -968,24 +996,24 @@ namespace Mono.Linker.Steps assembly = null; } - TypeDefinition td; + TypeDefinition? td; if (args.Count >= 2 && args[1].Value is string typeName) { AssemblyDefinition assemblyDef = assembly ?? ((MemberReference) context).Module.Assembly; - td = _context.TryResolve (assemblyDef, typeName); + td = Context.TryResolve (assemblyDef, typeName); if (td == null) { - _context.LogWarning ( + Context.LogWarning ( $"Could not resolve dependency type '{typeName}' specified in a 'PreserveDependency' attribute.", 2004, context); return; } MarkingHelpers.MarkMatchingExportedType (td, assemblyDef, new DependencyInfo (DependencyKind.PreservedDependency, ca)); } else { - td = _context.TryResolve (context.DeclaringType); + td = context.DeclaringType; } - string member = null; - string[] signature = null; + string? member = null; + string[]? signature = null; if (args.Count >= 1 && args[0].Value is string memberSignature) { memberSignature = memberSignature.Replace (" ", ""); var sign_start = memberSignature.IndexOf ('('); @@ -1004,17 +1032,19 @@ namespace Mono.Linker.Steps return; } - if (MarkDependencyMethod (td, member, signature, new DependencyInfo (DependencyKind.PreservedDependency, ca))) - return; + if (member != null) { + if (MarkDependencyMethod (td, member, signature, new DependencyInfo (DependencyKind.PreservedDependency, ca))) + return; - if (MarkNamedField (td, member, new DependencyInfo (DependencyKind.PreservedDependency, ca))) - return; + if (MarkNamedField (td, member, new DependencyInfo (DependencyKind.PreservedDependency, ca))) + return; + } - _context.LogWarning ( + Context.LogWarning ( $"Could not resolve dependency member '{member}' declared in type '{td.GetDisplayName ()}' specified in a 'PreserveDependency' attribute.", 2005, context); } - bool MarkDependencyMethod (TypeDefinition type, string name, string[] signature, in DependencyInfo reason) + bool MarkDependencyMethod (TypeDefinition type, string name, string[]? signature, in DependencyInfo reason) { bool marked = false; @@ -1079,7 +1109,7 @@ namespace Mono.Linker.Steps MarkCustomAttributeArguments (ca); TypeReference constructor_type = ca.Constructor.DeclaringType; - TypeDefinition type = _context.Resolve (constructor_type); + TypeDefinition? type = Context.Resolve (constructor_type); if (type == null) { return; @@ -1093,7 +1123,7 @@ namespace Mono.Linker.Steps { var attr_type = ca.AttributeType; - if (_context.KeepUsedAttributeTypesOnly) { + if (Context.KeepUsedAttributeTypesOnly) { switch (attr_type.FullName) { // These are required by the runtime case "System.ThreadStaticAttribute": @@ -1108,7 +1138,7 @@ namespace Mono.Linker.Steps return true; } - TypeDefinition type = _context.Resolve (attr_type); + TypeDefinition? type = Context.Resolve (attr_type); if (type is null || !Annotations.IsMarked (type)) return false; } @@ -1121,7 +1151,7 @@ namespace Mono.Linker.Steps if (Annotations.HasPreservedStaticCtor (type)) return false; - if (type.IsBeforeFieldInit && _context.IsOptimizationEnabled (CodeOptimizations.BeforeFieldInit, type)) + if (type.IsBeforeFieldInit && Context.IsOptimizationEnabled (CodeOptimizations.BeforeFieldInit, type)) return false; return true; @@ -1182,7 +1212,7 @@ namespace Mono.Linker.Steps protected virtual void MarkSecurityAttribute (SecurityAttribute sa, in DependencyInfo reason) { TypeReference security_type = sa.AttributeType; - TypeDefinition type = _context.Resolve (security_type); + TypeDefinition? type = Context.Resolve (security_type); if (type == null) { return; } @@ -1205,26 +1235,27 @@ namespace Mono.Linker.Steps protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca, in DependencyInfo reason) { - PropertyDefinition property = GetProperty (attribute, namedArgument.Name); + PropertyDefinition? property = GetProperty (attribute, namedArgument.Name); if (property != null) MarkMethod (property.SetMethod, reason); MarkCustomAttributeArgument (namedArgument.Argument, ca); - if (property != null && _context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (property.SetMethod)) { - var scanner = new ReflectionMethodBodyScanner (_context, this, _scopeStack); + if (property != null && Context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (property.SetMethod)) { + var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack); scanner.ProcessAttributeDataflow (property.SetMethod, new List<CustomAttributeArgument> { namedArgument.Argument }); } } - PropertyDefinition GetProperty (TypeDefinition type, string propertyname) + PropertyDefinition? GetProperty (TypeDefinition inputType, string propertyname) { + TypeDefinition? type = inputType; while (type != null) { - PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname); + PropertyDefinition? property = type.Properties.FirstOrDefault (p => p.Name == propertyname); if (property != null) return property; - type = _context.TryResolve (type.BaseType); + type = Context.TryResolve (type.BaseType); } return null; @@ -1241,39 +1272,41 @@ namespace Mono.Linker.Steps protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute, ICustomAttribute ca) { - FieldDefinition field = GetField (attribute, namedArgument.Name); + FieldDefinition? field = GetField (attribute, namedArgument.Name); if (field != null) MarkField (field, new DependencyInfo (DependencyKind.CustomAttributeField, ca)); MarkCustomAttributeArgument (namedArgument.Argument, ca); - if (field != null && _context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (field)) { - var scanner = new ReflectionMethodBodyScanner (_context, this, _scopeStack); + if (field != null && Context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (field)) { + var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack); scanner.ProcessAttributeDataflow (field, namedArgument.Argument); } } - FieldDefinition GetField (TypeDefinition type, string fieldname) + FieldDefinition? GetField (TypeDefinition inputType, string fieldname) { + TypeDefinition? type = inputType; while (type != null) { - FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname); + FieldDefinition? field = type.Fields.FirstOrDefault (f => f.Name == fieldname); if (field != null) return field; - type = _context.TryResolve (type.BaseType); + type = Context.TryResolve (type.BaseType); } return null; } - MethodDefinition GetMethodWithNoParameters (TypeDefinition type, string methodname) + MethodDefinition? GetMethodWithNoParameters (TypeDefinition inputType, string methodname) { + TypeDefinition? type = inputType; while (type != null) { - MethodDefinition method = type.Methods.FirstOrDefault (m => m.Name == methodname && !m.HasParameters); + MethodDefinition? method = type.Methods.FirstOrDefault (m => m.Name == methodname && !m.HasParameters); if (method != null) return method; - type = _context.TryResolve (type.BaseType); + type = Context.TryResolve (type.BaseType); } return null; @@ -1287,9 +1320,9 @@ namespace Mono.Linker.Steps foreach (var argument in ca.ConstructorArguments) MarkCustomAttributeArgument (argument, ca); - var resolvedConstructor = _context.TryResolve (ca.Constructor); - if (resolvedConstructor != null && _context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (resolvedConstructor)) { - var scanner = new ReflectionMethodBodyScanner (_context, this, _scopeStack); + var resolvedConstructor = Context.TryResolve (ca.Constructor); + if (resolvedConstructor != null && Context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (resolvedConstructor)) { + var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack); scanner.ProcessAttributeDataflow (resolvedConstructor, ca.ConstructorArguments); } } @@ -1340,20 +1373,20 @@ namespace Mono.Linker.Steps if (CheckProcessed (assembly)) return; - using var assemblyScope = _scopeStack.PushScope (new MessageOrigin (assembly)); + using var assemblyScope = ScopeStack.PushScope (new MessageOrigin (assembly)); - EmbeddedXmlInfo.ProcessDescriptors (assembly, _context); + EmbeddedXmlInfo.ProcessDescriptors (assembly, Context); - foreach (Action<AssemblyDefinition> handleMarkAssembly in _markContext.MarkAssemblyActions) + foreach (Action<AssemblyDefinition> handleMarkAssembly in MarkContext.MarkAssemblyActions) handleMarkAssembly (assembly); // Security attributes do not respect the attributes XML - if (_context.StripSecurity) - RemoveSecurity.ProcessAssembly (assembly, _context); + if (Context.StripSecurity) + RemoveSecurity.ProcessAssembly (assembly, Context); - MarkExportedTypesTarget.ProcessAssembly (assembly, _context); + MarkExportedTypesTarget.ProcessAssembly (assembly, Context); - if (ProcessReferencesStep.IsFullyPreservedAction (_context.Annotations.GetAction (assembly))) { + if (ProcessReferencesStep.IsFullyPreservedAction (Context.Annotations.GetAction (assembly))) { MarkEntireAssembly (assembly); return; } @@ -1426,7 +1459,7 @@ namespace Mono.Linker.Steps void ProcessModuleType (AssemblyDefinition assembly) { // The <Module> type may have an initializer, in which case we want to keep it. - TypeDefinition moduleType = assembly.MainModule.Types.FirstOrDefault (t => t.MetadataToken.RID == 1); + TypeDefinition? moduleType = assembly.MainModule.Types.FirstOrDefault (t => t.MetadataToken.RID == 1); if (moduleType != null && moduleType.HasMethods) MarkType (moduleType, new DependencyInfo (DependencyKind.TypeInAssembly, assembly)); } @@ -1451,9 +1484,9 @@ namespace Mono.Linker.Steps Debug.Assert (provider is ModuleDefinition or AssemblyDefinition); var assembly = (provider is ModuleDefinition module) ? module.Assembly : provider as AssemblyDefinition; - using var assemblyScope = _scopeStack.PushScope (new MessageOrigin (assembly)); + using var assemblyScope = ScopeStack.PushScope (new MessageOrigin (assembly)); - var resolved = _context.Resolve (customAttribute.Constructor); + var resolved = Context.Resolve (customAttribute.Constructor); if (resolved == null) { continue; } @@ -1474,12 +1507,18 @@ namespace Mono.Linker.Steps string attributeFullName = customAttribute.Constructor.DeclaringType.FullName; switch (attributeFullName) { - case "System.Diagnostics.DebuggerDisplayAttribute": - MarkTypeWithDebuggerDisplayAttribute (GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider), customAttribute); - break; - case "System.Diagnostics.DebuggerTypeProxyAttribute": - MarkTypeWithDebuggerTypeProxyAttribute (GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider), customAttribute); - break; + case "System.Diagnostics.DebuggerDisplayAttribute": { + TypeDefinition? targetType = GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider); + if (targetType != null) + MarkTypeWithDebuggerDisplayAttribute (targetType, customAttribute); + break; + } + case "System.Diagnostics.DebuggerTypeProxyAttribute": { + TypeDefinition? targetType = GetDebuggerAttributeTargetType (assemblyLevelAttribute.Attribute, (AssemblyDefinition) assemblyLevelAttribute.Provider); + if (targetType != null) + MarkTypeWithDebuggerTypeProxyAttribute (targetType, customAttribute); + break; + } } } @@ -1504,7 +1543,7 @@ namespace Mono.Linker.Steps var customAttribute = attributeProviderPair.Attribute; var provider = attributeProviderPair.Provider; - var resolved = _context.Resolve (customAttribute.Constructor); + var resolved = Context.Resolve (customAttribute.Constructor); if (resolved == null) { continue; } @@ -1515,7 +1554,7 @@ namespace Mono.Linker.Steps } markOccurred = true; - using (_scopeStack.PushScope (scope)) { + using (ScopeStack.PushScope (scope)) { MarkCustomAttribute (customAttribute, reason); MarkSpecialCustomAttributeDependencies (customAttribute, provider); } @@ -1534,13 +1573,13 @@ namespace Mono.Linker.Steps Debug.Assert (reason.Kind == DependencyKind.FieldAccess || reason.Kind == DependencyKind.Ldtoken); // Blame the field reference (without actually marking) on the original reason. Tracer.AddDirectDependency (reference, reason, marked: false); - MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference), new MessageOrigin (_context.TryResolve (reference))); + MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference), new MessageOrigin (Context.TryResolve (reference))); // Blame the field definition that we will resolve on the field reference. reason = new DependencyInfo (DependencyKind.FieldOnGenericInstance, reference); } - FieldDefinition field = _context.Resolve (reference); + FieldDefinition? field = Context.Resolve (reference); if (field == null) { return; @@ -1558,7 +1597,7 @@ namespace Mono.Linker.Steps // annotation on a type, not a callsite which uses the annotation. We always want to warn about // possible reflection access indicated by these annotations. - var type = _scopeStack.CurrentScope.Origin.Provider as TypeDefinition; + var type = ScopeStack.CurrentScope.Origin.Provider as TypeDefinition; Debug.Assert (type != null); static bool IsDeclaredWithinType (IMemberDefinition member, TypeDefinition type) @@ -1571,12 +1610,12 @@ namespace Mono.Linker.Steps } var reportOnMember = IsDeclaredWithinType (member, type); - var memberScope = reportOnMember ? _scopeStack.PushScope (new MessageOrigin (member)) : null; + var memberScope = reportOnMember ? ScopeStack.PushScope (new MessageOrigin (member)) : null; try { - var origin = _scopeStack.CurrentScope.Origin; + var origin = ScopeStack.CurrentScope.Origin; - if (Annotations.DoesMemberRequireUnreferencedCode (member, out RequiresUnreferencedCodeAttribute requiresUnreferencedCodeAttribute)) { + if (Annotations.DoesMemberRequireUnreferencedCode (member, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCodeAttribute)) { var message = string.Format ( "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.{2}{3}", type.GetDisplayName (), @@ -1584,16 +1623,16 @@ namespace Mono.Linker.Steps MessageFormat.FormatRequiresAttributeMessageArg (requiresUnreferencedCodeAttribute.Message), MessageFormat.FormatRequiresAttributeMessageArg (requiresUnreferencedCodeAttribute.Url)); var code = reportOnMember ? 2112 : 2113; - _context.LogWarning (message, code, origin, MessageSubCategory.TrimAnalysis); + Context.LogWarning (message, code, origin, MessageSubCategory.TrimAnalysis); } - if (_context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (member)) { + if (Context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (member)) { var message = string.Format ( "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements.", type.GetDisplayName (), - (member as MemberReference).GetDisplayName ()); + ((MemberReference) member).GetDisplayName ()); var code = reportOnMember ? 2114 : 2115; - _context.LogWarning (message, code, origin, MessageSubCategory.TrimAnalysis); + Context.LogWarning (message, code, origin, MessageSubCategory.TrimAnalysis); } } finally { memberScope?.Dispose (); @@ -1614,21 +1653,21 @@ namespace Mono.Linker.Steps } if (reason.Kind != DependencyKind.DynamicallyAccessedMemberOnType && - Annotations.DoesFieldRequireUnreferencedCode (field, out RequiresUnreferencedCodeAttribute requiresUnreferencedCodeAttribute) && + Annotations.DoesFieldRequireUnreferencedCode (field, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCodeAttribute) && !ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode ()) - ReportRequiresUnreferencedCode (field.GetDisplayName (), requiresUnreferencedCodeAttribute, _scopeStack.CurrentScope.Origin); + ReportRequiresUnreferencedCode (field.GetDisplayName (), requiresUnreferencedCodeAttribute, ScopeStack.CurrentScope.Origin); switch (reason.Kind) { case DependencyKind.AccessedViaReflection: case DependencyKind.DynamicDependency: case DependencyKind.DynamicallyAccessedMember: case DependencyKind.InteropMethodDependency: - if (_context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (field) && + if (Context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (field) && !ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode ()) - _context.LogWarning ( + Context.LogWarning ( $"Field '{field.GetDisplayName ()}' with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field.", 2110, - _scopeStack.CurrentScope.Origin, + ScopeStack.CurrentScope.Origin, MessageSubCategory.TrimAnalysis); break; @@ -1643,7 +1682,7 @@ namespace Mono.Linker.Steps // Use the original scope for marking the declaring type - it provides better warning message location MarkType (field.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, field)); - using var fieldScope = _scopeStack.PushScope (new MessageOrigin (field)); + using var fieldScope = ScopeStack.PushScope (new MessageOrigin (field)); MarkType (field.FieldType, new DependencyInfo (DependencyKind.FieldType, field)); MarkCustomAttributes (field, new DependencyInfo (DependencyKind.CustomAttribute, field)); MarkMarshalSpec (field, new DependencyInfo (DependencyKind.FieldMarshalSpec, field)); @@ -1660,10 +1699,10 @@ namespace Mono.Linker.Steps if (!field.DeclaringType.IsValueType && !field.DeclaringType.IsAutoLayout) { // We also need to walk the base hierarchy because the offset of the field depends on the // layout of the base. - TypeDefinition typeWithFields = field.DeclaringType; + TypeDefinition? typeWithFields = field.DeclaringType; while (typeWithFields != null) { MarkImplicitlyUsedFields (typeWithFields); - typeWithFields = _context.TryResolve (typeWithFields.BaseType); + typeWithFields = Context.TryResolve (typeWithFields.BaseType); } } @@ -1685,8 +1724,8 @@ namespace Mono.Linker.Steps protected virtual bool IgnoreScope (IMetadataScope scope) { - AssemblyDefinition assembly = _context.Resolve (scope); - return Annotations.GetAction (assembly) != AssemblyAction.Link; + AssemblyDefinition? assembly = Context.Resolve (scope); + return assembly != null && Annotations.GetAction (assembly) != AssemblyAction.Link; } void MarkModule (ModuleDefinition module, DependencyInfo reason) @@ -1706,7 +1745,7 @@ namespace Mono.Linker.Steps if (!type.HasMethods) return; - if (_context.GetTargetRuntimeVersion () > TargetRuntimeVersion.NET5) + if (Context.GetTargetRuntimeVersion () > TargetRuntimeVersion.NET5) return; if (type.IsSerializable ()) { @@ -1717,7 +1756,7 @@ namespace Mono.Linker.Steps MarkMethodsIf (type.Methods, HasOnSerializeOrDeserializeAttribute, new DependencyInfo (DependencyKind.SerializationMethodForType, type)); } - protected internal virtual TypeDefinition MarkTypeVisibleToReflection (TypeReference type, TypeDefinition definition, in DependencyInfo reason) + protected internal virtual TypeDefinition? MarkTypeVisibleToReflection (TypeReference type, TypeDefinition definition, in DependencyInfo reason) { // If a type is visible to reflection, we need to stop doing optimization that could cause observable difference // in reflection APIs. This includes APIs like MakeGenericType (where variant castability of the produced type @@ -1776,7 +1815,7 @@ namespace Mono.Linker.Steps /// <param name="reference">The type reference to mark.</param> /// <param name="reason">The reason why the marking is occuring</param> /// <returns>The resolved type definition if the reference can be resolved</returns> - protected internal virtual TypeDefinition MarkType (TypeReference reference, DependencyInfo reason, MessageOrigin? origin = null) + protected internal virtual TypeDefinition? MarkType (TypeReference reference, DependencyInfo reason, MessageOrigin? origin = null) { #if DEBUG if (!_typeReasons.Contains (reason.Kind)) @@ -1785,7 +1824,7 @@ namespace Mono.Linker.Steps if (reference == null) return null; - using var localScope = origin.HasValue ? _scopeStack.PushScope (origin.Value) : null; + using var localScope = origin.HasValue ? ScopeStack.PushScope (origin.Value) : null; (reference, reason) = GetOriginalType (reference, reason); @@ -1795,7 +1834,7 @@ namespace Mono.Linker.Steps if (reference is GenericParameter) return null; - TypeDefinition type = _context.Resolve (reference); + TypeDefinition? type = Context.Resolve (reference); if (type == null) return null; @@ -1814,29 +1853,30 @@ namespace Mono.Linker.Steps if (type.HasMethods && ShouldMarkTypeStaticConstructor (type) && reason.Kind == DependencyKind.DeclaringTypeOfCalledMethod) MarkStaticConstructor (type, new DependencyInfo (DependencyKind.TriggersCctorForCalledMethod, reason.Source)); - if (_context.Annotations.HasLinkerAttribute<RemoveAttributeInstancesAttribute> (type)) { + if (Context.Annotations.HasLinkerAttribute<RemoveAttributeInstancesAttribute> (type)) { // Don't warn about references from the removed attribute itself (for example the .ctor on the attribute // will call MarkType on the attribute type itself). // If for some reason we do keep the attribute type (could be because of previous reference which would cause IL2045 // or because of a copy assembly with a reference and so on) then we should not spam the warnings due to the type itself. if (!(reason.Source is IMemberDefinition sourceMemberDefinition && sourceMemberDefinition.DeclaringType == type)) - _context.LogWarning ( + Context.LogWarning ( $"Attribute '{type.GetDisplayName ()}' is being referenced in code but the trimmer was " + $"instructed to remove all instances of this attribute. If the attribute instances are necessary make sure to " + $"either remove the trimmer attribute XML portion which removes the attribute instances, " + $"or override the removal by using the trimmer XML descriptor to keep the attribute type " + $"(which in turn keeps all of its instances).", - 2045, _scopeStack.CurrentScope.Origin, subcategory: MessageSubCategory.TrimAnalysis); + 2045, ScopeStack.CurrentScope.Origin, subcategory: MessageSubCategory.TrimAnalysis); } if (CheckProcessed (type)) return type; - MarkModule (type.Scope as ModuleDefinition, new DependencyInfo (DependencyKind.ScopeOfType, type)); + if (type.Scope is ModuleDefinition module) + MarkModule (module, new DependencyInfo (DependencyKind.ScopeOfType, type)); - using var typeScope = _scopeStack.PushScope (new MessageOrigin (type)); + using var typeScope = ScopeStack.PushScope (new MessageOrigin (type)); - foreach (Action<TypeDefinition> handleMarkType in _markContext.MarkTypeActions) + foreach (Action<TypeDefinition> handleMarkType in MarkContext.MarkTypeActions) handleMarkType (type); MarkType (type.BaseType, new DependencyInfo (DependencyKind.BaseType, type)); @@ -1844,24 +1884,24 @@ namespace Mono.Linker.Steps // The DynamicallyAccessedMembers hiearchy processing must be done after the base type was marked // (to avoid inconsistencies in the cache), but before anything else as work done below // might need the results of the processing here. - _dynamicallyAccessedMembersTypeHierarchy.ProcessMarkedTypeForDynamicallyAccessedMembersHierarchy (type); + DynamicallyAccessedMembersTypeHierarchy.ProcessMarkedTypeForDynamicallyAccessedMembersHierarchy (type); if (type.DeclaringType != null) MarkType (type.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, type)); MarkCustomAttributes (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); MarkSecurityDeclarations (type, new DependencyInfo (DependencyKind.CustomAttribute, type)); - if (_context.TryResolve (type.BaseType) is TypeDefinition baseType && - !_context.Annotations.HasLinkerAttribute<RequiresUnreferencedCodeAttribute> (type) && - _context.Annotations.TryGetLinkerAttribute (baseType, out RequiresUnreferencedCodeAttribute effectiveRequiresUnreferencedCode)) { + if (Context.TryResolve (type.BaseType) is TypeDefinition baseType && + !Context.Annotations.HasLinkerAttribute<RequiresUnreferencedCodeAttribute> (type) && + Context.Annotations.TryGetLinkerAttribute (baseType, out RequiresUnreferencedCodeAttribute? effectiveRequiresUnreferencedCode)) { - var currentOrigin = _scopeStack.CurrentScope.Origin; + var currentOrigin = ScopeStack.CurrentScope.Origin; string formatString = SharedStrings.RequiresOnBaseClassMessage; string arg1 = MessageFormat.FormatRequiresAttributeMessageArg (effectiveRequiresUnreferencedCode.Message); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg (effectiveRequiresUnreferencedCode.Url); string message = string.Format (formatString, type, type.BaseType.GetDisplayName (), arg1, arg2); - _context.LogWarning (message, 2109, currentOrigin, MessageSubCategory.TrimAnalysis); + Context.LogWarning (message, 2109, currentOrigin, MessageSubCategory.TrimAnalysis); } @@ -1876,7 +1916,7 @@ namespace Mono.Linker.Steps // This marks static fields of KeyWords/OpCodes/Tasks subclasses of an EventSource type. // The special handling of EventSource is still needed in .NET6 in library mode - if ((!_context.DisableEventSourceSpecialHandling || _context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6) && BCL.EventTracingForWindows.IsEventSourceImplementation (type, _context)) { + if ((!Context.DisableEventSourceSpecialHandling || Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6) && BCL.EventTracingForWindows.IsEventSourceImplementation (type, Context)) { MarkEventSourceProviders (type); } @@ -1911,13 +1951,13 @@ namespace Mono.Linker.Steps } if (type.HasInterfaces) - _typesWithInterfaces.Add ((type, _scopeStack.CurrentScope)); + _typesWithInterfaces.Add ((type, ScopeStack.CurrentScope)); if (type.HasMethods) { // For virtuals that must be preserved, blame the declaring type. MarkMethodsIf (type.Methods, IsVirtualNeededByTypeDueToPreservedScope, new DependencyInfo (DependencyKind.VirtualNeededDueToPreservedScope, type)); if (ShouldMarkTypeStaticConstructor (type) && reason.Kind != DependencyKind.TriggersCctorForCalledMethod) { - using (_scopeStack.PopToParent ()) + using (ScopeStack.PopToParent ()) MarkStaticConstructor (type, new DependencyInfo (DependencyKind.CctorForType, type)); } } @@ -1965,21 +2005,21 @@ namespace Mono.Linker.Steps { } - TypeDefinition GetDebuggerAttributeTargetType (CustomAttribute ca, AssemblyDefinition asm) + TypeDefinition? GetDebuggerAttributeTargetType (CustomAttribute ca, AssemblyDefinition asm) { foreach (var property in ca.Properties) { if (property.Name == "Target") - return _context.TryResolve ((TypeReference) property.Argument.Value); + return Context.TryResolve ((TypeReference) property.Argument.Value); if (property.Name == "TargetTypeName") { string targetTypeName = (string) property.Argument.Value; TypeName typeName = TypeParser.ParseTypeName (targetTypeName); if (typeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName) { - AssemblyDefinition assembly = _context.TryResolve (assemblyQualifiedTypeName.AssemblyName.Name); - return _context.TryResolve (assembly, targetTypeName); + AssemblyDefinition? assembly = Context.TryResolve (assemblyQualifiedTypeName.AssemblyName.Name); + return assembly == null ? null : Context.TryResolve (assembly, targetTypeName); } - return _context.TryResolve (asm, targetTypeName); + return Context.TryResolve (asm, targetTypeName); } } @@ -1993,12 +2033,12 @@ namespace Mono.Linker.Steps foreach (CustomAttribute attribute in type.CustomAttributes) { var attrType = attribute.Constructor.DeclaringType; - var resolvedAttributeType = _context.Resolve (attrType); + var resolvedAttributeType = Context.Resolve (attrType); if (resolvedAttributeType == null) { continue; } - if (_context.Annotations.HasLinkerAttribute<RemoveAttributeInstancesAttribute> (resolvedAttributeType) && Annotations.GetAction (type.Module.Assembly) == AssemblyAction.Link) + if (Context.Annotations.HasLinkerAttribute<RemoveAttributeInstancesAttribute> (resolvedAttributeType) && Annotations.GetAction (type.Module.Assembly) == AssemblyAction.Link) continue; switch (attrType.Name) { @@ -2012,7 +2052,7 @@ namespace Mono.Linker.Steps MarkTypeWithDebuggerTypeProxyAttribute (type, attribute); break; // The special handling of EventSource is still needed in .NET6 in library mode - case "EventDataAttribute" when attrType.Namespace == "System.Diagnostics.Tracing" && (!_context.DisableEventSourceSpecialHandling || _context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6): + case "EventDataAttribute" when attrType.Namespace == "System.Diagnostics.Tracing" && (!Context.DisableEventSourceSpecialHandling || Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6): if (MarkMethodsIf (type.Methods, MethodDefinitionExtensions.IsPublicInstancePropertyMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, type))) Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); break; @@ -2056,7 +2096,7 @@ namespace Mono.Linker.Steps void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute) { - if (TryGetStringArgument (attribute, out string name)) { + if (TryGetStringArgument (attribute, out string? name)) { Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); MarkNamedMethod (type, name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); } @@ -2068,16 +2108,18 @@ namespace Mono.Linker.Steps if (args.Count < 1) return; - TypeDefinition typeDefinition = null; + TypeDefinition? typeDefinition = null; switch (attribute.ConstructorArguments[0].Value) { case string s: - typeDefinition = _context.TryResolve (_context.TypeNameResolver.ResolveTypeName (s, _scopeStack.CurrentScope.Origin.Provider, out AssemblyDefinition assemblyDefinition)); + if (!Context.TypeNameResolver.TryResolveTypeName (s, ScopeStack.CurrentScope.Origin.Provider, out TypeReference? typeRef, out AssemblyDefinition? assemblyDefinition)) + break; + typeDefinition = Context.TryResolve (typeRef); if (typeDefinition != null) MarkingHelpers.MarkMatchingExportedType (typeDefinition, assemblyDefinition, new DependencyInfo (DependencyKind.CustomAttribute, provider)); break; case TypeReference type: - typeDefinition = _context.Resolve (type); + typeDefinition = Context.Resolve (type); break; } @@ -2092,7 +2134,7 @@ namespace Mono.Linker.Steps void MarkTypeWithDebuggerDisplayAttribute (TypeDefinition type, CustomAttribute attribute) { - if (_context.KeepMembersForDebugger) { + if (Context.KeepMembersForDebugger) { // Members referenced by the DebuggerDisplayAttribute are kept even if the attribute may not be. // Record a logical dependency on the attribute so that we can blame it for the kept members below. @@ -2122,19 +2164,19 @@ namespace Mono.Linker.Steps if (methodName.Contains ('.')) continue; - MethodDefinition method = GetMethodWithNoParameters (type, methodName); + MethodDefinition? method = GetMethodWithNoParameters (type, methodName); if (method != null) { MarkMethod (method, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); continue; } } else { - FieldDefinition field = GetField (type, realMatch); + FieldDefinition? field = GetField (type, realMatch); if (field != null) { MarkField (field, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); continue; } - PropertyDefinition property = GetProperty (type, realMatch); + PropertyDefinition? property = GetProperty (type, realMatch); if (property != null) { if (property.GetMethod != null) { MarkMethod (property.GetMethod, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); @@ -2146,12 +2188,14 @@ namespace Mono.Linker.Steps } } - while (type != null) { + while (true) { // Currently if we don't understand the DebuggerDisplayAttribute we mark everything on the type // This can be improved: dotnet/linker/issues/1873 MarkMethods (type, new DependencyInfo (DependencyKind.KeptForSpecialAttribute, attribute)); MarkFields (type, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); - type = _context.TryResolve (type.BaseType); + if (Context.TryResolve (type.BaseType) is not TypeDefinition baseType) + break; + type = baseType; } return; } @@ -2160,9 +2204,9 @@ namespace Mono.Linker.Steps void MarkTypeWithDebuggerTypeProxyAttribute (TypeDefinition type, CustomAttribute attribute) { - if (_context.KeepMembersForDebugger) { + if (Context.KeepMembersForDebugger) { object constructorArgument = attribute.ConstructorArguments[0].Value; - TypeReference proxyTypeReference = constructorArgument as TypeReference; + TypeReference? proxyTypeReference = constructorArgument as TypeReference; if (proxyTypeReference == null) { if (constructorArgument is string proxyTypeReferenceString) { proxyTypeReference = type.Module.GetType (proxyTypeReferenceString, runtimeName: true); @@ -2176,15 +2220,14 @@ namespace Mono.Linker.Steps Tracer.AddDirectDependency (attribute, new DependencyInfo (DependencyKind.CustomAttribute, type), marked: false); MarkType (proxyTypeReference, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); - TypeDefinition proxyType = _context.TryResolve (proxyTypeReference); - if (proxyType != null) { + if (Context.TryResolve (proxyTypeReference) is TypeDefinition proxyType) { MarkMethods (proxyType, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); MarkFields (proxyType, includeStatic: true, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); } } } - static bool TryGetStringArgument (CustomAttribute attribute, out string argument) + static bool TryGetStringArgument (CustomAttribute attribute, [NotNullWhen (true)] out string? argument) { argument = null; @@ -2215,7 +2258,7 @@ namespace Mono.Linker.Steps void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute) { - if (!TryGetStringArgument (attribute, out string member_name)) + if (!TryGetStringArgument (attribute, out string? member_name)) return; MarkNamedField (method.DeclaringType, member_name, new DependencyInfo (DependencyKind.ReferencedBySpecialAttribute, attribute)); @@ -2247,7 +2290,7 @@ namespace Mono.Linker.Steps if (property.Name != property_name) continue; - using (_scopeStack.PushScope (new MessageOrigin (property))) { + using (ScopeStack.PushScope (new MessageOrigin (property))) { // This marks methods directly without reporting the property. MarkMethod (property.GetMethod, reason); MarkMethod (property.SetMethod, reason); @@ -2263,7 +2306,7 @@ namespace Mono.Linker.Steps foreach (var iface in type.Interfaces) { // Only mark interface implementations of interface types that have been marked. // This enables stripping of interfaces that are never used - var resolvedInterfaceType = _context.Resolve (iface.InterfaceType); + var resolvedInterfaceType = Context.Resolve (iface.InterfaceType); if (resolvedInterfaceType == null) { continue; } @@ -2370,7 +2413,7 @@ namespace Mono.Linker.Steps return marked; } - protected MethodDefinition MarkMethodIf (Collection<MethodDefinition> methods, Func<MethodDefinition, bool> predicate, in DependencyInfo reason) + protected MethodDefinition? MarkMethodIf (Collection<MethodDefinition> methods, Func<MethodDefinition, bool> predicate, in DependencyInfo reason) { foreach (MethodDefinition method in methods) { if (predicate (method)) { @@ -2399,8 +2442,9 @@ namespace Mono.Linker.Steps reason); } - void MarkICustomMarshalerMethods (TypeDefinition type, in DependencyInfo reason) + void MarkICustomMarshalerMethods (TypeDefinition inputType, in DependencyInfo reason) { + TypeDefinition? type = inputType; do { if (!type.HasInterfaces) continue; @@ -2414,7 +2458,7 @@ namespace Mono.Linker.Steps // Instead of trying to guess where to find the interface declaration linker walks // the list of implemented interfaces and resolve the declaration from there // - var tdef = _context.Resolve (iface_type); + var tdef = Context.Resolve (iface_type); if (tdef == null) { return; } @@ -2424,7 +2468,7 @@ namespace Mono.Linker.Steps MarkInterfaceImplementation (iface, new MessageOrigin (type)); return; } - } while ((type = _context.TryResolve (type.BaseType)) != null); + } while ((type = Context.TryResolve (type.BaseType)) != null); } static bool IsNonEmptyStaticConstructor (MethodDefinition method) @@ -2478,7 +2522,7 @@ namespace Mono.Linker.Steps void MarkEventSourceProviders (TypeDefinition td) { - Debug.Assert (_context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6 || !_context.DisableEventSourceSpecialHandling); + Debug.Assert (Context.GetTargetRuntimeVersion () < TargetRuntimeVersion.NET6 || !Context.DisableEventSourceSpecialHandling); foreach (var nestedType in td.NestedTypes) { if (BCL.EventTracingForWindows.IsProviderName (nestedType.Name)) MarkStaticFields (nestedType, new DependencyInfo (DependencyKind.EventSourceProviderField, td)); @@ -2548,14 +2592,14 @@ namespace Mono.Linker.Steps var argument = arguments[i]; var parameter = parameters[i]; - TypeDefinition argumentTypeDef = MarkType (argument, new DependencyInfo (DependencyKind.GenericArgumentType, instance)); + TypeDefinition? argumentTypeDef = MarkType (argument, new DependencyInfo (DependencyKind.GenericArgumentType, instance)); - if (_context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (parameter)) { + if (Context.Annotations.FlowAnnotations.RequiresDataFlowAnalysis (parameter)) { // The only two implementations of IGenericInstance both derive from MemberReference Debug.Assert (instance is MemberReference); - using var _ = _scopeStack.CurrentScope.Origin.Provider == null ? _scopeStack.PushScope (new MessageOrigin (((MemberReference) instance).Resolve ())) : null; - var scanner = new ReflectionMethodBodyScanner (_context, this, _scopeStack); + using var _ = ScopeStack.CurrentScope.Origin.Provider == null ? ScopeStack.PushScope (new MessageOrigin (((MemberReference) instance).Resolve ())) : null; + var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack); scanner.ProcessGenericArgumentDataFlow (parameter, argument); } @@ -2569,20 +2613,20 @@ namespace Mono.Linker.Steps } } - IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance) + IGenericParameterProvider? GetGenericProviderFromInstance (IGenericInstance instance) { if (instance is GenericInstanceMethod method) - return _context.TryResolve (method.ElementMethod); + return Context.TryResolve (method.ElementMethod); if (instance is GenericInstanceType type) - return _context.TryResolve (type.ElementType); + return Context.TryResolve (type.ElementType); return null; } void ApplyPreserveInfo (TypeDefinition type) { - using var typeScope = _scopeStack.PushScope (new MessageOrigin (type)); + using var typeScope = ScopeStack.PushScope (new MessageOrigin (type)); if (Annotations.TryGetPreserve (type, out TypePreserve preserve)) { if (!Annotations.SetAppliedPreserve (type, preserve)) @@ -2598,11 +2642,11 @@ namespace Mono.Linker.Steps case TypePreserve.Fields: if (!MarkFields (type, true, di, true)) - _context.LogWarning ($"Type '{type.GetDisplayName ()}' has no fields to preserve.", 2001, type); + Context.LogWarning ($"Type '{type.GetDisplayName ()}' has no fields to preserve.", 2001, type); break; case TypePreserve.Methods: if (!MarkMethods (type, di)) - _context.LogWarning ($"Type '{type.GetDisplayName ()}' has no methods to preserve.", 2002, type); + Context.LogWarning ($"Type '{type.GetDisplayName ()}' has no methods to preserve.", 2002, type); break; } } @@ -2714,7 +2758,7 @@ namespace Mono.Linker.Steps return true; } - static PropertyDefinition SearchPropertiesForMatchingFieldDefinition (FieldDefinition field) + static PropertyDefinition? SearchPropertiesForMatchingFieldDefinition (FieldDefinition field) { foreach (var property in field.DeclaringType.Properties) { var instr = property.GetMethod?.Body?.Instructions; @@ -2762,7 +2806,7 @@ namespace Mono.Linker.Steps Annotations.MarkIndirectlyCalledMethod (method); } - protected virtual MethodDefinition MarkMethod (MethodReference reference, DependencyInfo reason) + protected virtual MethodDefinition? MarkMethod (MethodReference reference, DependencyInfo reason) { DependencyKind originalReasonKind = reason.Kind; (reference, reason) = GetOriginalMethod (reference, reason); @@ -2770,7 +2814,7 @@ namespace Mono.Linker.Steps if (reference.DeclaringType is ArrayType arrayType) { MarkType (reference.DeclaringType, new DependencyInfo (DependencyKind.DeclaringType, reference)); - if (reference.Name == ".ctor" && _context.TryResolve (arrayType) is TypeDefinition typeDefinition) { + if (reference.Name == ".ctor" && Context.TryResolve (arrayType) is TypeDefinition typeDefinition) { Annotations.MarkRelevantToVariantCasting (typeDefinition); } return null; @@ -2784,14 +2828,14 @@ namespace Mono.Linker.Steps reason = new DependencyInfo (DependencyKind.MethodOnGenericInstance, reference); } - MethodDefinition method = _context.Resolve (reference); + MethodDefinition? method = Context.Resolve (reference); if (method == null) return null; if (Annotations.GetAction (method) == MethodAction.Nothing) Annotations.SetAction (method, MethodAction.Parse); - EnqueueMethod (method, reason, _scopeStack.CurrentScope); + EnqueueMethod (method, reason, ScopeStack.CurrentScope); // Use the original reason as it's important to correctly generate warnings // the updated reason is only useful for better tracking of dependencies. @@ -2880,7 +2924,7 @@ namespace Mono.Linker.Steps CheckAndReportRequiresUnreferencedCode (method); - if (_context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method)) { + if (Context.Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method)) { // If the current scope has analysis warnings suppressed, don't generate any if (ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode ()) return; @@ -2896,10 +2940,10 @@ namespace Mono.Linker.Steps break; } - _context.LogWarning ( + Context.LogWarning ( $"Method '{method.GetDisplayName ()}' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.", 2111, - _scopeStack.CurrentScope.Origin, + ScopeStack.CurrentScope.Origin, MessageSubCategory.TrimAnalysis); } } @@ -2910,14 +2954,14 @@ namespace Mono.Linker.Steps // since that attribute automatically suppresses all trim analysis warnings. // Check both the immediate origin method as well as suppression context method // since that will be different for compiler generated code. - var currentOrigin = _scopeStack.CurrentScope.Origin; + var currentOrigin = ScopeStack.CurrentScope.Origin; - ICustomAttributeProvider suppressionContextMember = currentOrigin.SuppressionContextMember; + ICustomAttributeProvider? suppressionContextMember = currentOrigin.SuppressionContextMember; if (suppressionContextMember is MethodDefinition && Annotations.IsMethodInRequiresUnreferencedCodeScope ((MethodDefinition) suppressionContextMember)) return true; - ICustomAttributeProvider originMember = currentOrigin.Provider; + ICustomAttributeProvider? originMember = currentOrigin.Provider; if (originMember is MethodDefinition && suppressionContextMember != originMember && Annotations.IsMethodInRequiresUnreferencedCodeScope ((MethodDefinition) originMember)) return true; @@ -2932,10 +2976,10 @@ namespace Mono.Linker.Steps if (ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode ()) return; - if (!Annotations.DoesMethodRequireUnreferencedCode (method, out RequiresUnreferencedCodeAttribute requiresUnreferencedCode)) + if (!Annotations.DoesMethodRequireUnreferencedCode (method, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCode)) return; - ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode, _scopeStack.CurrentScope.Origin); + ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode, ScopeStack.CurrentScope.Origin); } private void ReportRequiresUnreferencedCode (string displayName, RequiresUnreferencedCodeAttribute requiresUnreferencedCode, MessageOrigin currentOrigin) @@ -2943,7 +2987,7 @@ namespace Mono.Linker.Steps string arg1 = MessageFormat.FormatRequiresAttributeMessageArg (requiresUnreferencedCode.Message); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg (requiresUnreferencedCode.Url); string message = string.Format (SharedStrings.RequiresUnreferencedCodeMessage, displayName, arg1, arg2); - _context.LogWarning (message, 2026, currentOrigin, MessageSubCategory.TrimAnalysis); + Context.LogWarning (message, 2026, currentOrigin, MessageSubCategory.TrimAnalysis); } protected (MethodReference, DependencyInfo) GetOriginalMethod (MethodReference method, DependencyInfo reason) @@ -2968,9 +3012,9 @@ namespace Mono.Linker.Steps if (!_methodReasons.Contains (reason.Kind)) throw new InternalErrorException ($"Unsupported method dependency {reason.Kind}"); #endif - _scopeStack.AssertIsEmpty (); - using var parentScope = _scopeStack.PushScope (scope); - using var methodScope = _scopeStack.PushScope (new MessageOrigin (method)); + ScopeStack.AssertIsEmpty (); + using var parentScope = ScopeStack.PushScope (scope); + using var methodScope = ScopeStack.PushScope (new MessageOrigin (method)); // Record the reason for marking a method on each call. The logic under CheckProcessed happens // only once per method. @@ -2999,9 +3043,9 @@ namespace Mono.Linker.Steps if (CheckProcessed (method)) return; - _unreachableBlocksOptimizer.ProcessMethod (method); + UnreachableBlocksOptimizer.ProcessMethod (method); - foreach (Action<MethodDefinition> handleMarkMethod in _markContext.MarkMethodActions) + foreach (Action<MethodDefinition> handleMarkMethod in MarkContext.MarkMethodActions) handleMarkMethod (method); if (!markedForCall) @@ -3015,15 +3059,15 @@ namespace Mono.Linker.Steps MarkRequirementsForInstantiatedTypes (method.DeclaringType); Tracer.AddDirectDependency (method.DeclaringType, new DependencyInfo (DependencyKind.InstantiatedByCtor, method), marked: false); } else if (method.IsStaticConstructor () && Annotations.HasLinkerAttribute<RequiresUnreferencedCodeAttribute> (method)) - _context.LogWarning (new DiagnosticString (DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor).GetMessage (method.GetDisplayName ()), (int) DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor, _scopeStack.CurrentScope.Origin, MessageSubCategory.TrimAnalysis); + Context.LogWarning (new DiagnosticString (DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor).GetMessage (method.GetDisplayName ()), (int) DiagnosticId.RequiresUnreferencedCodeOnStaticConstructor, ScopeStack.CurrentScope.Origin, MessageSubCategory.TrimAnalysis); if (method.IsConstructor) { if (!Annotations.ProcessSatelliteAssemblies && KnownMembers.IsSatelliteAssemblyMarker (method)) Annotations.ProcessSatelliteAssemblies = true; - } else if (method.IsPropertyMethod ()) - MarkProperty (method.GetProperty (), new DependencyInfo (DependencyKind.PropertyOfPropertyMethod, method)); - else if (method.IsEventMethod ()) - MarkEvent (method.GetEvent (), new DependencyInfo (DependencyKind.EventOfEventMethod, method)); + } else if (method.TryGetProperty (out PropertyDefinition? property)) + MarkProperty (property, new DependencyInfo (DependencyKind.PropertyOfPropertyMethod, method)); + else if (method.TryGetEvent (out EventDefinition? @event)) + MarkEvent (@event, new DependencyInfo (DependencyKind.EventOfEventMethod, method)); if (method.HasParameters) { foreach (ParameterDefinition pd in method.Parameters) { @@ -3042,7 +3086,7 @@ namespace Mono.Linker.Steps MarkMethodSpecialCustomAttributes (method); if (method.IsVirtual) - _virtual_methods.Add ((method, _scopeStack.CurrentScope)); + _virtual_methods.Add ((method, ScopeStack.CurrentScope)); MarkNewCodeDependencies (method); @@ -3060,7 +3104,7 @@ namespace Mono.Linker.Steps MarkMethodBody (method.Body); if (method.DeclaringType.IsMulticastDelegate ()) { - string methodPair = null; + string? methodPair = null; if (method.Name == "BeginInvoke") methodPair = "EndInvoke"; else if (method.Name == "EndInvoke") @@ -3099,7 +3143,7 @@ namespace Mono.Linker.Steps Annotations.MarkInstantiated (type); - using var typeScope = _scopeStack.PushScope (new MessageOrigin (type)); + using var typeScope = ScopeStack.PushScope (new MessageOrigin (type)); MarkInterfaceImplementations (type); @@ -3128,14 +3172,12 @@ namespace Mono.Linker.Steps void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReference ov) { - MethodDefinition resolvedOverride = _context.Resolve (ov); - - if (resolvedOverride == null) + if (Context.Resolve (ov) is not MethodDefinition resolvedOverride) return; if (resolvedOverride.DeclaringType.IsInterface) { foreach (var ifaceImpl in method.DeclaringType.Interfaces) { - var resolvedInterfaceType = _context.Resolve (ifaceImpl.InterfaceType); + var resolvedInterfaceType = Context.Resolve (ifaceImpl.InterfaceType); if (resolvedInterfaceType == null) { continue; } @@ -3155,10 +3197,12 @@ namespace Mono.Linker.Steps if (!method.IsInstanceConstructor ()) return; - var baseType = _context.Resolve (method.DeclaringType.BaseType); + var baseType = Context.Resolve (method.DeclaringType.BaseType); + if (baseType == null) + break; if (!MarkDefaultConstructor (baseType, new DependencyInfo (DependencyKind.BaseDefaultCtorForStubbedMethod, method))) throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ($"Cannot stub constructor on '{method.DeclaringType}' when base type does not have default constructor", - 1006, origin: _scopeStack.CurrentScope.Origin)); + 1006, origin: ScopeStack.CurrentScope.Origin)); break; @@ -3170,44 +3214,44 @@ namespace Mono.Linker.Steps protected virtual void MarkAndCacheConvertToThrowExceptionCtor (DependencyInfo reason) { - if (_context.MarkedKnownMembers.NotSupportedExceptionCtorString != null) + if (Context.MarkedKnownMembers.NotSupportedExceptionCtorString != null) return; - var nse = BCL.FindPredefinedType ("System", "NotSupportedException", _context); + var nse = BCL.FindPredefinedType ("System", "NotSupportedException", Context); if (nse == null) throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ("Missing predefined 'System.NotSupportedException' type", 1007)); MarkType (nse, reason); var nseCtor = MarkMethodIf (nse.Methods, KnownMembers.IsNotSupportedExceptionCtorString, reason); - _context.MarkedKnownMembers.NotSupportedExceptionCtorString = nseCtor ?? + Context.MarkedKnownMembers.NotSupportedExceptionCtorString = nseCtor ?? throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ($"Could not find constructor on '{nse.GetDisplayName ()}'", 1008)); - var objectType = BCL.FindPredefinedType ("System", "Object", _context); + var objectType = BCL.FindPredefinedType ("System", "Object", Context); if (objectType == null) throw new NotSupportedException ("Missing predefined 'System.Object' type"); MarkType (objectType, reason); var objectCtor = MarkMethodIf (objectType.Methods, MethodDefinitionExtensions.IsDefaultConstructor, reason); - _context.MarkedKnownMembers.ObjectCtor = objectCtor ?? + Context.MarkedKnownMembers.ObjectCtor = objectCtor ?? throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ($"Could not find constructor on '{objectType.GetDisplayName ()}'", 1008)); } bool MarkDisablePrivateReflectionAttribute () { - if (_context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor != null) + if (Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor != null) return false; - var disablePrivateReflection = BCL.FindPredefinedType ("System.Runtime.CompilerServices", "DisablePrivateReflectionAttribute", _context); + var disablePrivateReflection = BCL.FindPredefinedType ("System.Runtime.CompilerServices", "DisablePrivateReflectionAttribute", Context); if (disablePrivateReflection == null) throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ("Missing predefined 'System.Runtime.CompilerServices.DisablePrivateReflectionAttribute' type", 1007)); - using (_scopeStack.PushScope (new MessageOrigin (null as ICustomAttributeProvider))) { + using (ScopeStack.PushScope (new MessageOrigin (null as ICustomAttributeProvider))) { MarkType (disablePrivateReflection, DependencyInfo.DisablePrivateReflectionRequirement); var ctor = MarkMethodIf (disablePrivateReflection.Methods, MethodDefinitionExtensions.IsDefaultConstructor, new DependencyInfo (DependencyKind.DisablePrivateReflectionRequirement, disablePrivateReflection)); - _context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor ?? + Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor = ctor ?? throw new LinkerFatalErrorException (MessageContainer.CreateErrorMessage ($"Could not find constructor on '{disablePrivateReflection.GetDisplayName ()}'", 1010)); } @@ -3234,17 +3278,17 @@ namespace Mono.Linker.Steps if (method.IsPInvokeImpl && method.PInvokeInfo != null) { var pii = method.PInvokeInfo; Annotations.MarkProcessed (pii.Module, new DependencyInfo (DependencyKind.InteropMethodDependency, method)); - if (!string.IsNullOrEmpty (_context.PInvokesListFile)) { - _context.PInvokes.Add (new PInvokeInfo { - AssemblyName = method.DeclaringType.Module.Name, - EntryPoint = pii.EntryPoint, - FullName = method.FullName, - ModuleName = pii.Module.Name - }); + if (!string.IsNullOrEmpty (Context.PInvokesListFile)) { + Context.PInvokes.Add (new PInvokeInfo ( + assemblyName: method.DeclaringType.Module.Name, + entryPoint: pii.EntryPoint, + fullName: method.FullName, + moduleName: pii.Module.Name + )); } } - TypeDefinition returnTypeDefinition = _context.TryResolve (method.ReturnType); + TypeDefinition? returnTypeDefinition = Context.TryResolve (method.ReturnType); const bool includeStaticFields = false; if (returnTypeDefinition != null) { @@ -3265,7 +3309,7 @@ namespace Mono.Linker.Steps if (paramTypeReference is TypeSpecification paramTypeSpecification) { paramTypeReference = paramTypeSpecification.ElementType; } - TypeDefinition paramTypeDefinition = _context.TryResolve (paramTypeReference); + TypeDefinition? paramTypeDefinition = Context.TryResolve (paramTypeReference); if (paramTypeDefinition != null) { if (!paramTypeDefinition.IsImport) { // What we keep here is correct most of the time, but not every time. Fine for now. @@ -3287,7 +3331,9 @@ namespace Mono.Linker.Steps case MethodAction.ForceParse: return true; case MethodAction.Parse: - AssemblyDefinition assembly = _context.Resolve (method.DeclaringType.Scope); + AssemblyDefinition? assembly = Context.Resolve (method.DeclaringType.Scope); + if (assembly == null) + return false; switch (Annotations.GetAction (assembly)) { case AssemblyAction.Link: case AssemblyAction.Copy: @@ -3307,7 +3353,7 @@ namespace Mono.Linker.Steps { Tracer.AddDirectDependency (prop, reason, marked: false); - using var propertyScope = _scopeStack.PushScope (new MessageOrigin (prop)); + using var propertyScope = ScopeStack.PushScope (new MessageOrigin (prop)); // Consider making this more similar to MarkEvent method? MarkCustomAttributes (prop, new DependencyInfo (DependencyKind.CustomAttribute, prop)); @@ -3319,7 +3365,7 @@ namespace Mono.Linker.Steps // Record the event without marking it in Annotations. Tracer.AddDirectDependency (evt, reason, marked: false); - using var eventScope = _scopeStack.PushScope (new MessageOrigin (evt)); + using var eventScope = ScopeStack.PushScope (new MessageOrigin (evt)); MarkCustomAttributes (evt, new DependencyInfo (DependencyKind.CustomAttribute, evt)); MarkMethodIfNotNull (evt.AddMethod, new DependencyInfo (DependencyKind.EventMethod, evt)); @@ -3338,9 +3384,9 @@ namespace Mono.Linker.Steps protected virtual void MarkMethodBody (MethodBody body) { - if (_context.IsOptimizationEnabled (CodeOptimizations.UnreachableBodies, body.Method) && IsUnreachableBody (body)) { + if (Context.IsOptimizationEnabled (CodeOptimizations.UnreachableBodies, body.Method) && IsUnreachableBody (body)) { MarkAndCacheConvertToThrowExceptionCtor (new DependencyInfo (DependencyKind.UnreachableBodyRequirement, body.Method)); - _unreachableBodies.Add ((body, _scopeStack.CurrentScope)); + _unreachableBodies.Add ((body, ScopeStack.CurrentScope)); return; } @@ -3352,7 +3398,7 @@ namespace Mono.Linker.Steps MarkType (eh.CatchType, new DependencyInfo (DependencyKind.CatchType, body.Method)); bool requiresReflectionMethodBodyScanner = - ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody (_context.Annotations.FlowAnnotations, body.Method); + ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody (Context.Annotations.FlowAnnotations, body.Method); foreach (Instruction instruction in body.Instructions) MarkInstruction (instruction, body.Method, ref requiresReflectionMethodBodyScanner); @@ -3378,7 +3424,7 @@ namespace Mono.Linker.Steps // If a type could be on the stack in the body and an interface it implements could be on the stack on the body // then we need to mark that interface implementation. When this occurs it is not safe to remove the interface implementation from the type // even if the type is never instantiated - var implementations = new InterfacesOnStackScanner (_context).GetReferencedInterfaces (body); + var implementations = new InterfacesOnStackScanner (Context).GetReferencedInterfaces (body); if (implementations == null) return; @@ -3396,14 +3442,14 @@ namespace Mono.Linker.Steps case Code.Ldflda: // Field address loads (as those can be used to store values to annotated field and thus must be checked) case Code.Ldsflda: requiresReflectionMethodBodyScanner |= - ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForAccess (_context, (FieldReference) instruction.Operand); + ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForAccess (Context, (FieldReference) instruction.Operand); break; default: // Other field operations are not interesting as they don't need to be checked break; } - _scopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); MarkField ((FieldReference) instruction.Operand, new DependencyInfo (DependencyKind.FieldAccess, method)); break; @@ -3419,9 +3465,9 @@ namespace Mono.Linker.Steps }; requiresReflectionMethodBodyScanner |= - ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForCallSite (_context, (MethodReference) instruction.Operand); + ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForCallSite (Context, (MethodReference) instruction.Operand); - _scopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); MarkMethod ((MethodReference) instruction.Operand, new DependencyInfo (dependencyKind, method)); break; } @@ -3430,12 +3476,12 @@ namespace Mono.Linker.Steps object token = instruction.Operand; Debug.Assert (instruction.OpCode.Code == Code.Ldtoken); var reason = new DependencyInfo (DependencyKind.Ldtoken, method); - _scopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); if (token is TypeReference typeReference) { // Error will be reported as part of MarkType - TypeDefinition type = _context.TryResolve (typeReference); - MarkTypeVisibleToReflection (typeReference, type, reason); + if (Context.TryResolve (typeReference) is TypeDefinition type) + MarkTypeVisibleToReflection (typeReference, type, reason); } else if (token is MethodReference methodReference) { MarkMethod (methodReference, reason); } else { @@ -3448,17 +3494,17 @@ namespace Mono.Linker.Steps var operand = (TypeReference) instruction.Operand; switch (instruction.OpCode.Code) { case Code.Newarr: - if (_context.TryResolve (operand) is TypeDefinition typeDefinition) + if (Context.TryResolve (operand) is TypeDefinition typeDefinition) Annotations.MarkRelevantToVariantCasting (typeDefinition); break; case Code.Isinst: if (operand is TypeSpecification || operand is GenericParameter) break; - if (!_context.CanApplyOptimization (CodeOptimizations.UnusedTypeChecks, method.DeclaringType.Module.Assembly)) + if (!Context.CanApplyOptimization (CodeOptimizations.UnusedTypeChecks, method.DeclaringType.Module.Assembly)) break; - TypeDefinition type = _context.Resolve (operand); + TypeDefinition? type = Context.Resolve (operand); if (type == null) return; @@ -3473,7 +3519,7 @@ namespace Mono.Linker.Steps break; } - _scopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); + ScopeStack.UpdateCurrentScopeInstructionOffset (instruction.Offset); MarkType (operand, new DependencyInfo (DependencyKind.InstructionTypeRef, method)); break; } @@ -3487,7 +3533,7 @@ namespace Mono.Linker.Steps if (Annotations.IsMarked (resolvedInterfaceType)) return true; - if (!_context.IsOptimizationEnabled (CodeOptimizations.UnusedInterfaces, type)) + if (!Context.IsOptimizationEnabled (CodeOptimizations.UnusedInterfaces, type)) return true; // It's hard to know if a com or windows runtime interface will be needed from managed code alone, @@ -3503,13 +3549,13 @@ namespace Mono.Linker.Steps if (Annotations.IsMarked (iface)) return; - using var localScope = origin.HasValue ? _scopeStack.PushScope (origin.Value) : null; + using var localScope = origin.HasValue ? ScopeStack.PushScope (origin.Value) : null; // Blame the type that has the interfaceimpl, expecting the type itself to get marked for other reasons. MarkCustomAttributes (iface, new DependencyInfo (DependencyKind.CustomAttribute, iface)); // Blame the interface type on the interfaceimpl itself. MarkType (iface.InterfaceType, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationInterfaceType, iface)); - Annotations.MarkProcessed (iface, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationOnType, _scopeStack.CurrentScope.Origin.Provider)); + Annotations.MarkProcessed (iface, reason ?? new DependencyInfo (DependencyKind.InterfaceImplementationOnType, ScopeStack.CurrentScope.Origin.Provider)); } // @@ -3526,7 +3572,7 @@ namespace Mono.Linker.Steps protected virtual void MarkReflectionLikeDependencies (MethodBody body, bool requiresReflectionMethodBodyScanner) { if (requiresReflectionMethodBodyScanner) { - var scanner = new ReflectionMethodBodyScanner (_context, this, _scopeStack); + var scanner = new ReflectionMethodBodyScanner (Context, this, ScopeStack); scanner.ScanAndProcessReturnValue (body); } } diff --git a/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs b/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs index d005c248e..f97004fd0 100644 --- a/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs +++ b/src/linker/Linker.Steps/MarkSubStepsDispatcher.cs @@ -1,7 +1,9 @@ // 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; +using System.Diagnostics; using Mono.Cecil; using Mono.Collections.Generic; @@ -19,12 +21,13 @@ namespace Mono.Linker.Steps { readonly List<ISubStep> substeps; - List<ISubStep> on_assemblies; - List<ISubStep> on_types; - List<ISubStep> on_fields; - List<ISubStep> on_methods; - List<ISubStep> on_properties; - List<ISubStep> on_events; + CategorizedSubSteps? categorized; + CategorizedSubSteps Categorized { + get { + Debug.Assert (categorized.HasValue); + return categorized.Value; + } + } public MarkSubStepsDispatcher (IEnumerable<ISubStep> subSteps) { @@ -43,7 +46,7 @@ namespace Mono.Linker.Steps { CategorizeSubSteps (assembly); - if (HasSubSteps (on_assemblies)) + if (HasSubSteps (Categorized.on_assemblies)) DispatchAssembly (assembly); if (!ShouldDispatchTypes ()) @@ -54,11 +57,11 @@ namespace Mono.Linker.Steps bool ShouldDispatchTypes () { - return HasSubSteps (on_types) - || HasSubSteps (on_fields) - || HasSubSteps (on_methods) - || HasSubSteps (on_properties) - || HasSubSteps (on_events); + return HasSubSteps (Categorized.on_types) + || HasSubSteps (Categorized.on_fields) + || HasSubSteps (Categorized.on_methods) + || HasSubSteps (Categorized.on_properties) + || HasSubSteps (Categorized.on_events); } void BrowseTypes (Collection<TypeDefinition> types) @@ -66,22 +69,22 @@ namespace Mono.Linker.Steps foreach (TypeDefinition type in types) { DispatchType (type); - if (type.HasFields && HasSubSteps (on_fields)) { + if (type.HasFields && HasSubSteps (Categorized.on_fields)) { foreach (FieldDefinition field in type.Fields) DispatchField (field); } - if (type.HasMethods && HasSubSteps (on_methods)) { + if (type.HasMethods && HasSubSteps (Categorized.on_methods)) { foreach (MethodDefinition method in type.Methods) DispatchMethod (method); } - if (type.HasProperties && HasSubSteps (on_properties)) { + if (type.HasProperties && HasSubSteps (Categorized.on_properties)) { foreach (PropertyDefinition property in type.Properties) DispatchProperty (property); } - if (type.HasEvents && HasSubSteps (on_events)) { + if (type.HasEvents && HasSubSteps (Categorized.on_events)) { foreach (EventDefinition @event in type.Events) DispatchEvent (@event); } @@ -93,42 +96,42 @@ namespace Mono.Linker.Steps void DispatchAssembly (AssemblyDefinition assembly) { - foreach (var substep in on_assemblies) { + foreach (var substep in Categorized.on_assemblies) { substep.ProcessAssembly (assembly); } } void DispatchType (TypeDefinition type) { - foreach (var substep in on_types) { + foreach (var substep in Categorized.on_types) { substep.ProcessType (type); } } void DispatchField (FieldDefinition field) { - foreach (var substep in on_fields) { + foreach (var substep in Categorized.on_fields) { substep.ProcessField (field); } } void DispatchMethod (MethodDefinition method) { - foreach (var substep in on_methods) { + foreach (var substep in Categorized.on_methods) { substep.ProcessMethod (method); } } void DispatchProperty (PropertyDefinition property) { - foreach (var substep in on_properties) { + foreach (var substep in Categorized.on_properties) { substep.ProcessProperty (property); } } void DispatchEvent (EventDefinition @event) { - foreach (var substep in on_events) { + foreach (var substep in Categorized.on_events) { substep.ProcessEvent (@event); } } @@ -141,12 +144,14 @@ namespace Mono.Linker.Steps void CategorizeSubSteps (AssemblyDefinition assembly) { - on_assemblies = new List<ISubStep> (); - on_types = new List<ISubStep> (); - on_fields = new List<ISubStep> (); - on_methods = new List<ISubStep> (); - on_properties = new List<ISubStep> (); - on_events = new List<ISubStep> (); + categorized = new CategorizedSubSteps { + on_assemblies = new List<ISubStep> (), + on_types = new List<ISubStep> (), + on_fields = new List<ISubStep> (), + on_methods = new List<ISubStep> (), + on_properties = new List<ISubStep> (), + on_events = new List<ISubStep> () + }; foreach (var substep in substeps) CategorizeSubStep (substep, assembly); @@ -157,12 +162,12 @@ namespace Mono.Linker.Steps if (!substep.IsActiveFor (assembly)) return; - CategorizeTarget (substep, SubStepTargets.Assembly, on_assemblies); - CategorizeTarget (substep, SubStepTargets.Type, on_types); - CategorizeTarget (substep, SubStepTargets.Field, on_fields); - CategorizeTarget (substep, SubStepTargets.Method, on_methods); - CategorizeTarget (substep, SubStepTargets.Property, on_properties); - CategorizeTarget (substep, SubStepTargets.Event, on_events); + CategorizeTarget (substep, SubStepTargets.Assembly, Categorized.on_assemblies); + CategorizeTarget (substep, SubStepTargets.Type, Categorized.on_types); + CategorizeTarget (substep, SubStepTargets.Field, Categorized.on_fields); + CategorizeTarget (substep, SubStepTargets.Method, Categorized.on_methods); + CategorizeTarget (substep, SubStepTargets.Property, Categorized.on_properties); + CategorizeTarget (substep, SubStepTargets.Event, Categorized.on_events); } static void CategorizeTarget (ISubStep substep, SubStepTargets target, List<ISubStep> list) diff --git a/src/linker/Linker.Steps/OutputStep.cs b/src/linker/Linker.Steps/OutputStep.cs index 1917965a1..b28d52c8d 100644 --- a/src/linker/Linker.Steps/OutputStep.cs +++ b/src/linker/Linker.Steps/OutputStep.cs @@ -39,7 +39,7 @@ namespace Mono.Linker.Steps public class OutputStep : BaseStep { - private Dictionary<UInt16, TargetArchitecture> architectureMap; + private Dictionary<UInt16, TargetArchitecture>? architectureMap; private enum NativeOSOverride { diff --git a/src/linker/Linker.Steps/ProcessLinkerXmlBase.cs b/src/linker/Linker.Steps/ProcessLinkerXmlBase.cs index fd333cd31..4582a3410 100644 --- a/src/linker/Linker.Steps/ProcessLinkerXmlBase.cs +++ b/src/linker/Linker.Steps/ProcessLinkerXmlBase.cs @@ -13,8 +13,6 @@ using System.Xml.Linq; using System.Xml.XPath; using Mono.Cecil; -#nullable enable - namespace Mono.Linker.Steps { [Flags] @@ -140,7 +138,7 @@ namespace Mono.Linker.Steps ProcessAssembly (assembly, assemblyNav, warnOnUnresolvedTypes: false); } else { Debug.Assert (!processAllAssemblies); - AssemblyDefinition assembly = assemblyToProcess ?? _context.TryResolve (name!); + AssemblyDefinition? assembly = assemblyToProcess ?? _context.TryResolve (name!); if (assembly == null) { LogWarning ($"Could not resolve assembly '{name!.Name}'.", 2007, assemblyNav); diff --git a/src/linker/Linker.Steps/ReflectionBlockedStep.cs b/src/linker/Linker.Steps/ReflectionBlockedStep.cs index 22b7e4633..9114f6a19 100644 --- a/src/linker/Linker.Steps/ReflectionBlockedStep.cs +++ b/src/linker/Linker.Steps/ReflectionBlockedStep.cs @@ -1,10 +1,18 @@ +using System; +using System.Diagnostics; using Mono.Cecil; namespace Mono.Linker.Steps { public class ReflectionBlockedStep : BaseStep { - AssemblyDefinition assembly; + AssemblyDefinition? assembly; + AssemblyDefinition Assembly { + get { + Debug.Assert (assembly != null); + return assembly; + } + } protected override void ProcessAssembly (AssemblyDefinition assembly) { @@ -56,8 +64,8 @@ namespace Mono.Linker.Steps { // We are using DisableReflectionAttribute which is not exact match but it's quite // close to what we need and it already exists in the BCL - MethodReference ctor = Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor; - ctor = assembly.MainModule.ImportReference (ctor); + MethodReference ctor = Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor ?? throw new InvalidOperationException (); + ctor = Assembly.MainModule.ImportReference (ctor); var ca = new CustomAttribute (ctor); caProvider.CustomAttributes.Add (ca); diff --git a/src/linker/Linker.Steps/RootAssemblyInputStep.cs b/src/linker/Linker.Steps/RootAssemblyInputStep.cs index 55b4e7806..47ebc79fa 100644 --- a/src/linker/Linker.Steps/RootAssemblyInputStep.cs +++ b/src/linker/Linker.Steps/RootAssemblyInputStep.cs @@ -19,7 +19,7 @@ namespace Mono.Linker.Steps protected override void Process () { - AssemblyDefinition assembly = LoadAssemblyFile (); + AssemblyDefinition? assembly = LoadAssemblyFile (); if (assembly == null) return; @@ -95,13 +95,13 @@ namespace Mono.Linker.Steps } } - AssemblyDefinition LoadAssemblyFile () + AssemblyDefinition? LoadAssemblyFile () { - AssemblyDefinition assembly; + AssemblyDefinition? assembly; if (File.Exists (fileName)) { assembly = Context.Resolver.GetAssembly (fileName); - AssemblyDefinition loaded = Context.GetLoadedAssembly (assembly.Name.Name); + AssemblyDefinition? loaded = Context.GetLoadedAssembly (assembly.Name.Name); // The same assembly could be already loaded if there are multiple inputs pointing to same file if (loaded != null) diff --git a/src/linker/Linker.Steps/SealerStep.cs b/src/linker/Linker.Steps/SealerStep.cs index b68203289..cf98d7985 100644 --- a/src/linker/Linker.Steps/SealerStep.cs +++ b/src/linker/Linker.Steps/SealerStep.cs @@ -10,7 +10,7 @@ namespace Mono.Linker.Steps { public class SealerStep : BaseStep { - HashSet<TypeDefinition> referencedBaseTypeCache; + HashSet<TypeDefinition>? referencedBaseTypeCache; public SealerStep () { @@ -56,7 +56,7 @@ namespace Mono.Linker.Steps } var bt = Context.TryResolve (type); - return referencedBaseTypeCache.Contains (bt); + return bt != null && referencedBaseTypeCache.Contains (bt); } void ProcessType (TypeDefinition type) @@ -123,7 +123,7 @@ namespace Mono.Linker.Steps method.IsFinal = true; } - bool IsAnyMarked (IEnumerable<OverrideInformation> list) + bool IsAnyMarked (IEnumerable<OverrideInformation>? list) { if (list == null) return false; @@ -135,7 +135,7 @@ namespace Mono.Linker.Steps return false; } - bool IsAnyMarked (List<MethodDefinition> list) + bool IsAnyMarked (List<MethodDefinition>? list) { if (list == null) return false; diff --git a/src/linker/Linker.Steps/SubStepsDispatcher.cs b/src/linker/Linker.Steps/SubStepsDispatcher.cs index 050010e9c..3ed5a6e1c 100644 --- a/src/linker/Linker.Steps/SubStepsDispatcher.cs +++ b/src/linker/Linker.Steps/SubStepsDispatcher.cs @@ -1,13 +1,25 @@ // 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; +using System.Diagnostics; using Mono.Cecil; using Mono.Collections.Generic; namespace Mono.Linker.Steps { + struct CategorizedSubSteps + { + public List<ISubStep> on_assemblies; + public List<ISubStep> on_types; + public List<ISubStep> on_fields; + public List<ISubStep> on_methods; + public List<ISubStep> on_properties; + public List<ISubStep> on_events; + } + // // Generic steps dispatcher is intended to by used by custom linker step which // consist of multiple steps. It simplifies their implementation as well as the @@ -17,12 +29,13 @@ namespace Mono.Linker.Steps { readonly List<ISubStep> substeps; - List<ISubStep> on_assemblies; - List<ISubStep> on_types; - List<ISubStep> on_fields; - List<ISubStep> on_methods; - List<ISubStep> on_properties; - List<ISubStep> on_events; + CategorizedSubSteps? categorized; + CategorizedSubSteps Categorized { + get { + Debug.Assert (categorized.HasValue); + return categorized.Value; + } + } protected SubStepsDispatcher () { @@ -53,7 +66,7 @@ namespace Mono.Linker.Steps foreach (var assembly in assemblies) { CategorizeSubSteps (assembly); - if (HasSubSteps (on_assemblies)) + if (HasSubSteps (Categorized.on_assemblies)) DispatchAssembly (assembly); if (!ShouldDispatchTypes ()) @@ -65,11 +78,11 @@ namespace Mono.Linker.Steps bool ShouldDispatchTypes () { - return HasSubSteps (on_types) - || HasSubSteps (on_fields) - || HasSubSteps (on_methods) - || HasSubSteps (on_properties) - || HasSubSteps (on_events); + return HasSubSteps (Categorized.on_types) + || HasSubSteps (Categorized.on_fields) + || HasSubSteps (Categorized.on_methods) + || HasSubSteps (Categorized.on_properties) + || HasSubSteps (Categorized.on_events); } void BrowseTypes (Collection<TypeDefinition> types) @@ -77,22 +90,22 @@ namespace Mono.Linker.Steps foreach (TypeDefinition type in types) { DispatchType (type); - if (type.HasFields && HasSubSteps (on_fields)) { + if (type.HasFields && HasSubSteps (Categorized.on_fields)) { foreach (FieldDefinition field in type.Fields) DispatchField (field); } - if (type.HasMethods && HasSubSteps (on_methods)) { + if (type.HasMethods && HasSubSteps (Categorized.on_methods)) { foreach (MethodDefinition method in type.Methods) DispatchMethod (method); } - if (type.HasProperties && HasSubSteps (on_properties)) { + if (type.HasProperties && HasSubSteps (Categorized.on_properties)) { foreach (PropertyDefinition property in type.Properties) DispatchProperty (property); } - if (type.HasEvents && HasSubSteps (on_events)) { + if (type.HasEvents && HasSubSteps (Categorized.on_events)) { foreach (EventDefinition @event in type.Events) DispatchEvent (@event); } @@ -104,42 +117,42 @@ namespace Mono.Linker.Steps void DispatchAssembly (AssemblyDefinition assembly) { - foreach (var substep in on_assemblies) { + foreach (var substep in Categorized.on_assemblies) { substep.ProcessAssembly (assembly); } } void DispatchType (TypeDefinition type) { - foreach (var substep in on_types) { + foreach (var substep in Categorized.on_types) { substep.ProcessType (type); } } void DispatchField (FieldDefinition field) { - foreach (var substep in on_fields) { + foreach (var substep in Categorized.on_fields) { substep.ProcessField (field); } } void DispatchMethod (MethodDefinition method) { - foreach (var substep in on_methods) { + foreach (var substep in Categorized.on_methods) { substep.ProcessMethod (method); } } void DispatchProperty (PropertyDefinition property) { - foreach (var substep in on_properties) { + foreach (var substep in Categorized.on_properties) { substep.ProcessProperty (property); } } void DispatchEvent (EventDefinition @event) { - foreach (var substep in on_events) { + foreach (var substep in Categorized.on_events) { substep.ProcessEvent (@event); } } @@ -152,12 +165,14 @@ namespace Mono.Linker.Steps void CategorizeSubSteps (AssemblyDefinition assembly) { - on_assemblies = new List<ISubStep> (); - on_types = new List<ISubStep> (); - on_fields = new List<ISubStep> (); - on_methods = new List<ISubStep> (); - on_properties = new List<ISubStep> (); - on_events = new List<ISubStep> (); + categorized = new CategorizedSubSteps { + on_assemblies = new List<ISubStep> (), + on_types = new List<ISubStep> (), + on_fields = new List<ISubStep> (), + on_methods = new List<ISubStep> (), + on_properties = new List<ISubStep> (), + on_events = new List<ISubStep> () + }; foreach (var substep in substeps) CategorizeSubStep (substep, assembly); @@ -168,12 +183,12 @@ namespace Mono.Linker.Steps if (!substep.IsActiveFor (assembly)) return; - CategorizeTarget (substep, SubStepTargets.Assembly, on_assemblies); - CategorizeTarget (substep, SubStepTargets.Type, on_types); - CategorizeTarget (substep, SubStepTargets.Field, on_fields); - CategorizeTarget (substep, SubStepTargets.Method, on_methods); - CategorizeTarget (substep, SubStepTargets.Property, on_properties); - CategorizeTarget (substep, SubStepTargets.Event, on_events); + CategorizeTarget (substep, SubStepTargets.Assembly, Categorized.on_assemblies); + CategorizeTarget (substep, SubStepTargets.Type, Categorized.on_types); + CategorizeTarget (substep, SubStepTargets.Field, Categorized.on_fields); + CategorizeTarget (substep, SubStepTargets.Method, Categorized.on_methods); + CategorizeTarget (substep, SubStepTargets.Property, Categorized.on_properties); + CategorizeTarget (substep, SubStepTargets.Event, Categorized.on_events); } static void CategorizeTarget (ISubStep substep, SubStepTargets target, List<ISubStep> list) diff --git a/src/linker/Linker.Steps/SweepStep.cs b/src/linker/Linker.Steps/SweepStep.cs index ebc096004..c560d4e13 100644 --- a/src/linker/Linker.Steps/SweepStep.cs +++ b/src/linker/Linker.Steps/SweepStep.cs @@ -39,7 +39,6 @@ namespace Mono.Linker.Steps { public class SweepStep : BaseStep { - AssemblyDefinition[] assemblies; readonly bool sweepSymbols; readonly HashSet<AssemblyDefinition> BypassNGenToSave = new HashSet<AssemblyDefinition> (); @@ -51,7 +50,7 @@ namespace Mono.Linker.Steps protected override void Process () { // To keep facades, scan all references so that even unused facades are kept - assemblies = Context.KeepTypeForwarderOnlyAssemblies ? + var assemblies = Context.KeepTypeForwarderOnlyAssemblies ? Context.GetReferencedAssemblies ().ToArray () : Annotations.GetAssemblies ().ToArray (); // Ensure that any assemblies which need to be removed are marked for deletion, @@ -122,7 +121,7 @@ namespace Mono.Linker.Steps case AssemblyAction.AddBypassNGen: case AssemblyAction.AddBypassNGenUsed: foreach (var reference in assembly.MainModule.AssemblyReferences) { - AssemblyDefinition ad = Context.Resolver.Resolve (reference); + AssemblyDefinition? ad = Context.Resolver.Resolve (reference); if (ad == null) continue; @@ -386,7 +385,10 @@ namespace Mono.Linker.Steps if (!providerAsSecurity.HasSecurityDeclarations) { // If the method or type had security before and all attributes were removed, or no remaining attributes are security attributes, // then we need to set HasSecurity to false - if (!provider.HasCustomAttributes || provider.CustomAttributes.All (attr => !IsSecurityAttributeType (Context.TryResolve (attr.AttributeType)))) + if (!provider.HasCustomAttributes || provider.CustomAttributes.All (attr => { + TypeDefinition? attributeType = Context.TryResolve (attr.AttributeType); + return attributeType == null || !IsSecurityAttributeType (attributeType); + })) return true; } @@ -407,11 +409,11 @@ namespace Mono.Linker.Steps }; } - definition = Context.TryResolve (definition.BaseType); - if (definition == null) + var baseDefinition = Context.TryResolve (definition.BaseType); + if (baseDefinition == null) return false; - return IsSecurityAttributeType (definition); + return IsSecurityAttributeType (baseDefinition); } protected bool SweepCustomAttributes (ICustomAttributeProvider provider) @@ -464,7 +466,7 @@ namespace Mono.Linker.Steps void SweepDebugInfo (Collection<MethodDefinition> methods) { - List<ScopeDebugInformation> sweptScopes = null; + List<ScopeDebugInformation>? sweptScopes = null; foreach (var m in methods) { if (m.DebugInformation == null) continue; diff --git a/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs b/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs index e6e52fecb..b48f143bf 100644 --- a/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs +++ b/src/linker/Linker.Steps/UnreachableBlocksOptimizer.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; @@ -17,7 +18,7 @@ namespace Mono.Linker.Steps public class UnreachableBlocksOptimizer { readonly LinkContext _context; - MethodDefinition IntPtrSize, UIntPtrSize; + MethodDefinition? IntPtrSize, UIntPtrSize; readonly struct ProcessingNode { @@ -166,7 +167,7 @@ namespace Mono.Linker.Steps // To fix this go over the stack and find the "oldest" node with the current version - the "oldest" node which // is part of the loop: - LinkedListNode<ProcessingNode> lastNodeWithCurrentVersion = null; + LinkedListNode<ProcessingNode>? lastNodeWithCurrentVersion = null; var candidateNodeToMoveToTop = _processingStack.Last; bool foundNodesWithNonCurrentVersion = false; while (candidateNodeToMoveToTop != stackNode) { @@ -265,7 +266,7 @@ namespace Mono.Linker.Steps Debug.Assert (_processingMethods.Count == 0); } - Instruction AnalyzeMethodForConstantResult (MethodDefinition method, Collection<Instruction> instructions) + Instruction? AnalyzeMethodForConstantResult (MethodDefinition method, Collection<Instruction>? instructions) { if (method.ReturnType.MetadataType == MetadataType.Void) return null; @@ -306,9 +307,9 @@ namespace Mono.Linker.Steps /// constantResultInstruction is set to an instance if the method returns a constant, otherwise it's set to null /// false - if the method has not yet been analyzed and the caller should retry later /// </returns> - bool TryGetConstantResultForMethod (MethodDefinition method, out Instruction constantResultInstruction) + bool TryGetConstantResultForMethod (MethodDefinition method, out Instruction? constantResultInstruction) { - if (!_processedMethods.TryGetValue (method, out Instruction methodValue)) { + if (!_processedMethods.TryGetValue (method, out Instruction? methodValue)) { if (_processingMethods.TryGetValue (method, out var stackNode)) { // Method is already in the stack - not yet processed // Move it to the top of the stack @@ -350,7 +351,7 @@ namespace Mono.Linker.Steps changed = false; bool hasUnprocessedDependencies = false; var instructions = reducer.Body.Instructions; - Instruction targetResult; + Instruction? targetResult; for (int i = 0; i < instructions.Count; ++i) { var instr = instructions[i]; @@ -416,7 +417,7 @@ namespace Mono.Linker.Steps if (field == null) break; - if (_context.Annotations.TryGetFieldUserValue (field, out object value)) { + if (_context.Annotations.TryGetFieldUserValue (field, out object? value)) { targetResult = CodeRewriterStep.CreateConstantResultInstruction (_context, field.FieldType, value); if (targetResult == null) break; @@ -431,7 +432,7 @@ namespace Mono.Linker.Steps // which are simple static properties commonly overwritten. Instead of forcing C# code style // we handle both via static Size property // - MethodDefinition sizeOfImpl = null; + MethodDefinition? sizeOfImpl = null; var operand = (TypeReference) instr.Operand; if (operand.MetadataType == MetadataType.UIntPtr) { @@ -460,7 +461,7 @@ namespace Mono.Linker.Steps return !hasUnprocessedDependencies; } - static MethodDefinition FindSizeMethod (TypeDefinition type) + static MethodDefinition? FindSizeMethod (TypeDefinition? type) { if (type == null) return null; @@ -471,13 +472,13 @@ namespace Mono.Linker.Steps struct BodyReducer { readonly LinkContext context; - Dictionary<Instruction, int> mapping; + Dictionary<Instruction, int>? mapping; // // Sorted list of body instruction indexes which were // replaced pass-through nop // - List<int> conditionInstrsToRemove; + List<int>? conditionInstrsToRemove; public BodyReducer (MethodBody body, LinkContext context) { @@ -494,7 +495,7 @@ namespace Mono.Linker.Steps public int InstructionsReplaced { get; set; } - public Collection<Instruction> FoldedInstructions { get; private set; } + public Collection<Instruction>? FoldedInstructions { get; private set; } public void Rewrite (int index, Instruction newInstruction) { @@ -502,6 +503,7 @@ namespace Mono.Linker.Steps FoldedInstructions = new Collection<Instruction> (Body.Instructions); mapping = new Dictionary<Instruction, int> (); } + Debug.Assert (mapping != null); // Tracks mapping for replaced instructions for easier // branch targets resolution later @@ -687,8 +689,9 @@ namespace Mono.Linker.Steps bool RemoveConditions () { + Debug.Assert (FoldedInstructions != null); bool changed = false; - object left, right; + object? left, right; // // Finds any branchable instruction and checks if the operand or operands @@ -825,12 +828,13 @@ namespace Mono.Linker.Steps return changed; } - BitArray GetReachableInstructionsMap (out List<ExceptionHandler> unreachableHandlers) + BitArray GetReachableInstructionsMap (out List<ExceptionHandler>? unreachableHandlers) { + Debug.Assert (FoldedInstructions != null); unreachableHandlers = null; var reachable = new BitArray (FoldedInstructions.Count); - Stack<int> condBranches = null; + Stack<int>? condBranches = null; bool exceptionHandlersChecked = !Body.HasExceptionHandlers; Instruction target; int i = 0; @@ -934,6 +938,7 @@ namespace Mono.Linker.Steps // int GetInstructionIndex (Instruction instruction) { + Debug.Assert (FoldedInstructions != null && mapping != null); if (mapping.TryGetValue (instruction, out int idx)) return idx; @@ -942,8 +947,9 @@ namespace Mono.Linker.Steps return idx; } - bool GetOperandsConstantValues (int index, out object left, out object right) + bool GetOperandsConstantValues (int index, out object? left, out object? right) { + Debug.Assert (FoldedInstructions != null); left = default; right = default; @@ -954,7 +960,7 @@ namespace Mono.Linker.Steps GetConstantValue (FoldedInstructions[index - 1], out right); } - static bool GetConstantValue (Instruction instruction, out object value) + static bool GetConstantValue (Instruction instruction, out object? value) { switch (instruction.OpCode.Code) { case Code.Ldc_I4_0: @@ -1084,6 +1090,7 @@ namespace Mono.Linker.Steps bool IsJumpTargetRange (int firstInstr, int lastInstr) { + Debug.Assert (FoldedInstructions != null); foreach (var instr in FoldedInstructions) { switch (instr.OpCode.FlowControl) { case FlowControl.Branch: @@ -1112,11 +1119,17 @@ namespace Mono.Linker.Steps { readonly MethodBody body; readonly BitArray reachable; - readonly List<ExceptionHandler> unreachableExceptionHandlers; + readonly List<ExceptionHandler>? unreachableExceptionHandlers; readonly LinkContext context; - LinkerILProcessor ilprocessor; + LinkerILProcessor? ilprocessor; + LinkerILProcessor ILProcessor { + get { + Debug.Assert (ilprocessor != null); + return ilprocessor; + } + } - public BodySweeper (MethodBody body, BitArray reachable, List<ExceptionHandler> unreachableEH, LinkContext context) + public BodySweeper (MethodBody body, BitArray reachable, List<ExceptionHandler>? unreachableEH, LinkContext context) { this.body = body; this.reachable = reachable; @@ -1159,9 +1172,9 @@ namespace Mono.Linker.Steps return true; } - public void Process (List<int> conditionInstrsToRemove, out List<Instruction> sentinelNops) + public void Process (List<int>? conditionInstrsToRemove, out List<Instruction>? sentinelNops) { - List<VariableDefinition> removedVariablesReferences = null; + List<VariableDefinition>? removedVariablesReferences = null; // // Initial pass which replaces unreachable instructions with nops or @@ -1181,10 +1194,10 @@ namespace Mono.Linker.Steps newInstr = Instruction.Create (OpCodes.Nop); } - ilprocessor.Replace (i, newInstr); + ILProcessor.Replace (i, newInstr); InstructionsReplaced++; - VariableDefinition variable = GetVariableReference (instr); + VariableDefinition? variable = GetVariableReference (instr); if (variable != null) { if (removedVariablesReferences == null) removedVariablesReferences = new List<VariableDefinition> (); @@ -1223,12 +1236,12 @@ namespace Mono.Linker.Steps sentinelNops = new List<Instruction> (); sentinelNops.Add (nop); - ilprocessor.Replace (index - 1, Instruction.Create (OpCodes.Pop)); - ilprocessor.Replace (index, nop); + ILProcessor.Replace (index - 1, Instruction.Create (OpCodes.Pop)); + ILProcessor.Replace (index, nop); } else { var pop = Instruction.Create (OpCodes.Pop); - ilprocessor.Replace (index, pop); - ilprocessor.InsertAfter (pop, Instruction.Create (OpCodes.Pop)); + ILProcessor.Replace (index, pop); + ILProcessor.InsertAfter (pop, Instruction.Create (OpCodes.Pop)); // // conditionInstrsToRemove is always sorted and instead of @@ -1238,7 +1251,7 @@ namespace Mono.Linker.Steps } break; case StackBehaviour.Popi: - ilprocessor.Replace (index, Instruction.Create (OpCodes.Pop)); + ILProcessor.Replace (index, Instruction.Create (OpCodes.Pop)); InstructionsReplaced++; break; } @@ -1257,7 +1270,7 @@ namespace Mono.Linker.Steps void CleanRemovedVariables (List<VariableDefinition> variables) { foreach (var instr in body.Instructions) { - VariableDefinition variable = GetVariableReference (instr); + VariableDefinition? variable = GetVariableReference (instr); if (variable == null) continue; @@ -1297,7 +1310,7 @@ namespace Mono.Linker.Steps body.ExceptionHandlers.Remove (eh); } - VariableDefinition GetVariableReference (Instruction instruction) + VariableDefinition? GetVariableReference (Instruction instruction) { switch (instruction.OpCode.Code) { case Code.Stloc_0: @@ -1360,8 +1373,8 @@ namespace Mono.Linker.Steps readonly Collection<Instruction> instructions; readonly LinkContext context; - Stack<Instruction> stack_instr; - Dictionary<int, Instruction> locals; + Stack<Instruction>? stack_instr; + Dictionary<int, Instruction>? locals; public ConstantExpressionMethodAnalyzer (LinkContext context, MethodDefinition method) { @@ -1379,8 +1392,9 @@ namespace Mono.Linker.Steps this.instructions = instructions; } - public Instruction Result { get; private set; } + public Instruction? Result { get; private set; } + [MemberNotNullWhen (true, "Result")] public bool Analyze () { var body = method.Body; @@ -1388,8 +1402,8 @@ namespace Mono.Linker.Steps return false; VariableReference vr; - Instruction jmpTarget = null; - Instruction linstr; + Instruction? jmpTarget = null; + Instruction? linstr; foreach (var instr in instructions) { if (jmpTarget != null) { @@ -1403,6 +1417,8 @@ namespace Mono.Linker.Steps case Code.Nop: continue; case Code.Pop: + if (stack_instr == null) + Debug.Fail ("Invalid IL?"); stack_instr.Pop (); continue; @@ -1501,6 +1517,7 @@ namespace Mono.Linker.Steps return false; } + [MemberNotNullWhen (true, "Result")] bool ConvertStackToResult () { if (stack_instr == null) @@ -1534,9 +1551,9 @@ namespace Mono.Linker.Steps return false; } - Instruction GetLocalsValue (int index, MethodBody body) + Instruction? GetLocalsValue (int index, MethodBody body) { - if (locals != null && locals.TryGetValue (index, out Instruction instruction)) + if (locals != null && locals.TryGetValue (index, out Instruction? instruction)) return instruction; if (!body.InitLocals) @@ -1559,6 +1576,8 @@ namespace Mono.Linker.Steps if (locals == null) locals = new Dictionary<int, Instruction> (); + if (stack_instr == null) + Debug.Fail ("Invalid IL?"); locals[index] = stack_instr.Pop (); } } diff --git a/src/linker/Linker/Annotations.cs b/src/linker/Linker/Annotations.cs index 781eaa516..eb5274a46 100644 --- a/src/linker/Linker/Annotations.cs +++ b/src/linker/Linker/Annotations.cs @@ -25,7 +25,6 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#nullable enable using System; using System.Collections.Generic; @@ -402,12 +401,12 @@ namespace Mono.Linker return preserved_exportedtype_members.TryGetValue (type, out preserve); } - public bool TryGetMethodStubValue (MethodDefinition method, out object value) + public bool TryGetMethodStubValue (MethodDefinition method, out object? value) { return MemberActions.TryGetMethodStubValue (method, out value); } - public bool TryGetFieldUserValue (FieldDefinition field, out object value) + public bool TryGetFieldUserValue (FieldDefinition field, out object? value) { return MemberActions.TryGetFieldUserValue (field, out value); } @@ -438,17 +437,17 @@ namespace Mono.Linker return public_api.Contains (provider); } - public IEnumerable<OverrideInformation> GetOverrides (MethodDefinition method) + public IEnumerable<OverrideInformation>? GetOverrides (MethodDefinition method) { return TypeMapInfo.GetOverrides (method); } - public IEnumerable<(TypeDefinition InstanceType, InterfaceImplementation ProvidingInterface)> GetDefaultInterfaceImplementations (MethodDefinition method) + public IEnumerable<(TypeDefinition InstanceType, InterfaceImplementation ProvidingInterface)>? GetDefaultInterfaceImplementations (MethodDefinition method) { return TypeMapInfo.GetDefaultInterfaceImplementations (method); } - public List<MethodDefinition> GetBaseMethods (MethodDefinition method) + public List<MethodDefinition>? GetBaseMethods (MethodDefinition method) { return TypeMapInfo.GetBaseMethods (method); } diff --git a/src/linker/Linker/ArrayBuilder.cs b/src/linker/Linker/ArrayBuilder.cs index d249c4057..0dee12a9d 100644 --- a/src/linker/Linker/ArrayBuilder.cs +++ b/src/linker/Linker/ArrayBuilder.cs @@ -14,7 +14,7 @@ namespace Mono.Linker public bool Any (Predicate<T> callback) => _list?.Exists (callback) == true; - public T[] ToArray () => _list?.ToArray (); + public T[]? ToArray () => _list?.ToArray (); public int Count => _list?.Count ?? 0; } diff --git a/src/linker/Linker/AssemblyDefinitionExtensions.cs b/src/linker/Linker/AssemblyDefinitionExtensions.cs index d5aced51a..caf0a13f0 100644 --- a/src/linker/Linker/AssemblyDefinitionExtensions.cs +++ b/src/linker/Linker/AssemblyDefinitionExtensions.cs @@ -4,7 +4,7 @@ namespace Mono.Linker { public static class AssemblyDefinitionExtensions { - public static EmbeddedResource FindEmbeddedResource (this AssemblyDefinition assembly, string name) + public static EmbeddedResource? FindEmbeddedResource (this AssemblyDefinition assembly, string name) { foreach (var resource in assembly.MainModule.Resources) { if (resource is EmbeddedResource embeddedResource && embeddedResource.Name == name) diff --git a/src/linker/Linker/AssemblyResolver.cs b/src/linker/Linker/AssemblyResolver.cs index 73571e5f8..d579dda90 100644 --- a/src/linker/Linker/AssemblyResolver.cs +++ b/src/linker/Linker/AssemblyResolver.cs @@ -43,8 +43,8 @@ namespace Mono.Linker readonly List<MemoryMappedViewStream> _viewStreams = new (); readonly ReaderParameters _defaultReaderParameters; - HashSet<string> _unresolvedAssemblies; - HashSet<string> _reportedUnresolvedAssemblies; + HashSet<string>? _unresolvedAssemblies; + HashSet<string>? _reportedUnresolvedAssemblies; public AssemblyResolver (LinkContext context) { @@ -58,13 +58,13 @@ namespace Mono.Linker public string GetAssemblyLocation (AssemblyDefinition assembly) { - if (_assemblyToPath.TryGetValue (assembly, out string path)) + if (_assemblyToPath.TryGetValue (assembly, out string? path)) return path; throw new InternalErrorException ($"Assembly '{assembly}' was not loaded using linker resolver"); } - AssemblyDefinition ResolveFromReferences (AssemblyNameReference name) + AssemblyDefinition? ResolveFromReferences (AssemblyNameReference name) { foreach (var reference in _references) { foreach (var extension in Extensions) { @@ -82,9 +82,9 @@ namespace Mono.Linker return null; } - public AssemblyDefinition Resolve (AssemblyNameReference name, bool probing) + public AssemblyDefinition? Resolve (AssemblyNameReference name, bool probing) { - if (AssemblyCache.TryGetValue (name.Name, out AssemblyDefinition asm)) + if (AssemblyCache.TryGetValue (name.Name, out AssemblyDefinition? asm)) return asm; if (_unresolvedAssemblies?.Contains (name.Name) == true) { @@ -135,7 +135,7 @@ namespace Mono.Linker public AssemblyDefinition GetAssembly (string file) { - MemoryMappedViewStream viewStream = null; + MemoryMappedViewStream? viewStream = null; try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict using var fileStream = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); @@ -159,7 +159,7 @@ namespace Mono.Linker } } - public AssemblyDefinition Resolve (AssemblyNameReference name) + public AssemblyDefinition? Resolve (AssemblyNameReference name) { return Resolve (name, probing: false); } @@ -172,7 +172,7 @@ namespace Mono.Linker static readonly string[] Extensions = new[] { ".dll", ".exe" }; - AssemblyDefinition SearchDirectory (AssemblyNameReference name) + AssemblyDefinition? SearchDirectory (AssemblyNameReference name) { foreach (var directory in _directories) { foreach (var extension in Extensions) { diff --git a/src/linker/Linker/BCL.cs b/src/linker/Linker/BCL.cs index 3eadf8cd9..23aaedaec 100644 --- a/src/linker/Linker/BCL.cs +++ b/src/linker/Linker/BCL.cs @@ -63,10 +63,10 @@ namespace Mono.Linker "netstandard" }; - public static TypeDefinition FindPredefinedType (string ns, string name, LinkContext context) + public static TypeDefinition? FindPredefinedType (string ns, string name, LinkContext context) { foreach (var corlibName in corlibNames) { - AssemblyDefinition corlib = context.TryResolve (corlibName); + AssemblyDefinition? corlib = context.TryResolve (corlibName); if (corlib == null) continue; diff --git a/src/linker/Linker/CompilerGeneratedState.cs b/src/linker/Linker/CompilerGeneratedState.cs index 34821288b..47780ace0 100644 --- a/src/linker/Linker/CompilerGeneratedState.cs +++ b/src/linker/Linker/CompilerGeneratedState.cs @@ -41,7 +41,7 @@ namespace Mono.Linker case "AsyncIteratorStateMachineAttribute": case "AsyncStateMachineAttribute": case "IteratorStateMachineAttribute": - TypeDefinition stateMachineType = GetFirstConstructorArgumentAsType (attribute); + TypeDefinition? stateMachineType = GetFirstConstructorArgumentAsType (attribute); if (stateMachineType != null) { if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd (stateMachineType, method)) { var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType]; @@ -59,7 +59,7 @@ namespace Mono.Linker } } - static TypeDefinition GetFirstConstructorArgumentAsType (CustomAttribute attribute) + static TypeDefinition? GetFirstConstructorArgumentAsType (CustomAttribute attribute) { if (!attribute.HasConstructorArguments) return null; @@ -67,13 +67,13 @@ namespace Mono.Linker return attribute.ConstructorArguments[0].Value as TypeDefinition; } - public MethodDefinition GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) + public MethodDefinition? GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) { if (sourceMember == null) return null; TypeDefinition compilerGeneratedType = (sourceMember as TypeDefinition) ?? sourceMember.DeclaringType; - if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition userDefinedMethod)) + if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition? userDefinedMethod)) return userDefinedMethod; // Only handle async or iterator state machine diff --git a/src/linker/Linker/CustomAttributeSource.cs b/src/linker/Linker/CustomAttributeSource.cs index 55f7a11a6..6b5033a8c 100644 --- a/src/linker/Linker/CustomAttributeSource.cs +++ b/src/linker/Linker/CustomAttributeSource.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Mono.Cecil; namespace Mono.Linker @@ -10,13 +11,13 @@ namespace Mono.Linker public class CustomAttributeSource { public AttributeInfo PrimaryAttributeInfo { get; } - private readonly Dictionary<AssemblyDefinition, AttributeInfo> _embeddedXmlInfos; + private readonly Dictionary<AssemblyDefinition, AttributeInfo?> _embeddedXmlInfos; readonly LinkContext _context; public CustomAttributeSource (LinkContext context) { PrimaryAttributeInfo = new AttributeInfo (); - _embeddedXmlInfos = new Dictionary<AssemblyDefinition, AttributeInfo> (); + _embeddedXmlInfos = new Dictionary<AssemblyDefinition, AttributeInfo?> (); _context = context; } @@ -34,7 +35,7 @@ namespace Mono.Linker }; } - public bool TryGetEmbeddedXmlInfo (ICustomAttributeProvider provider, out AttributeInfo xmlInfo) + public bool TryGetEmbeddedXmlInfo (ICustomAttributeProvider provider, [NotNullWhen (true)] out AttributeInfo? xmlInfo) { var assembly = GetAssemblyFromCustomAttributeProvider (provider); diff --git a/src/linker/Linker/DependencyInfo.cs b/src/linker/Linker/DependencyInfo.cs index 72ab233df..96be4dbf7 100644 --- a/src/linker/Linker/DependencyInfo.cs +++ b/src/linker/Linker/DependencyInfo.cs @@ -145,13 +145,13 @@ namespace Mono.Linker public readonly struct DependencyInfo : IEquatable<DependencyInfo> { public DependencyKind Kind { get; } - public object Source { get; } - public DependencyInfo (DependencyKind kind, object source) => (Kind, Source) = (kind, source); + public object? Source { get; } + public DependencyInfo (DependencyKind kind, object? source) => (Kind, Source) = (kind, source); public static readonly DependencyInfo Unspecified = new DependencyInfo (DependencyKind.Unspecified, null); public static readonly DependencyInfo AlreadyMarked = new DependencyInfo (DependencyKind.AlreadyMarked, null); public static readonly DependencyInfo DisablePrivateReflectionRequirement = new DependencyInfo (DependencyKind.DisablePrivateReflectionRequirement, null); public bool Equals (DependencyInfo other) => (Kind, Source) == (other.Kind, other.Source); - public override bool Equals (Object obj) => obj is DependencyInfo info && this.Equals (info); + public override bool Equals (Object? obj) => obj is DependencyInfo info && this.Equals (info); public override int GetHashCode () => (Kind, Source).GetHashCode (); public static bool operator == (DependencyInfo lhs, DependencyInfo rhs) => lhs.Equals (rhs); public static bool operator != (DependencyInfo lhs, DependencyInfo rhs) => !lhs.Equals (rhs); diff --git a/src/linker/Linker/DocumentationSignatureGenerator.PartVisitor.cs b/src/linker/Linker/DocumentationSignatureGenerator.PartVisitor.cs index 3a2e1458c..65211abd9 100644 --- a/src/linker/Linker/DocumentationSignatureGenerator.PartVisitor.cs +++ b/src/linker/Linker/DocumentationSignatureGenerator.PartVisitor.cs @@ -146,7 +146,10 @@ namespace Mono.Linker } if (typeReference.IsNested) { - VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver), builder, resolver); + Debug.Assert (typeReference is not SentinelType && typeReference is not PinnedType); + // GetInflatedDeclaringType may return null for generic parameters, byrefs, and pointers, but these + // are separately handled above. + VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver)!, builder, resolver); builder.Append ('.'); } diff --git a/src/linker/Linker/DocumentationSignatureGenerator.cs b/src/linker/Linker/DocumentationSignatureGenerator.cs index f473f7759..1a9e545cd 100644 --- a/src/linker/Linker/DocumentationSignatureGenerator.cs +++ b/src/linker/Linker/DocumentationSignatureGenerator.cs @@ -28,19 +28,19 @@ namespace Mono.Linker { switch (member.MetadataToken.TokenType) { case TokenType.TypeDef: - VisitTypeDefinition (member as TypeDefinition, builder, resolver); + VisitTypeDefinition ((TypeDefinition) member, builder, resolver); break; case TokenType.Method: - VisitMethod (member as MethodDefinition, builder, resolver); + VisitMethod ((MethodDefinition) member, builder, resolver); break; case TokenType.Property: - VisitProperty (member as PropertyDefinition, builder, resolver); + VisitProperty ((PropertyDefinition) member, builder, resolver); break; case TokenType.Field: - VisitField (member as FieldDefinition, builder, resolver); + VisitField ((FieldDefinition) member, builder, resolver); break; case TokenType.Event: - VisitEvent (member as EventDefinition, builder, resolver); + VisitEvent ((EventDefinition) member, builder, resolver); break; default: break; diff --git a/src/linker/Linker/DocumentationSignatureParser.cs b/src/linker/Linker/DocumentationSignatureParser.cs index f55c281b4..8a6594e47 100644 --- a/src/linker/Linker/DocumentationSignatureParser.cs +++ b/src/linker/Linker/DocumentationSignatureParser.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index 79d5413ff..2c52424d5 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Runtime.Loader; @@ -66,7 +67,13 @@ namespace Mono.Linker readonly Queue<string> arguments; bool _needAddBypassNGenStep; - protected LinkContext context; + LinkContext? context; + protected LinkContext Context { + get { + Debug.Assert (context != null); + return context; + } + } public Driver (Queue<string> arguments) { @@ -148,7 +155,7 @@ namespace Mono.Linker void ErrorMissingArgument (string optionName) { - context.LogError ($"Missing argument for '{optionName}' option.", 1018); + Context.LogError ($"Missing argument for '{optionName}' option.", 1018); } // Perform setup of the LinkContext and parse the arguments. @@ -156,7 +163,7 @@ namespace Mono.Linker // 0 => successfully set up context with all arguments // 1 => argument processing stopped early without errors // -1 => error setting up context - protected int SetupContext (ILogger customLogger = null) + protected int SetupContext (ILogger? customLogger = null) { Pipeline p = GetStandardPipeline (); context = GetDefaultContext (p, customLogger); @@ -164,9 +171,9 @@ namespace Mono.Linker var body_substituter_steps = new Stack<string> (); var xml_custom_attribute_steps = new Stack<string> (); var custom_steps = new List<string> (); - var set_optimizations = new List<(CodeOptimizations, string, bool)> (); + var set_optimizations = new List<(CodeOptimizations, string?, bool)> (); bool dumpDependencies = false; - string dependenciesFileName = null; + string? dependenciesFileName = null; context.StripSecurity = true; bool new_mvid_used = false; bool deterministic_used = false; @@ -253,7 +260,7 @@ namespace Mono.Linker return -1; } - if (!GetStringParam (token, out string substitutionFile)) + if (!GetStringParam (token, out string? substitutionFile)) return -1; body_substituter_steps.Push (substitutionFile); @@ -266,14 +273,14 @@ namespace Mono.Linker continue; case "--action": { - if (!GetStringParam (token, out string actionString)) + if (!GetStringParam (token, out string? actionString)) return -1; AssemblyAction? action = ParseAssemblyAction (actionString); if (action == null) return -1; - string assemblyName = GetNextStringValue (); + string? assemblyName = GetNextStringValue (); if (assemblyName == null) { context.DefaultAction = action.Value; continue; @@ -288,7 +295,7 @@ namespace Mono.Linker continue; } case "--trim-mode": { - if (!GetStringParam (token, out string actionString)) + if (!GetStringParam (token, out string? actionString)) return -1; AssemblyAction? action = ParseAssemblyAction (actionString); @@ -299,7 +306,7 @@ namespace Mono.Linker continue; } case "--custom-step": - if (!GetStringParam (token, out string custom_step)) + if (!GetStringParam (token, out string? custom_step)) return -1; custom_steps.Add (custom_step); @@ -341,7 +348,7 @@ namespace Mono.Linker continue; case "--keep-metadata": { - if (!GetStringParam (token, out string mname)) + if (!GetStringParam (token, out string? mname)) return -1; if (!TryGetMetadataTrimming (mname, out var type)) @@ -382,32 +389,32 @@ namespace Mono.Linker continue; case "--disable-opt": { - if (!GetStringParam (token, out string optName)) + if (!GetStringParam (token, out string? optName)) return -1; if (!GetOptimizationName (optName, out var opt)) return -1; - string assemblyName = GetNextStringValue (); + string? assemblyName = GetNextStringValue (); set_optimizations.Add ((opt, assemblyName, false)); continue; } case "--enable-opt": { - if (!GetStringParam (token, out string optName)) + if (!GetStringParam (token, out string? optName)) return -1; if (!GetOptimizationName (optName, out var opt)) return -1; - string assemblyName = GetNextStringValue (); + string? assemblyName = GetNextStringValue (); set_optimizations.Add ((opt, assemblyName, true)); continue; } case "--feature": { - if (!GetStringParam (token, out string featureName)) + if (!GetStringParam (token, out string? featureName)) return -1; if (!GetBoolParam (token, value => { @@ -440,7 +447,7 @@ namespace Mono.Linker continue; case "--output-assemblylist": - if (!GetStringParam (token, out string assemblyListFile)) + if (!GetStringParam (token, out string? assemblyListFile)) return -1; context.AssemblyListFile = assemblyListFile; @@ -448,7 +455,7 @@ namespace Mono.Linker continue; case "--output-pinvokes": - if (!GetStringParam (token, out string pinvokesListFile)) + if (!GetStringParam (token, out string? pinvokesListFile)) return -1; context.PInvokesListFile = pinvokesListFile; @@ -461,7 +468,7 @@ namespace Mono.Linker return -1; } - if (!GetStringParam (token, out string fileList)) + if (!GetStringParam (token, out string? fileList)) return -1; foreach (string file in GetFiles (fileList)) @@ -470,7 +477,7 @@ namespace Mono.Linker continue; case "--generate-warning-suppressions": - if (!GetStringParam (token, out string generateWarningSuppressionsArgument)) + if (!GetStringParam (token, out string? generateWarningSuppressionsArgument)) return -1; if (!GetWarningSuppressionWriterFileOutputKind (generateWarningSuppressionsArgument, out var fileOutputKind)) { @@ -482,7 +489,7 @@ namespace Mono.Linker continue; case "--nowarn": - if (!GetStringParam (token, out string noWarnArgument)) + if (!GetStringParam (token, out string? noWarnArgument)) return -1; context.NoWarn.UnionWith (ProcessWarningCodes (noWarnArgument)); @@ -516,7 +523,7 @@ namespace Mono.Linker continue; case "--warn": - if (!GetStringParam (token, out string warnVersionArgument)) + if (!GetStringParam (token, out string? warnVersionArgument)) return -1; if (!GetWarnVersion (warnVersionArgument, out WarnVersion version)) @@ -528,7 +535,7 @@ namespace Mono.Linker case "--singlewarn": case "--singlewarn+": { - string assemblyName = GetNextStringValue (); + string? assemblyName = GetNextStringValue (); if (assemblyName != null) { if (!IsValidAssemblyName (assemblyName)) { context.LogError ($"Invalid assembly name '{assemblyName}'.", 1036); @@ -545,7 +552,7 @@ namespace Mono.Linker } case "--singlewarn-": { - string assemblyName = GetNextStringValue (); + string? assemblyName = GetNextStringValue (); if (assemblyName != null) { if (!IsValidAssemblyName (assemblyName)) { context.LogError ($"Invalid assembly name '{assemblyName}'.", 1036); @@ -575,7 +582,7 @@ namespace Mono.Linker switch (token.Substring (1)) { case "d": - if (!GetStringParam (token, out string directory)) + if (!GetStringParam (token, out string? directory)) return -1; DirectoryInfo info = new DirectoryInfo (directory); @@ -584,7 +591,7 @@ namespace Mono.Linker continue; case "o": case "out": - if (!GetStringParam (token, out string outputDirectory)) + if (!GetStringParam (token, out string? outputDirectory)) return -1; context.OutputDirectory = outputDirectory; @@ -594,7 +601,7 @@ namespace Mono.Linker context.KeepTypeForwarderOnlyAssemblies = true; continue; case "x": { - if (!GetStringParam (token, out string xmlFile)) + if (!GetStringParam (token, out string? xmlFile)) return -1; if (!File.Exists (xmlFile)) { @@ -606,7 +613,7 @@ namespace Mono.Linker continue; } case "a": { - if (!GetStringParam (token, out string assemblyFile)) + if (!GetStringParam (token, out string? assemblyFile)) return -1; if (!File.Exists (assemblyFile) && assemblyFile.EndsWith (".dll", StringComparison.InvariantCultureIgnoreCase)) { @@ -649,7 +656,7 @@ namespace Mono.Linker return 1; case "reference": - if (!GetStringParam (token, out string reference)) + if (!GetStringParam (token, out string? reference)) return -1; context.Resolver.AddReferenceAssembly (reference); @@ -756,7 +763,7 @@ namespace Mono.Linker // to the error code. // May propagate exceptions, which will result in the process getting an // exit code determined by dotnet. - public int Run (ILogger customLogger = null) + public int Run (ILogger? customLogger = null) { int setupStatus = SetupContext (customLogger); if (setupStatus > 0) @@ -764,32 +771,32 @@ namespace Mono.Linker if (setupStatus < 0) return 1; - Pipeline p = context.Pipeline; + Pipeline p = Context.Pipeline; PreProcessPipeline (p); try { - p.Process (context); + p.Process (Context); } catch (LinkerFatalErrorException lex) { - context.LogMessage (lex.MessageContainer); + Context.LogMessage (lex.MessageContainer); Console.Error.WriteLine (lex.ToString ()); Debug.Assert (lex.MessageContainer.Category == MessageCategory.Error); Debug.Assert (lex.MessageContainer.Code != null); Debug.Assert (lex.MessageContainer.Code.Value != 0); return lex.MessageContainer.Code ?? 1; } catch (ResolutionException e) { - context.LogError ($"{e.Message}", 1040); + Context.LogError ($"{e.Message}", 1040); } catch (Exception) { // Unhandled exceptions are usually linker bugs. Ask the user to report it. - context.LogError ($"IL Trimmer has encountered an unexpected error. Please report the issue at https://github.com/dotnet/linker/issues", 1012); + Context.LogError ($"IL Trimmer has encountered an unexpected error. Please report the issue at https://github.com/dotnet/linker/issues", 1012); // Don't swallow the exception and exit code - rethrow it and let the surrounding tooling decide what to do. // The stack trace will go to stderr, and the MSBuild task will surface it with High importance. throw; } finally { - context.FlushCachedWarnings (); - context.Tracer.Finish (); + Context.FlushCachedWarnings (); + Context.Tracer.Finish (); } - return context.ErrorsCount > 0 ? 1 : 0; + return Context.ErrorsCount > 0 ? 1 : 0; } partial void PreProcessPipeline (Pipeline pipeline); @@ -815,7 +822,7 @@ namespace Mono.Linker } } - Assembly GetCustomAssembly (string arg) + Assembly? GetCustomAssembly (string arg) { if (Path.IsPathRooted (arg)) { var assemblyPath = Path.GetFullPath (arg); @@ -824,9 +831,9 @@ namespace Mono.Linker // (or even if a different path specifies the "same" assembly, based on the MVID). return AssemblyLoadContext.Default.LoadFromAssemblyPath (assemblyPath); } - context.LogError ($"The assembly '{arg}' specified for '--custom-step' option could not be found.", 1022); + Context.LogError ($"The assembly '{arg}' specified for '--custom-step' option could not be found.", 1022); } else - context.LogError ($"The path to the assembly '{arg}' specified for '--custom-step' must be fully qualified.", 1023); + Context.LogError ($"The path to the assembly '{arg}' specified for '--custom-step' must be fully qualified.", 1023); return null; } @@ -846,14 +853,14 @@ namespace Mono.Linker pipeline.AddStepBefore (typeof (MarkStep), new BodySubstituterStep (File.OpenRead (file), file)); } - protected virtual void AddXmlDependencyRecorder (LinkContext context, string fileName) + protected virtual void AddXmlDependencyRecorder (LinkContext context, string? fileName) { context.Tracer.AddRecorder (new XmlDependencyRecorder (context, fileName)); } protected bool AddMarkHandler (Pipeline pipeline, string arg) { - if (!TryGetCustomAssembly (ref arg, out Assembly custom_assembly)) + if (!TryGetCustomAssembly (ref arg, out Assembly? custom_assembly)) return false; var step = ResolveStep<IMarkHandler> (arg, custom_assembly); @@ -864,12 +871,12 @@ namespace Mono.Linker return true; } - bool TryGetCustomAssembly (ref string arg, out Assembly assembly) + bool TryGetCustomAssembly (ref string arg, [NotNullWhen (true)] out Assembly? assembly) { assembly = null; int pos = arg.IndexOf (","); if (pos == -1) - return true; + return false; assembly = GetCustomAssembly (arg.Substring (pos + 1)); if (assembly == null) @@ -881,24 +888,24 @@ namespace Mono.Linker protected bool AddCustomStep (Pipeline pipeline, string arg) { - if (!TryGetCustomAssembly (ref arg, out Assembly custom_assembly)) + if (!TryGetCustomAssembly (ref arg, out Assembly? custom_assembly)) return false; string customStepName; - string targetName = null; + string? targetName = null; bool before = false; if (!arg.Contains (':')) { customStepName = arg; } else { string[] parts = arg.Split (':'); if (parts.Length != 2) { - context.LogError ($"Invalid value '{arg}' specified for '--custom-step' option.", 1024); + Context.LogError ($"Invalid value '{arg}' specified for '--custom-step' option.", 1024); return false; } customStepName = parts[1]; if (!parts[0].StartsWith ("-") && !parts[0].StartsWith ("+")) { - context.LogError ($"Expected '+' or '-' to control new step insertion.", 1025); + Context.LogError ($"Expected '+' or '-' to control new step insertion.", 1025); return false; } @@ -912,15 +919,15 @@ namespace Mono.Linker if (typeof (IStep).IsAssignableFrom (stepType)) { - var customStep = (IStep) Activator.CreateInstance (stepType); + var customStep = (IStep?) Activator.CreateInstance (stepType) ?? throw new InvalidOperationException (); if (targetName == null) { pipeline.AppendStep (customStep); return true; } - IStep target = FindStep (pipeline, targetName); + IStep? target = FindStep (pipeline, targetName); if (target == null) { - context.LogError ($"Pipeline step '{targetName}' could not be found.", 1026); + Context.LogError ($"Pipeline step '{targetName}' could not be found.", 1026); return false; } @@ -934,15 +941,15 @@ namespace Mono.Linker if (typeof (IMarkHandler).IsAssignableFrom (stepType)) { - var customStep = (IMarkHandler) Activator.CreateInstance (stepType); + var customStep = (IMarkHandler?) Activator.CreateInstance (stepType) ?? throw new InvalidOperationException (); if (targetName == null) { pipeline.AppendMarkHandler (customStep); return true; } - IMarkHandler target = FindMarkHandler (pipeline, targetName); + IMarkHandler? target = FindMarkHandler (pipeline, targetName); if (target == null) { - context.LogError ($"Pipeline step '{targetName}' could not be found.", 1026); + Context.LogError ($"Pipeline step '{targetName}' could not be found.", 1026); return false; } @@ -954,11 +961,11 @@ namespace Mono.Linker return true; } - context.LogError ($"Custom step '{stepType}' is incompatible with this trimmer version.", 1028); + Context.LogError ($"Custom step '{stepType}' is incompatible with this trimmer version.", 1028); return false; } - protected virtual IStep FindStep (Pipeline pipeline, string name) + protected virtual IStep? FindStep (Pipeline pipeline, string name) { foreach (IStep step in pipeline.GetSteps ()) { Type t = step.GetType (); @@ -969,7 +976,7 @@ namespace Mono.Linker return null; } - static IMarkHandler FindMarkHandler (Pipeline pipeline, string name) + static IMarkHandler? FindMarkHandler (Pipeline pipeline, string name) { foreach (IMarkHandler step in pipeline.MarkHandlers) { Type t = step.GetType (); @@ -980,33 +987,33 @@ namespace Mono.Linker return null; } - Type ResolveStepType (string type, Assembly assembly) + Type? ResolveStepType (string type, Assembly assembly) { - Type step = assembly != null ? assembly.GetType (type) : Type.GetType (type, false); + Type? step = assembly != null ? assembly.GetType (type) : Type.GetType (type, false); if (step == null) { - context.LogError ($"Custom step '{type}' could not be found.", 1027); + Context.LogError ($"Custom step '{type}' could not be found.", 1027); return null; } return step; } - TStep ResolveStep<TStep> (string type, Assembly assembly) where TStep : class + TStep? ResolveStep<TStep> (string type, Assembly assembly) where TStep : class { - Type step = assembly != null ? assembly.GetType (type) : Type.GetType (type, false); + Type? step = assembly != null ? assembly.GetType (type) : Type.GetType (type, false); if (step == null) { - context.LogError ($"Custom step '{type}' could not be found.", 1027); + Context.LogError ($"Custom step '{type}' could not be found.", 1027); return null; } if (!typeof (TStep).IsAssignableFrom (step)) { - context.LogError ($"Custom step '{type}' is incompatible with this trimmer version.", 1028); + Context.LogError ($"Custom step '{type}' is incompatible with this trimmer version.", 1028); return null; } - return (TStep) Activator.CreateInstance (step); + return (TStep?) Activator.CreateInstance (step); } static string[] GetFiles (string param) @@ -1022,7 +1029,7 @@ namespace Mono.Linker { var lines = new List<string> (); using (StreamReader reader = new StreamReader (file)) { - string line; + string? line; while ((line = reader.ReadLine ()) != null) lines.Add (line); } @@ -1049,7 +1056,7 @@ namespace Mono.Linker return AssemblyAction.AddBypassNGenUsed; } - context.LogError ($"Invalid assembly action '{s}'.", 1031); + Context.LogError ($"Invalid assembly action '{s}'.", 1031); return null; } @@ -1068,7 +1075,7 @@ namespace Mono.Linker return AssemblyRootMode.Library; } - context.LogError ($"Invalid assembly root mode '{s}'.", 1037); + Context.LogError ($"Invalid assembly root mode '{s}'.", 1037); return null; } @@ -1080,7 +1087,7 @@ namespace Mono.Linker return true; } - context.LogError ($"Invalid warning version '{text}'.", 1016); + Context.LogError ($"Invalid warning version '{text}'.", 1016); version = 0; return false; } @@ -1111,7 +1118,7 @@ namespace Mono.Linker return true; } - context.LogError ($"Invalid optimization value '{text}'.", 1029); + Context.LogError ($"Invalid optimization value '{text}'.", 1029); optimization = 0; return false; } @@ -1130,7 +1137,7 @@ namespace Mono.Linker return true; } - context.LogError ($"Invalid metadata value '{text}'.", 1046); + Context.LogError ($"Invalid metadata value '{text}'.", 1046); metadataTrimming = 0; return false; } @@ -1171,11 +1178,11 @@ namespace Mono.Linker return true; } - context.LogError ($"Invalid argument for '{token}' option.", 1030); + Context.LogError ($"Invalid argument for '{token}' option.", 1030); return false; } - bool GetStringParam (string token, out string value) + bool GetStringParam (string token, [NotNullWhen (true)] out string? value) { value = null; if (arguments.Count < 1) { @@ -1193,7 +1200,7 @@ namespace Mono.Linker return false; } - string GetNextStringValue () + string? GetNextStringValue () { if (arguments.Count < 1) return null; @@ -1206,7 +1213,7 @@ namespace Mono.Linker return arg; } - protected virtual LinkContext GetDefaultContext (Pipeline pipeline, ILogger logger) + protected virtual LinkContext GetDefaultContext (Pipeline pipeline, ILogger? logger) { return new LinkContext (pipeline, logger ?? new ConsoleLogger (), "output") { TrimAction = AssemblyAction.Link, diff --git a/src/linker/Linker/DynamicDependency.cs b/src/linker/Linker/DynamicDependency.cs index bd139f1c8..8b6c56e13 100644 --- a/src/linker/Linker/DynamicDependency.cs +++ b/src/linker/Linker/DynamicDependency.cs @@ -2,8 +2,6 @@ using System; using System.Diagnostics.CodeAnalysis; using Mono.Cecil; -#nullable enable - namespace Mono.Linker { /// Tracks dependencies created via DynamicDependencyAttribute in the linker. diff --git a/src/linker/Linker/EmbeddedXmlInfo.cs b/src/linker/Linker/EmbeddedXmlInfo.cs index 143d41d3c..14871394b 100644 --- a/src/linker/Linker/EmbeddedXmlInfo.cs +++ b/src/linker/Linker/EmbeddedXmlInfo.cs @@ -13,7 +13,7 @@ namespace Mono.Linker { public static class EmbeddedXmlInfo { - static EmbeddedResource GetEmbeddedXml (AssemblyDefinition assembly, Func<Resource, bool> predicate) + static EmbeddedResource? GetEmbeddedXml (AssemblyDefinition assembly, Func<Resource, bool> predicate) { return assembly.Modules .SelectMany (mod => mod.Resources) @@ -32,7 +32,7 @@ namespace Mono.Linker if (rsc == null) return; - DescriptorMarker marker = null; + DescriptorMarker? marker = null; try { context.LogMessage ($"Processing embedded linker descriptor '{rsc.Name}' from '{assembly.Name}'."); marker = GetExternalResolveStep (context, rsc, assembly); @@ -45,7 +45,7 @@ namespace Mono.Linker marker.Mark (); } - public static SubstitutionInfo ProcessSubstitutions (AssemblyDefinition assembly, LinkContext context) + public static SubstitutionInfo? ProcessSubstitutions (AssemblyDefinition assembly, LinkContext context) { if (context.Annotations.GetAction (assembly) == AssemblyAction.Skip) return null; @@ -54,7 +54,7 @@ namespace Mono.Linker if (rsc == null) return null; - BodySubstitutionParser parser = null; + BodySubstitutionParser? parser = null; try { context.LogMessage ($"Processing embedded substitution descriptor '{rsc.Name}' from '{assembly.Name}'."); parser = GetExternalSubstitutionParser (context, rsc, assembly); @@ -70,7 +70,7 @@ namespace Mono.Linker return substitutionInfo; } - public static AttributeInfo ProcessAttributes (AssemblyDefinition assembly, LinkContext context) + public static AttributeInfo? ProcessAttributes (AssemblyDefinition assembly, LinkContext context) { if (context.Annotations.GetAction (assembly) == AssemblyAction.Skip) return null; @@ -79,7 +79,7 @@ namespace Mono.Linker if (rsc == null) return null; - LinkAttributesParser parser = null; + LinkAttributesParser? parser = null; try { context.LogMessage ($"Processing embedded '{rsc.Name}' from '{assembly.Name}'."); parser = GetExternalLinkAttributesParser (context, rsc, assembly); diff --git a/src/linker/Linker/IReflectionPatternRecorder.cs b/src/linker/Linker/IReflectionPatternRecorder.cs index 411b03a6a..9be6698b8 100644 --- a/src/linker/Linker/IReflectionPatternRecorder.cs +++ b/src/linker/Linker/IReflectionPatternRecorder.cs @@ -49,7 +49,7 @@ namespace Mono.Linker /// This can be null if there's no logical instruction to assign to the pattern.</param> /// <param name="accessedItem">The item accessed through reflection. This can be one of: /// TypeDefinition, MethodDefinition, PropertyDefinition, FieldDefinition, EventDefinition, InterfaceImplementation.</param> - void RecognizedReflectionAccessPattern (ICustomAttributeProvider source, Instruction sourceInstruction, IMetadataTokenProvider accessedItem); + void RecognizedReflectionAccessPattern (ICustomAttributeProvider? source, Instruction? sourceInstruction, IMetadataTokenProvider accessedItem); /// <summary> /// Called when the linker detected a reflection access but was not able to recognize the entire pattern. @@ -64,6 +64,6 @@ namespace Mono.Linker /// <param name="messageCode">Message code to use when reporting the unrecognized pattern as a warning.</param> /// <remarks>This effectively means that there's a potential hole in the linker marking - some items which are accessed only through /// reflection may not be marked correctly and thus may fail at runtime.</remarks> - void UnrecognizedReflectionAccessPattern (in MessageOrigin origin, ICustomAttributeProvider source, Instruction sourceInstruction, IMetadataTokenProvider accessedItem, string message, int messageCode); + void UnrecognizedReflectionAccessPattern (in MessageOrigin origin, ICustomAttributeProvider? source, Instruction? sourceInstruction, IMetadataTokenProvider accessedItem, string message, int messageCode); } } diff --git a/src/linker/Linker/KnownMembers.cs b/src/linker/Linker/KnownMembers.cs index 0b916dbd2..85be9c628 100644 --- a/src/linker/Linker/KnownMembers.cs +++ b/src/linker/Linker/KnownMembers.cs @@ -4,11 +4,11 @@ namespace Mono.Linker { public class KnownMembers { - public MethodDefinition NotSupportedExceptionCtorString { get; set; } - public MethodDefinition DisablePrivateReflectionAttributeCtor { get; set; } - public MethodDefinition ObjectCtor { get; set; } + public MethodDefinition? NotSupportedExceptionCtorString { get; set; } + public MethodDefinition? DisablePrivateReflectionAttributeCtor { get; set; } + public MethodDefinition? ObjectCtor { get; set; } - public TypeDefinition RemoveAttributeInstancesAttributeDefinition { get; set; } + public TypeDefinition? RemoveAttributeInstancesAttributeDefinition { get; set; } public static bool IsNotSupportedExceptionCtorString (MethodDefinition method) { diff --git a/src/linker/Linker/LinkContext.cs b/src/linker/Linker/LinkContext.cs index eba7a7190..23d5a7a6f 100644 --- a/src/linker/Linker/LinkContext.cs +++ b/src/linker/Linker/LinkContext.cs @@ -26,8 +26,6 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -267,27 +265,27 @@ namespace Mono.Linker string asmname = fullName.Substring (pos + 1); fullName = fullName.Substring (0, pos); - AssemblyDefinition assembly = Resolve (AssemblyNameReference.Parse (asmname)); - return assembly.MainModule.GetType (fullName); + AssemblyDefinition? assembly = Resolve (AssemblyNameReference.Parse (asmname)); + return assembly?.MainModule.GetType (fullName); } - public AssemblyDefinition TryResolve (string name) + public AssemblyDefinition? TryResolve (string name) { return TryResolve (new AssemblyNameReference (name, new Version ())); } - public AssemblyDefinition TryResolve (AssemblyNameReference name) + public AssemblyDefinition? TryResolve (AssemblyNameReference name) { return _resolver.Resolve (name, probing: true); } - public AssemblyDefinition Resolve (IMetadataScope scope) + public AssemblyDefinition? Resolve (IMetadataScope scope) { AssemblyNameReference reference = GetReference (scope); return _resolver.Resolve (reference); } - public AssemblyDefinition Resolve (AssemblyNameReference name) + public AssemblyDefinition? Resolve (AssemblyNameReference name) { return _resolver.Resolve (name); } @@ -340,7 +338,7 @@ namespace Mono.Linker return references; foreach (AssemblyNameReference reference in assembly.MainModule.AssemblyReferences) { - AssemblyDefinition definition = Resolve (reference); + AssemblyDefinition? definition = Resolve (reference); if (definition != null) references.Add (definition); } @@ -526,8 +524,8 @@ namespace Mono.Linker if (WarningSuppressionWriter != null && message.IsWarningMessage (out int? code) && - message.Origin?.Provider != null) - WarningSuppressionWriter.AddWarning (code.Value, message.Origin?.Provider); + message.Origin?.Provider is Mono.Cecil.ICustomAttributeProvider provider) + WarningSuppressionWriter.AddWarning (code.Value, provider); if (message.Category == MessageCategory.Error || message.Category == MessageCategory.WarningAsError) ErrorsCount++; @@ -665,7 +663,7 @@ namespace Mono.Linker if (_targetRuntime != null) return _targetRuntime.Value; - TypeDefinition objectType = BCL.FindPredefinedType ("System", "Object", this); + TypeDefinition? objectType = BCL.FindPredefinedType ("System", "Object", this); _targetRuntime = objectType?.Module.Assembly.Name.Version.Major ?? -1; return _targetRuntime.Value; @@ -805,7 +803,9 @@ namespace Mono.Linker public TypeDefinition? TryResolve (AssemblyDefinition assembly, string typeNameString) { // It could be cached if it shows up on fast path - return TryResolve (_typeNameResolver.ResolveTypeName (assembly, typeNameString)); + return _typeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference) + ? TryResolve (typeReference) + : null; } readonly HashSet<MemberReference> unresolved_reported = new (); diff --git a/src/linker/Linker/LinkerAttributesInformation.cs b/src/linker/Linker/LinkerAttributesInformation.cs index ca74c9c3a..0d431999e 100644 --- a/src/linker/Linker/LinkerAttributesInformation.cs +++ b/src/linker/Linker/LinkerAttributesInformation.cs @@ -12,9 +12,9 @@ namespace Mono.Linker { readonly struct LinkerAttributesInformation { - readonly Dictionary<Type, List<Attribute>> _linkerAttributes; + readonly Dictionary<Type, List<Attribute>>? _linkerAttributes; - private LinkerAttributesInformation (Dictionary<Type, List<Attribute>> cache) + private LinkerAttributesInformation (Dictionary<Type, List<Attribute>>? cache) { this._linkerAttributes = cache; } @@ -23,12 +23,12 @@ namespace Mono.Linker { Debug.Assert (context.CustomAttributes.HasAny (provider)); - Dictionary<Type, List<Attribute>> cache = null; + Dictionary<Type, List<Attribute>>? cache = null; foreach (var customAttribute in context.CustomAttributes.GetCustomAttributes (provider)) { var attributeType = customAttribute.AttributeType; - Attribute attributeValue; + Attribute? attributeValue; switch (attributeType.Name) { case "RequiresUnreferencedCodeAttribute" when attributeType.Namespace == "System.Diagnostics.CodeAnalysis": attributeValue = ProcessRequiresUnreferencedCodeAttribute (context, provider, customAttribute); @@ -84,7 +84,7 @@ namespace Mono.Linker return attributeList.Cast<T> (); } - static Attribute ProcessRequiresUnreferencedCodeAttribute (LinkContext context, ICustomAttributeProvider provider, CustomAttribute customAttribute) + static Attribute? ProcessRequiresUnreferencedCodeAttribute (LinkContext context, ICustomAttributeProvider provider, CustomAttribute customAttribute) { if (!(provider is MethodDefinition || provider is TypeDefinition)) return null; @@ -109,7 +109,7 @@ namespace Mono.Linker return null; } - static RemoveAttributeInstancesAttribute BuildRemoveAttributeInstancesAttribute (LinkContext context, TypeDefinition attributeContext, CustomAttribute ca) + static RemoveAttributeInstancesAttribute? BuildRemoveAttributeInstancesAttribute (LinkContext context, TypeDefinition attributeContext, CustomAttribute ca) { switch (ca.ConstructorArguments.Count) { case 0: diff --git a/src/linker/Linker/LinkerILProcessor.cs b/src/linker/Linker/LinkerILProcessor.cs index 1cc82319c..2be7b138b 100644 --- a/src/linker/Linker/LinkerILProcessor.cs +++ b/src/linker/Linker/LinkerILProcessor.cs @@ -43,7 +43,7 @@ namespace Mono.Linker public void Append (Instruction instruction) { - Instruction lastInstruction = Instructions.Count == 0 ? null : Instructions[Instructions.Count - 1]; + Instruction? lastInstruction = Instructions.Count == 0 ? null : Instructions[Instructions.Count - 1]; RedirectScopeEnd (lastInstruction, instruction); _ilProcessor.Append (instruction); } @@ -64,8 +64,8 @@ namespace Mono.Linker if (index == -1) throw new ArgumentOutOfRangeException (nameof (instruction)); - Instruction nextInstruction = Instructions.Count == index + 1 ? null : Instructions[index + 1]; - Instruction previousInstruction = index == 0 ? null : Instructions[index - 1]; + Instruction? nextInstruction = Instructions.Count == index + 1 ? null : Instructions[index + 1]; + Instruction? previousInstruction = index == 0 ? null : Instructions[index - 1]; RedirectScopeStart (instruction, nextInstruction); RedirectScopeEnd (instruction, previousInstruction); @@ -75,7 +75,7 @@ namespace Mono.Linker public void RemoveAt (int index) => Remove (Instructions[index]); - void RedirectScopeStart (Instruction oldTarget, Instruction newTarget) + void RedirectScopeStart (Instruction oldTarget, Instruction? newTarget) { // In Cecil "start" pointers point to the first instruction in a given scope // and the "end" pointers point to the first instruction after the given block @@ -96,14 +96,14 @@ namespace Mono.Linker } #pragma warning disable IDE0060 // Remove unused parameter - static void RedirectScopeEnd (Instruction oldTarget, Instruction newTarget) + static void RedirectScopeEnd (Instruction? oldTarget, Instruction? newTarget) #pragma warning restore IDE0060 // Remove unused parameter { // Currently Cecil treats all block boundaries as "starts" // so nothing to do here. } - void ReplaceInstructionReference (Instruction oldTarget, Instruction newTarget) + void ReplaceInstructionReference (Instruction oldTarget, Instruction? newTarget) { foreach (var instr in Instructions) { switch (instr.OpCode.FlowControl) { diff --git a/src/linker/Linker/LoggingReflectionPatternRecorder.cs b/src/linker/Linker/LoggingReflectionPatternRecorder.cs index 36d8713dc..eb30e5247 100644 --- a/src/linker/Linker/LoggingReflectionPatternRecorder.cs +++ b/src/linker/Linker/LoggingReflectionPatternRecorder.cs @@ -37,12 +37,12 @@ namespace Mono.Linker _context = context; } - public void RecognizedReflectionAccessPattern (ICustomAttributeProvider source, Instruction sourceInstruction, IMetadataTokenProvider accessedItem) + public void RecognizedReflectionAccessPattern (ICustomAttributeProvider? source, Instruction? sourceInstruction, IMetadataTokenProvider accessedItem) { // Do nothing - there's no logging for successfully recognized patterns } - public void UnrecognizedReflectionAccessPattern (in MessageOrigin origin, ICustomAttributeProvider source, Instruction sourceInstruction, IMetadataTokenProvider accessedItem, string message, int messageCode) + public void UnrecognizedReflectionAccessPattern (in MessageOrigin origin, ICustomAttributeProvider? source, Instruction? sourceInstruction, IMetadataTokenProvider accessedItem, string message, int messageCode) { _context.LogWarning (message, messageCode, origin, MessageSubCategory.TrimAnalysis); } diff --git a/src/linker/Linker/MarkingHelpers.cs b/src/linker/Linker/MarkingHelpers.cs index 57dfd6059..887214310 100644 --- a/src/linker/Linker/MarkingHelpers.cs +++ b/src/linker/Linker/MarkingHelpers.cs @@ -35,7 +35,9 @@ namespace Mono.Linker if (typeReference.Scope is AssemblyNameReference) { var assembly = _context.Resolve (typeReference.Scope); - if (assembly != null && assembly.MainModule.GetMatchingExportedType (_context.TryResolve (typeReference), out var exportedType)) + if (assembly != null && + _context.TryResolve (typeReference) is TypeDefinition typeDefinition && + assembly.MainModule.GetMatchingExportedType (typeDefinition, out var exportedType)) MarkExportedType (exportedType, assembly.MainModule, new DependencyInfo (DependencyKind.ExportedType, typeReference)); } } diff --git a/src/linker/Linker/MemberActionStore.cs b/src/linker/Linker/MemberActionStore.cs index c5be4dd52..3826a441b 100644 --- a/src/linker/Linker/MemberActionStore.cs +++ b/src/linker/Linker/MemberActionStore.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Mono.Cecil; namespace Mono.Linker @@ -9,17 +10,17 @@ namespace Mono.Linker public class MemberActionStore { public SubstitutionInfo PrimarySubstitutionInfo { get; } - private readonly Dictionary<AssemblyDefinition, SubstitutionInfo> _embeddedXmlInfos; + private readonly Dictionary<AssemblyDefinition, SubstitutionInfo?> _embeddedXmlInfos; readonly LinkContext _context; public MemberActionStore (LinkContext context) { PrimarySubstitutionInfo = new SubstitutionInfo (); - _embeddedXmlInfos = new Dictionary<AssemblyDefinition, SubstitutionInfo> (); + _embeddedXmlInfos = new Dictionary<AssemblyDefinition, SubstitutionInfo?> (); _context = context; } - public bool TryGetSubstitutionInfo (MemberReference member, out SubstitutionInfo xmlInfo) + public bool TryGetSubstitutionInfo (MemberReference member, [NotNullWhen (true)] out SubstitutionInfo? xmlInfo) { var assembly = member.Module.Assembly; if (!_embeddedXmlInfos.TryGetValue (assembly, out xmlInfo)) { @@ -43,7 +44,7 @@ namespace Mono.Linker return MethodAction.Nothing; } - public bool TryGetMethodStubValue (MethodDefinition method, out object value) + public bool TryGetMethodStubValue (MethodDefinition method, out object? value) { if (PrimarySubstitutionInfo.MethodStubValues.TryGetValue (method, out value)) return true; @@ -54,7 +55,7 @@ namespace Mono.Linker return embeddedXml.MethodStubValues.TryGetValue (method, out value); } - public bool TryGetFieldUserValue (FieldDefinition field, out object value) + public bool TryGetFieldUserValue (FieldDefinition field, out object? value) { if (PrimarySubstitutionInfo.FieldValues.TryGetValue (field, out value)) return true; diff --git a/src/linker/Linker/MessageContainer.cs b/src/linker/Linker/MessageContainer.cs index f0a4afd09..89d51ff97 100644 --- a/src/linker/Linker/MessageContainer.cs +++ b/src/linker/Linker/MessageContainer.cs @@ -274,7 +274,7 @@ namespace Mono.Linker public bool Equals (MessageContainer other) => (Category, Text, Code, SubCategory, Origin) == (other.Category, other.Text, other.Code, other.SubCategory, other.Origin); - public override bool Equals (object obj) => obj is MessageContainer messageContainer && Equals (messageContainer); + public override bool Equals (object? obj) => obj is MessageContainer messageContainer && Equals (messageContainer); public override int GetHashCode () => (Category, Text, Code, SubCategory, Origin).GetHashCode (); public int CompareTo (MessageContainer other) diff --git a/src/linker/Linker/MessageOrigin.cs b/src/linker/Linker/MessageOrigin.cs index 84357b26a..6bb30e8d1 100644 --- a/src/linker/Linker/MessageOrigin.cs +++ b/src/linker/Linker/MessageOrigin.cs @@ -12,29 +12,28 @@ namespace Mono.Linker { public readonly struct MessageOrigin : IComparable<MessageOrigin>, IEquatable<MessageOrigin> { -#nullable enable public string? FileName { get; } public ICustomAttributeProvider? Provider { get; } - readonly ICustomAttributeProvider _suppressionContextMember; + readonly ICustomAttributeProvider? _suppressionContextMember; public ICustomAttributeProvider? SuppressionContextMember { get { Debug.Assert (_suppressionContextMember == null || _suppressionContextMember is IMemberDefinition || _suppressionContextMember is AssemblyDefinition); return _suppressionContextMember ?? Provider; } } -#nullable disable + public int SourceLine { get; } public int SourceColumn { get; } public int? ILOffset { get; } const int HiddenLineNumber = 0xfeefee; - public MessageOrigin (IMemberDefinition memberDefinition, int? ilOffset = null) + public MessageOrigin (IMemberDefinition? memberDefinition, int? ilOffset = null) : this (memberDefinition as ICustomAttributeProvider, ilOffset) { } - public MessageOrigin (ICustomAttributeProvider provider) + public MessageOrigin (ICustomAttributeProvider? provider) : this (provider, null) { } @@ -49,12 +48,12 @@ namespace Mono.Linker ILOffset = null; } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset) : this (provider, ilOffset, null) { } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset, ICustomAttributeProvider suppressionContextMember) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset, ICustomAttributeProvider? suppressionContextMember) { Debug.Assert (provider == null || provider is IMemberDefinition || provider is AssemblyDefinition); Debug.Assert (suppressionContextMember == null || suppressionContextMember is IMemberDefinition || provider is AssemblyDefinition); @@ -66,7 +65,7 @@ namespace Mono.Linker ILOffset = ilOffset; } - public MessageOrigin (MessageOrigin other, IMemberDefinition suppressionContextMember) + public MessageOrigin (MessageOrigin other, IMemberDefinition? suppressionContextMember) { FileName = other.FileName; Provider = other.Provider; @@ -76,21 +75,21 @@ namespace Mono.Linker ILOffset = other.ILOffset; } - public override string ToString () + public override string? ToString () { int sourceLine = SourceLine, sourceColumn = SourceColumn; - string fileName = FileName; + string? fileName = FileName; if (Provider is MethodDefinition method && method.DebugInformation.HasSequencePoints) { var offset = ILOffset ?? 0; - SequencePoint correspondingSequencePoint = method.DebugInformation.SequencePoints + SequencePoint? correspondingSequencePoint = method.DebugInformation.SequencePoints .Where (s => s.Offset <= offset)?.Last (); // If the warning comes from hidden line (compiler generated code typically) // search for any sequence point with non-hidden line number and report that as a best effort. - if (correspondingSequencePoint.StartLine == HiddenLineNumber) { + if (correspondingSequencePoint?.StartLine == HiddenLineNumber) { correspondingSequencePoint = method.DebugInformation.SequencePoints - .Where (s => s.StartLine != HiddenLineNumber)?.FirstOrDefault (); + .Where (s => s.StartLine != HiddenLineNumber).FirstOrDefault (); } if (correspondingSequencePoint != null) { @@ -118,7 +117,7 @@ namespace Mono.Linker public bool Equals (MessageOrigin other) => (FileName, Provider, SourceLine, SourceColumn, ILOffset) == (other.FileName, other.Provider, other.SourceLine, other.SourceColumn, other.ILOffset); - public override bool Equals (object obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); + public override bool Equals (object? obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); public override int GetHashCode () => (FileName, Provider, SourceLine, SourceColumn).GetHashCode (); public static bool operator == (MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals (rhs); public static bool operator != (MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals (rhs); @@ -128,12 +127,12 @@ namespace Mono.Linker if (Provider != null && other.Provider != null) { var thisMember = Provider as IMemberDefinition; var otherMember = other.Provider as IMemberDefinition; - TypeDefinition thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; - TypeDefinition otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; var thisAssembly = thisTypeDef?.Module.Assembly ?? Provider as AssemblyDefinition; var otherAssembly = otherTypeDef?.Module.Assembly ?? other.Provider as AssemblyDefinition; - int result = (thisAssembly.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo - ((otherAssembly.Name.Name, otherTypeDef?.Name, otherMember?.Name)); + int result = (thisAssembly?.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo + ((otherAssembly?.Name.Name, otherTypeDef?.Name, otherMember?.Name)); if (result != 0) return result; diff --git a/src/linker/Linker/MethodBodyScanner.cs b/src/linker/Linker/MethodBodyScanner.cs index cf86c4e8f..a2d68f9c9 100644 --- a/src/linker/Linker/MethodBodyScanner.cs +++ b/src/linker/Linker/MethodBodyScanner.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; @@ -11,7 +12,7 @@ namespace Mono.Linker public static bool IsWorthConvertingToThrow (MethodBody body) { // Some bodies are cheaper size wise to leave alone than to convert to a throw - Instruction previousMeaningful = null; + Instruction? previousMeaningful = null; int meaningfulCount = 0; foreach (var ins in body.Instructions) { // Handle ignoring noops because because (1) it's a valid case to ignore @@ -60,7 +61,7 @@ namespace Mono.Linker this.context = context; } - public IEnumerable<(InterfaceImplementation, TypeDefinition)> GetReferencedInterfaces (MethodBody body) + public IEnumerable<(InterfaceImplementation, TypeDefinition)>? GetReferencedInterfaces (MethodBody body) { var possibleStackTypes = AllPossibleStackTypes (body.Method); if (possibleStackTypes.Count == 0) @@ -80,7 +81,7 @@ namespace Mono.Linker if (!type.IsClass) continue; - TypeDefinition currentType = type; + TypeDefinition? currentType = type; while (currentType?.BaseType != null) // Checking BaseType != null to skip System.Object { AddMatchingInterfaces (interfaceImplementations, currentType, interfaceTypes); @@ -113,7 +114,8 @@ namespace Mono.Linker foreach (Instruction instruction in body.Instructions) { if (instruction.Operand is FieldReference fieldReference) { - AddIfResolved (types, context.TryResolve (fieldReference)?.FieldType); + if (context.TryResolve (fieldReference)?.FieldType is TypeReference fieldType) + AddIfResolved (types, fieldType); } else if (instruction.Operand is MethodReference methodReference) { if (methodReference is GenericInstanceMethod genericInstanceMethod) AddFromGenericInstance (types, genericInstanceMethod); @@ -145,12 +147,12 @@ namespace Mono.Linker return; foreach (var interfaceType in interfaceTypes) { - if (HasInterface (type, interfaceType, out InterfaceImplementation implementation)) + if (HasInterface (type, interfaceType, out InterfaceImplementation? implementation)) results.Add ((implementation, type)); } } - bool HasInterface (TypeDefinition type, TypeDefinition interfaceType, out InterfaceImplementation implementation) + bool HasInterface (TypeDefinition type, TypeDefinition interfaceType, [NotNullWhen (true)] out InterfaceImplementation? implementation) { implementation = null; if (!type.HasInterfaces) diff --git a/src/linker/Linker/MethodDefinitionExtensions.cs b/src/linker/Linker/MethodDefinitionExtensions.cs index caae82ed8..165b75138 100644 --- a/src/linker/Linker/MethodDefinitionExtensions.cs +++ b/src/linker/Linker/MethodDefinitionExtensions.cs @@ -1,4 +1,6 @@ -using Mono.Cecil; +using System; +using System.Diagnostics.CodeAnalysis; +using Mono.Cecil; namespace Mono.Linker { @@ -46,24 +48,36 @@ namespace Mono.Linker (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0; } - public static PropertyDefinition GetProperty (this MethodDefinition md) + public static bool TryGetProperty (this MethodDefinition md, [NotNullWhen (true)] out PropertyDefinition? property) { + property = null; + if (!md.IsPropertyMethod ()) + return false; + TypeDefinition declaringType = md.DeclaringType; foreach (PropertyDefinition prop in declaringType.Properties) - if (prop.GetMethod == md || prop.SetMethod == md) - return prop; + if (prop.GetMethod == md || prop.SetMethod == md) { + property = prop; + return true; + } - return null; + return false; } - public static EventDefinition GetEvent (this MethodDefinition md) + public static bool TryGetEvent (this MethodDefinition md, [NotNullWhen (true)] out EventDefinition? @event) { + @event = null; + if (!md.IsEventMethod ()) + return false; + TypeDefinition declaringType = md.DeclaringType; foreach (EventDefinition evt in declaringType.Events) - if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md) - return evt; + if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md) { + @event = evt; + return true; + } - return null; + return false; } public static bool IsStaticConstructor (this MethodDefinition method) diff --git a/src/linker/Linker/MethodReferenceExtensions.cs b/src/linker/Linker/MethodReferenceExtensions.cs index 446cadbfe..e9272fdb7 100644 --- a/src/linker/Linker/MethodReferenceExtensions.cs +++ b/src/linker/Linker/MethodReferenceExtensions.cs @@ -52,7 +52,7 @@ namespace Mono.Linker return sb.ToString (); } - public static TypeReference GetReturnType (this MethodReference method, LinkContext context) + public static TypeReference? GetReturnType (this MethodReference method, LinkContext context) { if (method.DeclaringType is GenericInstanceType genericInstance) return TypeReferenceExtensions.InflateGenericType (genericInstance, method.ReturnType, context); @@ -60,7 +60,7 @@ namespace Mono.Linker return method.ReturnType; } - public static TypeReference GetParameterType (this MethodReference method, int parameterIndex, LinkContext context) + public static TypeReference? GetParameterType (this MethodReference method, int parameterIndex, LinkContext context) { if (method.DeclaringType is GenericInstanceType genericInstance) return TypeReferenceExtensions.InflateGenericType (genericInstance, method.Parameters[parameterIndex].ParameterType, context); diff --git a/src/linker/Linker/ModuleDefinitionExtensions.cs b/src/linker/Linker/ModuleDefinitionExtensions.cs index 71c266cc6..1ea8bb351 100644 --- a/src/linker/Linker/ModuleDefinitionExtensions.cs +++ b/src/linker/Linker/ModuleDefinitionExtensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using Mono.Cecil; namespace Mono.Linker @@ -11,10 +12,10 @@ namespace Mono.Linker (module.Attributes & ModuleAttributes.ILLibrary) != 0; } - public static bool GetMatchingExportedType (this ModuleDefinition module, TypeDefinition typeDefinition, out ExportedType exportedType) + public static bool GetMatchingExportedType (this ModuleDefinition module, TypeDefinition typeDefinition, [NotNullWhen (true)] out ExportedType? exportedType) { exportedType = null; - if (!module.HasExportedTypes || typeDefinition == null) + if (!module.HasExportedTypes) return false; foreach (var et in module.ExportedTypes) @@ -26,11 +27,8 @@ namespace Mono.Linker return false; } - public static TypeDefinition ResolveType (this ModuleDefinition module, string typeFullName, ITryResolveMetadata resolver) + public static TypeDefinition? ResolveType (this ModuleDefinition module, string typeFullName, ITryResolveMetadata resolver) { - if (typeFullName == null) - return null; - var type = module.GetType (typeFullName); if (type != null) return type; diff --git a/src/linker/Linker/OverrideInformation.cs b/src/linker/Linker/OverrideInformation.cs index d40f87637..827045111 100644 --- a/src/linker/Linker/OverrideInformation.cs +++ b/src/linker/Linker/OverrideInformation.cs @@ -8,7 +8,7 @@ namespace Mono.Linker { readonly ITryResolveMetadata resolver; - public OverrideInformation (MethodDefinition @base, MethodDefinition @override, ITryResolveMetadata resolver, InterfaceImplementation matchingInterfaceImplementation = null) + public OverrideInformation (MethodDefinition @base, MethodDefinition @override, ITryResolveMetadata resolver, InterfaceImplementation? matchingInterfaceImplementation = null) { Base = @base; Override = @override; @@ -18,7 +18,7 @@ namespace Mono.Linker public MethodDefinition Base { get; } public MethodDefinition Override { get; } - public InterfaceImplementation MatchingInterfaceImplementation { get; } + public InterfaceImplementation? MatchingInterfaceImplementation { get; } public bool IsOverrideOfInterfaceMember { get { @@ -29,7 +29,7 @@ namespace Mono.Linker } } - public TypeDefinition InterfaceType { + public TypeDefinition? InterfaceType { get { if (!IsOverrideOfInterfaceMember) return null; diff --git a/src/linker/Linker/PInvokeInfo.cs b/src/linker/Linker/PInvokeInfo.cs index 590ee163d..84193b153 100644 --- a/src/linker/Linker/PInvokeInfo.cs +++ b/src/linker/Linker/PInvokeInfo.cs @@ -18,7 +18,15 @@ namespace Mono.Linker [DataMember (Name = "moduleName")] internal string ModuleName { get; set; } - public int CompareTo (PInvokeInfo other) + public PInvokeInfo (string assemblyName, string entryPoint, string fullName, string moduleName) + { + AssemblyName = assemblyName; + EntryPoint = entryPoint; + FullName = fullName; + ModuleName = moduleName; + } + + public int CompareTo (PInvokeInfo? other) { if (other == null) return 1; diff --git a/src/linker/Linker/SerializationMarker.cs b/src/linker/Linker/SerializationMarker.cs index 2672c83c2..c55b7f306 100644 --- a/src/linker/Linker/SerializationMarker.cs +++ b/src/linker/Linker/SerializationMarker.cs @@ -55,7 +55,7 @@ namespace Mono.Linker SerializerKind ActiveSerializers { get; set; } - Dictionary<SerializerKind, HashSet<ICustomAttributeProvider>> _trackedRoots; + Dictionary<SerializerKind, HashSet<ICustomAttributeProvider>>? _trackedRoots; Dictionary<SerializerKind, HashSet<ICustomAttributeProvider>> TrackedRoots { get { if (_trackedRoots == null) @@ -65,7 +65,7 @@ namespace Mono.Linker } } - HashSet<TypeDefinition> _recursiveTypes; + HashSet<TypeDefinition>? _recursiveTypes; HashSet<TypeDefinition> RecursiveTypes { get { if (_recursiveTypes == null) @@ -185,7 +185,7 @@ namespace Mono.Linker // This doesn't handle other TypeSpecs. We are only matching what xamarin-android used to do. // Arrays will still work because Resolve returns the array element type. - TypeDefinition type = _context.TryResolve (typeRef); + TypeDefinition? type = _context.TryResolve (typeRef); if (type == null) return; diff --git a/src/linker/Linker/SubstitutionInfo.cs b/src/linker/Linker/SubstitutionInfo.cs index 600714b33..9e54b8043 100644 --- a/src/linker/Linker/SubstitutionInfo.cs +++ b/src/linker/Linker/SubstitutionInfo.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using Mono.Cecil; -#nullable enable - namespace Mono.Linker { public class SubstitutionInfo diff --git a/src/linker/Linker/Tracer.cs b/src/linker/Linker/Tracer.cs index 32876937c..28a71a995 100644 --- a/src/linker/Linker/Tracer.cs +++ b/src/linker/Linker/Tracer.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Mono.Linker { @@ -35,7 +36,7 @@ namespace Mono.Linker { protected readonly LinkContext context; - List<IDependencyRecorder> recorders; + List<IDependencyRecorder>? recorders; public Tracer (LinkContext context) { @@ -63,6 +64,7 @@ namespace Mono.Linker recorders.Add (recorder); } + [MemberNotNullWhen (true, "recorders")] bool IsRecordingEnabled () { return recorders != null; diff --git a/src/linker/Linker/TypeHierarchyCache.cs b/src/linker/Linker/TypeHierarchyCache.cs index 470e34f6d..bc036c7a5 100644 --- a/src/linker/Linker/TypeHierarchyCache.cs +++ b/src/linker/Linker/TypeHierarchyCache.cs @@ -31,7 +31,7 @@ namespace Mono.Linker flags |= HierarchyFlags.IsSystemReflectionIReflect; } - TypeDefinition baseType = resolvedType; + TypeDefinition? baseType = resolvedType; while (baseType != null) { if (baseType.Name == "Type" && baseType.Namespace == "System") { flags |= HierarchyFlags.IsSystemType; diff --git a/src/linker/Linker/TypeMapInfo.cs b/src/linker/Linker/TypeMapInfo.cs index 8a5301a23..2d1350290 100644 --- a/src/linker/Linker/TypeMapInfo.cs +++ b/src/linker/Linker/TypeMapInfo.cs @@ -54,21 +54,21 @@ namespace Mono.Linker MapType (type); } - public IEnumerable<OverrideInformation> GetOverrides (MethodDefinition method) + public IEnumerable<OverrideInformation>? GetOverrides (MethodDefinition method) { EnsureProcessed (method.Module.Assembly); - override_methods.TryGetValue (method, out List<OverrideInformation> overrides); + override_methods.TryGetValue (method, out List<OverrideInformation>? overrides); return overrides; } - public List<MethodDefinition> GetBaseMethods (MethodDefinition method) + public List<MethodDefinition>? GetBaseMethods (MethodDefinition method) { EnsureProcessed (method.Module.Assembly); - base_methods.TryGetValue (method, out List<MethodDefinition> bases); + base_methods.TryGetValue (method, out List<MethodDefinition>? bases); return bases; } - public IEnumerable<(TypeDefinition InstanceType, InterfaceImplementation ProvidingInterface)> GetDefaultInterfaceImplementations (MethodDefinition method) + public IEnumerable<(TypeDefinition InstanceType, InterfaceImplementation ProvidingInterface)>? GetDefaultInterfaceImplementations (MethodDefinition method) { default_interface_implementations.TryGetValue (method, out var ret); return ret; @@ -76,7 +76,7 @@ namespace Mono.Linker public void AddBaseMethod (MethodDefinition method, MethodDefinition @base) { - if (!base_methods.TryGetValue (method, out List<MethodDefinition> methods)) { + if (!base_methods.TryGetValue (method, out List<MethodDefinition>? methods)) { methods = new List<MethodDefinition> (); base_methods[method] = methods; } @@ -84,9 +84,9 @@ namespace Mono.Linker methods.Add (@base); } - public void AddOverride (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) + public void AddOverride (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation? matchingInterfaceImplementation = null) { - if (!override_methods.TryGetValue (@base, out List<OverrideInformation> methods)) { + if (!override_methods.TryGetValue (@base, out List<OverrideInformation>? methods)) { methods = new List<OverrideInformation> (); override_methods.Add (@base, methods); } @@ -125,7 +125,7 @@ namespace Mono.Linker // to find the method implementation and record it. foreach (var interfaceImpl in type.GetInflatedInterfaces (context)) { foreach (MethodReference interfaceMethod in interfaceImpl.InflatedInterface.GetMethods (context)) { - MethodDefinition resolvedInterfaceMethod = context.TryResolve (interfaceMethod); + MethodDefinition? resolvedInterfaceMethod = context.TryResolve (interfaceMethod); if (resolvedInterfaceMethod == null) continue; @@ -139,7 +139,7 @@ namespace Mono.Linker continue; // Try to find an implementation with a name/sig match on the current type - MethodDefinition exactMatchOnType = TryMatchMethod (type, interfaceMethod); + MethodDefinition? exactMatchOnType = TryMatchMethod (type, interfaceMethod); if (exactMatchOnType != null) { AnnotateMethods (resolvedInterfaceMethod, exactMatchOnType); continue; @@ -181,7 +181,7 @@ namespace Mono.Linker void MapVirtualMethod (MethodDefinition method) { - MethodDefinition @base = GetBaseMethodInTypeHierarchy (method); + MethodDefinition? @base = GetBaseMethodInTypeHierarchy (method); if (@base == null) return; @@ -191,7 +191,7 @@ namespace Mono.Linker void MapOverrides (MethodDefinition method) { foreach (MethodReference override_ref in method.Overrides) { - MethodDefinition @override = context.TryResolve (override_ref); + MethodDefinition? @override = context.TryResolve (override_ref); if (@override == null) continue; @@ -199,22 +199,22 @@ namespace Mono.Linker } } - void AnnotateMethods (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation matchingInterfaceImplementation = null) + void AnnotateMethods (MethodDefinition @base, MethodDefinition @override, InterfaceImplementation? matchingInterfaceImplementation = null) { AddBaseMethod (@override, @base); AddOverride (@base, @override, matchingInterfaceImplementation); } - MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) + MethodDefinition? GetBaseMethodInTypeHierarchy (MethodDefinition method) { return GetBaseMethodInTypeHierarchy (method.DeclaringType, method); } - MethodDefinition GetBaseMethodInTypeHierarchy (TypeDefinition type, MethodReference method) + MethodDefinition? GetBaseMethodInTypeHierarchy (TypeDefinition type, MethodReference method) { - TypeReference @base = GetInflatedBaseType (type); + TypeReference? @base = GetInflatedBaseType (type); while (@base != null) { - MethodDefinition base_method = TryMatchMethod (@base, method); + MethodDefinition? base_method = TryMatchMethod (@base, method); if (base_method != null) return base_method; @@ -224,7 +224,7 @@ namespace Mono.Linker return null; } - TypeReference GetInflatedBaseType (TypeReference type) + TypeReference? GetInflatedBaseType (TypeReference type) { if (type == null) return null; @@ -300,7 +300,7 @@ namespace Mono.Linker } } - MethodDefinition TryMatchMethod (TypeReference type, MethodReference method) + MethodDefinition? TryMatchMethod (TypeReference type, MethodReference method) { foreach (var candidate in type.GetMethods (context)) { var md = context.TryResolve (candidate); @@ -327,7 +327,9 @@ namespace Mono.Linker // we need to track what the generic parameter represent - as we cannot allow it to // differ between the return type or any parameter - if (!TypeMatch (candidate.GetReturnType (context), method.GetReturnType (context))) + if (candidate.GetReturnType (context) is not TypeReference candidateReturnType || + method.GetReturnType (context) is not TypeReference methodReturnType || + !TypeMatch (candidateReturnType, methodReturnType)) return false; if (!candidate.HasParameters) @@ -342,7 +344,9 @@ namespace Mono.Linker return false; for (int i = 0; i < cp.Count; i++) { - if (!TypeMatch (candidate.GetParameterType (i, context), method.GetParameterType (i, context))) + if (candidate.GetParameterType (i, context) is not TypeReference candidateParameterType || + method.GetParameterType (i, context) is not TypeReference methodParameterType || + !TypeMatch (candidateParameterType, methodParameterType)) return false; } diff --git a/src/linker/Linker/TypeNameResolver.cs b/src/linker/Linker/TypeNameResolver.cs index 3c6ae6ea0..392aed9e9 100644 --- a/src/linker/Linker/TypeNameResolver.cs +++ b/src/linker/Linker/TypeNameResolver.cs @@ -1,4 +1,6 @@ using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection.Runtime.TypeParsing; using Mono.Cecil; @@ -13,27 +15,29 @@ namespace Mono.Linker _context = context; } - public TypeReference ResolveTypeName (string typeNameString, ICustomAttributeProvider origin, out AssemblyDefinition typeAssembly, bool needsAssemblyName = true) + public bool TryResolveTypeName (string typeNameString, ICustomAttributeProvider? origin, [NotNullWhen (true)] out TypeReference? typeReference, [NotNullWhen (true)] out AssemblyDefinition? typeAssembly, bool needsAssemblyName = true) { + typeReference = null; typeAssembly = null; if (string.IsNullOrEmpty (typeNameString)) - return null; + return false; TypeName parsedTypeName; try { parsedTypeName = TypeParser.ParseTypeName (typeNameString); } catch (ArgumentException) { - return null; + return false; } catch (System.IO.FileLoadException) { - return null; + return false; } if (parsedTypeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName) { typeAssembly = _context.TryResolve (assemblyQualifiedTypeName.AssemblyName.Name); if (typeAssembly == null) - return null; + return false; - return ResolveTypeName (typeAssembly, assemblyQualifiedTypeName.TypeName); + typeReference = ResolveTypeName (typeAssembly, assemblyQualifiedTypeName.TypeName); + return typeReference != null; } // If parsedTypeName doesn't have an assembly name in it but it does have a namespace, @@ -47,13 +51,13 @@ namespace Mono.Linker _ => throw new NotSupportedException () }; - if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out var typeRef)) - return typeRef; + if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference)) + return true; // If type is not found in the caller's assembly, try in core assembly. typeAssembly = _context.TryResolve (PlatformAssemblies.CoreLib); - if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out var typeRefFromSPCL)) - return typeRefFromSPCL; + if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference)) + 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. @@ -64,9 +68,9 @@ namespace Mono.Linker } typeAssembly = null; - return null; + return false; - bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName typeName, out TypeReference typeReference) + bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName typeName, [NotNullWhen (true)] out TypeReference? typeReference) { typeReference = null; if (assemblyDefinition == null) @@ -77,17 +81,18 @@ namespace Mono.Linker } } - public TypeReference ResolveTypeName (AssemblyDefinition assembly, string typeNameString) + public bool TryResolveTypeName (AssemblyDefinition assembly, string typeNameString, [NotNullWhen (true)] out TypeReference? typeReference) { - return ResolveTypeName (assembly, TypeParser.ParseTypeName (typeNameString)); + typeReference = ResolveTypeName (assembly, TypeParser.ParseTypeName (typeNameString)); + return typeReference != null; } - TypeReference ResolveTypeName (AssemblyDefinition assembly, TypeName typeName) + TypeReference? ResolveTypeName (AssemblyDefinition assembly, TypeName typeName) { if (typeName is AssemblyQualifiedTypeName assemblyQualifiedTypeName) { // In this case we ignore the assembly parameter since the type name has assembly in it var assemblyFromName = _context.TryResolve (assemblyQualifiedTypeName.AssemblyName.Name); - return ResolveTypeName (assemblyFromName, assemblyQualifiedTypeName.TypeName); + return assemblyFromName == null ? null : ResolveTypeName (assemblyFromName, assemblyQualifiedTypeName.TypeName); } if (assembly == null || typeName == null) @@ -98,8 +103,8 @@ namespace Mono.Linker if (genericTypeRef == null) return null; - TypeDefinition genericType = _context.TryResolve (genericTypeRef); - var genericInstanceType = new GenericInstanceType (genericType); + Debug.Assert (genericTypeRef is TypeDefinition); + var genericInstanceType = new GenericInstanceType (genericTypeRef); foreach (var arg in constructedGenericTypeName.GenericArguments) { var genericArgument = ResolveTypeName (assembly, arg); if (genericArgument == null) diff --git a/src/linker/Linker/TypeReferenceExtensions.cs b/src/linker/Linker/TypeReferenceExtensions.cs index 9077971cf..d72485074 100644 --- a/src/linker/Linker/TypeReferenceExtensions.cs +++ b/src/linker/Linker/TypeReferenceExtensions.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using Mono.Cecil; @@ -26,7 +27,7 @@ namespace Mono.Linker if (type == null) return sb; - Stack<TypeReference> genericArguments = null; + Stack<TypeReference>? genericArguments = null; while (true) { switch (type) { case ArrayType arrayType: @@ -61,10 +62,11 @@ namespace Mono.Linker break; } - type = type.DeclaringType; - if (type == null) + if (type.DeclaringType is not TypeReference declaringType) break; + type = declaringType; + sb.Insert (0, '.'); } @@ -109,11 +111,8 @@ namespace Mono.Linker } } - public static TypeReference GetInflatedDeclaringType (this TypeReference type, ITryResolveMetadata resolver) + public static TypeReference? GetInflatedDeclaringType (this TypeReference type, ITryResolveMetadata resolver) { - if (type == null) - return null; - if (type.IsGenericParameter || type.IsByReference || type.IsPointer) return null; @@ -140,9 +139,11 @@ namespace Mono.Linker return declaringType; } - var resolved = resolver.TryResolve (type); - System.Diagnostics.Debug.Assert (resolved == type); - return resolved?.DeclaringType; + if (type is TypeDefinition typeDefinition) + return typeDefinition.DeclaringType; + + Debug.Assert (false); + return null; } public static IEnumerable<(TypeReference InflatedInterface, InterfaceImplementation OriginalImpl)> GetInflatedInterfaces (this TypeReference typeRef, ITryResolveMetadata resolver) @@ -153,15 +154,18 @@ namespace Mono.Linker yield break; if (typeRef is GenericInstanceType genericInstance) { - foreach (var interfaceImpl in typeDef.Interfaces) - yield return (InflateGenericType (genericInstance, interfaceImpl.InterfaceType, resolver), interfaceImpl); + foreach (var interfaceImpl in typeDef.Interfaces) { + // InflateGenericType only returns null when inflating generic parameters (and the generic instance type doesn't resolve). + // Here we are not inflating a generic parameter but an interface type reference. + yield return (InflateGenericType (genericInstance, interfaceImpl.InterfaceType, resolver), interfaceImpl)!; + } } else { foreach (var interfaceImpl in typeDef.Interfaces) yield return (interfaceImpl.InterfaceType, interfaceImpl); } } - public static TypeReference InflateGenericType (GenericInstanceType genericInstanceProvider, TypeReference typeToInflate, ITryResolveMetadata resolver) + public static TypeReference? InflateGenericType (GenericInstanceType genericInstanceProvider, TypeReference typeToInflate, ITryResolveMetadata resolver) { if (typeToInflate is ArrayType arrayType) { var inflatedElementType = InflateGenericType (genericInstanceProvider, arrayType.ElementType, resolver); @@ -262,7 +266,7 @@ namespace Mono.Linker public static IEnumerable<MethodReference> GetMethods (this TypeReference type, ITryResolveMetadata resolver) { - TypeDefinition typeDef = resolver.TryResolve (type); + TypeDefinition? typeDef = resolver.TryResolve (type); if (typeDef?.HasMethods != true) yield break; @@ -341,7 +345,7 @@ namespace Mono.Linker public static bool IsSubclassOf (this TypeReference type, string ns, string name, ITryResolveMetadata resolver) { - TypeDefinition baseType = resolver.TryResolve (type); + TypeDefinition? baseType = resolver.TryResolve (type); while (baseType != null) { if (baseType.IsTypeOf (ns, name)) return true; diff --git a/src/linker/Linker/TypeReferenceWalker.cs b/src/linker/Linker/TypeReferenceWalker.cs index c4f894812..46b5f1a5a 100644 --- a/src/linker/Linker/TypeReferenceWalker.cs +++ b/src/linker/Linker/TypeReferenceWalker.cs @@ -7,8 +7,6 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; -#nullable enable - namespace Mono.Linker { abstract class TypeReferenceWalker diff --git a/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs b/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs index 989636447..edf184e1c 100644 --- a/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs +++ b/src/linker/Linker/UnconditionalSuppressMessageAttributeState.cs @@ -29,7 +29,7 @@ namespace Mono.Linker suppressions = new Dictionary<int, SuppressMessageInfo> (); _suppressions.Add (provider, suppressions); } else if (suppressions.ContainsKey (info.Id)) { - string elementName = provider is MemberReference memberRef ? memberRef.GetDisplayName () : provider.ToString (); + string? elementName = provider is MemberReference memberRef ? memberRef.GetDisplayName () : provider.ToString (); _context.LogMessage ($"Element '{elementName}' has more than one unconditional suppression. Note that only the last one is used."); } @@ -42,25 +42,24 @@ namespace Mono.Linker // (if they're different). This is to correctly handle compiler generated code // which needs to use suppressions from both the compiler generated scope // as well as the original user defined method. - ICustomAttributeProvider suppressionContextMember = warningOrigin.SuppressionContextMember; + ICustomAttributeProvider? suppressionContextMember = warningOrigin.SuppressionContextMember; if (IsSuppressed (id, suppressionContextMember, out info)) return true; - ICustomAttributeProvider provider = warningOrigin.Provider; + ICustomAttributeProvider? provider = warningOrigin.Provider; if (suppressionContextMember != provider && IsSuppressed (id, provider, out info)) return true; return false; } - bool IsSuppressed (int id, ICustomAttributeProvider warningOrigin, out SuppressMessageInfo info) + bool IsSuppressed (int id, ICustomAttributeProvider? warningOrigin, out SuppressMessageInfo info) { info = default; if (warningOrigin == null) return false; - ModuleDefinition module = GetModuleFromProvider (warningOrigin); if (warningOrigin is IMemberDefinition warningOriginMember) { while (warningOriginMember != null) { if (IsSuppressedOnElement (id, warningOriginMember, out info)) @@ -70,6 +69,10 @@ namespace Mono.Linker } } + ModuleDefinition? module = GetModuleFromProvider (warningOrigin); + if (module == null) + return false; + // Check if there's an assembly or module level suppression. if (IsSuppressedOnElement (id, module, out info) || IsSuppressedOnElement (id, module.Assembly, out info)) @@ -78,7 +81,7 @@ namespace Mono.Linker return false; } - bool IsSuppressedOnElement (int id, ICustomAttributeProvider provider, out SuppressMessageInfo info) + bool IsSuppressedOnElement (int id, ICustomAttributeProvider? provider, out SuppressMessageInfo info) { info = default; if (provider == null) @@ -95,12 +98,13 @@ namespace Mono.Linker // Gather assembly-level suppressions if we haven't already. To ensure that we always cache // complete information for a member, we will also scan for attributes on any other members // targeted by the assembly-level suppressions. - var module = GetModuleFromProvider (provider); - var assembly = module.Assembly; - if (InitializedAssemblies.Add (assembly)) { - foreach (var suppression in DecodeAssemblyAndModuleSuppressions (module)) { - AddSuppression (suppression.Info, suppression.Target); - membersToScan.Add (suppression.Target); + if (GetModuleFromProvider (provider) is ModuleDefinition module) { + var assembly = module.Assembly; + if (InitializedAssemblies.Add (assembly)) { + foreach (var suppression in DecodeAssemblyAndModuleSuppressions (module)) { + AddSuppression (suppression.Info, suppression.Target); + membersToScan.Add (suppression.Target); + } } } @@ -142,14 +146,14 @@ namespace Mono.Linker if (attribute.HasProperties) { foreach (var p in attribute.Properties) { switch (p.Name) { - case ScopeProperty: - info.Scope = p.Argument.Value as string; + case ScopeProperty when p.Argument.Value is string scope: + info.Scope = scope; break; - case TargetProperty: - info.Target = p.Argument.Value as string; + case TargetProperty when p.Argument.Value is string target: + info.Target = target; break; - case MessageIdProperty: - info.MessageId = p.Argument.Value as string; + case MessageIdProperty when p.Argument.Value is string messageId: + info.MessageId = messageId; break; } } @@ -158,7 +162,7 @@ namespace Mono.Linker return true; } - public static ModuleDefinition GetModuleFromProvider (ICustomAttributeProvider provider) + public static ModuleDefinition? GetModuleFromProvider (ICustomAttributeProvider provider) { switch (provider.MetadataToken.TokenType) { case TokenType.Module: diff --git a/src/linker/Linker/WarningSuppressionWriter.cs b/src/linker/Linker/WarningSuppressionWriter.cs index 37d5f2aa8..d8421f099 100644 --- a/src/linker/Linker/WarningSuppressionWriter.cs +++ b/src/linker/Linker/WarningSuppressionWriter.cs @@ -33,7 +33,10 @@ namespace Mono.Linker if (provider is not IMemberDefinition memberDefinition) return; - var assemblyName = UnconditionalSuppressMessageAttributeState.GetModuleFromProvider (memberDefinition).Assembly.Name; + if (UnconditionalSuppressMessageAttributeState.GetModuleFromProvider (provider) is not ModuleDefinition module) + return; + + var assemblyName = module.Assembly.Name; if (!_warnings.TryGetValue (assemblyName, out var warnings)) { warnings = new HashSet<(int, IMemberDefinition)> (); _warnings.Add (assemblyName, warnings); diff --git a/src/linker/Linker/XmlDependencyRecorder.cs b/src/linker/Linker/XmlDependencyRecorder.cs index 0e3b2f538..6ff4284d8 100644 --- a/src/linker/Linker/XmlDependencyRecorder.cs +++ b/src/linker/Linker/XmlDependencyRecorder.cs @@ -39,10 +39,10 @@ namespace Mono.Linker public const string DefaultDependenciesFileName = "linker-dependencies.xml.gz"; private readonly LinkContext context; - private XmlWriter writer; - private Stream stream; + private XmlWriter? writer; + private Stream? stream; - public XmlDependencyRecorder (LinkContext context, string fileName = null) + public XmlDependencyRecorder (LinkContext context, string? fileName = null) { this.context = context; @@ -83,13 +83,16 @@ namespace Mono.Linker writer.WriteEndDocument (); writer.Flush (); writer.Dispose (); - stream.Dispose (); + stream?.Dispose (); writer = null; stream = null; } public void RecordDependency (object target, in DependencyInfo reason, bool marked) { + if (writer == null) + throw new InvalidOperationException (); + if (reason.Kind == DependencyKind.Unspecified) return; @@ -97,8 +100,11 @@ namespace Mono.Linker RecordDependency (reason.Source, target, marked); } - public void RecordDependency (object source, object target, bool marked) + public void RecordDependency (object? source, object target, bool marked) { + if (writer == null) + throw new InvalidOperationException (); + if (!ShouldRecord (source) && !ShouldRecord (target)) return; @@ -136,7 +142,7 @@ namespace Mono.Linker return false; } - string TokenString (object o) + string TokenString (object? o) { if (o == null) return "N:null"; @@ -173,7 +179,7 @@ namespace Mono.Linker } } - bool ShouldRecord (object o) + bool ShouldRecord (object? o) { if (!context.EnableReducedTracing) return true; diff --git a/src/linker/Mono.Linker.csproj b/src/linker/Mono.Linker.csproj index 54612fbcb..391300aad 100644 --- a/src/linker/Mono.Linker.csproj +++ b/src/linker/Mono.Linker.csproj @@ -2,7 +2,6 @@ <PropertyGroup> <OutputType>Exe</OutputType> - <Nullable>warnings</Nullable> <ServerGarbageCollection>true</ServerGarbageCollection> </PropertyGroup> |