Rollup merge of #150939 - impasse, r=estebank
resolve: Relax some asserts in glob overwriting and add tests Fixes https://github.com/rust-lang/rust/issues/150927. Fixes https://github.com/rust-lang/rust/issues/150928. Fixes https://github.com/rust-lang/rust/issues/150929. Fixes https://github.com/rust-lang/rust/issues/150976. Fixes https://github.com/rust-lang/rust/issues/150977. Fixes https://github.com/rust-lang/rust/issues/151008. Fixes https://github.com/rust-lang/rust/issues/151037. Fixes https://github.com/rust-lang/rust-clippy/issues/16398. r? @yaahc
This commit is contained in:
commit
6cdcef5454
11 changed files with 202 additions and 15 deletions
|
|
@ -212,12 +212,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
&mut self,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
new_binding: Decl<'ra>,
|
||||
old_binding: Decl<'ra>,
|
||||
new_binding: Decl<'ra>,
|
||||
) {
|
||||
// Error on the second of two conflicting names
|
||||
if old_binding.span.lo() > new_binding.span.lo() {
|
||||
return self.report_conflict(ident, ns, old_binding, new_binding);
|
||||
return self.report_conflict(ident, ns, new_binding, old_binding);
|
||||
}
|
||||
|
||||
let container = match old_binding.parent_module.unwrap().kind {
|
||||
|
|
|
|||
|
|
@ -300,13 +300,16 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra
|
|||
if let DeclKind::Import { import: import1, source_decl: d1_next } = d1.kind
|
||||
&& let DeclKind::Import { import: import2, source_decl: d2_next } = d2.kind
|
||||
&& import1 == import2
|
||||
&& d1.warn_ambiguity.get() == d2.warn_ambiguity.get()
|
||||
{
|
||||
assert_eq!(d1.ambiguity.get(), d2.ambiguity.get());
|
||||
assert!(!d1.warn_ambiguity.get());
|
||||
assert_eq!(d1.expansion, d2.expansion);
|
||||
assert_eq!(d1.span, d2.span);
|
||||
assert_eq!(d1.vis(), d2.vis());
|
||||
if d1.ambiguity.get() != d2.ambiguity.get() {
|
||||
assert!(d1.ambiguity.get().is_some());
|
||||
assert!(d2.ambiguity.get().is_none());
|
||||
}
|
||||
// Visibility of the new import declaration may be different,
|
||||
// because it already incorporates the visibility of the source binding.
|
||||
// `warn_ambiguity` of a re-fetched glob can also change in both directions.
|
||||
remove_same_import(d1_next, d2_next)
|
||||
} else {
|
||||
(d1, d2)
|
||||
|
|
@ -348,8 +351,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
/// decide which one to keep.
|
||||
fn select_glob_decl(
|
||||
&self,
|
||||
glob_decl: Decl<'ra>,
|
||||
old_glob_decl: Decl<'ra>,
|
||||
glob_decl: Decl<'ra>,
|
||||
warn_ambiguity: bool,
|
||||
) -> Decl<'ra> {
|
||||
assert!(glob_decl.is_glob_import());
|
||||
|
|
@ -369,7 +372,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// with the re-fetched decls.
|
||||
// This is probably incorrect in corner cases, and the outdated decls still get
|
||||
// propagated to other places and get stuck there, but that's what we have at the moment.
|
||||
let (deep_decl, old_deep_decl) = remove_same_import(glob_decl, old_glob_decl);
|
||||
let (old_deep_decl, deep_decl) = remove_same_import(old_glob_decl, glob_decl);
|
||||
if deep_decl != glob_decl {
|
||||
// Some import layers have been removed, need to overwrite.
|
||||
assert_ne!(old_deep_decl, old_glob_decl);
|
||||
|
|
@ -377,6 +380,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// assert_ne!(old_deep_decl, deep_decl);
|
||||
// assert!(old_deep_decl.is_glob_import());
|
||||
assert!(!deep_decl.is_glob_import());
|
||||
if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {
|
||||
// Do not lose glob ambiguities when re-fetching the glob.
|
||||
glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());
|
||||
}
|
||||
if glob_decl.is_ambiguity_recursive() {
|
||||
glob_decl.warn_ambiguity.set_unchecked(true);
|
||||
}
|
||||
|
|
@ -436,7 +443,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
match (old_decl.is_glob_import(), decl.is_glob_import()) {
|
||||
(true, true) => {
|
||||
resolution.glob_decl =
|
||||
Some(this.select_glob_decl(decl, old_decl, warn_ambiguity));
|
||||
Some(this.select_glob_decl(old_decl, decl, warn_ambiguity));
|
||||
}
|
||||
(old_glob @ true, false) | (old_glob @ false, true) => {
|
||||
let (glob_decl, non_glob_decl) =
|
||||
|
|
@ -446,7 +453,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
&& old_glob_decl != glob_decl
|
||||
{
|
||||
resolution.glob_decl =
|
||||
Some(this.select_glob_decl(glob_decl, old_glob_decl, false));
|
||||
Some(this.select_glob_decl(old_glob_decl, glob_decl, false));
|
||||
} else {
|
||||
resolution.glob_decl = Some(glob_decl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ extern crate use_by_macro;
|
|||
use use_by_macro::*;
|
||||
|
||||
my_struct!(define);
|
||||
//~^ ERROR the name `MyStruct` is defined multiple times
|
||||
my_struct!(define);
|
||||
//~^ ERROR the name `MyStruct` is defined multiple times
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
error[E0428]: the name `MyStruct` is defined multiple times
|
||||
--> $DIR/cross-crate-redefine.rs:10:1
|
||||
--> $DIR/cross-crate-redefine.rs:11:1
|
||||
|
|
||||
LL | my_struct!(define);
|
||||
| ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here
|
||||
LL |
|
||||
LL | my_struct!(define);
|
||||
| ------------------ previous definition of the type `MyStruct` here
|
||||
LL | my_struct!(define);
|
||||
| ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here
|
||||
|
|
||||
= note: `MyStruct` must be defined only once in the type namespace of this module
|
||||
= note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
|||
22
tests/ui/imports/overwrite-deep-glob.rs
Normal file
22
tests/ui/imports/overwrite-deep-glob.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@ check-pass
|
||||
|
||||
mod openssl {
|
||||
pub use self::handwritten::*;
|
||||
|
||||
mod handwritten {
|
||||
mod m1 {
|
||||
pub struct S {}
|
||||
}
|
||||
mod m2 {
|
||||
#[derive(Default)]
|
||||
pub struct S {}
|
||||
}
|
||||
|
||||
pub use self::m1::*; //~ WARN ambiguous glob re-exports
|
||||
pub use self::m2::*;
|
||||
}
|
||||
}
|
||||
|
||||
pub use openssl::*;
|
||||
|
||||
fn main() {}
|
||||
12
tests/ui/imports/overwrite-deep-glob.stderr
Normal file
12
tests/ui/imports/overwrite-deep-glob.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
warning: ambiguous glob re-exports
|
||||
--> $DIR/overwrite-deep-glob.rs:15:17
|
||||
|
|
||||
LL | pub use self::m1::*;
|
||||
| ^^^^^^^^^^^ the name `S` in the type namespace is first re-exported here
|
||||
LL | pub use self::m2::*;
|
||||
| ----------- but the name `S` in the type namespace is also re-exported here
|
||||
|
|
||||
= note: `#[warn(ambiguous_glob_reexports)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
24
tests/ui/imports/overwrite-different-ambig-2.rs
Normal file
24
tests/ui/imports/overwrite-different-ambig-2.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
mod m1 {
|
||||
mod inner {
|
||||
pub struct S {}
|
||||
}
|
||||
pub use self::inner::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct S {}
|
||||
}
|
||||
|
||||
mod m2 {
|
||||
pub struct S {}
|
||||
}
|
||||
|
||||
// First we have a glob ambiguity in this glob (with `m2::*`).
|
||||
// Then we re-fetch `m1::*` because non-glob `m1::S` materializes from derive,
|
||||
// and we need to make sure that the glob ambiguity is not lost during re-fetching.
|
||||
use m1::*;
|
||||
use m2::*;
|
||||
|
||||
fn main() {
|
||||
let _: m1::S = S {}; //~ ERROR `S` is ambiguous
|
||||
//~| WARN this was previously accepted
|
||||
}
|
||||
49
tests/ui/imports/overwrite-different-ambig-2.stderr
Normal file
49
tests/ui/imports/overwrite-different-ambig-2.stderr
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
error: `S` is ambiguous
|
||||
--> $DIR/overwrite-different-ambig-2.rs:22:20
|
||||
|
|
||||
LL | let _: m1::S = S {};
|
||||
| ^ ambiguous name
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
|
||||
= note: ambiguous because of multiple glob imports of a name in the same module
|
||||
note: `S` could refer to the struct imported here
|
||||
--> $DIR/overwrite-different-ambig-2.rs:18:5
|
||||
|
|
||||
LL | use m1::*;
|
||||
| ^^^^^
|
||||
= help: consider adding an explicit import of `S` to disambiguate
|
||||
note: `S` could also refer to the struct imported here
|
||||
--> $DIR/overwrite-different-ambig-2.rs:19:5
|
||||
|
|
||||
LL | use m2::*;
|
||||
| ^^^^^
|
||||
= help: consider adding an explicit import of `S` to disambiguate
|
||||
= note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: `S` is ambiguous
|
||||
--> $DIR/overwrite-different-ambig-2.rs:22:20
|
||||
|
|
||||
LL | let _: m1::S = S {};
|
||||
| ^ ambiguous name
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
|
||||
= note: ambiguous because of multiple glob imports of a name in the same module
|
||||
note: `S` could refer to the struct imported here
|
||||
--> $DIR/overwrite-different-ambig-2.rs:18:5
|
||||
|
|
||||
LL | use m1::*;
|
||||
| ^^^^^
|
||||
= help: consider adding an explicit import of `S` to disambiguate
|
||||
note: `S` could also refer to the struct imported here
|
||||
--> $DIR/overwrite-different-ambig-2.rs:19:5
|
||||
|
|
||||
LL | use m2::*;
|
||||
| ^^^^^
|
||||
= help: consider adding an explicit import of `S` to disambiguate
|
||||
= note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default
|
||||
|
||||
25
tests/ui/imports/overwrite-different-ambig.rs
Normal file
25
tests/ui/imports/overwrite-different-ambig.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//@ check-pass
|
||||
//@ edition:2024
|
||||
|
||||
mod a {
|
||||
mod b {
|
||||
mod c {
|
||||
pub struct E;
|
||||
}
|
||||
mod d {
|
||||
mod c {
|
||||
pub struct E;
|
||||
}
|
||||
mod d {
|
||||
#[derive(Debug)]
|
||||
pub struct E;
|
||||
}
|
||||
pub use c::*;
|
||||
use d::*;
|
||||
}
|
||||
use c::*;
|
||||
use d::*;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
21
tests/ui/imports/overwrite-different-vis.rs
Normal file
21
tests/ui/imports/overwrite-different-vis.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//@ check-pass
|
||||
|
||||
mod b {
|
||||
pub mod http {
|
||||
pub struct HeaderMap;
|
||||
}
|
||||
|
||||
pub(crate) use self::http::*;
|
||||
#[derive(Debug)]
|
||||
pub struct HeaderMap;
|
||||
}
|
||||
|
||||
mod a {
|
||||
pub use crate::b::*;
|
||||
|
||||
fn check_type() {
|
||||
let _: HeaderMap = crate::b::HeaderMap;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
28
tests/ui/imports/overwrite-different-warn-ambiguity.rs
Normal file
28
tests/ui/imports/overwrite-different-warn-ambiguity.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//@ check-pass
|
||||
//@ edition:2024
|
||||
|
||||
mod framing {
|
||||
mod public_message_in {
|
||||
mod public_message {
|
||||
mod public_message {
|
||||
pub struct ConfirmedTranscriptHashInput;
|
||||
}
|
||||
mod public_message_in {
|
||||
use super::*;
|
||||
#[derive(Debug)]
|
||||
pub struct ConfirmedTranscriptHashInput;
|
||||
}
|
||||
pub use public_message::*;
|
||||
use public_message_in::*;
|
||||
}
|
||||
mod public_message_in {
|
||||
#[derive(Debug)]
|
||||
pub struct ConfirmedTranscriptHashInput;
|
||||
}
|
||||
pub use public_message::*;
|
||||
use public_message_in::*;
|
||||
}
|
||||
use public_message_in::*;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue