diff --git a/CHANGELOG.md b/CHANGELOG.md index ab5409aba8ec..b5f001cd688a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6221,6 +6221,7 @@ Released 2018-09-13 [`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default [`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used [`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms +[`use_crate_prefix_for_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_crate_prefix_for_self_imports [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug [`use_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_self [`used_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 5d6e8b875166..3eefa5413b65 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -23,5 +23,5 @@ mod conf; mod metadata; pub mod types; -pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation}; -pub use metadata::ClippyConfiguration; +pub use crate::conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation}; +pub use crate::metadata::ClippyConfiguration; diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 90be1e8876bd..bf947173c507 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -783,6 +783,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::unwrap::UNNECESSARY_UNWRAP_INFO, crate::unwrap_in_result::UNWRAP_IN_RESULT_INFO, crate::upper_case_acronyms::UPPER_CASE_ACRONYMS_INFO, + crate::use_crate_prefix_for_self_imports::USE_CRATE_PREFIX_FOR_SELF_IMPORTS_INFO, crate::use_self::USE_SELF_INFO, crate::useless_conversion::USELESS_CONVERSION_INFO, crate::vec::USELESS_VEC_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6708be5b332c..fcdb7f11e67f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -392,6 +392,7 @@ mod unused_unit; mod unwrap; mod unwrap_in_result; mod upper_case_acronyms; +mod use_crate_prefix_for_self_imports; mod use_self; mod useless_conversion; mod vec; @@ -405,11 +406,11 @@ mod zero_sized_map_values; mod zombie_processes; // end lints modules, do not remove this comment, it’s used in `update_lints` +use crate::utils::attr_collector::{AttrCollector, AttrStorage}; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; -use utils::attr_collector::{AttrCollector, AttrStorage}; /// Register all pre expansion lints /// @@ -476,7 +477,7 @@ pub(crate) enum LintCategory { } #[allow(clippy::enum_glob_use)] -use LintCategory::*; +use crate::LintCategory::*; impl LintCategory { fn is_all(self) -> bool { @@ -980,5 +981,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(non_std_lazy_statics::NonStdLazyStatic::new(conf))); store.register_late_pass(|_| Box::new(manual_option_as_slice::ManualOptionAsSlice::new(conf))); store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap)); + store.register_late_pass(|_| Box::new(use_crate_prefix_for_self_imports::UseCratePrefixForSelfImports::default())); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/use_crate_prefix_for_self_imports.rs b/clippy_lints/src/use_crate_prefix_for_self_imports.rs new file mode 100644 index 000000000000..5b882381027d --- /dev/null +++ b/clippy_lints/src/use_crate_prefix_for_self_imports.rs @@ -0,0 +1,172 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use def_id::LOCAL_CRATE; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::{Attribute, Item, ItemKind, UsePath, def_id}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::impl_lint_pass; +use rustc_span::{BytePos, FileName, RealFileName, Span, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// This lint checks for imports from the current crate that do not use the `crate::` prefix. + /// It suggests using `crate::` to make it clear that the item is from the same crate. + /// + /// ### Why is this bad? + /// When imports from the current crate lack the `crate::` prefix, it can make the code less readable + /// because it’s not immediately clear if the imported item is from the current crate or an external dependency. + /// Using `crate::` for self-imports provides a consistent style, making the origin of each import clear. + /// This helps reduce confusion and maintain a uniform codebase. + /// + /// ### Example + /// ```rust,ignore + /// // lib.rs + /// mod foo; + /// use foo::bar; + /// ``` + /// + /// ```rust,ignore + /// // foo.rs + /// #[path = "./foo.rs"] + /// pub fn bar() {} + /// ``` + /// + /// Use instead: + /// ```rust,ignore + /// // lib.rs + /// mod foo; + /// use crate::foo::bar; + /// ``` + /// + /// ```rust,ignore + /// // foo.rs + /// #[path = "./foo.rs"] + /// pub fn bar() {} + /// ``` + #[clippy::version = "1.84.0"] + pub USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + nursery, + "checks that imports from the current crate use the `crate::` prefix" +} + +#[derive(Clone, Default)] +pub struct UseCratePrefixForSelfImports<'a, 'tcx> { + /// collect `use` in current block + use_block: Vec<&'a UsePath<'tcx>>, + /// collect `mod` in current block + mod_names: FxHashSet, + /// spans of `mod`, `use`, and attributes + spans: Vec, +} + +impl_lint_pass!(UseCratePrefixForSelfImports<'_, '_> => [USE_CRATE_PREFIX_FOR_SELF_IMPORTS]); + +impl<'a, 'tcx> LateLintPass<'tcx> for UseCratePrefixForSelfImports<'a, 'tcx> { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'a Item<'tcx>) { + let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(item.span) else { + self.clear(); + return; + }; + let Some(file_name) = p.file_name() else { + self.clear(); + return; + }; + // only check `main.rs` and `lib.rs` + if !(file_name == "main.rs" || file_name == "lib.rs") { + return; + } + + if self.in_same_block(item.span) { + self.insert_item(item); + } else { + self.deal(cx); + self.clear(); + self.insert_item(item); + } + } + + fn check_attribute(&mut self, cx: &LateContext<'tcx>, attribute: &'a Attribute) { + let FileName::Real(RealFileName::LocalPath(p)) = cx.sess().source_map().span_to_filename(attribute.span) else { + self.clear(); + return; + }; + let Some(file_name) = p.file_name() else { + self.clear(); + return; + }; + // only check `main.rs` and `lib.rs` + if !(file_name == "main.rs" || file_name == "lib.rs") { + return; + } + + if self.in_same_block(attribute.span) { + self.spans.push(attribute.span); + } else { + self.deal(cx); + self.clear(); + self.spans.push(attribute.span); + } + } +} + +impl<'tcx> UseCratePrefixForSelfImports<'_, 'tcx> { + fn in_same_block(&self, span: Span) -> bool { + if self.spans.is_empty() { + return true; + } + if self.spans.iter().any(|x| x.contains(span)) { + return true; + } + if self.spans.iter().any(|x| span.lo() - x.hi() == BytePos(1)) { + return true; + } + false + } + + fn insert_item(&mut self, item: &Item<'tcx>) { + match item.kind { + ItemKind::Mod(_) => { + self.spans.push(item.span); + self.mod_names.insert(item.ident.name); + }, + ItemKind::Use(use_tree, _) => { + self.spans.push(item.span); + self.use_block.push(use_tree); + }, + _ => {}, + } + } + + fn deal(&self, cx: &LateContext<'tcx>) { + for use_path in &self.use_block { + if let Some(segment) = use_path.segments.first() + && let Res::Def(_, def_id) = segment.res + && def_id.krate == LOCAL_CRATE + { + let root = segment.ident.name; + if root != rustc_span::symbol::kw::Crate + && root != rustc_span::symbol::kw::Super + && root != rustc_span::symbol::kw::SelfLower + && !self.mod_names.contains(&root) + { + span_lint_and_sugg( + cx, + USE_CRATE_PREFIX_FOR_SELF_IMPORTS, + segment.ident.span, + "this import is not clear", + "prefix with `crate::`", + format!("crate::{root}"), + Applicability::MachineApplicable, + ); + } + } + } + } + + fn clear(&mut self) { + self.use_block.clear(); + self.mod_names.clear(); + self.spans.clear(); + } +} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 0d9502c50db6..b790f8d0fa05 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -112,6 +112,7 @@ use rustc_hir::{ }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; +use rustc_middle::hir::nested_filter; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; @@ -126,13 +127,11 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_span::{InnerSpan, Span, sym}; use rustc_target::abi::Integer; -use visitors::{Visitable, for_each_unconsumed_temporary}; use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; use crate::higher::Range; use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type}; -use crate::visitors::for_each_expr_without_closures; -use rustc_middle::hir::nested_filter; +use crate::visitors::{Visitable, for_each_expr_without_closures, for_each_unconsumed_temporary}; #[macro_export] macro_rules! extract_msrv_attr { diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr new file mode 100644 index 000000000000..e559b590f5f7 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.stderr @@ -0,0 +1,10 @@ +error: this import is not clear + --> src/main.rs:3:5 + | +3 | use foo::Foo; + | ^^^ help: prefix with `crate::`: `crate::foo` + | + = note: `-D clippy::use-crate-prefix-for-self-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::use_crate_prefix_for_self_imports)]` + +error: could not compile `fail` (bin "fail") due to 1 previous error diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml new file mode 100644 index 000000000000..e2d17bfe9a76 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fail" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs new file mode 100644 index 000000000000..7e75c10f1b5b --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/fail/src/main.rs @@ -0,0 +1,9 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +use foo::Foo; + +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml new file mode 100644 index 000000000000..68783fafe997 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs new file mode 100644 index 000000000000..820faee159b7 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass/src/main.rs @@ -0,0 +1,9 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +use crate::foo::Foo; + +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml new file mode 100644 index 000000000000..a9248778777a --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pass_attribute" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] + +[features] +default = ["bar"] +bar = [] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs new file mode 100644 index 000000000000..1ebe7984e084 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute/src/lib.rs @@ -0,0 +1,6 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +#[cfg(feature = "bar")] +mod foo; +#[cfg(feature = "bar")] +pub use foo::Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml new file mode 100644 index 000000000000..202d81f7a503 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_attribute_2" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs new file mode 100644 index 000000000000..0633d3a88fc9 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_attribute_2/src/lib.rs @@ -0,0 +1,5 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +mod foo; +#[doc(hidden)] +pub use foo::Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml new file mode 100644 index 000000000000..c1abf357a802 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs new file mode 100644 index 000000000000..6fc7b021514a --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling/src/main.rs @@ -0,0 +1,8 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +mod foo; +use foo::Foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml new file mode 100644 index 000000000000..a1d2fd853185 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling_2" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/foo.rs new file mode 100644 index 000000000000..4a835673a596 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/foo.rs @@ -0,0 +1 @@ +pub struct Foo; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs new file mode 100644 index 000000000000..9502ca88022f --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_2/src/main.rs @@ -0,0 +1,8 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +use foo::Foo; +mod foo; + +fn main() { + let _foo = Foo; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml new file mode 100644 index 000000000000..b03557dce1a2 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling_3" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs new file mode 100644 index 000000000000..3e1446bda001 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/foo.rs @@ -0,0 +1,2 @@ +pub struct Foo; +pub struct Bar; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs new file mode 100644 index 000000000000..0f62eabb5fef --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_3/src/main.rs @@ -0,0 +1,9 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +mod foo; +pub use foo::{Bar, Foo}; + +fn main() { + let _foo = Foo; + let _bar = Bar; +} diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml new file mode 100644 index 000000000000..1a7f71070fce --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "pass_sibling_4" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs new file mode 100644 index 000000000000..3e1446bda001 --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/foo.rs @@ -0,0 +1,2 @@ +pub struct Foo; +pub struct Bar; diff --git a/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs new file mode 100644 index 000000000000..22fc2fafb4df --- /dev/null +++ b/tests/ui-cargo/use_crate_prefix_for_self_imports/pass_sibling_4/src/main.rs @@ -0,0 +1,9 @@ +#![warn(clippy::use_crate_prefix_for_self_imports)] + +pub use foo::{Bar, Foo}; +mod foo; + +fn main() { + let _foo = Foo; + let _bar = Bar; +}