Skip to content

Commit b9478ee

Browse files
committed
auto merge of #17321 : apoelstra/rust/error-on-unknown-impl, r=alexcrichton
Followup to RFC 57. Fixes #7607 Fixes #8767 Fixes #12729 Fixes #15060
2 parents 496b68d + bb58079 commit b9478ee

File tree

6 files changed

+163
-12
lines changed

6 files changed

+163
-12
lines changed

src/librustc/middle/resolve.rs

+71-10
Original file line numberDiff line numberDiff line change
@@ -2945,16 +2945,53 @@ impl<'a> Resolver<'a> {
29452945
match *name_bindings.type_def.borrow() {
29462946
None => {}
29472947
Some(ref ty) => {
2948-
let msg = format!("import `{}` conflicts with type in \
2949-
this module",
2950-
token::get_name(name).get());
2951-
self.session.span_err(import_span, msg.as_slice());
2952-
match ty.type_span {
2953-
None => {}
2954-
Some(span) => {
2955-
self.session
2956-
.span_note(span,
2957-
"conflicting type here")
2948+
match ty.module_def {
2949+
None => {
2950+
let msg = format!("import `{}` conflicts with type in \
2951+
this module",
2952+
token::get_name(name).get());
2953+
self.session.span_err(import_span, msg.as_slice());
2954+
match ty.type_span {
2955+
None => {}
2956+
Some(span) => {
2957+
self.session
2958+
.span_note(span,
2959+
"note conflicting type here")
2960+
}
2961+
}
2962+
}
2963+
Some(ref module_def) => {
2964+
match module_def.kind.get() {
2965+
ImplModuleKind => {
2966+
match ty.type_span {
2967+
None => { /* this can't ever happen */ }
2968+
Some(span) => {
2969+
let msg = format!("inherent implementations \
2970+
are only allowed on types \
2971+
defined in the current module");
2972+
self.session
2973+
.span_err(span, msg.as_slice());
2974+
self.session
2975+
.span_note(import_span,
2976+
"import from other module here")
2977+
}
2978+
}
2979+
}
2980+
_ => {
2981+
let msg = format!("import `{}` conflicts with existing \
2982+
submodule",
2983+
token::get_name(name).get());
2984+
self.session.span_err(import_span, msg.as_slice());
2985+
match ty.type_span {
2986+
None => {}
2987+
Some(span) => {
2988+
self.session
2989+
.span_note(span,
2990+
"note conflicting module here")
2991+
}
2992+
}
2993+
}
2994+
}
29582995
}
29592996
}
29602997
}
@@ -4610,6 +4647,30 @@ impl<'a> Resolver<'a> {
46104647
});
46114648
});
46124649
});
4650+
4651+
// Check that the current type is indeed a type, if we have an anonymous impl
4652+
if opt_trait_reference.is_none() {
4653+
match self_type.node {
4654+
// TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
4655+
// where we created a module with the name of the type in order to implement
4656+
// an anonymous trait. In the case that the path does not resolve to an actual
4657+
// type, the result will be that the type name resolves to a module but not
4658+
// a type (shadowing any imported modules or types with this name), leading
4659+
// to weird user-visible bugs. So we ward this off here. See #15060.
4660+
TyPath(ref path, _, path_id) => {
4661+
match self.def_map.borrow().find(&path_id) {
4662+
// FIXME: should we catch other options and give more precise errors?
4663+
Some(&DefMod(_)) => {
4664+
self.resolve_error(path.span, "inherent implementations are not \
4665+
allowed for types not defined in \
4666+
the current module.");
4667+
}
4668+
_ => {}
4669+
}
4670+
}
4671+
_ => { }
4672+
}
4673+
}
46134674
}
46144675

46154676
fn check_trait_item(&self, ident: Ident, span: Span) {

src/test/compile-fail/issue-12729.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
pub struct Foo;
14+
15+
mod bar {
16+
use Foo;
17+
18+
impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
19+
fn baz(&self) {}
20+
}
21+
}
22+
fn main() {}
23+

src/test/compile-fail/issue-7607-1.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
struct Foo {
14+
x: int
15+
}
16+
17+
impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module.
18+
fn foo() {}
19+
}
20+
21+
fn main() {}
22+

src/test/compile-fail/issue-7607-2.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
pub mod a {
14+
pub struct Foo { a: uint }
15+
}
16+
17+
pub mod b {
18+
use a::Foo;
19+
impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
20+
fn bar(&self) { }
21+
}
22+
}
23+
24+
pub fn main() { }
25+
26+

src/test/compile-fail/issue-8767.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module.
14+
}
15+
16+
fn main() {
17+
}
18+

src/test/compile-fail/trait-or-new-type-instead.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// FIXME(#8767) bad error message; Option is not a module
12-
impl<T> Option<T> { //~ERROR found module name used as a type
11+
// ignore-tidy-linelength
12+
13+
impl<T> Option<T> { //~ERROR inherent implementations are not allowed for types not defined in the current module.
1314
pub fn foo(&self) { }
1415
}
1516

0 commit comments

Comments
 (0)