Skip to content

#[test] visibility changes can produce conflicts and type errors with glob use. #52557

Description

@djrenren

Because #[test] marks tests as public so that they can be reexported (avoiding E0364), they can cause namespace pollutions that only occur in test builds.

Minimal repro:

mod A {
    #[test]
    fn foo() {}
}

mod B {
    pub fn foo() -> bool {
        true
    }
}

use B::foo;
use A::*;

fn conflict() {
    let x: bool = foo();
}

In a normal build, the only foo in scope is B::foo, but in a test build A::foo will shadow it. And produce the following error:

error[E0308]: mismatched types
  --> ./test.rs:20:19
   |
20 |     let x: bool = foo();
   |                   ^^^^^ expected bool, found ()
   |
   = note: expected type `bool`
              found type `()`

Activity

  1. djrenren commented on Jul 20, 2018

    @djrenren
    ContributorAuthor

    I propose that instead of expanding:

    #[test]
    fn foo() {}

    to:

    pub fn foo(){}
    pub mod __test_reexports {
       pub use super::foo;
    }

    we expand to:

    pub mod __test_reexports {
        use super::*;
        pub fn foo() {...}
    }

    This is a breaking change but only for the semi-pathological case where you have test functions referencing each other. It also brings test into line with standard builds in that #[test] are not referenceable. (in debug/release due to removal, and in test due to a gensymed module).

  2. added
    T-dev-toolsRelevant to the dev-tools subteam, which will review and decide on the PR/issue.
    A-libtestArea: `#[test]` / the `test` library
    on Jul 20, 2018
  3. nrc commented on Jul 20, 2018

    @nrc
    Member

    the semi-pathological case where you have test functions referencing each other

    I bet that's not uncommon enough to make a breaking change. However, I would expect test functions that reference each other to do so via relative paths, and this would only be breaking if absolute paths were used (iiuc). In any case we should probably just fix this and do a Crater run.

  4. nrc commented on Jul 20, 2018

    @nrc
    Member

    cc @petrochenkov and @rust-lang/compiler

    We might be able to hack something in name resolution? Perhaps glob imports don't treat test functions as public? Or we give them some weird hygiene marker or something?

  5. djrenren commented on Jul 20, 2018

    @djrenren
    ContributorAuthor

    Actually if we did:

    use __test_reexports::*;
    
    pub mod __test_reexports {
        use super::*;
        pub fn foo() {...}
    }

    I think we'd be compatible and safe

  6. djrenren commented on Jul 20, 2018

    @djrenren
    ContributorAuthor

    Well, technically we should use or pub use each test in accordance with its visibility

  7. eddyb commented on Aug 1, 2018

    @eddyb
    Contributor

    I much better prefer rust-lang/rfcs#2471 (comment) as a solution to all our testing woes. I'll maybe try to prototype it soon.

  8. added a commit that references this issue on Aug 2, 2018
  9. djrenren commented on Aug 2, 2018

    @djrenren
    ContributorAuthor

    Fixed by #52890

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-libtestArea: `#[test]` / the `test` libraryT-dev-toolsRelevant to the dev-tools subteam, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions