Skip to content

Commit 6cdcef5

Browse files
Rollup merge of #150939 - impasse, r=estebank
resolve: Relax some asserts in glob overwriting and add tests Fixes #150927. Fixes #150928. Fixes #150929. Fixes #150976. Fixes #150977. Fixes #151008. Fixes #151037. Fixes rust-lang/rust-clippy#16398. r? @yaahc
2 parents 7cab643 + 83c5f2c commit 6cdcef5

11 files changed

Lines changed: 202 additions & 15 deletions

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
212212
&mut self,
213213
ident: Ident,
214214
ns: Namespace,
215-
new_binding: Decl<'ra>,
216215
old_binding: Decl<'ra>,
216+
new_binding: Decl<'ra>,
217217
) {
218218
// Error on the second of two conflicting names
219219
if old_binding.span.lo() > new_binding.span.lo() {
220-
return self.report_conflict(ident, ns, old_binding, new_binding);
220+
return self.report_conflict(ident, ns, new_binding, old_binding);
221221
}
222222

223223
let container = match old_binding.parent_module.unwrap().kind {

compiler/rustc_resolve/src/imports.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,16 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
300300
if let DeclKind::Import { import: import1, source_decl: d1_next } = d1.kind
301301
&& let DeclKind::Import { import: import2, source_decl: d2_next } = d2.kind
302302
&& import1 == import2
303-
&& d1.warn_ambiguity.get() == d2.warn_ambiguity.get()
304303
{
305-
assert_eq!(d1.ambiguity.get(), d2.ambiguity.get());
306-
assert!(!d1.warn_ambiguity.get());
307304
assert_eq!(d1.expansion, d2.expansion);
308305
assert_eq!(d1.span, d2.span);
309-
assert_eq!(d1.vis(), d2.vis());
306+
if d1.ambiguity.get() != d2.ambiguity.get() {
307+
assert!(d1.ambiguity.get().is_some());
308+
assert!(d2.ambiguity.get().is_none());
309+
}
310+
// Visibility of the new import declaration may be different,
311+
// because it already incorporates the visibility of the source binding.
312+
// `warn_ambiguity` of a re-fetched glob can also change in both directions.
310313
remove_same_import(d1_next, d2_next)
311314
} else {
312315
(d1, d2)
@@ -348,8 +351,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
348351
/// decide which one to keep.
349352
fn select_glob_decl(
350353
&self,
351-
glob_decl: Decl<'ra>,
352354
old_glob_decl: Decl<'ra>,
355+
glob_decl: Decl<'ra>,
353356
warn_ambiguity: bool,
354357
) -> Decl<'ra> {
355358
assert!(glob_decl.is_glob_import());
@@ -369,14 +372,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
369372
// with the re-fetched decls.
370373
// This is probably incorrect in corner cases, and the outdated decls still get
371374
// propagated to other places and get stuck there, but that's what we have at the moment.
372-
let (deep_decl, old_deep_decl) = remove_same_import(glob_decl, old_glob_decl);
375+
let (old_deep_decl, deep_decl) = remove_same_import(old_glob_decl, glob_decl);
373376
if deep_decl != glob_decl {
374377
// Some import layers have been removed, need to overwrite.
375378
assert_ne!(old_deep_decl, old_glob_decl);
376379
// FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).
377380
// assert_ne!(old_deep_decl, deep_decl);
378381
// assert!(old_deep_decl.is_glob_import());
379382
assert!(!deep_decl.is_glob_import());
383+
if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
384+
// Do not lose glob ambiguities when re-fetching the glob.
385+
glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
386+
}
380387
if glob_decl.is_ambiguity_recursive() {
381388
glob_decl.warn_ambiguity.set_unchecked(true);
382389
}
@@ -436,7 +443,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
436443
match (old_decl.is_glob_import(), decl.is_glob_import()) {
437444
(true, true) => {
438445
resolution.glob_decl =
439-
Some(this.select_glob_decl(decl, old_decl, warn_ambiguity));
446+
Some(this.select_glob_decl(old_decl, decl, warn_ambiguity));
440447
}
441448
(old_glob @ true, false) | (old_glob @ false, true) => {
442449
let (glob_decl, non_glob_decl) =
@@ -446,7 +453,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
446453
&& old_glob_decl != glob_decl
447454
{
448455
resolution.glob_decl =
449-
Some(this.select_glob_decl(glob_decl, old_glob_decl, false));
456+
Some(this.select_glob_decl(old_glob_decl, glob_decl, false));
450457
} else {
451458
resolution.glob_decl = Some(glob_decl);
452459
}

tests/ui/hygiene/cross-crate-redefine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern crate use_by_macro;
88
use use_by_macro::*;
99

1010
my_struct!(define);
11-
//~^ ERROR the name `MyStruct` is defined multiple times
1211
my_struct!(define);
12+
//~^ ERROR the name `MyStruct` is defined multiple times
1313

1414
fn main() {}

tests/ui/hygiene/cross-crate-redefine.stderr

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
error[E0428]: the name `MyStruct` is defined multiple times
2-
--> $DIR/cross-crate-redefine.rs:10:1
2+
--> $DIR/cross-crate-redefine.rs:11:1
33
|
4-
LL | my_struct!(define);
5-
| ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here
6-
LL |
74
LL | my_struct!(define);
85
| ------------------ previous definition of the type `MyStruct` here
6+
LL | my_struct!(define);
7+
| ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here
98
|
109
= note: `MyStruct` must be defined only once in the type namespace of this module
1110
= note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ check-pass
2+
3+
mod openssl {
4+
pub use self::handwritten::*;
5+
6+
mod handwritten {
7+
mod m1 {
8+
pub struct S {}
9+
}
10+
mod m2 {
11+
#[derive(Default)]
12+
pub struct S {}
13+
}
14+
15+
pub use self::m1::*; //~ WARN ambiguous glob re-exports
16+
pub use self::m2::*;
17+
}
18+
}
19+
20+
pub use openssl::*;
21+
22+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
warning: ambiguous glob re-exports
2+
--> $DIR/overwrite-deep-glob.rs:15:17
3+
|
4+
LL | pub use self::m1::*;
5+
| ^^^^^^^^^^^ the name `S` in the type namespace is first re-exported here
6+
LL | pub use self::m2::*;
7+
| ----------- but the name `S` in the type namespace is also re-exported here
8+
|
9+
= note: `#[warn(ambiguous_glob_reexports)]` on by default
10+
11+
warning: 1 warning emitted
12+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
mod m1 {
2+
mod inner {
3+
pub struct S {}
4+
}
5+
pub use self::inner::*;
6+
7+
#[derive(Debug)]
8+
pub struct S {}
9+
}
10+
11+
mod m2 {
12+
pub struct S {}
13+
}
14+
15+
// First we have a glob ambiguity in this glob (with `m2::*`).
16+
// Then we re-fetch `m1::*` because non-glob `m1::S` materializes from derive,
17+
// and we need to make sure that the glob ambiguity is not lost during re-fetching.
18+
use m1::*;
19+
use m2::*;
20+
21+
fn main() {
22+
let _: m1::S = S {}; //~ ERROR `S` is ambiguous
23+
//~| WARN this was previously accepted
24+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error: `S` is ambiguous
2+
--> $DIR/overwrite-different-ambig-2.rs:22:20
3+
|
4+
LL | let _: m1::S = S {};
5+
| ^ ambiguous name
6+
|
7+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
8+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
9+
= note: ambiguous because of multiple glob imports of a name in the same module
10+
note: `S` could refer to the struct imported here
11+
--> $DIR/overwrite-different-ambig-2.rs:18:5
12+
|
13+
LL | use m1::*;
14+
| ^^^^^
15+
= help: consider adding an explicit import of `S` to disambiguate
16+
note: `S` could also refer to the struct imported here
17+
--> $DIR/overwrite-different-ambig-2.rs:19:5
18+
|
19+
LL | use m2::*;
20+
| ^^^^^
21+
= help: consider adding an explicit import of `S` to disambiguate
22+
= note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
23+
24+
error: aborting due to 1 previous error
25+
26+
Future incompatibility report: Future breakage diagnostic:
27+
error: `S` is ambiguous
28+
--> $DIR/overwrite-different-ambig-2.rs:22:20
29+
|
30+
LL | let _: m1::S = S {};
31+
| ^ ambiguous name
32+
|
33+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
34+
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
35+
= note: ambiguous because of multiple glob imports of a name in the same module
36+
note: `S` could refer to the struct imported here
37+
--> $DIR/overwrite-different-ambig-2.rs:18:5
38+
|
39+
LL | use m1::*;
40+
| ^^^^^
41+
= help: consider adding an explicit import of `S` to disambiguate
42+
note: `S` could also refer to the struct imported here
43+
--> $DIR/overwrite-different-ambig-2.rs:19:5
44+
|
45+
LL | use m2::*;
46+
| ^^^^^
47+
= help: consider adding an explicit import of `S` to disambiguate
48+
= note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
49+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ check-pass
2+
//@ edition:2024
3+
4+
mod a {
5+
mod b {
6+
mod c {
7+
pub struct E;
8+
}
9+
mod d {
10+
mod c {
11+
pub struct E;
12+
}
13+
mod d {
14+
#[derive(Debug)]
15+
pub struct E;
16+
}
17+
pub use c::*;
18+
use d::*;
19+
}
20+
use c::*;
21+
use d::*;
22+
}
23+
}
24+
25+
fn main() {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ check-pass
2+
3+
mod b {
4+
pub mod http {
5+
pub struct HeaderMap;
6+
}
7+
8+
pub(crate) use self::http::*;
9+
#[derive(Debug)]
10+
pub struct HeaderMap;
11+
}
12+
13+
mod a {
14+
pub use crate::b::*;
15+
16+
fn check_type() {
17+
let _: HeaderMap = crate::b::HeaderMap;
18+
}
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)