Skip to content

C#: Use fully qualified type names #1275

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

just-ero
Copy link

Closes #1265.

@just-ero just-ero force-pushed the cs-fully-qualified-typenames branch from 3c9f118 to 8b7231f Compare April 16, 2025 19:26
@just-ero just-ero changed the title Use fully qualified type names C#: Use fully qualified type names Apr 16, 2025
@just-ero just-ero force-pushed the cs-fully-qualified-typenames branch 2 times, most recently from 87c3fb2 to e8daded Compare April 17, 2025 11:25
@just-ero just-ero force-pushed the cs-fully-qualified-typenames branch from e8daded to d0be31c Compare April 17, 2025 11:48
@@ -948,7 +935,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
uwrite!(
self.src,
"
var {array} = new List<{ty}>({length});
var {array} = new global::System.Collections.Generic.List<{ty}>({length});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does type_name_with_qualifier give ty the global name too ?

Copy link
Author

Choose a reason for hiding this comment

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

I do not believe so. Please lead me in the right direction to make this happen. It should be unnecessary as long as ty is either a primitive or a type already contained within the same namespace as this emitted code.

Copy link
Collaborator

@pavelsavara pavelsavara Apr 22, 2025

Choose a reason for hiding this comment

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

I don't know much about the generator codebase, @jsturtevant please advise.

I just noticed that different flavors ty is sprinkled thru the code.

I'm thinking that we could have built-in hash table (or switch) translating known system types from short name to long name. All of them for consistency sake.

For int -> global::System.Int32

I guess later we will also generate marshaling for global::System.Threading.Tasks.Task which is not in System namespace. Also global::System.Threading.Tasks.Task<global::System.Int32>

And I think WIT can do list of list ?
global::System.Collections.Generic.List<global::System.Collections.Generic.List<global::System.Int32>>

Copy link
Author

Choose a reason for hiding this comment

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

I don't personally believe that primitives (int) should be fully specified, but that's up to you.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not big deal for me, I mentioned it for consistency. This generated code should not be something that people need to read often and compiler sees that as equivalent.

Copy link
Member

Choose a reason for hiding this comment

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

Does type_name_with_qualifier give ty the global name too ?

No type_name_with_qualifier will not add global:: in-front of the type name.

And I think WIT can do list of list ?

Yes it can.

I like that this makes the code generation part a lot easier. On a personal opinion thought I don't particularly like the fact that we will be generating code that you would normally never write yourself (I know this isn't true for everything already, but I would prefer if we can take it in that direction). Would adjusting the current code to address the scenario of usage of types that haven't been imported (by adding the using statement in the generated code, for those missing places) be sufficient or do you think there is a broader problem with that approach @just-ero ?

Copy link
Author

@just-ero just-ero Apr 22, 2025

Choose a reason for hiding this comment

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

Since wit-bindgen is a standalone tool (as in, not directly connected to componentize-dotnet), it seems reasonable to me to generate code that a human might write.

However, a couple things to dissuade;

  • Since the generated header explicitly discourages editing of the generated code, users would interact with it very rarely. The appearance of the generated code would not matter in most cases, as it is rarely even observed.
  • Fully qualified type names are safer, as they leave no ambiguity. Please read string vs. String is not a style debate by Jared Parsons.
    To be clear: in our case, the fully qualified type name would be closer to the string variant, including namespaces and using just the type name is closer to the String variant.

Copy link
Author

Choose a reason for hiding this comment

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

In general, one requirement of generated code (at least for .NET) is to fulfill the lowest common denominator. In C# that might mean not using interpolated strings, file-scoped namespaces, or other more modern features, as the user may target a language version which does not support those features.

componentize-dotnet is basically hard locked to projects which target .NET 10 and up, so this would only be a problem if the user explicitly downgraded using the LangVersion MSBuild property. It's not a scenario I would worry too much about, but I thought I'd mention it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's not worry about below Net10

Copy link
Collaborator

Choose a reason for hiding this comment

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

Fully qualified type names are safer, as they leave no ambiguity.

This is compelling to me for generated code. So I am +1 to this change.

@pavelsavara pavelsavara added the gen-c# Related to the C# code generator label Apr 22, 2025
@just-ero
Copy link
Author

just-ero commented Apr 25, 2025

It may make sense to introduce constants for some namespace or type names; const SPAN: &str = "global::System.Span";. What are your opinions on this? How is this done conventionally in Rust?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gen-c# Related to the C# code generator
Projects
None yet
Development

Successfully merging this pull request may close these issues.

C#: Generated code contains compilation errors (+ lots of other opinionated problems)
4 participants