Skip to content

Conversation

@GuillaumeGomez
Copy link
Member

Fixes #9278.

This is something that we need for cg_gcc (cc @antoyo). It's almost the same as #6674 (which I used as base).

changelog: Add new disallowed_fields lint

r? @samueltardieu

@rustbot rustbot added needs-fcp S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Dec 11, 2025
// Very round-about way to get the field `DefId` from the expr: first we get its
// parent `Ty`. Then we go through all its fields to find the one with the expected
// name and get the `DefId` from it.
if let Some(parent_ty) = cx.typeck_results().expr_ty_opt(e)
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'm really not sure this is the best way to get the DefId from Expr::Field but couldn't find another way. I'd love to know if there is one!

Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to use the adjusted type.

.filter_by_name_unhygienic(name)
.find(|assoc_item| ns.matches(Some(assoc_item.namespace())))
.map(|assoc_item| assoc_item.def_id),
ItemKind::Struct(_, _, rustc_hir::VariantData::Struct { fields, .. }) => fields.iter().find_map(|field| {
Copy link
Member Author

Choose a reason for hiding this comment

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

Basically added support to look for fields in lookup_path (above in this file). it's used to check if the paths are valid in the config file.

So to link to a field (for example with struct X { y: u8 }: X::y.

Copy link
Contributor

@Jarcho Jarcho Dec 15, 2025

Choose a reason for hiding this comment

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

This is going to cause a problem. Fields and associated items can have the same name. You can add a Field variant to PathNS and constrain matches to that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair enough, added it as well.

@GuillaumeGomez GuillaumeGomez force-pushed the disallowed_fields branch 2 times, most recently from eacd758 to d017b2c Compare December 11, 2025 20:22
@GuillaumeGomez
Copy link
Member Author

Finally updated all things that needed to be updated. :')

@Jarcho
Copy link
Contributor

Jarcho commented Dec 11, 2025

This doesn't prevent reading via destructuring. e.g. let Foo { x } = y

@samueltardieu
Copy link
Member

r? @Jarcho

@rustbot rustbot assigned Jarcho and unassigned samueltardieu Dec 11, 2025
@GuillaumeGomez
Copy link
Member Author

Thanks for the review @Jarcho! Just a heads-up: gonna try to come back to this PR in the next days.

use rustc_hir::def_id::DefIdMap;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{Adt, TyCtxt};
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: We don't normally import TyKind variants and use ty::Adt instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Noted, removed the Adt import.

Comment on lines 83 to 94
// Very round-about way to get the field `DefId` from the expr: first we get its
// parent `Ty`. Then we go through all its fields to find the one with the expected
// name and get the `DefId` from it.
if let Some(parent_ty) = cx.typeck_results().expr_ty_opt(e)
&& let Adt(adt_def, ..) = parent_ty.kind()
&& let Some(field_def_id) = adt_def.all_fields().find_map(|field| {
if field.name == ident.name {
Some(field.did)
} else {
None
}
})
Copy link
Contributor

Choose a reason for hiding this comment

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

There's get_field_by_name in clippy_utils for this.

Copy link
Member Author

Choose a reason for hiding this comment

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

It returns a Ty and I need a DefId so sadly it doesn't work in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you extract this into it's own util function then. Something like get_field_def_by_name. It can join the other field resolving functions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, done!

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Dec 15, 2025
@rustbot
Copy link
Collaborator

rustbot commented Dec 30, 2025

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@GuillaumeGomez
Copy link
Member Author

It now checks patterns as well. I added UI tests to ensure it. Ready for a new review round. :)

@GuillaumeGomez
Copy link
Member Author

Forgot to check it was Adt(Struct), fixed that.

@GuillaumeGomez
Copy link
Member Author

CI passed! \o/

Copy link
Member

@samueltardieu samueltardieu left a comment

Choose a reason for hiding this comment

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

How are fields in a variant handled, especially homonyms?

View changes since this review

Comment on lines +1252 to +1254
adt_def
.all_fields()
.find_map(|field| if field.name == name { Some(field.did) } else { None })
Copy link
Member

Choose a reason for hiding this comment

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

  • This shares some code with the code in check_pat(), maybe this could be factored further.

Copy link
Member Author

Choose a reason for hiding this comment

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

Function is 4 lines so not sure if it's really worth it. I can add a fixme comment if someone wants to make this improvement later on though if you want?

@GuillaumeGomez
Copy link
Member Author

How are fields in a variant handled, especially homonyms?

Easy: they're not. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-fcp S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add disallowed_fields lint

5 participants