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

Add FieldInfo::field_type_name #2863

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

Conversation

workingjubilee
Copy link
Member

In my case, I want to make a field private and wrap it behind an accessor function that makes the field unsafe to access. I need the field's type in order to make this decision correctly. In some cases a type name is not available and I am fine with that.

@workingjubilee workingjubilee force-pushed the add-field-type-name-to-fieldinfo branch from 197e7ff to 827f57c Compare July 5, 2024 18:56
@pvdrz
Copy link
Contributor

pvdrz commented Jul 5, 2024

Is there any chance you could document this in the changelog? it looks good to me otherwise

@@ -205,4 +205,6 @@ pub struct FieldInfo<'a> {
pub type_name: &'a str,
/// The name of the field.
pub field_name: &'a str,
/// The name of the type of the field.
pub field_type_name: Option<&'a str>,
Copy link
Contributor

Choose a reason for hiding this comment

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

IT seems we should probably include c++ namespaces and so on here? So, use the same name as all the blocklists etc use.

Copy link
Member Author

Choose a reason for hiding this comment

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

uhhh can I be counseled on how that should be done because I am not very familiar with this codebase, much less C++

Copy link
Member Author

Choose a reason for hiding this comment

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

I also should note that I specifically want None instead of the unnamed at file... output that currently is given in certain other cases, because I think that output is pointless, even harmful: it requires me to filter-by-string for anonymous types, which is much more error-prone and dependent on the vagaries of bindgen's output instead of using a type encoding.

Copy link
Contributor

Choose a reason for hiding this comment

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

@emilio do we include c++ namespaces for the type name as well? otherwise it would be a bit inconsistent.

Copy link
Contributor

Choose a reason for hiding this comment

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

@pvdrz type_name currently uses canonical_name, so yes, I think so.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't really need the canonical name, though, because I don't need ExprEvalStep__bindgen_ty_1, because what's important to me is that it is an anonymous structure, and I don't necessarily want to reason about anonymous structures by their name. Maybe their other attributes, but the real answer for their name is the empty string.

Copy link
Contributor

@emilio emilio Jul 7, 2024

Choose a reason for hiding this comment

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

Well, sure, but my point is, if you have:

namespace foo {
  class Bar { ... };
}
namespace baz {
  class Bar { ... };
}

You want to be able to differentiate between one and the other right? btw, it's unclear to me what this does for pointer fields, templates, and so on. I assume the answer is reasonable, but still it'd be worth having some tests.

You might still can make the anonymous / non-anonymous distinction (if thing.name().is_some() { Some(thing.canonical_name()) } else { None } or same using map or what not)

Copy link
Member Author

Choose a reason for hiding this comment

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

My answer is that I don't really care about whatever the answer is to that because I don't use C++, not personally, nor in a work context, and in the one case where I've tried to use bindgen against it in anger, its insistence on qualifying namespaces was actually a disadvantage as the namespaces were effectively meaningless and I would have been better off if the Rust code did not know about them (they were used as a crude implementation of parameterized modules, instead of using something sensible for this facility, like e.g. template parameters).

Copy link
Contributor

Choose a reason for hiding this comment

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

To be honest, I'd rather see this working in C and sort of working in C++ that not seeing it working at all. I think it wouldn't be unreasonable to take this as it is and see if someone else actually ends up using this and requiring the canonical_name as we could either add it as a new field or use it instead of the regular name if a flag is enabled.

@workingjubilee @emilio does that works for both of you?

Copy link
Member Author

@workingjubilee workingjubilee Aug 22, 2024

Choose a reason for hiding this comment

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

Sure.

And I'd be happy to do the .map-based solution, but my main point of confusion at this juncture is in this code:

pub(crate) trait ItemCanonicalName {
/// Get the canonical name for this item.
fn canonical_name(&self, ctx: &BindgenContext) -> String;
}
/// The same, but specifies the path that needs to be followed to reach an item.
///
/// To contrast with canonical_name, here's an example:
///
/// ```c++
/// namespace foo {
/// const BAR = 3;
/// }
/// ```
///
/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical
/// name is just `"BAR"`.
pub(crate) trait ItemCanonicalPath {
/// Get the namespace-aware canonical path for this item. This means that if
/// namespaces are disabled, you'll get a single item, and otherwise you get
/// the whole path.
fn namespace_aware_canonical_path(
&self,
ctx: &BindgenContext,
) -> Vec<String>;
/// Get the canonical path for this item.
fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
}

With "namespace-aware canonical paths" being a thing, this suggests it's more complicated than just calling canonical_name(), so I feel, basically, not qualified to evaluate what "canonical name" means in bindgen because it conflates C++ namespaces with generated symbols.

The relevance of making a ield private may depend on a field's type.
Some fields should be protected against manipulation by Rust code for
the same reason `Vec::set_len` is `unsafe`.
@workingjubilee workingjubilee force-pushed the add-field-type-name-to-fieldinfo branch from 827f57c to e169561 Compare July 5, 2024 22:37
@bors-servo
Copy link

☔ The latest upstream changes (presumably 9a8e5ca) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants