about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/internal.rs
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-05-30 01:37:48 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2025-06-03 08:23:21 +1000
commit8747ccbcdf54fe8227e10bc2584f3e9a2fee9103 (patch)
tree3ca55070770fde8d544324c2910d46a441499a81 /compiler/rustc_lint/src/internal.rs
parent176c34a946df6b096cc2bce19c477fd49c0c9a09 (diff)
downloadrust-8747ccbcdf54fe8227e10bc2584f3e9a2fee9103.tar.gz
rust-8747ccbcdf54fe8227e10bc2584f3e9a2fee9103.zip
Overhaul `UsePath`.
`UsePath` contains a `SmallVec<[Res; 3]>`. This holds up to three `Res`
results, one per namespace (type, value, or macro). `lower_import_res`
takes a `PerNS<Option<Res<NodeId>>>` result and lowers it into the
`SmallVec`. This is pretty weird. The input `PerNS` makes it clear which
`Res` belongs to which namespace, but the `SmallVec` throws that
information away.

And code that operates on the `SmallVec` tends to use iteration (or even
just grabbing the first entry!) without knowing which namespace the
`Res` belongs to. Even weirder! Also, `SmallVec` is an overly flexible
type to use here, because it can contain any number of elements (even
though it's optimized for 3 in this case).

This commit changes `UsePath` so it also contains a
`PerNS<Option<Res<HirId>>>`. This type preserves more information and is
more self-documenting. The commit also changes a lot of the use sites to
access the result for a particular namespace. E.g. if you're looking up
a trait, it will be in the `Res` for the type namespace if it's present;
it's silly to look in the `Res` for the value namespace or macro
namespace. Overall I find the new code much easier to understand.

However, some use sites still iterate. These now use `present_items`
because that filters out the `None` results.

Also, `redundant_pub_crate.rs` gets a bigger change. A
`UseKind:ListStem` item gets no `Res` results, which means the old `all`
call in `is_not_macro_export` would succeed (because `all` succeeds on
an empty iterator) and the `ListStem` would be ignored. This is what we
want, but was more by luck than design. The new code detects `ListStem`
explicitly. The commit generalizes the name of that function
accordingly.

Finally, the commit also removes the `use_path` arena, because
`PerNS<Option<Res>>` impls `Copy` (unlike `SmallVec`) and it can be
allocated in the arena shared by all `Copy` types.
Diffstat (limited to 'compiler/rustc_lint/src/internal.rs')
-rw-r--r--compiler/rustc_lint/src/internal.rs7
1 files changed, 5 insertions, 2 deletions
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index e7350a75179..1805a674d68 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -338,7 +338,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
             cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
         }
         // Final path resolutions, like `use rustc_type_ir::inherent`
-        else if path.res.iter().any(|&res| is_mod_inherent(res)) {
+        else if let Some(type_ns) = path.res.type_ns
+            && is_mod_inherent(type_ns)
+        {
             cx.emit_span_lint(
                 USAGE_OF_TYPE_IR_INHERENT,
                 path.segments.last().unwrap().ident.span,
@@ -351,7 +353,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
                 (segment.ident.span, item.kind.ident().unwrap().span, "*")
             }
             [.., segment]
-                if path.res.iter().any(|&res| is_mod_inherent(res))
+                if let Some(type_ns) = path.res.type_ns
+                    && is_mod_inherent(type_ns)
                     && let rustc_hir::UseKind::Single(ident) = kind =>
             {
                 let (lo, snippet) =