item_like_imports: Can "ambiguity error" items be reexported?

c7b770c
Opened by Vadim Petrochenkov at 2024-08-21 15:03:05

Is the next code well formed or not?

#![feature(item_like_imports)]

mod ty1 {
    pub type A = u8;
}
mod ty2 {
    pub type A = u8;
}
mod ambig {
    // Create an ambiguity item in type namespace.
    pub use ty1::*;
    pub use ty2::*;
}
mod merge {
    pub use ambig::*; // <- reexports an ambiguity error, or reexports nothing?
    pub use ty1::*; // <- does this contribute to the ambiguity error or create a valid name?
}

fn main() {
    let _: merge::A; // <- Valid or an ambiguity error?
}

Currently the behavior of this code depends on whether the "merge" step is done in the same crate or in some other crate. In a single crate scenario the snippet above fails to compile with A is ambiguous error. If merge is moved to another crate, then all erroneous resolutions are filtered away and are not represented in metadata, pub use ambig::* becomes an empty import and merge::A unambiguously means ty1::A. Supposedly, local and cross-crate behavior should be the same.

cc @jseyfried @nrc

  1. My opinion so far is that reexported Def::Errs (ambiguity and others) should never affect resolution results, but may affect diagnostics and give better error messages, i.e. the code above is valid.

    Vadim Petrochenkov at 2016-09-29 21:02:37

  2. I agree that ideally your example would be valid, but I don't think that's possible to implement, at least not without introducing a lot of ambiguous imports ("deadlocking") in code that compiles today.

    For example, if we resolve pub use ty2::*; first and resolve pub use ambig::*; next, then the resolution of A in merge is determined to be ty2::A, so it could be re-exported in other places or used in other imports' module paths (if it were a module instead of a type alias).

    If we couldn't assume that the resolution of A in merge was ty2::A in the above case, I don't think we'd be able to make enough progress to support a lot of existing code.

    Jeffrey Seyfried at 2016-09-29 21:24:13

  3. More specifically, if we wanted to support that example then we wouldn't be able to glob-import a name unless we knew that the name would never become ambiguous in the glob-imported module.

    Thus, we wouldn't be able to support the following, which compiles today:

    mod foo {
        pub mod quux {}
    }
    mod bar {
        pub use foo::*;
        pub use baz::quux::*; // We need to resolve this to deduce that `bar::quux` isn't ambiguous,
    }
    mod baz {
        pub use bar::*; // but that requires importing `quux` here, which we wouldn't be able to do until we have deduced that `quux` isn't ambiguous.
    }
    

    Jeffrey Seyfried at 2016-09-29 21:51:05

  4. Cross-crate encoding for reexported ambiguities was implemented in https://github.com/rust-lang/rust/pull/114682 but not merged.

    Issue "Tracking Issue for ambiguous_glob_imports lint" is also relevant here because cross-crate reexports for ambiguities that are usable for backward compatibility are a part of that warning.

    Vadim Petrochenkov at 2024-08-21 15:03:05