Skip to content

Commit b12859a

Browse files
authored
Merge pull request rust-lang#18413 from ShoyuVanilla/extern-crate-reexport
fix: Allow public re-export of `extern crate` import
2 parents 9a7fd6f + 0abb563 commit b12859a

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

Diff for: src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,11 @@ impl UseTree {
11661166
self.expand_impl(None, &mut cb)
11671167
}
11681168

1169+
/// The [`UseTreeKind`] of this `UseTree`.
1170+
pub fn kind(&self) -> &UseTreeKind {
1171+
&self.kind
1172+
}
1173+
11691174
fn expand_impl(
11701175
&self,
11711176
prefix: Option<ModPath>,

Diff for: src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::{
3131
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
3232
item_tree::{
3333
self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
34-
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
34+
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
3535
},
3636
macro_call_as_call_id, macro_call_as_call_id_with_eager,
3737
nameres::{
@@ -1058,8 +1058,33 @@ impl DefCollector<'_> {
10581058
vis: Visibility,
10591059
def_import_type: Option<ImportType>,
10601060
) -> bool {
1061-
if let Some((_, v, _)) = defs.types.as_mut() {
1062-
*v = v.min(vis, &self.def_map).unwrap_or(vis);
1061+
// `extern crate crate_name` things can be re-exported as `pub use crate_name`.
1062+
// But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
1063+
// or `pub use ::crate_name`.
1064+
//
1065+
// This has been historically allowed, but may be not allowed in future
1066+
// https://github.com/rust-lang/rust/issues/127909
1067+
if let Some((_, v, it)) = defs.types.as_mut() {
1068+
let is_extern_crate_reimport_without_prefix = || {
1069+
let Some(ImportOrExternCrate::ExternCrate(_)) = it else {
1070+
return false;
1071+
};
1072+
let Some(ImportType::Import(id)) = def_import_type else {
1073+
return false;
1074+
};
1075+
let use_id = id.import.lookup(self.db).id;
1076+
let item_tree = use_id.item_tree(self.db);
1077+
let use_kind = item_tree[use_id.value].use_tree.kind();
1078+
let UseTreeKind::Single { path, .. } = use_kind else {
1079+
return false;
1080+
};
1081+
path.segments().len() < 2
1082+
};
1083+
if is_extern_crate_reimport_without_prefix() {
1084+
*v = vis;
1085+
} else {
1086+
*v = v.min(vis, &self.def_map).unwrap_or(vis);
1087+
}
10631088
}
10641089
if let Some((_, v, _)) = defs.values.as_mut() {
10651090
*v = v.min(vis, &self.def_map).unwrap_or(vis);

Diff for: src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs

+46
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,52 @@ 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+
use importer::extern_crate1::exported::*;
395+
use importer::allowed_reexport::*;
396+
use importer::extern_crate2::*;
397+
use importer::not_allowed_reexport1;
398+
use importer::not_allowed_reexport2;
399+
400+
//- /importer.rs crate:importer deps:extern_crate1,extern_crate2
401+
extern crate extern_crate1;
402+
extern crate extern_crate2;
403+
404+
pub use extern_crate1;
405+
pub use extern_crate1 as allowed_reexport;
406+
407+
pub use ::extern_crate;
408+
pub use self::extern_crate as not_allowed_reexport1;
409+
pub use crate::extern_crate as not_allowed_reexport2;
410+
411+
//- /extern_crate1.rs crate:extern_crate1
412+
pub mod exported {
413+
pub struct PublicItem;
414+
struct PrivateItem;
415+
}
416+
417+
pub struct Exported;
418+
419+
//- /extern_crate2.rs crate:extern_crate2
420+
pub struct NotExported;
421+
"#,
422+
expect![[r#"
423+
crate
424+
Exported: t v
425+
PublicItem: t v
426+
allowed_reexport: t
427+
exported: t
428+
not_allowed_reexport1: _
429+
not_allowed_reexport2: _
430+
"#]],
431+
);
432+
}
433+
388434
#[test]
389435
fn extern_crate_rename_2015_edition() {
390436
check(

0 commit comments

Comments
 (0)