rustc_marker_type built in attribute created to have certain marker types not trigger dead code warnings from clippy#154978
Conversation
|
Some changes occurred in compiler/rustc_hir/src/attrs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
|
r? @davidtwco rustbot has assigned @davidtwco. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
218306c to
2206c25
Compare
260b712 to
55627ab
Compare
This comment has been minimized.
This comment has been minimized.
55627ab to
7b574a6
Compare
This comment has been minimized.
This comment has been minimized.
7b574a6 to
60f81d1
Compare
This comment has been minimized.
This comment has been minimized.
60f81d1 to
c29ad8c
Compare
| use std::marker::PhantomData; | ||
|
|
||
| pub mod inner { | ||
| use std::marker; |
There was a problem hiding this comment.
For some reason, it kept telling me that it couldn't find std::marker crate, so I couldn't shortcut the field types to marker::PhantomPinned/marker::PhantomData<T>.
I'm not sure how this test operated prior to this, or if I screwed up something to cause this issue.
| } | ||
|
|
||
| /// Checks whether a given result of a name resolution are marked as `#[rustc_marker_type]` | ||
| pub fn has_rustc_marker_type_attr(tcx: TyCtxt<'_>, res: &Res) -> bool { |
There was a problem hiding this comment.
After hours of exploring how attributes works in the compiler, I figured out that the DefId that I could get from a field type's basic result (if it doesn't Err) could inform me about whether that field type has a specific attribute associated with it. If there's a better way to do this than the way I'm doing it, I'm all ears; I'm not even sure if this is the idiomatic way of getting an attribute from a specific type.
There was a problem hiding this comment.
I expect that rustc also has lints that check for phantom_pinned, so you might want to make sure to check for this there too and replace all uses of phantom_pinned that are for this purpose with the more generic mechanism you're introducing.
In that case, you might want to move this helper to somewhere in rustc. I'd expect it to take a Ty or DefId and do something along the lines of ty.ty_adt_def().map(|adt| /* find_attr */).unwrap_or(false).
There was a problem hiding this comment.
I expect that rustc also has lints that check for
phantom_pinned, so you might want to make sure to check for this there too and replace all uses ofphantom_pinnedthat are for this purpose with the more generic mechanism you're introducing.
I don't see anything from the rustc side that lints for PhantomPinned (though there are ui tests that checks for certain behavior with PhantomPinned). Also, to note, PhantomPinned doesn't have a lang item associated with it, so there's no LangItem::PhantomPinned in language item table. The comment above the library/core/src/marker.rs file suggest that this will be deprecated, so I'm not too sure if this should be added into the table (though that seems like a separate PR to work if necessary):
/// A marker type which does not implement `Unpin`.
///
/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default.
//
// FIXME(unsafe_pinned): This is *not* a stable guarantee we want to make, at least not yet.
// Note that for backwards compatibility with the new [`UnsafePinned`] wrapper type, placing this
// marker in your struct acts as if you wrapped the entire struct in an `UnsafePinned`. This type
// will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead.
#[stable(feature = "pin", since = "1.33.0")]
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[rustc_no_dead_code_warning]
pub struct PhantomPinned;In that case, you might want to move this helper to somewhere in rustc. I'd expect it to take a
TyorDefIdand do something along the lines ofty.ty_adt_def().map(|adt| /* find_attr */).unwrap_or(false).
I'm fine with moving the helper to rustc considering that this attribute is built from the compiler end than clippy. Currently, what I'm thinking about doing is adding a method to the AttributeExt trait in rustc_ast/src/attr/mod.rs, something like is_rustc_no_dead_code_warning(&self, tcx: TyCtxt<'_>, def_id: DefId) -> bool.
I'm not sure if we could use ty.ty_adt_def().map(|adt| /* find_attr */).unwrap_or(false) because field.ty from clippy is a &'hir Ty<'hir, ()> and I believe the ty_adt_def() method is exposed to the Ty<'tcx> impl in rustc_middle.
Are there any other approaches I could take?
There was a problem hiding this comment.
I couldn't find a way to have TyCtxt inside rustc_ast/src/attr/mod.rs since rustc_middle couldn't be imported.
I haven't changed much here except using unwrap_or to write it a bit more ergonomically. Let me know if there's a better way for me to create a helper method on the rustc side and be able to call it here (in a similar fashion to function like is_doc_hidden as seen earlier in this file.
| RustcMain, | ||
|
|
||
| /// Represents `#[rustc_marker_type]` | ||
| RustcMarkerType(Symbol, Span), |
There was a problem hiding this comment.
I'm not sure if this is correct. I took inspiration from other enum members written like this (like Lang or RustcAsPtr). I do know that it operates with attribute parsing from lint_helpers.rs and I assume that lets us know what symbol name represents this AttributeKind, whether duplicate of the attribute applied to a certain target produces a compiler error, what target is this attribute limited to. I'm unsure what create does specifically. My hunch tells me that it's related to whether the attribute macro takes an argument or not, but unsure; if that's the case, I might just not need any arguments as part of this enum member.
There was a problem hiding this comment.
Yeah, I don't think this needs any fields - the variant itself indicates that a rustc_marker_type attribute was found, we don't need additional context to tell us any more information. That's different from, say, Lang, as while the presence of the variant tells us we found a #[lang], the Symbol tells us what lang item it was - e.g. #[lang = "phantom_pinned"] has Lang(sym::phantom_pinned). Likewise, you aren't using the Span so we can drop it.
| ), | ||
| rustc_attr!(rustc_force_inline,"`#[rustc_force_inline]` forces a free function to be inlined"), | ||
| rustc_attr!(rustc_scalable_vector,"`#[rustc_scalable_vector]` defines a scalable vector type"), | ||
| rustc_attr!( rustc_marker_type, "the `#[rustc_marker_type]` attribute is used by the standard library to mark certain marker types \ |
There was a problem hiding this comment.
Also, let me know if this is the correct spot to put the rustc_attr! for rustc_marker_type. It's in miscellaneous right now.
This comment has been minimized.
This comment has been minimized.
c29ad8c to
36cbcae
Compare
|
Some changes occurred in compiler/rustc_attr_parsing |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
36cbcae to
9f0d57d
Compare
This comment has been minimized.
This comment has been minimized.
| "enums with `#[rustc_must_match_exhaustively]` must be matched on with a match block that mentions all variants explicitly" | ||
| ), | ||
| rustc_attr!( | ||
| rustc_marker_type, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, |
There was a problem hiding this comment.
Instead of rustc_marker_type, I'd rename this rustc_no_dead_code_warning as there's nothing specific to marker types about the behaviour of this attribute - it could be used on anything that we didn't want dead-code warnings for.
| RustcMain, | ||
|
|
||
| /// Represents `#[rustc_marker_type]` | ||
| RustcMarkerType(Symbol, Span), |
There was a problem hiding this comment.
Yeah, I don't think this needs any fields - the variant itself indicates that a rustc_marker_type attribute was found, we don't need additional context to tell us any more information. That's different from, say, Lang, as while the presence of the variant tells us we found a #[lang], the Symbol tells us what lang item it was - e.g. #[lang = "phantom_pinned"] has Lang(sym::phantom_pinned). Likewise, you aren't using the Span so we can drop it.
| } | ||
|
|
||
| /// Checks whether a given result of a name resolution are marked as `#[rustc_marker_type]` | ||
| pub fn has_rustc_marker_type_attr(tcx: TyCtxt<'_>, res: &Res) -> bool { |
There was a problem hiding this comment.
I expect that rustc also has lints that check for phantom_pinned, so you might want to make sure to check for this there too and replace all uses of phantom_pinned that are for this purpose with the more generic mechanism you're introducing.
In that case, you might want to move this helper to somewhere in rustc. I'd expect it to take a Ty or DefId and do something along the lines of ty.ty_adt_def().map(|adt| /* find_attr */).unwrap_or(false).
|
Reminder, once the PR becomes ready for a review, use |
9f0d57d to
73c1815
Compare
This comment has been minimized.
This comment has been minimized.
73c1815 to
bc8b9a1
Compare
| const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; | ||
| const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | ||
| Allow(Target::Struct), | ||
| Allow(Target::Enum), |
There was a problem hiding this comment.
Added that the attribute can be applied to enums and type aliases. I wasn't sure how to go about testing it in the rustc's tests/ui; it's not giving me warning when I do something similar in clippy_lints like:
struct S {
unused_field: i32,
}
impl fmt::Debug for S5 {
//~ WARN unused field
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("S")
.finish()
}
}
Is this something I would have to test for only on the clippy side of things?
This comment has been minimized.
This comment has been minimized.
…ypes not trigger dead code warnings from clippy
bc8b9a1 to
00ca298
Compare
|
This PR was rebased onto a different main 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. |
View all comments
This PR fixes the issue on
PhantomPinnedtriggering field is never read warning by clippy through a built in attribute calledrustc_marker_type.A few questions I have are:
Phantom*types?Note: This is my first time contributing to the compiler side of Rust repos, so I'm unsure if I'm doing anything wrong with making a built in attribute. I'm just going based off my intuition from go to references in my IDE on what everything is doing.
cc @clarfonthey