-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve ILLink warnings in System.Linq.Expressions (Final) (#55856)
* Resolve ILLink warnings in System.Linq.Expressions (Final) Suppress ILLink warnings for operator methods now that dotnet/linker#1821 is resolved. Add TrimmingTests for Linq.Expressions operators. Fix #45623
- Loading branch information
Showing
10 changed files
with
294 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 0 additions & 17 deletions
17
src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Suppressions.xml
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
src/libraries/System.Linq.Expressions/tests/TrimmingTests/BinaryOperatorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// 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.Linq.Expressions; | ||
|
||
/// <summary> | ||
/// Tests that Expression.Add expressions still work correctly and find | ||
/// the + operator in a trimmed app. | ||
/// </summary> | ||
internal class Program | ||
{ | ||
static int Main(string[] args) | ||
{ | ||
ParameterExpression leftParameter = Expression.Parameter(typeof(Class1)); | ||
ParameterExpression rightParameter = Expression.Parameter(typeof(Class1)); | ||
ParameterExpression result = Expression.Variable(typeof(Class1)); | ||
|
||
Func<Class1, Class1, Class1> func = | ||
Expression.Lambda<Func<Class1, Class1, Class1>>( | ||
Expression.Block( | ||
new[] { result }, | ||
Expression.Assign(result, Expression.Add(leftParameter, rightParameter)), | ||
result), | ||
leftParameter, rightParameter) | ||
.Compile(); | ||
|
||
Class1 actual = func(new Class1("left"), new Class1("right")); | ||
if (actual.Name != "left+right") | ||
{ | ||
return -1; | ||
} | ||
|
||
// make sure Class2 was trimmed since it wasn't used, even though Class1 has a binary operator using it | ||
int i = 2; | ||
if (typeof(Program).Assembly.GetType("Class" + i) != null) | ||
{ | ||
return -2; | ||
} | ||
|
||
return 100; | ||
} | ||
} | ||
|
||
internal class Class1 | ||
{ | ||
public Class1(string name) => Name = name; | ||
|
||
public string Name { get; set; } | ||
|
||
public static Class1 operator +(Class1 left, Class1 right) => | ||
new Class1($"{left.Name}+{right.Name}"); | ||
|
||
public static Class1 operator +(Class1 left, Class2 right) => | ||
new Class1($"{left.Name}+{right.Name}2"); | ||
public static Class2 operator +(Class2 left, Class1 right) => | ||
new Class2($"{left.Name}2+{right.Name}"); | ||
} | ||
|
||
internal class Class2 | ||
{ | ||
public Class2(string name) => Name = name; | ||
|
||
public string Name { get; set; } | ||
} |
91 changes: 91 additions & 0 deletions
91
src/libraries/System.Linq.Expressions/tests/TrimmingTests/ConvertOperatorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// 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.Linq.Expressions; | ||
using System.Reflection; | ||
|
||
/// <summary> | ||
/// Tests that Expression.Convert expressions still work correctly and find | ||
/// implicit and explicit operators in a trimmed app. | ||
/// </summary> | ||
internal class Program | ||
{ | ||
static int Main(string[] args) | ||
{ | ||
Type[] convertTypes = new Type[] { typeof(Class2), typeof(Class3) }; | ||
|
||
ParameterExpression class1Parameter = Expression.Parameter(typeof(Class1), "class1"); | ||
MethodInfo getNameMethodInfo = typeof(Program).GetMethod("GetName"); | ||
foreach (Type convertType in convertTypes) | ||
{ | ||
UnaryExpression conversion = Expression.Convert(class1Parameter, convertType); | ||
|
||
Func<Class1, string> getNameFunc = | ||
Expression.Lambda<Func<Class1, string>>( | ||
Expression.Call(null, getNameMethodInfo, conversion), | ||
class1Parameter) | ||
.Compile(); | ||
|
||
string name = getNameFunc(new Class1() { Name = convertType.Name }); | ||
if (convertType.Name == "Class2") | ||
{ | ||
if (name != "Class2_implicit") | ||
{ | ||
return -1; | ||
} | ||
} | ||
else if (convertType.Name == "Class3") | ||
{ | ||
if (name != "Class3_explicit") | ||
{ | ||
return -2; | ||
} | ||
} | ||
else | ||
{ | ||
return -3; | ||
} | ||
} | ||
|
||
// make sure Class4 was trimmed since it wasn't used, even though Class1 has a conversion operator to it | ||
int i = 4; | ||
if (typeof(Program).Assembly.GetType("Class" + i) != null) | ||
{ | ||
return -4; | ||
} | ||
|
||
return 100; | ||
} | ||
|
||
public static string GetName(IHasName hasName) => hasName.Name; | ||
} | ||
|
||
interface IHasName | ||
{ | ||
string Name { get; } | ||
} | ||
|
||
internal class Class1 : IHasName | ||
{ | ||
public string Name { get; set; } | ||
|
||
public static implicit operator Class2(Class1 class1) => new Class2() { Name = class1.Name + "_implicit" }; | ||
public static explicit operator Class3(Class1 class1) => new Class3() { Name = class1.Name + "_explicit" }; | ||
public static implicit operator Class4(Class1 class1) => new Class4() { Name = class1.Name + "_implicit" }; | ||
} | ||
|
||
internal class Class2 : IHasName | ||
{ | ||
public string Name { get; set; } | ||
} | ||
|
||
internal class Class3 : IHasName | ||
{ | ||
public string Name { get; set; } | ||
} | ||
|
||
internal class Class4 : IHasName | ||
{ | ||
public string Name { get; set; } | ||
} |
Oops, something went wrong.