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

Under what conditions can TypeBuilder.CreateType() return null #68840

Closed
1 of 3 tasks
lonix1 opened this issue Apr 9, 2022 · 7 comments · Fixed by #72180
Closed
1 of 3 tasks

Under what conditions can TypeBuilder.CreateType() return null #68840

lonix1 opened this issue Apr 9, 2022 · 7 comments · Fixed by #72180
Assignees
Labels
area-System.Reflection.Emit good first issue Issue should be easy to implement, good for first-time contributors help wanted [up-for-grabs] Good issue for external contributors
Milestone

Comments

@lonix1
Copy link

lonix1 commented Apr 9, 2022

Issue description
Under what conditions can TypeBuilder.CreateType() return null?

Target framework

  • .NET Core 5, 6
  • .NET Framework
  • .NET Standard

Details
The TypeBuilder.CreateType() method is defined as nullable:

public Type? CreateType();

Under what conditions can it return null? The docs do not say.

Please document this method signature.

@PRMerger15 PRMerger15 added the Pri3 label Apr 9, 2022
@gewarren gewarren transferred this issue from dotnet/docs Apr 13, 2022
@daiplusplus
Copy link

daiplusplus commented Apr 14, 2022

@lonix1 Under what conditions can TypeBuilder.CreateType() return null?

TL;DR: There is no situation when TypeBuilder.CreateType() will return null when CreateType() is being called by user-code. You can safely add a null-forgiving ! to a CreateType() call-site.


The current source is at

  • A quick browse of the current source shows that TypeBuilder.CreateType() only returns null when the TypeBuilder is the builder for an assembly's hidden <Module> class.
    • The <Module> class is a special type that allows assemblies/modules to have eager-initialized globals.
    • The C# language itself doesn't use <Module>, though other languages do (e.g. C++/CLI).
    • Since C# 9.0, you can now opt-in to adding <Module> members via the [ModuleInitializer] attribute.
    • Of course, if you're using Reflection.Emit then you will have always been able to use ModuleBuilder going back to .NET 1.x in 2001.
  • <Module>-building TypeBuilder instances cannot be directly instantiated by user-code as it requires a specific internal TypeBuilder() constructor invocation - instead this ctor is called only when you use the ModuleBuilder type.
  • The only situation when TypeBuilder.CreateType() method does indeed return null is inside void ModuleBuilder.CreateGlobalFunctions(), which basically ensures that a class <Module> will be defined in the generated dynamic-assembly.

So based on that, I think the design of TypeBuilder's API should be changed in a minimally-breaking way:

  • Change the current public Type? TypeBuilder.CreateType() method into private Type? TypeBuilder.CreateTypeImpl().
  • Add back public Type TypeBuilder.CreateType() (without the nullable return type) which just calls CreateTypeImpl() directly, maybe adding a debug assertion that CreateTypeImpl did not return null?).
  • Add a new method to TypeBuilder: internal void CreateGlobalModuleType() which first checks that this.m_isHiddenGlobalType == true (and if not throws, I suppose) and then calls CreateTypeImpl() with a debug assertion that it did return null.

Alternatively, refactor the CreateType() method more thoroughly?

@lonix1
Copy link
Author

lonix1 commented Apr 14, 2022

Wow @Jehoel that was incredibly in depth - my mind boggles at how you'd know all that, thank you!

EDIT
Oh... I see your profile says you're a "former human", so now it makes sense. You're actually a highly intelligent sentient AI / advanced robot. 😄 👍

@lonix1
Copy link
Author

lonix1 commented Apr 14, 2022

BTW I also have an open issue on SO if you copy-paste that into an answer I'll close that. Thanks once more for your help.

@daiplusplus
Copy link

daiplusplus commented Apr 14, 2022

my mind boggles at how you'd know all that, thank you!

Oh... I see your profile says you're a "former human", so now it makes sense. You're actually a highly intelligent sentient AI / advanced robot. 😄 👍

Nah, I'm just on the spectrum

@jeffhandley jeffhandley added the untriaged New issue has not been triaged by the area owner label Apr 29, 2022
@buyaa-n
Copy link
Contributor

buyaa-n commented May 3, 2022

@Jehoel is right, we should separate the public API from internal nullable API and make public API non nullable, moving to runtime repo for that

@buyaa-n buyaa-n transferred this issue from dotnet/dotnet-api-docs May 3, 2022
@buyaa-n buyaa-n added this to the 7.0.0 milestone May 3, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label May 3, 2022
@buyaa-n buyaa-n added help wanted [up-for-grabs] Good issue for external contributors and removed Pri3 labels May 3, 2022
@buyaa-n buyaa-n added the good first issue Issue should be easy to implement, good for first-time contributors label Jul 6, 2022
@JosieBigler
Copy link
Contributor

I'd be interested in making the above changes @Jehoel outlined. In terms of testing, would that be a new Assertion in the current Theory or a new Theory?

@buyaa-n
Copy link
Contributor

buyaa-n commented Jul 12, 2022

Thanks @JosieBigler, assigning to you. If it is covered well with current tests then no need to add new tests, just need to fix the current test behavior, could not say for sure as I did not check the existing tests. you would see test coverage after fixing the issue and running the tests

@buyaa-n buyaa-n modified the milestones: 7.0.0, 8.0.0 Jul 12, 2022
JosieBigler added a commit to JosieBigler/runtime that referenced this issue Jul 14, 2022
There is no situation when TypeBuilder.CreateType will return null when
being called by user-code.

issue dotnet#68840
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 20, 2022
jkotas pushed a commit that referenced this issue Jul 26, 2022
* Make TypeBuilder.CreateType return non nullable

There is no situation when TypeBuilder.CreateType will return null when
being called by user-code.

issue #68840

* Update tests for null check after module.CreateGlobalFunctions()

* Check not null for additional CreateType Unit Tests

* Remove ! from DispatchProxyGenerator CreateType()

* Update Ref for non-null CreateType

* Change CreateTypeInfo to return non-null.

* Refactored CreateTypeInfo().AsType() to be CreateType()

* Annotate failing Mono Assert.Null
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 26, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Aug 26, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Reflection.Emit good first issue Issue should be easy to implement, good for first-time contributors help wanted [up-for-grabs] Good issue for external contributors
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants