From 20403c7acf515db2bb6af5ec0ec3fdfb23ae7b69 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 9 Jun 2021 09:10:08 -0700 Subject: [PATCH] Always show IL2026 for IsTrimmable assemblies --- src/linker/Linker/LinkContext.cs | 14 +++++-- src/linker/Linker/MessageContainer.cs | 41 ++++++++++++++----- .../TriggerWarnings_TrimmableLib.cs | 24 +++++++++++ ...TrimmableAssembliesCanSurviveSingleWarn.cs | 23 +++++++++++ 4 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 test/Mono.Linker.Tests.Cases/Warnings/Dependencies/TriggerWarnings_TrimmableLib.cs create mode 100644 test/Mono.Linker.Tests.Cases/Warnings/WarningsFromTrimmableAssembliesCanSurviveSingleWarn.cs diff --git a/src/linker/Linker/LinkContext.cs b/src/linker/Linker/LinkContext.cs index 851f77ec79ac..d6d6ef02f1fd 100644 --- a/src/linker/Linker/LinkContext.cs +++ b/src/linker/Linker/LinkContext.cs @@ -72,6 +72,7 @@ public class LinkContext : IMetadataResolver, IDisposable readonly CustomAttributeSource _customAttributes; readonly List _cachedWarningMessageContainers; readonly ILogger _logger; + readonly Dictionary _isTrimmable; public Pipeline Pipeline { get { return _pipeline; } @@ -210,6 +211,7 @@ public LinkContext (Pipeline pipeline, ILogger logger) _parameters = new Dictionary (StringComparer.Ordinal); _customAttributes = new CustomAttributeSource (this); _cachedWarningMessageContainers = new List (); + _isTrimmable = new Dictionary (); FeatureSettings = new Dictionary (StringComparer.Ordinal); SymbolReaderProvider = new DefaultSymbolReaderProvider (false); @@ -424,12 +426,15 @@ static bool IsCPPCLIAssembly (ModuleDefinition module) } } - bool IsTrimmable (AssemblyDefinition assembly) + public bool IsTrimmable (AssemblyDefinition assembly) { - if (!assembly.HasCustomAttributes) - return false; + if (_isTrimmable.TryGetValue (assembly, out bool isTrimmable)) + return isTrimmable; - bool isTrimmable = false; + if (!assembly.HasCustomAttributes) { + _isTrimmable.Add (assembly, false); + return false; + } foreach (var ca in assembly.CustomAttributes) { if (!ca.AttributeType.IsTypeOf ()) @@ -450,6 +455,7 @@ bool IsTrimmable (AssemblyDefinition assembly) isTrimmable = true; } + _isTrimmable.Add (assembly, isTrimmable); return isTrimmable; } diff --git a/src/linker/Linker/MessageContainer.cs b/src/linker/Linker/MessageContainer.cs index 32260af9bd1a..941772327674 100644 --- a/src/linker/Linker/MessageContainer.cs +++ b/src/linker/Linker/MessageContainer.cs @@ -132,17 +132,8 @@ private static MessageContainer CreateWarningMessageContainer (LinkContext conte if (version > context.WarnVersion) return Empty; - if (subcategory == MessageSubCategory.TrimAnalysis) { - Debug.Assert (origin.MemberDefinition != null); - var declaringType = origin.MemberDefinition?.DeclaringType ?? (origin.MemberDefinition as TypeDefinition); - var assembly = declaringType.Module.Assembly; - var assemblyName = assembly?.Name.Name; - if (assemblyName != null && context.IsSingleWarn (assemblyName)) { - if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName)) - context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly)); - return Empty; - } - } + if (TryLogSingleWarning (context, code, origin, subcategory)) + return Empty; if (context.IsWarningAsError (code)) return new MessageContainer (MessageCategory.WarningAsError, text, code, subcategory, origin); @@ -150,6 +141,34 @@ private static MessageContainer CreateWarningMessageContainer (LinkContext conte return new MessageContainer (MessageCategory.Warning, text, code, subcategory, origin); } + static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin origin, string subcategory) + { + if (subcategory != MessageSubCategory.TrimAnalysis) + return false; + + Debug.Assert (origin.MemberDefinition != null); + var declaringType = origin.MemberDefinition?.DeclaringType ?? (origin.MemberDefinition as TypeDefinition); + var assembly = declaringType.Module.Assembly; + + Debug.Assert (assembly != null); + if (assembly == null) + return false; + + // Any IL2026 warnings left in an assembly with an IsTrimmable attribute are considered intentional + // and should not be collapsed, so that the user-visible RUC message gets printed. + if (code == 2026 && context.IsTrimmable (assembly)) + return false; + + var assemblyName = assembly.Name.Name; + if (!context.IsSingleWarn (assemblyName)) + return false; + + if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName)) + context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly)); + + return true; + } + /// /// Create a info message. /// diff --git a/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/TriggerWarnings_TrimmableLib.cs b/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/TriggerWarnings_TrimmableLib.cs new file mode 100644 index 000000000000..73160856790a --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Warnings/Dependencies/TriggerWarnings_TrimmableLib.cs @@ -0,0 +1,24 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +[assembly: AssemblyMetadata ("IsTrimmable", "True")] + +namespace Mono.Linker.Tests.Cases.Warnings.Dependencies +{ + public class TriggerWarnings_TrimmableLib + { + public static void Main () + { + RequirePublicMethods (UnknownType ()); + RUCIntentional (); + } + + static Type UnknownType () => null; + + static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } + + [RequiresUnreferencedCode ("RUC warning left in the trimmable assembly.")] + static void RUCIntentional () { } + } +} diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningsFromTrimmableAssembliesCanSurviveSingleWarn.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningsFromTrimmableAssembliesCanSurviveSingleWarn.cs new file mode 100644 index 000000000000..a9eedeaae603 --- /dev/null +++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningsFromTrimmableAssembliesCanSurviveSingleWarn.cs @@ -0,0 +1,23 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.Warnings.Dependencies; + +namespace Mono.Linker.Tests.Cases.Warnings +{ + [SkipKeptItemsValidation] + [SetupCompileBefore ("library.dll", new[] { typeof (TriggerWarnings_TrimmableLib) })] + [SetupLinkerArgument ("--singlewarn")] + [LogContains (".*warning IL2026: .*TriggerWarnings_TrimmableLib.RUCIntentional.*RUC warning left in the trimmable assembly.*", regexMatch: true)] + [LogDoesNotContain ("IL2072")] + [LogContains ("warning IL2104: Assembly 'library' produced trim warnings")] + [LogDoesNotContain ("IL2026")] + public class WarningsFromTrimmableAssembliesCanSurviveSingleWarn + { + public static void Main () + { + TriggerWarnings_TrimmableLib.Main (); + } + } +}