Skip to content

Commit 27839b2

Browse files
committed
[WIP] resolve: Make ambiguity checking stricter
1 parent 9b82a4f commit 27839b2

File tree

9 files changed

+68
-37
lines changed

9 files changed

+68
-37
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use Namespace::*;
55
use rustc_ast::{self as ast, NodeId};
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
8-
use rustc_middle::{bug, span_bug};
8+
use rustc_hir::def_id::DefId;
9+
use rustc_middle::{bug, span_bug, ty};
910
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
1011
use rustc_session::parse::feature_err;
1112
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
@@ -465,13 +466,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
465466
Ok((binding, flags))
466467
if sub_namespace_match(binding.macro_kinds(), macro_kind) =>
467468
{
469+
if !matches!(scope, Scope::MacroUsePrelude) {
470+
let adjusted_module = if let Scope::Module(module, _) = scope
471+
&& !matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..))
472+
{
473+
module
474+
} else {
475+
parent_scope.module
476+
};
477+
if !this.is_accessible_from(binding.vis, adjusted_module) {
478+
this.dcx()
479+
.struct_span_err(binding.span, "binding")
480+
.with_span_label(adjusted_module.span, "module")
481+
.emit();
482+
}
483+
}
484+
468485
// Below we report various ambiguity errors.
469486
// We do not need to report them if we are either in speculative resolution,
470487
// or in late resolution when everything is already imported and expanded
471488
// and no ambiguities exist.
472-
if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) {
473-
return ControlFlow::Break(Ok(binding));
474-
}
489+
let (significant_visibility, import_vis) = match finalize {
490+
None | Some(Finalize { stage: Stage::Late, .. }) => {
491+
return ControlFlow::Break(Ok(binding));
492+
}
493+
Some(Finalize { significant_visibility, import_vis, .. }) => {
494+
(significant_visibility, import_vis)
495+
}
496+
};
475497

476498
if let Some((innermost_binding, innermost_flags)) = innermost_result {
477499
// Found another solution, if the first one was "weak", report an error.
@@ -482,6 +504,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
482504
innermost_binding,
483505
flags,
484506
innermost_flags,
507+
significant_visibility,
508+
import_vis,
485509
extern_prelude_item_binding,
486510
extern_prelude_flag_binding,
487511
) {
@@ -730,11 +754,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
730754
innermost_binding: NameBinding<'ra>,
731755
flags: Flags,
732756
innermost_flags: Flags,
757+
significant_visibility: bool,
758+
import_vis: Option<ty::Visibility>,
733759
extern_prelude_item_binding: Option<NameBinding<'ra>>,
734760
extern_prelude_flag_binding: Option<NameBinding<'ra>>,
735761
) -> bool {
736762
let (res, innermost_res) = (binding.res(), innermost_binding.res());
737-
if res == innermost_res {
763+
764+
let vis_min = |v1: ty::Visibility<DefId>, v2: ty::Visibility<DefId>| {
765+
if v1.is_at_least(v2, self.tcx) { v2 } else { v1 }
766+
};
767+
let bad_vis = significant_visibility
768+
&& vis_min(binding.vis, import_vis.unwrap().to_def_id())
769+
!= vis_min(innermost_binding.vis, import_vis.unwrap().to_def_id());
770+
771+
if res == innermost_res && !bad_vis {
738772
return false;
739773
}
740774

@@ -1207,7 +1241,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12071241
&& shadowing == Shadowing::Restricted
12081242
&& finalize.stage == Stage::Early
12091243
&& binding.expansion != LocalExpnId::ROOT
1210-
&& binding.res() != shadowed_glob.res()
1244+
&& (binding.res() != shadowed_glob.res() || finalize.significant_visibility)
12111245
{
12121246
self.ambiguity_errors.push(AmbiguityError {
12131247
kind: AmbiguityKind::GlobVsExpanded,

compiler/rustc_resolve/src/imports.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
394394
&& non_glob_binding.expansion != LocalExpnId::ROOT
395395
&& glob_binding.res() != non_glob_binding.res()
396396
{
397+
// FIXME: record vis mismatches as well, but breakage in practice.
397398
resolution.non_glob_binding = Some(this.new_ambiguity_binding(
398399
AmbiguityKind::GlobVsExpanded,
399400
non_glob_binding,
@@ -413,7 +414,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
413414
glob_binding,
414415
false,
415416
));
416-
} else if !old_glob_binding.vis.is_at_least(binding.vis, this.tcx) {
417+
} else if !old_glob_binding.vis.is_at_least(glob_binding.vis, this.tcx)
418+
{
417419
resolution.glob_binding = Some(glob_binding);
418420
}
419421
} else {
@@ -957,7 +959,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
957959
&import.module_path,
958960
None,
959961
&import.parent_scope,
960-
Some(finalize),
962+
Some(Finalize { significant_visibility: false, ..finalize }),
961963
ignore_binding,
962964
Some(import),
963965
);
@@ -1135,7 +1137,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11351137
ident,
11361138
ns,
11371139
&import.parent_scope,
1138-
Some(Finalize { report_private: false, ..finalize }),
1140+
Some(Finalize {
1141+
report_private: false,
1142+
import_vis: Some(import.vis),
1143+
..finalize
1144+
}),
11391145
bindings[ns].get().binding(),
11401146
Some(import),
11411147
);

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14981498
opt_ns,
14991499
&self.parent_scope,
15001500
Some(source),
1501-
finalize,
1501+
finalize.map(|finalize| Finalize { significant_visibility: false, ..finalize }),
15021502
Some(&self.ribs),
15031503
None,
15041504
None,

compiler/rustc_resolve/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
20312031
warn_ambiguity: bool,
20322032
) {
20332033
if let Some((b2, kind)) = used_binding.ambiguity {
2034+
// FIXME: Need to check if the `AmbiguityKind::GlobVsGlob`s caused by visibility
2035+
// mismatch ever passed through an import, but it's too breaking.
20342036
let ambiguity_error = AmbiguityError {
20352037
kind,
20362038
ident,
@@ -2503,6 +2505,11 @@ struct Finalize {
25032505
used: Used = Used::Other,
25042506
/// Finalizing early or late resolution.
25052507
stage: Stage = Stage::Early,
2508+
/// Ambiguous bindings with different visibilities need to be reported
2509+
/// even if they have the same `Res`olutions.
2510+
significant_visibility: bool = true,
2511+
/// Tralala
2512+
import_vis: Option<Visibility> = None,
25062513
}
25072514

25082515
impl Finalize {

compiler/rustc_resolve/src/macros.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -868,11 +868,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
868868
for seg in &mut path {
869869
seg.id = None;
870870
}
871+
872+
let finalize = Finalize::new(ast::CRATE_NODE_ID, path_span);
871873
match self.cm().resolve_path(
872874
&path,
873875
Some(ns),
874876
&parent_scope,
875-
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
877+
Some(Finalize { significant_visibility: false, ..finalize }),
876878
None,
877879
None,
878880
) {
@@ -941,11 +943,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
941943

942944
let macro_resolutions = self.single_segment_macro_resolutions.take(self);
943945
for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions {
946+
let finalize = Finalize::new(ast::CRATE_NODE_ID, ident.span);
944947
match self.cm().resolve_ident_in_scope_set(
945948
ident,
946949
ScopeSet::Macro(kind),
947950
&parent_scope,
948-
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
951+
Some(Finalize { significant_visibility: false, ..finalize }),
949952
true,
950953
None,
951954
None,
@@ -996,11 +999,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
996999

9971000
let builtin_attrs = mem::take(&mut self.builtin_attrs);
9981001
for (ident, parent_scope) in builtin_attrs {
1002+
let finalize = Finalize::new(ast::CRATE_NODE_ID, ident.span);
9991003
let _ = self.cm().resolve_ident_in_scope_set(
10001004
ident,
10011005
ScopeSet::Macro(MacroKind::Attr),
10021006
&parent_scope,
1003-
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
1007+
Some(Finalize { significant_visibility: false, ..finalize }),
10041008
true,
10051009
None,
10061010
None,

tests/ui/imports/auxiliary/same-res-ambigious-extern-fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ globbing! {} // this imports the same `RustEmbed` macro with `pub` visibility
1313

1414
pub trait RustEmbed {}
1515

16-
pub use RustEmbed as Embed;
16+
pub use self::RustEmbed as Embed;

tests/ui/imports/auxiliary/same-res-ambigious-extern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ pub use same_res_ambigious_extern_macro::*;
88

99
pub trait RustEmbed {}
1010

11-
pub use RustEmbed as Embed;
11+
pub use self::RustEmbed as Embed;

tests/ui/imports/same-res-ambigious.fail.stderr

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//@ edition: 2018
22
//@ revisions: fail pass
3-
//@[pass] check-pass
3+
//@ check-pass
44
//@[pass] aux-crate: ambigious_extern=same-res-ambigious-extern.rs
55
//@[fail] aux-crate: ambigious_extern=same-res-ambigious-extern-fail.rs
66
// see https://github.com/rust-lang/rust/pull/147196
77

8-
#[derive(ambigious_extern::Embed)] //[fail]~ ERROR: derive macro `Embed` is private
8+
#[derive(ambigious_extern::Embed)]
99
struct Foo{}
1010

1111
fn main(){}

0 commit comments

Comments
 (0)