Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoiding discarding exception details of MissingMethodException in RuntimeType.CreateInstanceImpl #108876

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4e2921b
Update RuntimeType.CoreCLR.cs (Should not trash the stack trace of `M…
Takym Oct 15, 2024
f512d99
Merge branch 'dotnet:main' into AvoidingDiscardingExceptionDetails/20…
Takym Oct 15, 2024
9b22861
Update RuntimeType.Mono.cs (Should not trash the stack trace of `Miss…
Takym Oct 15, 2024
419d8f6
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 15, 2024
8c83f90
Rethrow for modifying the message to include the method name certainl…
Takym Oct 17, 2024
ab24087
Fix RuntimeType.CoreCLR.cs (var scope mistake)
Takym Oct 17, 2024
72bf64f
Update RuntimeType.CoreCLR.cs
Takym Oct 17, 2024
87a9780
Rethrow for modifying the message to include the method name certainl…
Takym Oct 17, 2024
79f9749
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 17, 2024
aa86d82
Merge branch 'dotnet:main' into AvoidingDiscardingExceptionDetails/20…
Takym Oct 17, 2024
2a75ccf
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 18, 2024
40c463e
Update comments in `RuntimeType.CreateInstanceImpl`
Takym Oct 18, 2024
75b3c3a
Merge branch 'AvoidingDiscardingExceptionDetails/2024_10' of https://…
Takym Oct 18, 2024
e4a8824
Added a new test for RuntimeType.CreateInstanceImpl throws MissingMet…
Takym Oct 18, 2024
936a2bb
Update src/libraries/System.Runtime/tests/System.Runtime.Tests/System…
Takym Oct 18, 2024
cc148ce
Update src/libraries/System.Runtime/tests/System.Runtime.Tests/System…
Takym Oct 18, 2024
4ccbc9d
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 18, 2024
a9c94a8
Update src/libraries/System.Runtime/tests/System.Runtime.Tests/System…
Takym Oct 18, 2024
9e08d3d
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 18, 2024
1836b5d
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 19, 2024
28236f5
Merge branch 'main' into AvoidingDiscardingExceptionDetails/2024_10
Takym Oct 19, 2024
e4808c5
Fixed a tester bug (`ActivatorTests.CreateInstance_WithCustomBinder_T…
Takym Oct 20, 2024
8059876
Test more strictly (`ActivatorTests.CreateInstance_WithCustomBinder_T…
Takym Oct 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3915,13 +3915,18 @@ private void CreateInstanceCheckThis()
}

MethodBase? invokeMethod;
object? state = null;
object? state;

try
{
invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state);
}
catch (MissingMethodException) { invokeMethod = null; }
catch (MissingMethodException innerMME)
{
// Rethrows to rewrite a message to include the class name.
// Make sure the original exception is set as an inner exception.
throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, FullName), innerMME);
}

if (invokeMethod is null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,105 @@ public void CreateInstance_PublicOnlyTypeWithPrivateDefaultConstructor_ThrowsMis
Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(typeof(TypeWithPrivateDefaultConstructor), nonPublic: false));
}

[Fact]
public void CreateInstance_WithCustomBinder_ThrowsMissingMethodException()
{
// MissingMethodException not caused by a binder must not contain an inner exception.
var mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(typeof(TypeWithPrivateDefaultConstructor), nonPublic: false));
Assert.Contains("System.Tests.ActivatorTests+TypeWithPrivateDefaultConstructor", mme.Message);
Assert.Null(mme.InnerException);

mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(typeof(TypeWithoutDefaultCtor)));
Assert.Contains("System.Tests.ActivatorTests+TypeWithoutDefaultCtor", mme.Message);
Assert.Null(mme.InnerException);

// MissingMethodException caused by a binder must be wrapped.
mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(
typeof(object), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new MissingMethodException("Hello, World!!") },
null, null, null
));
Assert.Contains("System.Object", mme.Message);
Assert.NotNull(mme.InnerException);
Assert.IsType<MissingMethodException>(mme.InnerException);
Assert.Equal("Hello, World!!", mme.InnerException.Message);

mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(
typeof(Random), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new MissingMethodException("good-bye...") },
null, null, null
));
Assert.Contains("System.Random", mme.Message);
Assert.NotNull(mme.InnerException);
Assert.IsType<MissingMethodException>(mme.InnerException);
Assert.Equal("good-bye...", mme.InnerException.Message);

// Any other exceptions will not be caught.
Assert.Throws<Exception>(() => Activator.CreateInstance(
typeof(object), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new Exception() },
null, null, null
));
Assert.Throws<ArgumentNullException>(() => Activator.CreateInstance(
typeof(object), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new ArgumentNullException() },
null, null, null
));
Assert.Throws<FileNotFoundException>(() => Activator.CreateInstance(
typeof(Random), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new FileNotFoundException() },
null, null, null
));
Assert.Throws<InvalidOperationException>(() => Activator.CreateInstance(
typeof(Random), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => throw new InvalidOperationException() },
null, null, null
));

// MissingMethodException must not contain an inner exception when BindToMethod returns null.
mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(
typeof(object), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => null },
null, null, null
));
Assert.Contains("System.Object", mme.Message);
Assert.Null(mme.InnerException);

mme = Assert.Throws<MissingMethodException>(() => Activator.CreateInstance(
typeof(Random), BindingFlags.CreateInstance,
new CustomBinder() { BindToMethodAction = () => null },
null, null, null
));
Assert.Contains("System.Random", mme.Message);
Assert.Null(mme.InnerException);
}

class CustomBinder : Binder
{
public required Func<MethodBase?> BindToMethodAction { get; init; }

public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object?[] args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? names, out object? state)
Takym marked this conversation as resolved.
Show resolved Hide resolved
{
state = null;
return this.BindToMethodAction()!;
}

public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo? culture)
=> throw new NotImplementedException();

public override object ChangeType(object value, Type type, CultureInfo? culture)
=> throw new NotImplementedException();

public override void ReorderArgumentArray(ref object?[] args, object state)
=> throw new NotImplementedException();

public override MethodBase? SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[]? modifiers)
=> throw new NotImplementedException();

public override PropertyInfo? SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type? returnType, Type[]? indexes, ParameterModifier[]? modifiers)
=> throw new NotImplementedException();
}

[Fact]
public void CreateInstance_NullableType_ReturnsNull()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1549,13 +1549,18 @@ private void CreateInstanceCheckThis()
}

MethodBase? invokeMethod;
object? state = null;
object? state;

try
{
invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state);
}
catch (MissingMethodException) { invokeMethod = null; }
catch (MissingMethodException innerMME)
{
// Rethrows to rewrite a message to include the class name.
// Make sure the original exception is set as an inner exception.
throw new MissingMethodException(SR.Format(SR.MissingConstructor_Name, FullName), innerMME);
}

if (invokeMethod == null)
{
Expand Down
Loading