Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Allow public re-export of extern crate import #18413

Merged
merged 1 commit into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/hir-def/src/item_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,11 @@ impl UseTree {
self.expand_impl(None, &mut cb)
}

/// The [`UseTreeKind`] of this `UseTree`.
pub fn kind(&self) -> &UseTreeKind {
&self.kind
}

fn expand_impl(
&self,
prefix: Option<ModPath>,
Expand Down
31 changes: 28 additions & 3 deletions crates/hir-def/src/nameres/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{
self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
},
macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{
Expand Down Expand Up @@ -1058,8 +1058,33 @@ impl DefCollector<'_> {
vis: Visibility,
def_import_type: Option<ImportType>,
) -> bool {
if let Some((_, v, _)) = defs.types.as_mut() {
*v = v.min(vis, &self.def_map).unwrap_or(vis);
// `extern crate crate_name` things can be re-exported as `pub use crate_name`.
// But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
// or `pub use ::crate_name`.
//
// This has been historically allowed, but may be not allowed in future
// https://github.com/rust-lang/rust/issues/127909
if let Some((_, v, it)) = defs.types.as_mut() {
let is_extern_crate_reimport_without_prefix = || {
let Some(ImportOrExternCrate::ExternCrate(_)) = it else {
return false;
};
let Some(ImportType::Import(id)) = def_import_type else {
return false;
};
let use_id = id.import.lookup(self.db).id;
let item_tree = use_id.item_tree(self.db);
let use_kind = item_tree[use_id.value].use_tree.kind();
let UseTreeKind::Single { path, .. } = use_kind else {
return false;
};
path.segments().len() < 2
};
if is_extern_crate_reimport_without_prefix() {
*v = vis;
} else {
*v = v.min(vis, &self.def_map).unwrap_or(vis);
}
}
if let Some((_, v, _)) = defs.values.as_mut() {
*v = v.min(vis, &self.def_map).unwrap_or(vis);
Expand Down
46 changes: 46 additions & 0 deletions crates/hir-def/src/nameres/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,52 @@ pub struct Arc;
);
}

#[test]
fn extern_crate_reexport() {
check(
r#"
//- /main.rs crate:main deps:importer
use importer::*;
use importer::extern_crate1::exported::*;
use importer::allowed_reexport::*;
use importer::extern_crate2::*;
use importer::not_allowed_reexport1;
use importer::not_allowed_reexport2;

//- /importer.rs crate:importer deps:extern_crate1,extern_crate2
extern crate extern_crate1;
extern crate extern_crate2;

pub use extern_crate1;
pub use extern_crate1 as allowed_reexport;

pub use ::extern_crate;
pub use self::extern_crate as not_allowed_reexport1;
pub use crate::extern_crate as not_allowed_reexport2;

//- /extern_crate1.rs crate:extern_crate1
pub mod exported {
pub struct PublicItem;
struct PrivateItem;
}

pub struct Exported;

//- /extern_crate2.rs crate:extern_crate2
pub struct NotExported;
"#,
expect![[r#"
crate
Exported: t v
PublicItem: t v
allowed_reexport: t
exported: t
not_allowed_reexport1: _
not_allowed_reexport2: _
"#]],
);
}

#[test]
fn extern_crate_rename_2015_edition() {
check(
Expand Down