Skip to content

Commit 56c6db3

Browse files
authored
Unrolled build for #156014
Rollup merge of #156014 - petrochenkov:kvak, r=mu001999 resolve: Catch "cannot reexport" errors from macros 2.0 better After the macro 2.0 related holes are closed we can report `span_delayed_bug`s in more situations. Merging #155945 would make changes in this PR simpler, but that PR will probably have to wait for quite some time. This is a continuation of my import & privacy invariant hardening changes from #155257, #155213, #154149, etc. r? @mu001999
2 parents 740679e + fadb747 commit 56c6db3

7 files changed

Lines changed: 155 additions & 70 deletions

File tree

compiler/rustc_resolve/src/imports.rs

Lines changed: 105 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use rustc_attr_parsing::AttributeParser;
99
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
1010
use rustc_data_structures::intern::Interned;
1111
use rustc_errors::codes::*;
12-
use rustc_errors::{Applicability, Diagnostic, MultiSpan, pluralize, struct_span_code_err};
12+
use rustc_errors::{
13+
Applicability, BufferedEarlyLint, Diagnostic, MultiSpan, pluralize, struct_span_code_err,
14+
};
1315
use rustc_hir::Attribute;
1416
use rustc_hir::attrs::AttributeKind;
1517
use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};
@@ -19,6 +21,7 @@ use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};
1921
use rustc_middle::span_bug;
2022
use rustc_middle::ty::{TyCtxt, Visibility};
2123
use rustc_session::errors::feature_err;
24+
use rustc_session::lint::LintId;
2225
use rustc_session::lint::builtin::{
2326
AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,
2427
PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,
@@ -273,6 +276,8 @@ impl<'ra> ImportData<'ra> {
273276
vis: self.vis,
274277
nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(),
275278
is_single: matches!(self.kind, ImportKind::Single { .. }),
279+
priv_macro_use: matches!(self.kind, ImportKind::MacroUse { warn_private: true }),
280+
span: self.span,
276281
}
277282
}
278283
}
@@ -381,22 +386,31 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
381386
) -> Visibility {
382387
assert!(import.vis.is_accessible_from(import.nearest_parent_mod, self.tcx));
383388
let decl_vis = if min { decl.min_vis() } else { decl.vis() };
384-
if decl_vis.partial_cmp(import.vis, self.tcx) == Some(Ordering::Less)
389+
let ord = decl_vis.partial_cmp(import.vis, self.tcx);
390+
let extern_crate_hack = pub_use_of_private_extern_crate_hack(import, decl).is_some();
391+
if ord == Some(Ordering::Less)
385392
&& decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx)
386-
&& pub_use_of_private_extern_crate_hack(import, decl).is_none()
393+
&& !extern_crate_hack
387394
{
388395
// Imported declaration is less visible than the import, but is still visible
389396
// from the current module, use the declaration's visibility.
390397
decl_vis.expect_local()
391398
} else {
392399
// Good case - imported declaration is more visible than the import, or the same,
393400
// use the import's visibility.
401+
//
394402
// Bad case - imported declaration is too private for the current module.
395403
// It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE`
396-
// and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because either some error will be
397-
// reported, or the import declaration will be thrown away (unfortunately cannot use
398-
// delayed bug here for this reason).
404+
// and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because an error will be reported.
399405
// Use import visibility to keep the all declaration visibilities in a module ordered.
406+
if !min
407+
&& matches!(ord, None | Some(Ordering::Less))
408+
&& !extern_crate_hack
409+
&& !import.priv_macro_use
410+
{
411+
let msg = format!("cannot extend visibility from {decl_vis:?} to {:?}", import.vis);
412+
self.dcx().span_delayed_bug(import.span, msg);
413+
}
400414
import.vis
401415
}
402416
}
@@ -784,6 +798,29 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
784798
let resolution = resolution.borrow();
785799
let Some(binding) = resolution.best_decl() else { continue };
786800

801+
// Report "cannot reexport" errors for exotic cases involving macros 2.0
802+
// privacy bending or invariant-breaking code under deprecation lints.
803+
for decl in [resolution.non_glob_decl, resolution.glob_decl] {
804+
if let Some(decl) = decl
805+
&& let DeclKind::Import { source_decl, import } = decl.kind
806+
{
807+
// The source entity is too private to be reexported
808+
// with the given import declaration's visibility.
809+
let ord = source_decl.vis().partial_cmp(decl.vis(), self.tcx);
810+
if matches!(ord, None | Some(Ordering::Less)) {
811+
let ident = match import.kind {
812+
ImportKind::Single { source, .. } => source,
813+
_ => key.ident.orig(resolution.orig_ident_span),
814+
};
815+
if let Some(lint) =
816+
self.report_cannot_reexport(import, source_decl, ident, key.ns)
817+
{
818+
self.lint_buffer.add_early_lint(lint);
819+
}
820+
}
821+
}
822+
}
823+
787824
if let DeclKind::Import { import, .. } = binding.kind
788825
&& let Some(amb_binding) = binding.ambiguity.get()
789826
&& binding.res() != Res::Err
@@ -1515,76 +1552,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15151552

15161553
let mut reexport_error = None;
15171554
let mut any_successful_reexport = false;
1518-
let mut crate_private_reexport = false;
15191555
self.per_ns(|this, ns| {
1520-
let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) else {
1556+
let Some(binding) = bindings[ns].get().decl() else {
15211557
return;
15221558
};
15231559

15241560
if import.vis.greater_than(binding.vis(), this.tcx) {
1525-
reexport_error = Some((ns, binding));
1526-
if let Visibility::Restricted(binding_def_id) = binding.vis()
1527-
&& binding_def_id.is_top_level_module()
1528-
{
1529-
crate_private_reexport = true;
1530-
}
1561+
// In isolation, a declaration like this is not an error, but if *all* 1-3
1562+
// declarations introduced by the import are more private than the import item's
1563+
// nominal visibility, then it's an error.
1564+
reexport_error = Some((ns, binding.import_source()));
15311565
} else {
15321566
any_successful_reexport = true;
15331567
}
15341568
});
15351569

1536-
// All namespaces must be re-exported with extra visibility for an error to occur.
15371570
if !any_successful_reexport {
15381571
let (ns, binding) = reexport_error.unwrap();
1539-
if let Some(extern_crate_id) =
1540-
pub_use_of_private_extern_crate_hack(import.summary(), binding)
1541-
{
1542-
let extern_crate_sp = self.tcx.source_span(self.local_def_id(extern_crate_id));
1543-
self.lint_buffer.buffer_lint(
1544-
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
1545-
import_id,
1546-
import.span,
1547-
crate::errors::PrivateExternCrateReexport {
1548-
ident,
1549-
sugg: extern_crate_sp.shrink_to_lo(),
1550-
},
1551-
);
1552-
} else if ns == TypeNS {
1553-
let err = if crate_private_reexport {
1554-
self.dcx()
1555-
.create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
1556-
} else {
1557-
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
1558-
};
1559-
err.emit();
1560-
} else {
1561-
let mut err = if crate_private_reexport {
1562-
self.dcx()
1563-
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
1564-
} else {
1565-
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
1566-
};
1567-
1568-
match binding.kind {
1569-
DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))
1570-
// exclude decl_macro
1571-
if self.get_macro_by_def_id(def_id).macro_rules =>
1572-
{
1573-
err.subdiagnostic( ConsiderAddingMacroExport {
1574-
span: binding.span,
1575-
});
1576-
err.subdiagnostic( ConsiderMarkingAsPubCrate {
1577-
vis_span: import.vis_span,
1578-
});
1579-
}
1580-
_ => {
1581-
err.subdiagnostic( ConsiderMarkingAsPub {
1582-
span: import.span,
1583-
ident,
1584-
});
1585-
}
1586-
}
1587-
err.emit();
1572+
if let Some(lint) = self.report_cannot_reexport(import, binding, ident, ns) {
1573+
self.lint_buffer.add_early_lint(lint);
15881574
}
15891575
}
15901576

@@ -1613,6 +1599,61 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16131599
None
16141600
}
16151601

1602+
fn report_cannot_reexport(
1603+
&self,
1604+
import: Import<'ra>,
1605+
decl: Decl<'ra>,
1606+
ident: Ident,
1607+
ns: Namespace,
1608+
) -> Option<BufferedEarlyLint> {
1609+
let crate_private_reexport = match decl.vis() {
1610+
Visibility::Restricted(def_id) if def_id.is_top_level_module() => true,
1611+
_ => false,
1612+
};
1613+
1614+
if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl)
1615+
{
1616+
let ImportKind::Single { id, .. } = import.kind else { unreachable!() };
1617+
let sugg = self.tcx.source_span(self.local_def_id(extern_crate_id)).shrink_to_lo();
1618+
let diagnostic = crate::errors::PrivateExternCrateReexport { ident, sugg };
1619+
return Some(BufferedEarlyLint {
1620+
lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
1621+
node_id: id,
1622+
span: Some(import.span.into()),
1623+
diagnostic: diagnostic.into(),
1624+
});
1625+
} else if ns == TypeNS {
1626+
let err = if crate_private_reexport {
1627+
self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
1628+
} else {
1629+
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
1630+
};
1631+
err.emit();
1632+
} else {
1633+
let mut err = if crate_private_reexport {
1634+
self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident })
1635+
} else {
1636+
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
1637+
};
1638+
1639+
match decl.kind {
1640+
// exclude decl_macro
1641+
DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))
1642+
if self.get_macro_by_def_id(def_id).macro_rules =>
1643+
{
1644+
err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span });
1645+
err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span });
1646+
}
1647+
_ => {
1648+
err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident });
1649+
}
1650+
}
1651+
err.emit();
1652+
}
1653+
1654+
None
1655+
}
1656+
16161657
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {
16171658
// This function is only called for single imports.
16181659
let ImportKind::Single { source, target, ref decls, id, .. } = import.kind else {

compiler/rustc_resolve/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2750,6 +2750,8 @@ struct ImportSummary {
27502750
vis: Visibility,
27512751
nearest_parent_mod: LocalDefId,
27522752
is_single: bool,
2753+
priv_macro_use: bool,
2754+
span: Span,
27532755
}
27542756

27552757
/// Invariant: if `Finalize` is used, expansion and import resolution must be complete.

src/tools/rust-analyzer/crates/hir-def/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern crate rustc_parse_format;
1616
extern crate ra_ap_rustc_parse_format as rustc_parse_format;
1717

1818
extern crate ra_ap_rustc_abi as rustc_abi;
19+
pub extern crate ra_ap_rustc_abi as layout;
1920

2021
pub mod db;
2122

@@ -47,7 +48,6 @@ pub mod import_map;
4748
pub mod visibility;
4849

4950
use intern::{Interned, Symbol};
50-
pub use rustc_abi as layout;
5151
use thin_vec::ThinVec;
5252

5353
pub use crate::signatures::LocalFieldId;

tests/ui/hygiene/privacy-early.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod foo {
88

99
pub macro m() {
1010
use f as g; //~ ERROR `f` is private, and cannot be re-exported
11+
//~| ERROR `f` is private, and cannot be re-exported
1112
f!();
1213
}
1314
}

tests/ui/hygiene/privacy-early.stderr

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ LL | foo::m!();
1717
| --------- in this macro invocation
1818
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
1919

20-
error: aborting due to 1 previous error
20+
error[E0364]: `f` is private, and cannot be re-exported
21+
--> $DIR/privacy-early.rs:10:13
22+
|
23+
LL | use f as g;
24+
| ^^^^^^
25+
...
26+
LL | foo::m!();
27+
| --------- in this macro invocation
28+
|
29+
note: consider marking `f` as `pub` in the imported module
30+
--> $DIR/privacy-early.rs:10:13
31+
|
32+
LL | use f as g;
33+
| ^^^^^^
34+
...
35+
LL | foo::m!();
36+
| --------- in this macro invocation
37+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
38+
= note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info)
39+
40+
error: aborting due to 2 previous errors
2141

2242
For more information about this error, try `rustc --explain E0364`.

tests/ui/imports/private-from-decl-macro.fail.stderr

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1+
error[E0364]: `S` is private, and cannot be re-exported
2+
--> $DIR/private-from-decl-macro.rs:18:13
3+
|
4+
LL | use crate::m::*;
5+
| ^^^^^^^^^^^
6+
...
7+
LL | crate::m::mac_glob!();
8+
| --------------------- in this macro invocation
9+
|
10+
note: consider marking `S` as `pub` in the imported module
11+
--> $DIR/private-from-decl-macro.rs:18:13
12+
|
13+
LL | use crate::m::*;
14+
| ^^^^^^^^^^^
15+
...
16+
LL | crate::m::mac_glob!();
17+
| --------------------- in this macro invocation
18+
= note: this error originates in the macro `crate::m::mac_glob` (in Nightly builds, run with -Z macro-backtrace for more info)
19+
120
error[E0423]: expected value, found struct `S`
2-
--> $DIR/private-from-decl-macro.rs:27:17
21+
--> $DIR/private-from-decl-macro.rs:28:17
322
|
423
LL | pub struct S {}
524
| --------------- `S` defined here
@@ -22,6 +41,7 @@ LL - let s = S;
2241
LL + let s = s;
2342
|
2443

25-
error: aborting due to 1 previous error
44+
error: aborting due to 2 previous errors
2645

27-
For more information about this error, try `rustc --explain E0423`.
46+
Some errors have detailed explanations: E0364, E0423.
47+
For more information about an error, try `rustc --explain E0364`.

tests/ui/imports/private-from-decl-macro.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ mod m {
1414
}
1515

1616
pub macro mac_glob() {
17-
use crate::m::*;
17+
#[cfg(fail)]
18+
use crate::m::*; //[fail]~ ERROR `S` is private, and cannot be re-exported
1819
}
1920
}
2021

0 commit comments

Comments
 (0)