Skip to content

Commit 6c84aa8

Browse files
committed
fix: Allow public re-export of extern crate import
1 parent 6005446 commit 6c84aa8

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

crates/hir-def/src/nameres/collector.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::{
4545
},
4646
path::{ImportAlias, ModPath, PathKind},
4747
per_ns::PerNs,
48+
src::HasChildSource,
4849
tt,
4950
visibility::{RawVisibility, Visibility},
5051
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
@@ -1058,8 +1059,34 @@ impl DefCollector<'_> {
10581059
vis: Visibility,
10591060
def_import_type: Option<ImportType>,
10601061
) -> bool {
1061-
if let Some((_, v, _)) = defs.types.as_mut() {
1062-
*v = v.min(vis, &self.def_map).unwrap_or(vis);
1062+
// `extern crate crate_name` things can be re-exported as `pub use crate_name`.
1063+
// But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
1064+
// or `pub use ::crate_name`.
1065+
if let Some((_, v, it)) = defs.types.as_mut() {
1066+
let is_extern_crate_reimport_without_prefix = || {
1067+
let Some(ImportOrExternCrate::ExternCrate(_)) = it else {
1068+
return false;
1069+
};
1070+
let Some(ImportType::Import(id)) = def_import_type else {
1071+
return false;
1072+
};
1073+
let source = id.import.child_source(self.db);
1074+
let Some(use_tree_src) = source.value.get(id.idx) else {
1075+
return false;
1076+
};
1077+
use_tree_src.top_use_tree().path().and_then(|p| p.first_segment()).is_some_and(
1078+
|s| {
1079+
s.crate_token().is_none()
1080+
&& s.self_token().is_none()
1081+
&& s.coloncolon_token().is_none()
1082+
},
1083+
)
1084+
};
1085+
if is_extern_crate_reimport_without_prefix() {
1086+
*v = vis;
1087+
} else {
1088+
*v = v.min(vis, &self.def_map).unwrap_or(vis);
1089+
}
10631090
}
10641091
if let Some((_, v, _)) = defs.values.as_mut() {
10651092
*v = v.min(vis, &self.def_map).unwrap_or(vis);

crates/hir-def/src/nameres/tests.rs

+35
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,41 @@ pub struct Arc;
385385
);
386386
}
387387

388+
#[test]
389+
fn extern_crate_reexport() {
390+
check(
391+
r#"
392+
//- /main.rs crate:main deps:importer
393+
use importer::*;
394+
395+
//- /importer.rs crate:importer deps:extern_crate
396+
extern crate extern_crate;
397+
398+
pub use extern_crate::{self, exported::{self, *}, Exported};
399+
pub use ::extern_crate::NotExported1;
400+
pub use crate::extern_crate::NotExported2;
401+
pub use self::extern_crate::NotExported3;
402+
403+
//- /extern_crate.rs crate:extern_crate
404+
pub mod exported {
405+
pub struct PublicItem;
406+
struct PrivateItem;
407+
}
408+
409+
pub struct Exported;
410+
struct NotExported1;
411+
struct NotExported2;
412+
struct NotExported3;
413+
"#,
414+
expect![[r#"
415+
crate
416+
Exported: t v
417+
PublicItem: t v
418+
exported: t
419+
"#]],
420+
);
421+
}
422+
388423
#[test]
389424
fn extern_crate_rename_2015_edition() {
390425
check(

0 commit comments

Comments
 (0)