Skip to content

Commit

Permalink
auto merge of #17321 : apoelstra/rust/error-on-unknown-impl, r=alexcr…
Browse files Browse the repository at this point in the history
…ichton

Followup to RFC 57.

Fixes #7607
Fixes #8767
Fixes #12729
Fixes #15060
  • Loading branch information
bors committed Sep 29, 2014
2 parents 496b68d + bb58079 commit b9478ee
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 12 deletions.
81 changes: 71 additions & 10 deletions src/librustc/middle/resolve.rs
Expand Up @@ -2945,16 +2945,53 @@ impl<'a> Resolver<'a> {
match *name_bindings.type_def.borrow() {
None => {}
Some(ref ty) => {
let msg = format!("import `{}` conflicts with type in \
this module",
token::get_name(name).get());
self.session.span_err(import_span, msg.as_slice());
match ty.type_span {
None => {}
Some(span) => {
self.session
.span_note(span,
"conflicting type here")
match ty.module_def {
None => {
let msg = format!("import `{}` conflicts with type in \
this module",
token::get_name(name).get());
self.session.span_err(import_span, msg.as_slice());
match ty.type_span {
None => {}
Some(span) => {
self.session
.span_note(span,
"note conflicting type here")
}
}
}
Some(ref module_def) => {
match module_def.kind.get() {
ImplModuleKind => {
match ty.type_span {
None => { /* this can't ever happen */ }
Some(span) => {
let msg = format!("inherent implementations \
are only allowed on types \
defined in the current module");
self.session
.span_err(span, msg.as_slice());
self.session
.span_note(import_span,
"import from other module here")
}
}
}
_ => {
let msg = format!("import `{}` conflicts with existing \
submodule",
token::get_name(name).get());
self.session.span_err(import_span, msg.as_slice());
match ty.type_span {
None => {}
Some(span) => {
self.session
.span_note(span,
"note conflicting module here")
}
}
}
}
}
}
}
Expand Down Expand Up @@ -4610,6 +4647,30 @@ impl<'a> Resolver<'a> {
});
});
});

// Check that the current type is indeed a type, if we have an anonymous impl
if opt_trait_reference.is_none() {
match self_type.node {
// TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
// where we created a module with the name of the type in order to implement
// an anonymous trait. In the case that the path does not resolve to an actual
// type, the result will be that the type name resolves to a module but not
// a type (shadowing any imported modules or types with this name), leading
// to weird user-visible bugs. So we ward this off here. See #15060.
TyPath(ref path, _, path_id) => {
match self.def_map.borrow().find(&path_id) {
// FIXME: should we catch other options and give more precise errors?
Some(&DefMod(_)) => {
self.resolve_error(path.span, "inherent implementations are not \
allowed for types not defined in \
the current module.");
}
_ => {}
}
}
_ => { }
}
}
}

fn check_trait_item(&self, ident: Ident, span: Span) {
Expand Down
23 changes: 23 additions & 0 deletions src/test/compile-fail/issue-12729.rs
@@ -0,0 +1,23 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

pub struct Foo;

mod bar {
use Foo;

impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
fn baz(&self) {}
}
}
fn main() {}

22 changes: 22 additions & 0 deletions src/test/compile-fail/issue-7607-1.rs
@@ -0,0 +1,22 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

struct Foo {
x: int
}

impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module.
fn foo() {}
}

fn main() {}

26 changes: 26 additions & 0 deletions src/test/compile-fail/issue-7607-2.rs
@@ -0,0 +1,26 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

pub mod a {
pub struct Foo { a: uint }
}

pub mod b {
use a::Foo;
impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
fn bar(&self) { }
}
}

pub fn main() { }


18 changes: 18 additions & 0 deletions src/test/compile-fail/issue-8767.rs
@@ -0,0 +1,18 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module.
}

fn main() {
}

5 changes: 3 additions & 2 deletions src/test/compile-fail/trait-or-new-type-instead.rs
Expand Up @@ -8,8 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// FIXME(#8767) bad error message; Option is not a module
impl<T> Option<T> { //~ERROR found module name used as a type
// ignore-tidy-linelength

impl<T> Option<T> { //~ERROR inherent implementations are not allowed for types not defined in the current module.
pub fn foo(&self) { }
}

Expand Down

0 comments on commit b9478ee

Please sign in to comment.