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

An impl on Vec<T> for trait T causes Vec::from_slice to disappear #15060

Closed
apoelstra opened this issue Jun 20, 2014 · 7 comments · Fixed by #17321
Closed

An impl on Vec<T> for trait T causes Vec::from_slice to disappear #15060

apoelstra opened this issue Jun 20, 2014 · 7 comments · Fixed by #17321
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically

Comments

@apoelstra
Copy link
Contributor

The code

trait T {}
impl<U: T> Vec<U> {}
fn main() { let r = Vec::from_slice(&[1u]); }

fails with

break.rs:4:21: 4:36 error: unresolved name `Vec::from_slice`.
break.rs:4 fn main() { let r = Vec::from_slice(&[1u]); }

Removing the impl line causes the code to compile fine.

Thx Ms2ger for finding such a small example case.

@Ryman
Copy link
Contributor

Ryman commented Jun 20, 2014

I think this is related to anonymous modules appearing, Vec resolves to a module due to the impl.

If you change to this you get another interesting error:

trait T {}
impl<U: T> Vec<U> {
    fn from_slice<'a>(x: &'a [uint]) -> Vec<uint> {
        fail!()
    }
}
fn main() { let r = Vec::from_slice(&[1u]); }
error: found module name used as a type: impl Vec<U>::Vec<U> (id=5)
impl<U: T> Vec<U> {

@apoelstra
Copy link
Contributor Author

Note that a workaround is to wrap Vec<U> in parens, as

trait T {}
impl<U: T> (Vec<U>) {}
fn main() { let r = Vec::from_slice(&[1u]); }

Then you get the correct error message about trying to impl on a type outside of its crate.

@apoelstra
Copy link
Contributor Author

I've spent some time investigating this bug and I think that the cleanest thing to do is to fix #3785 (closed B-RFC right now, does anyone have a link to a relevant RFC?) and require impl Type to occur only in the same module as, and after, the definition of Type. This check would be done before creating the anonymous trait module with name Type.

Otherwise in the case of impl Type where a definition of Type is not visible, Type is not resolved until typeck (at which point the compiler will complain if Type is defined outside the current crate, or not at all), but if there are resolve errors like the current bug, these will be exposed to the user first and halt compilation.

The current behaviour upon encountering impl Type where Type has not been defined in the current module is to create a module Type (which shadows any other Type modules exposed by use statements) and try to resolve any Type::function symbols into this module. This means that the current support for impl Type outside of the module Type is defined in is already broken. Consider for example

break.rs:

use break1::MyGuy;

mod break1;

impl MyGuy {
  fn do2() { println!("do 2"); }
}

fn main() {
  MyGuy::do1();
  MyGuy::do2();
}

break1.rs:

pub struct MyGuy;

impl MyGuy {
  pub fn do1() { println!("do 1"); }
}

break.rs will error out with "unresolved name MyGuy::do1".

I'm sure I could come up with other examples of currently broken behaviour like this.

@pnkfelix
Copy link
Member

pnkfelix commented Jul 4, 2014

@apoelstra the closing of that bug predates our RFC process, so there would not be a link to an RFC.

@huonw
Copy link
Member

huonw commented Jul 4, 2014

Interestingly, this breaks in the opposite direction if you qualify the impl: http://is.gd/p8GatW

mod break1 {
    pub struct MyGuy;

    impl MyGuy {
        pub fn do1() { println!("do 1"); }
    }
}

impl break1::MyGuy {
    fn do2() { println!("do 2"); }
}

fn main() {
    break1::MyGuy::do1();
    break1::MyGuy::do2();
}
<anon>:15:5: 15:23 error: unresolved name `break1::MyGuy::do2`.
<anon>:15     break1::MyGuy::do2();
              ^~~~~~~~~~~~~~~~~~

@apoelstra
Copy link
Contributor Author

My suggestion is that impl break1::MyGuy should be disallowed. I will submit an RFC with these changes.

@apoelstra
Copy link
Contributor Author

rust-lang/rfcs#155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name/path resolution done by `rustc_resolve` specifically
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants