rustc_hir: Change representation of import paths to support multiple resolutions
This commit is contained in:
parent
6cd4dd3091
commit
1f259ae679
19 changed files with 136 additions and 114 deletions
|
@ -508,7 +508,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let mut resolutions = self.expect_full_res_from_use(id).fuse();
|
let mut resolutions = self.expect_full_res_from_use(id).fuse();
|
||||||
// We want to return *something* from this function, so hold onto the first item
|
// We want to return *something* from this function, so hold onto the first item
|
||||||
// for later.
|
// for later.
|
||||||
let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
|
let ret_res = smallvec![self.lower_res(resolutions.next().unwrap_or(Res::Err))];
|
||||||
|
|
||||||
// Here, we are looping over namespaces, if they exist for the definition
|
// Here, we are looping over namespaces, if they exist for the definition
|
||||||
// being imported. We only handle type and value namespaces because we
|
// being imported. We only handle type and value namespaces because we
|
||||||
|
@ -538,8 +538,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let span = path.span;
|
let span = path.span;
|
||||||
|
|
||||||
self.with_hir_id_owner(new_node_id, |this| {
|
self.with_hir_id_owner(new_node_id, |this| {
|
||||||
let res = this.lower_res(res);
|
let res = smallvec![this.lower_res(res)];
|
||||||
let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
|
let path = this.lower_use_path(res, &path, ParamMode::Explicit);
|
||||||
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
|
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
|
||||||
if let Some(attrs) = attrs {
|
if let Some(attrs) = attrs {
|
||||||
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
|
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
|
||||||
|
@ -556,15 +556,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
|
let path = self.lower_use_path(ret_res, &path, ParamMode::Explicit);
|
||||||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||||
}
|
}
|
||||||
UseTreeKind::Glob => {
|
UseTreeKind::Glob => {
|
||||||
let path = self.lower_path(
|
let res = self.expect_full_res(id);
|
||||||
id,
|
let res = smallvec![self.lower_res(res)];
|
||||||
&Path { segments, span: path.span, tokens: None },
|
let path = Path { segments, span: path.span, tokens: None };
|
||||||
ParamMode::Explicit,
|
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
|
||||||
);
|
|
||||||
hir::ItemKind::Use(path, hir::UseKind::Glob)
|
hir::ItemKind::Use(path, hir::UseKind::Glob)
|
||||||
}
|
}
|
||||||
UseTreeKind::Nested(ref trees) => {
|
UseTreeKind::Nested(ref trees) => {
|
||||||
|
@ -635,8 +634,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
|
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
|
||||||
let res = self.lower_res(res);
|
let res = smallvec![self.lower_res(res)];
|
||||||
let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
|
let path = self.lower_use_path(res, &prefix, ParamMode::Explicit);
|
||||||
hir::ItemKind::Use(path, hir::UseKind::ListStem)
|
hir::ItemKind::Use(path, hir::UseKind::ListStem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_hir::GenericArg;
|
||||||
use rustc_span::symbol::{kw, Ident};
|
use rustc_span::symbol::{kw, Ident};
|
||||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||||
|
|
||||||
use smallvec::smallvec;
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
|
@ -144,13 +144,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_path_extra(
|
pub(crate) fn lower_use_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
res: Res,
|
res: SmallVec<[Res; 3]>,
|
||||||
p: &Path,
|
p: &Path,
|
||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
) -> &'hir hir::Path<'hir> {
|
) -> &'hir hir::UsePath<'hir> {
|
||||||
self.arena.alloc(hir::Path {
|
self.arena.alloc(hir::UsePath {
|
||||||
res,
|
res,
|
||||||
segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
|
segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
|
||||||
self.lower_path_segment(
|
self.lower_path_segment(
|
||||||
|
@ -165,17 +165,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_path(
|
|
||||||
&mut self,
|
|
||||||
id: NodeId,
|
|
||||||
p: &Path,
|
|
||||||
param_mode: ParamMode,
|
|
||||||
) -> &'hir hir::Path<'hir> {
|
|
||||||
let res = self.expect_full_res(id);
|
|
||||||
let res = self.lower_res(res);
|
|
||||||
self.lower_path_extra(res, p, param_mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn lower_path_segment(
|
pub(crate) fn lower_path_segment(
|
||||||
&mut self,
|
&mut self,
|
||||||
path_span: Span,
|
path_span: Span,
|
||||||
|
|
|
@ -399,7 +399,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, CTX> HashStable<CTX> for SmallVec<[A; 1]>
|
impl<A, const N: usize, CTX> HashStable<CTX> for SmallVec<[A; N]>
|
||||||
where
|
where
|
||||||
A: HashStable<CTX>,
|
A: HashStable<CTX>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,7 @@ macro_rules! arena_types {
|
||||||
[] param: rustc_hir::Param<'tcx>,
|
[] param: rustc_hir::Param<'tcx>,
|
||||||
[] pat: rustc_hir::Pat<'tcx>,
|
[] pat: rustc_hir::Pat<'tcx>,
|
||||||
[] path: rustc_hir::Path<'tcx>,
|
[] path: rustc_hir::Path<'tcx>,
|
||||||
|
[] use_path: rustc_hir::UsePath<'tcx>,
|
||||||
[] path_segment: rustc_hir::PathSegment<'tcx>,
|
[] path_segment: rustc_hir::PathSegment<'tcx>,
|
||||||
[] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>,
|
[] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>,
|
||||||
[] qpath: rustc_hir::QPath<'tcx>,
|
[] qpath: rustc_hir::QPath<'tcx>,
|
||||||
|
|
|
@ -183,14 +183,17 @@ impl Lifetime {
|
||||||
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
|
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
|
||||||
/// along with a bunch of supporting information.
|
/// along with a bunch of supporting information.
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
pub struct Path<'hir> {
|
pub struct Path<'hir, R = Res> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The resolution for the path.
|
/// The resolution for the path.
|
||||||
pub res: Res,
|
pub res: R,
|
||||||
/// The segments in the path: the things separated by `::`.
|
/// The segments in the path: the things separated by `::`.
|
||||||
pub segments: &'hir [PathSegment<'hir>],
|
pub segments: &'hir [PathSegment<'hir>],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Up to three resolutions for type, value and macro namespaces.
|
||||||
|
pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
|
||||||
|
|
||||||
impl Path<'_> {
|
impl Path<'_> {
|
||||||
pub fn is_global(&self) -> bool {
|
pub fn is_global(&self) -> bool {
|
||||||
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
|
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
|
||||||
|
@ -3068,7 +3071,7 @@ pub enum ItemKind<'hir> {
|
||||||
/// or just
|
/// or just
|
||||||
///
|
///
|
||||||
/// `use foo::bar::baz;` (with `as baz` implicitly on the right).
|
/// `use foo::bar::baz;` (with `as baz` implicitly on the right).
|
||||||
Use(&'hir Path<'hir>, UseKind),
|
Use(&'hir UsePath<'hir>, UseKind),
|
||||||
|
|
||||||
/// A `static` item.
|
/// A `static` item.
|
||||||
Static(&'hir Ty<'hir>, Mutability, BodyId),
|
Static(&'hir Ty<'hir>, Mutability, BodyId),
|
||||||
|
|
|
@ -367,7 +367,7 @@ pub trait Visitor<'v>: Sized {
|
||||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
|
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
|
||||||
walk_fn(self, fk, fd, b, id)
|
walk_fn(self, fk, fd, b, id)
|
||||||
}
|
}
|
||||||
fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) {
|
fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
|
||||||
walk_use(self, path, hir_id)
|
walk_use(self, path, hir_id)
|
||||||
}
|
}
|
||||||
fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
|
fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
|
||||||
|
@ -938,9 +938,12 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) {
|
pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) {
|
||||||
visitor.visit_id(hir_id);
|
visitor.visit_id(hir_id);
|
||||||
visitor.visit_path(path, hir_id);
|
let UsePath { segments, ref res, span } = *path;
|
||||||
|
for &res in res {
|
||||||
|
visitor.visit_path(&Path { segments, res, span }, hir_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
|
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
|
||||||
|
|
|
@ -1591,7 +1591,7 @@ impl<'a> State<'a> {
|
||||||
self.print_ident(Ident::with_dummy_span(name))
|
self.print_ident(Ident::with_dummy_span(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) {
|
pub fn print_path<R>(&mut self, path: &hir::Path<'_, R>, colons_before_params: bool) {
|
||||||
self.maybe_print_comment(path.span.lo());
|
self.maybe_print_comment(path.span.lo());
|
||||||
|
|
||||||
for (i, segment) in path.segments.iter().enumerate() {
|
for (i, segment) in path.segments.iter().enumerate() {
|
||||||
|
|
|
@ -369,7 +369,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||||
hir_visit::walk_fn(self, fk, fd, b, id)
|
hir_visit::walk_fn(self, fk, fd, b, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_use(&mut self, p: &'v hir::Path<'v>, hir_id: hir::HirId) {
|
fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: hir::HirId) {
|
||||||
// This is `visit_use`, but the type is `Path` so record it that way.
|
// This is `visit_use`, but the type is `Path` so record it that way.
|
||||||
self.record("Path", Id::None, p);
|
self.record("Path", Id::None, p);
|
||||||
hir_visit::walk_use(self, p, hir_id)
|
hir_visit::walk_use(self, p, hir_id)
|
||||||
|
|
|
@ -185,13 +185,13 @@ impl<'tcx> DumpVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
|
fn write_sub_paths<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
|
||||||
self.write_segments(path.segments)
|
self.write_segments(path.segments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// As write_sub_paths, but does not process the last ident in the path (assuming it
|
// As write_sub_paths, but does not process the last ident in the path (assuming it
|
||||||
// will be processed elsewhere). See note on write_sub_paths about global.
|
// will be processed elsewhere). See note on write_sub_paths about global.
|
||||||
fn write_sub_paths_truncated(&mut self, path: &'tcx hir::Path<'tcx>) {
|
fn write_sub_paths_truncated<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
|
||||||
if let [segments @ .., _] = path.segments {
|
if let [segments @ .., _] = path.segments {
|
||||||
self.write_segments(segments)
|
self.write_segments(segments)
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,7 +594,9 @@ impl<'tcx> SaveContext<'tcx> {
|
||||||
match self.tcx.hir().get(hir_id) {
|
match self.tcx.hir().get(hir_id) {
|
||||||
Node::TraitRef(tr) => tr.path.res,
|
Node::TraitRef(tr) => tr.path.res,
|
||||||
|
|
||||||
Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res,
|
Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => {
|
||||||
|
path.res.get(0).copied().unwrap_or(Res::Err)
|
||||||
|
}
|
||||||
Node::PathSegment(seg) => {
|
Node::PathSegment(seg) => {
|
||||||
if seg.res != Res::Err {
|
if seg.res != Res::Err {
|
||||||
seg.res
|
seg.res
|
||||||
|
|
|
@ -2231,6 +2231,26 @@ fn clean_extern_crate<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_use_statement<'tcx>(
|
fn clean_use_statement<'tcx>(
|
||||||
|
import: &hir::Item<'tcx>,
|
||||||
|
name: Symbol,
|
||||||
|
path: &hir::UsePath<'tcx>,
|
||||||
|
kind: hir::UseKind,
|
||||||
|
cx: &mut DocContext<'tcx>,
|
||||||
|
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
|
||||||
|
) -> Vec<Item> {
|
||||||
|
let mut items = Vec::new();
|
||||||
|
let hir::UsePath { segments, ref res, span } = *path;
|
||||||
|
for &res in res {
|
||||||
|
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let path = hir::Path { segments, res, span };
|
||||||
|
items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
|
||||||
|
}
|
||||||
|
items
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clean_use_statement_inner<'tcx>(
|
||||||
import: &hir::Item<'tcx>,
|
import: &hir::Item<'tcx>,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
path: &hir::Path<'tcx>,
|
path: &hir::Path<'tcx>,
|
||||||
|
|
|
@ -242,7 +242,9 @@ impl ExternalCrate {
|
||||||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||||
if tcx.visibility(id.owner_id).is_public() =>
|
if tcx.visibility(id.owner_id).is_public() =>
|
||||||
{
|
{
|
||||||
as_keyword(path.res.expect_non_local())
|
path.res
|
||||||
|
.iter()
|
||||||
|
.find_map(|res| as_keyword(res.expect_non_local()))
|
||||||
.map(|(_, prim)| (id.owner_id.to_def_id(), prim))
|
.map(|(_, prim)| (id.owner_id.to_def_id(), prim))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -310,10 +312,11 @@ impl ExternalCrate {
|
||||||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||||
if tcx.visibility(id.owner_id).is_public() =>
|
if tcx.visibility(id.owner_id).is_public() =>
|
||||||
{
|
{
|
||||||
as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
|
path.res
|
||||||
|
.iter()
|
||||||
|
.find_map(|res| as_primitive(res.expect_non_local()))
|
||||||
// Pretend the primitive is local.
|
// Pretend the primitive is local.
|
||||||
(id.owner_id.to_def_id(), prim)
|
.map(|(_, prim)| (id.owner_id.to_def_id(), prim))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,12 +190,4 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
intravisit::walk_expr(self, expr);
|
intravisit::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_use(&mut self, path: &'tcx rustc_hir::Path<'tcx>, id: HirId) {
|
|
||||||
if self.handle_macro(path.span) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.handle_path(path);
|
|
||||||
intravisit::walk_use(self, path, id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,39 +301,40 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
hir::ItemKind::GlobalAsm(..) => {}
|
hir::ItemKind::GlobalAsm(..) => {}
|
||||||
hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
|
hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
|
||||||
hir::ItemKind::Use(path, kind) => {
|
hir::ItemKind::Use(path, kind) => {
|
||||||
let is_glob = kind == hir::UseKind::Glob;
|
for &res in &path.res {
|
||||||
|
// Struct and variant constructors and proc macro stubs always show up alongside
|
||||||
// Struct and variant constructors and proc macro stubs always show up alongside
|
// their definitions, we've already processed them so just discard these.
|
||||||
// their definitions, we've already processed them so just discard these.
|
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
|
||||||
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
|
continue;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let attrs = self.cx.tcx.hir().attrs(item.hir_id());
|
|
||||||
|
|
||||||
// If there was a private module in the current path then don't bother inlining
|
|
||||||
// anything as it will probably be stripped anyway.
|
|
||||||
if is_pub && self.inside_public_path {
|
|
||||||
let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
|
|
||||||
Some(ref list) if item.has_name(sym::doc) => {
|
|
||||||
list.iter().any(|i| i.has_name(sym::inline))
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
});
|
|
||||||
let ident = if is_glob { None } else { Some(name) };
|
|
||||||
if self.maybe_inline_local(
|
|
||||||
item.hir_id(),
|
|
||||||
path.res,
|
|
||||||
ident,
|
|
||||||
is_glob,
|
|
||||||
om,
|
|
||||||
please_inline,
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
om.items.push((item, renamed, parent_id))
|
let attrs = self.cx.tcx.hir().attrs(item.hir_id());
|
||||||
|
|
||||||
|
// If there was a private module in the current path then don't bother inlining
|
||||||
|
// anything as it will probably be stripped anyway.
|
||||||
|
if is_pub && self.inside_public_path {
|
||||||
|
let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
|
||||||
|
Some(ref list) if item.has_name(sym::doc) => {
|
||||||
|
list.iter().any(|i| i.has_name(sym::inline))
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
let is_glob = kind == hir::UseKind::Glob;
|
||||||
|
let ident = if is_glob { None } else { Some(name) };
|
||||||
|
if self.maybe_inline_local(
|
||||||
|
item.hir_id(),
|
||||||
|
res,
|
||||||
|
ident,
|
||||||
|
is_glob,
|
||||||
|
om,
|
||||||
|
please_inline,
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
om.items.push((item, renamed, parent_id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Macro(ref macro_def, _) => {
|
hir::ItemKind::Macro(ref macro_def, _) => {
|
||||||
// `#[macro_export] macro_rules!` items are handled separately in `visit()`,
|
// `#[macro_export] macro_rules!` items are handled separately in `visit()`,
|
||||||
|
|
|
@ -106,7 +106,9 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
|
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
|
||||||
self.check_res_emit(cx, &path.res, item.span);
|
for res in &path.res {
|
||||||
|
self.check_res_emit(cx, res, item.span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,10 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
|
||||||
let hir_id = item.hir_id();
|
let hir_id = item.hir_id();
|
||||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||||
if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
|
if let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use));
|
||||||
if let Res::Def(DefKind::Mod, id) = path.res;
|
if let Some(id) = path.res.iter().find_map(|res| match res {
|
||||||
|
Res::Def(DefKind::Mod, id) => Some(id),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
if !id.is_local();
|
if !id.is_local();
|
||||||
then {
|
then {
|
||||||
for kid in cx.tcx.module_children(id).iter() {
|
for kid in cx.tcx.module_children(id).iter() {
|
||||||
|
|
|
@ -66,35 +66,38 @@ impl LateLintPass<'_> for ImportRename {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||||
if_chain! {
|
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
|
||||||
if let ItemKind::Use(path, UseKind::Single) = &item.kind;
|
for &res in &path.res {
|
||||||
if let Res::Def(_, id) = path.res;
|
if_chain! {
|
||||||
if let Some(name) = self.renames.get(&id);
|
if let Res::Def(_, id) = res;
|
||||||
// Remove semicolon since it is not present for nested imports
|
if let Some(name) = self.renames.get(&id);
|
||||||
let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';');
|
// Remove semicolon since it is not present for nested imports
|
||||||
if let Some(snip) = snippet_opt(cx, span_without_semi);
|
let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';');
|
||||||
if let Some(import) = match snip.split_once(" as ") {
|
if let Some(snip) = snippet_opt(cx, span_without_semi);
|
||||||
None => Some(snip.as_str()),
|
if let Some(import) = match snip.split_once(" as ") {
|
||||||
Some((import, rename)) => {
|
None => Some(snip.as_str()),
|
||||||
if rename.trim() == name.as_str() {
|
Some((import, rename)) => {
|
||||||
None
|
if rename.trim() == name.as_str() {
|
||||||
} else {
|
None
|
||||||
Some(import.trim())
|
} else {
|
||||||
|
Some(import.trim())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
then {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
MISSING_ENFORCED_IMPORT_RENAMES,
|
||||||
|
span_without_semi,
|
||||||
|
"this import should be renamed",
|
||||||
|
"try",
|
||||||
|
format!(
|
||||||
|
"{import} as {name}",
|
||||||
|
),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
then {
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
MISSING_ENFORCED_IMPORT_RENAMES,
|
|
||||||
span_without_semi,
|
|
||||||
"this import should be renamed",
|
|
||||||
"try",
|
|
||||||
format!(
|
|
||||||
"{import} as {name}",
|
|
||||||
),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
||||||
|
|
||||||
fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
|
fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
|
||||||
if let ItemKind::Use(path, _) = item.kind {
|
if let ItemKind::Use(path, _) = item.kind {
|
||||||
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = path.res {
|
if path.res.iter().all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if let ItemKind::Macro(..) = item.kind {
|
} else if let ItemKind::Macro(..) = item.kind {
|
||||||
|
|
|
@ -176,7 +176,8 @@ impl LateLintPass<'_> for WildcardImports {
|
||||||
format!("{import_source_snippet}::{imports_string}")
|
format!("{import_source_snippet}::{imports_string}")
|
||||||
};
|
};
|
||||||
|
|
||||||
let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
|
// Glob imports always have a single resolution.
|
||||||
|
let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res[0] {
|
||||||
(ENUM_GLOB_USE, "usage of wildcard import for enum variants")
|
(ENUM_GLOB_USE, "usage of wildcard import for enum variants")
|
||||||
} else {
|
} else {
|
||||||
(WILDCARD_IMPORTS, "usage of wildcard import")
|
(WILDCARD_IMPORTS, "usage of wildcard import")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue