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

Fix covariant returns with generic return types #45275

Merged

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Nov 27, 2020

When a covariant return type was an uninstantiated generic type, the
ClassLoader::IsCompatibleWith was not working properly. In debug builds,
it was asserting because there was no MethodTable for that type and in
release builds, it resulted in ExecutionEngineException or an internal
CLR error.

This change fixes it by using TypeHandle::CanCastTo instead of
MethodTable::CanCastTo and adds a regression test for two cases where
the problem was observed (Assembly.GetTypes() and creating an instance
of a type with a covariant return with a problematic kind of type).

Close #45037
Close #45082

When a covariant return type was an uninstantiated generic type, the
ClassLoader::IsCompatibleWith was not working properly. In debug builds,
it was asserting because there was no MethodTable for that type and in
release builds, it resulted in ExecutionEngineException or an internal
CLR error.

This change fixes it by using TypeHandle::CanCastTo instead of
MethodTable::CanCastTo and adds a regression test for two cases where
the problem was observed (Assembly.GetTypes() and creating an instance
of a type with a covariant return with a problematic kind of type).
@benaadams
Copy link
Member

Also fixes #45082 ?

@janvorli
Copy link
Member Author

@benaadams I've just tried and it doesn't fix it. There is yet another issue hidden behind my fix (with my fix, it fails at a different place than before).

@benaadams
Copy link
Member

benaadams commented Nov 30, 2020

I did try changing the runtime to use covariant returns for RuntimeType; but it then crashes with both types of crossgen and jitdiff benaadams@e19bcfd so doesn't complete the build (does do the IL though)

@janvorli
Copy link
Member Author

@benaadams can you please create an issue for that? I'll look into it after fixing the #45082.

@benaadams
Copy link
Member

Raised #45356

@janvorli
Copy link
Member Author

janvorli commented Dec 1, 2020

I've updated the PR so that it fixes the #45082 too and added a regression test for that one.

There were two issues. First, the
ClassLoader::ValidateMethodsWithCovariantReturnTypes was called before
typeHnd.DoFullyLoad and that resulted in an assert down the call chain
of TypeDesc::CanCastTo due to a wrong load level.
Second, the SigTypeContext generation for the current MD in the
ClassLoader::ValidateMethodsWithCovariantReturnTypes requires the same
change for class instantiation as the one that we had for the parent MD.
@janvorli janvorli force-pushed the fix-covariant-returns-generic-definition branch from 5fdaacf to 1ad1828 Compare December 1, 2020 16:44
DFLPendingList pendingList;
BOOL fBailed = FALSE;

typeHnd.DoFullyLoad(NULL, CLASS_LOADED, &pendingList, &fBailed, pInstContext);

if (!typeHnd.IsTypeDesc())
{
ClassLoader::ValidateMethodsWithCovariantReturnTypes(typeHnd.AsMethodTable());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DoFullyLoad marks the type as fully loaded. Another thread that tries to load the same type may see it as fully loaded and won't perform this validation.

I think this needs to be done before the type is marked as fully loaded.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so I'll need to figure out how to fix the issue that was fixed by this change. The problem was that down the call chain of the ValidateMethodsWithCovariantReturnTypes, a load level assert fired.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only concern I have with this change.

Copy link
Member

@davidwrighton davidwrighton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the issue around DoFullyLoad

DFLPendingList pendingList;
BOOL fBailed = FALSE;

typeHnd.DoFullyLoad(NULL, CLASS_LOADED, &pendingList, &fBailed, pInstContext);

if (!typeHnd.IsTypeDesc())
{
ClassLoader::ValidateMethodsWithCovariantReturnTypes(typeHnd.AsMethodTable());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only concern I have with this change.

The call to ClassLoader::ValidateMethodsWithCovariantReturnTypes is now
in MethodTable::DoFullyLoad.
I have also added a test case that verifies a case that David Wrighton
has suggested offline, where there are 3 types... A, B and C.
C derives from B which derives from A. B has a bad override which
should produce an error.  Then, cause C to be fully loaded without
otherwise triggering a load of B.
@janvorli
Copy link
Member Author

janvorli commented Dec 3, 2020

The Libraries Test Run release mono windows x64 Debug leg keeps failing consistently in many libraries tests (even after closing / reopening the issue) and I cannot find previous failures of this leg. Moreover, this change doesn't touch anything from Mono stuff, so I am baffled what's going on. @jkotas or @marek-safar do you have any idea what can be going on?

@jkotas
Copy link
Member

jkotas commented Dec 3, 2020

@akoeplinger @safern Could you please disable the failing Mono legs or move them to the staging pipeline so that they do not cause all jobs to be red?

@akoeplinger
Copy link
Member

The leg was already disabled with #45529 but you'd need to rebase/merge master to get this change in the PR. I'd just merge.

@janvorli
Copy link
Member Author

janvorli commented Dec 3, 2020

Thanks @akoeplinger!

@janvorli janvorli merged commit 7520ca3 into dotnet:master Dec 3, 2020
@janvorli
Copy link
Member Author

janvorli commented Dec 9, 2020

/backport to release/5.0

@github-actions
Copy link
Contributor

github-actions bot commented Dec 9, 2020

Started backporting to release/5.0: https://github.com/dotnet/runtime/actions/runs/411777053

@ghost ghost locked as resolved and limited conversation to collaborators Jan 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
5 participants