Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unnecessary trait accessibility check. #28504

Merged
merged 2 commits into from Sep 23, 2015
Merged

Remove unnecessary trait accessibility check. #28504

merged 2 commits into from Sep 23, 2015

Conversation

ghost
Copy link

@ghost ghost commented Sep 19, 2015

Fixes #16264 / #18241.

As far as I can tell, it should be impossible for a trait to be inaccessible if it's in scope, so this check is unnecessary. Are there any cases where this check is actually needed?

@rust-highfive
Copy link
Collaborator

r? @brson

(rust_highfive has picked a reviewer for you, use r? to override)

@bluss
Copy link
Member

bluss commented Sep 19, 2015

Not sure what the behavior should be if the trait has a private supertrait.

@ghost
Copy link
Author

ghost commented Sep 19, 2015

I don't think this affects anything in that regard. It's already possible to reexport traits that depend on private supertraits anyway, e.g.:

pub use inner::Bar;

mod inner {
    trait Foo {
        fn foo(&self) { println!("foo"); }
    }
    pub trait Bar: Foo {
        fn bar(&self) { println!("bar"); }
    }
    impl Foo for i32 {}
    impl Bar for i32 {}
}

fn main() {
    //0i32.foo(); // Can't call this
    0i32.bar();
}

Playpen

@bluss
Copy link
Member

bluss commented Sep 19, 2015

Ok, I thought you could call .foo() if you remove the accessibility check.

By the way, you can call foo through Bar::foo.

@ghost
Copy link
Author

ghost commented Sep 19, 2015

Don't you think you can call .foo() if you remove the accessibility check?

Nope, still gives the same error as on playpen:

test.rs:15:10: 15:15 error: no method named `foo` found for type `i32` in the current scope
test.rs:15     0i32.foo();
                    ^~~~~
test.rs:15:10: 15:15 help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
test.rs:15:10: 15:15 help: candidate #1: use `inner::Foo`
error: aborting due to previous error

By the way, you can call foo through Bar::foo.

This also still works.

@bluss
Copy link
Member

bluss commented Sep 19, 2015

Ok, I'll report separate bugs for the Bar::foo problem.

@alexcrichton
Copy link
Member

It's been awhile since I've poked around the privacy-related code, but this looks good to me. To me it makes sense that the method call will only be resolved if the trait is already in scope, and because the import of the trait already had the privacy check run on it and verified then we don't have private trait methods so this is fine to let through.

That being said I'd like a second set of eyes on this, so:

r? @nrc

@rust-highfive rust-highfive assigned nrc and unassigned brson Sep 21, 2015
@nrc
Copy link
Member

nrc commented Sep 21, 2015

Does this still give an error?

mod foo {
    trait Bar {
        fn baz() {}
    }

    impl Bar for i32 {}
}

fn main() {
    <i32 as ::foo::Bar>::baz(); //~ERROR method `baz` is inaccessible
}

I assume that at the least the error message changes (to something about no impl for i32 in scope). Could you add a c-fail test (with some explanation) for this please?

@ghost
Copy link
Author

ghost commented Sep 22, 2015

Added a cfail test. The error is exactly the same as on latest stable/beta/nightly:

privacy-ufcs.rs:22:13: 22:29 error: method `baz` is inaccessible
privacy-ufcs.rs:22     <i32 as ::foo::Bar>::baz(); //~ERROR method `baz` is inaccessible
                               ^~~~~~~~~~~~~~~~
privacy-ufcs.rs:22:13: 22:29 note: trait `Bar` is private
privacy-ufcs.rs:22     <i32 as ::foo::Bar>::baz(); //~ERROR method `baz` is inaccessible
                               ^~~~~~~~~~~~~~~~
error: aborting due to previous error

@nrc
Copy link
Member

nrc commented Sep 22, 2015

@bors: r+

@bors
Copy link
Contributor

bors commented Sep 22, 2015

📌 Commit b3e1aca has been approved by nrc

bors added a commit that referenced this pull request Sep 22, 2015
Fixes #16264 / #18241.

As far as I can tell, it should be impossible for a trait to be inaccessible if it's in scope, so this check is unnecessary. Are there any cases where this check is actually needed?
@bors
Copy link
Contributor

bors commented Sep 22, 2015

⌛ Testing commit b3e1aca with merge ad82e0a...

@bors bors merged commit b3e1aca into rust-lang:master Sep 23, 2015
@ghost ghost deleted the fix-trait-privacy branch September 23, 2015 07:38
@petrochenkov
Copy link
Contributor

Hmm, there's a regression in current nightly (it may be intentional though):

mod m {
    trait Priv {
        fn f(&self) {}
    }
    impl Priv for super::S {}
    pub trait Pub: Priv {}
}

struct S;
impl m::Pub for S {}

fn g<T: m::Pub>(arg: T) {
    arg.f();
}

fn main() {
    // Compiles on nightly, reports error "source trait is private" on stable and beta
    g(S);
}

I guess it was caused by this patch?
cc @alexcrichton

@bluss
Copy link
Member

bluss commented Oct 23, 2015

@petrochenkov That behavior is nownot correct according to the discussion in #28514

@bluss
Copy link
Member

bluss commented Oct 23, 2015

Since all regressions should be tracked, do we need an issue for that? cc @brson

@alexcrichton
Copy link
Member

Thanks for the sharp eyes @petrochenkov! I've opened a PR to revert: #29325

bors added a commit that referenced this pull request Oct 27, 2015
These commits revert #28504 and add a regression test pointed out by @petrochenkov, it's not immediately clear with the regression that the accessibility check should be removed, so for now preserve the behavior on stable by default.

r? @nrc
bors added a commit that referenced this pull request Mar 6, 2016
…tsakis

This PR allows using methods from traits that are visible but are defined in an inaccessible module (fixes #18241). For example,
```rust
mod foo {
    pub use foo::bar::Tr;
    mod bar { // This module is inaccessible from `g`
        pub trait Tr { fn f(&self) {} }
    }
}
fn g<T: foo::Tr>(t: T) {
    t.f(); // Currently, this is a privacy error even though `foo::Tr` is visible
}
```

After this PR, it will continue to be a privacy error to use a method from a trait that is not visible. This can happen when a public trait inherits from a private trait (in violation of the `public_in_private` lint) -- see @petrochenkov's example in #28504.
r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants