Skip to content

Commit c4a7500

Browse files
committed
resolve: Improve diagnostics for ambiguities in extern prelude
1 parent f8849ed commit c4a7500

File tree

8 files changed

+39
-30
lines changed

8 files changed

+39
-30
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,14 +1865,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18651865
}
18661866
}
18671867

1868-
fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'_>) -> AmbiguityErrorDiag {
1868+
fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'ra>) -> AmbiguityErrorDiag {
18691869
let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error;
1870+
let extern_prelude_ambiguity = || {
1871+
self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)).is_some_and(|entry| {
1872+
entry.item_binding == Some(b1) && entry.flag_binding.get() == Some(b2)
1873+
})
1874+
};
18701875
let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
18711876
// We have to print the span-less alternative first, otherwise formatting looks bad.
18721877
(b2, b1, misc2, misc1, true)
18731878
} else {
18741879
(b1, b2, misc1, misc2, false)
18751880
};
1881+
18761882
let could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
18771883
let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
18781884
let note_msg = format!("`{ident}` could{also} refer to {what}");
@@ -1888,7 +1894,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18881894
"consider adding an explicit import of `{ident}` to disambiguate"
18891895
))
18901896
}
1891-
if b.is_extern_crate() && ident.span.at_least_rust_2018() {
1897+
if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
1898+
{
18921899
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
18931900
}
18941901
match misc {

compiler/rustc_resolve/src/ident.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
436436
// to detect potential ambiguities.
437437
let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
438438
let mut determinacy = Determinacy::Determined;
439+
// Shadowed bindings don't need to be marked as used or non-speculatively loaded.
440+
macro finalize_scope() {
441+
if innermost_result.is_none() { finalize } else { None }
442+
}
439443

440444
// Go through all the scopes and try to resolve the name.
441445
let break_result = self.visit_scopes(
@@ -501,13 +505,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
501505
_ => Err(Determinacy::Determined),
502506
},
503507
Scope::Module(module, derive_fallback_lint_id) => {
504-
let (adjusted_parent_scope, finalize) =
508+
let (adjusted_parent_scope, adjusted_finalize) =
505509
if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
506-
(parent_scope, finalize)
510+
(parent_scope, finalize_scope!())
507511
} else {
508512
(
509513
&ParentScope { module, ..*parent_scope },
510-
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
514+
finalize_scope!().map(|f| Finalize { used: Used::Scope, ..f }),
511515
)
512516
};
513517
let binding = this.reborrow().resolve_ident_in_module_unadjusted(
@@ -520,7 +524,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
520524
} else {
521525
Shadowing::Restricted
522526
},
523-
finalize,
527+
adjusted_finalize,
524528
ignore_binding,
525529
ignore_import,
526530
);
@@ -569,15 +573,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
569573
None => Err(Determinacy::Determined),
570574
},
571575
Scope::ExternPreludeItems => {
572-
match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) {
576+
match this
577+
.reborrow()
578+
.extern_prelude_get_item(ident, finalize_scope!().is_some())
579+
{
573580
Some(binding) => Ok((binding, Flags::empty())),
574581
None => Err(Determinacy::determined(
575582
this.graph_root.unexpanded_invocations.borrow().is_empty(),
576583
)),
577584
}
578585
}
579586
Scope::ExternPreludeFlags => {
580-
match this.extern_prelude_get_flag(ident, finalize.is_some()) {
587+
match this.extern_prelude_get_flag(ident, finalize_scope!().is_some()) {
581588
Some(binding) => Ok((binding, Flags::empty())),
582589
None => Err(Determinacy::Determined),
583590
}
@@ -612,8 +619,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
612619
if matches!(ident.name, sym::f16)
613620
&& !this.tcx.features().f16()
614621
&& !ident.span.allows_unstable(sym::f16)
615-
&& finalize.is_some()
616-
&& innermost_result.is_none()
622+
&& finalize_scope!().is_some()
617623
{
618624
feature_err(
619625
this.tcx.sess,
@@ -626,8 +632,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
626632
if matches!(ident.name, sym::f128)
627633
&& !this.tcx.features().f128()
628634
&& !ident.span.allows_unstable(sym::f128)
629-
&& finalize.is_some()
630-
&& innermost_result.is_none()
635+
&& finalize_scope!().is_some()
631636
{
632637
feature_err(
633638
this.tcx.sess,

compiler/rustc_resolve/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![feature(arbitrary_self_types)]
1616
#![feature(assert_matches)]
1717
#![feature(box_patterns)]
18+
#![feature(decl_macro)]
1819
#![feature(if_let_guard)]
1920
#![feature(iter_intersperse)]
2021
#![feature(rustc_attrs)]

tests/ui/imports/issue-109148.stderr

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ LL | use std::mem;
1717
|
1818
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
1919
= note: `std` could refer to a built-in crate
20-
= help: use `::std` to refer to this crate unambiguously
2120
note: `std` could also refer to the crate imported here
2221
--> $DIR/issue-109148.rs:6:9
2322
|
@@ -26,8 +25,7 @@ LL | extern crate core as std;
2625
...
2726
LL | m!();
2827
| ---- in this macro invocation
29-
= help: use `::std` to refer to this crate unambiguously
30-
= help: or use `crate::std` to refer to this crate unambiguously
28+
= help: use `crate::std` to refer to this crate unambiguously
3129
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
3230

3331
error[E0659]: `std` is ambiguous
@@ -38,7 +36,6 @@ LL | use ::std::mem as _;
3836
|
3937
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
4038
= note: `std` could refer to a built-in crate
41-
= help: use `::std` to refer to this crate unambiguously
4239
note: `std` could also refer to the crate imported here
4340
--> $DIR/issue-109148.rs:6:9
4441
|
@@ -47,7 +44,6 @@ LL | extern crate core as std;
4744
...
4845
LL | m!();
4946
| ---- in this macro invocation
50-
= help: use `::std` to refer to this crate unambiguously
5147
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
5248

5349
error: aborting due to 3 previous errors

tests/ui/macros/issue-78325-inconsistent-resolution.stderr

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ LL | core::panic!();
1717
|
1818
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
1919
= note: `core` could refer to a built-in crate
20-
= help: use `::core` to refer to this crate unambiguously
2120
note: `core` could also refer to the crate imported here
2221
--> $DIR/issue-78325-inconsistent-resolution.rs:5:9
2322
|
@@ -26,8 +25,7 @@ LL | extern crate std as core;
2625
...
2726
LL | define_other_core!();
2827
| -------------------- in this macro invocation
29-
= help: use `::core` to refer to this crate unambiguously
30-
= help: or use `crate::core` to refer to this crate unambiguously
28+
= help: use `crate::core` to refer to this crate unambiguously
3129
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
3230

3331
error[E0659]: `core` is ambiguous
@@ -38,7 +36,6 @@ LL | ::core::panic!();
3836
|
3937
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
4038
= note: `core` could refer to a built-in crate
41-
= help: use `::core` to refer to this crate unambiguously
4239
note: `core` could also refer to the crate imported here
4340
--> $DIR/issue-78325-inconsistent-resolution.rs:5:9
4441
|
@@ -47,7 +44,6 @@ LL | extern crate std as core;
4744
...
4845
LL | define_other_core!();
4946
| -------------------- in this macro invocation
50-
= help: use `::core` to refer to this crate unambiguously
5147
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
5248

5349
error: aborting due to 3 previous errors
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Non-existent path in `--extern` doesn't result in an error if it's shadowed by `extern crate`.
2+
3+
//@ check-pass
4+
//@ compile-flags: --extern something=/path/to/nowhere
5+
6+
extern crate std as something;
7+
8+
fn main() {
9+
something::println!();
10+
}

tests/ui/rust-2018/uniform-paths/deadlock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//@ compile-flags:--extern foo --extern bar
33

44
use bar::foo; //~ ERROR can't find crate for `bar`
5-
use foo::bar; //~ ERROR can't find crate for `foo`
5+
use foo::bar;
66
//~^^ ERROR unresolved imports `bar::foo`, `foo::bar`
77

88
fn main() {}

tests/ui/rust-2018/uniform-paths/deadlock.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ error[E0463]: can't find crate for `bar`
44
LL | use bar::foo;
55
| ^^^ can't find crate
66

7-
error[E0463]: can't find crate for `foo`
8-
--> $DIR/deadlock.rs:5:5
9-
|
10-
LL | use foo::bar;
11-
| ^^^ can't find crate
12-
137
error[E0432]: unresolved imports `bar::foo`, `foo::bar`
148
--> $DIR/deadlock.rs:4:5
159
|
@@ -18,7 +12,7 @@ LL | use bar::foo;
1812
LL | use foo::bar;
1913
| ^^^^^^^^
2014

21-
error: aborting due to 3 previous errors
15+
error: aborting due to 2 previous errors
2216

2317
Some errors have detailed explanations: E0432, E0463.
2418
For more information about an error, try `rustc --explain E0432`.

0 commit comments

Comments
 (0)