Skip to content

Commit f9bdf34

Browse files
committed
Resolve Self in impl headers
1 parent b4cb187 commit f9bdf34

File tree

5 files changed

+122
-67
lines changed

5 files changed

+122
-67
lines changed

src/librustc_resolve/lib.rs

+61-53
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,10 @@ impl<'a> Resolver<'a> {
15511551
}
15521552

15531553
ItemKind::DefaultImpl(_, ref trait_ref) => {
1554-
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
1554+
self.with_optional_trait_ref(Some(trait_ref), |this, _| {
1555+
// Resolve type arguments in trait path
1556+
visit::walk_trait_ref(this, trait_ref);
1557+
});
15551558
}
15561559
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
15571560
self.resolve_implementation(generics,
@@ -1715,7 +1718,6 @@ impl<'a> Resolver<'a> {
17151718
new_val = Some((def.def_id(), trait_ref.clone()));
17161719
new_id = Some(def.def_id());
17171720
}
1718-
visit::walk_trait_ref(self, trait_ref);
17191721
}
17201722
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
17211723
let result = f(self, new_id);
@@ -1743,60 +1745,66 @@ impl<'a> Resolver<'a> {
17431745
impl_items: &[ImplItem]) {
17441746
// If applicable, create a rib for the type parameters.
17451747
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
1746-
// Resolve the type parameters.
1747-
this.visit_generics(generics);
1748-
1749-
// Resolve the trait reference, if necessary.
1750-
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
1751-
// Resolve the self type.
1752-
this.visit_ty(self_type);
1753-
1754-
let item_def_id = this.definitions.local_def_id(item_id);
1755-
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
1756-
this.with_current_self_type(self_type, |this| {
1757-
for impl_item in impl_items {
1758-
this.check_proc_macro_attrs(&impl_item.attrs);
1759-
this.resolve_visibility(&impl_item.vis);
1760-
match impl_item.node {
1761-
ImplItemKind::Const(..) => {
1762-
// If this is a trait impl, ensure the const
1763-
// exists in trait
1764-
this.check_trait_item(impl_item.ident.name,
1765-
ValueNS,
1766-
impl_item.span,
1767-
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
1768-
visit::walk_impl_item(this, impl_item);
1769-
}
1770-
ImplItemKind::Method(ref sig, _) => {
1771-
// If this is a trait impl, ensure the method
1772-
// exists in trait
1773-
this.check_trait_item(impl_item.ident.name,
1774-
ValueNS,
1775-
impl_item.span,
1776-
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
1777-
1778-
// We also need a new scope for the method-
1779-
// specific type parameters.
1780-
let type_parameters =
1781-
HasTypeParameters(&sig.generics,
1782-
MethodRibKind(!sig.decl.has_self()));
1783-
this.with_type_parameter_rib(type_parameters, |this| {
1748+
// Dummy self type for better errors if `Self` is used in the trait path.
1749+
this.with_self_rib(Def::SelfTy(None, None), |this| {
1750+
// Resolve the trait reference, if necessary.
1751+
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
1752+
let item_def_id = this.definitions.local_def_id(item_id);
1753+
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
1754+
if let Some(trait_ref) = opt_trait_reference.as_ref() {
1755+
// Resolve type arguments in trait path
1756+
visit::walk_trait_ref(this, trait_ref);
1757+
}
1758+
// Resolve the self type.
1759+
this.visit_ty(self_type);
1760+
// Resolve the type parameters.
1761+
this.visit_generics(generics);
1762+
this.with_current_self_type(self_type, |this| {
1763+
for impl_item in impl_items {
1764+
this.check_proc_macro_attrs(&impl_item.attrs);
1765+
this.resolve_visibility(&impl_item.vis);
1766+
match impl_item.node {
1767+
ImplItemKind::Const(..) => {
1768+
// If this is a trait impl, ensure the const
1769+
// exists in trait
1770+
this.check_trait_item(impl_item.ident.name,
1771+
ValueNS,
1772+
impl_item.span,
1773+
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
17841774
visit::walk_impl_item(this, impl_item);
1785-
});
1786-
}
1787-
ImplItemKind::Type(ref ty) => {
1788-
// If this is a trait impl, ensure the type
1789-
// exists in trait
1790-
this.check_trait_item(impl_item.ident.name,
1791-
TypeNS,
1792-
impl_item.span,
1793-
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
1794-
1795-
this.visit_ty(ty);
1775+
}
1776+
ImplItemKind::Method(ref sig, _) => {
1777+
// If this is a trait impl, ensure the method
1778+
// exists in trait
1779+
this.check_trait_item(impl_item.ident.name,
1780+
ValueNS,
1781+
impl_item.span,
1782+
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
1783+
1784+
// We also need a new scope for the method-
1785+
// specific type parameters.
1786+
let type_parameters =
1787+
HasTypeParameters(&sig.generics,
1788+
MethodRibKind(!sig.decl.has_self()));
1789+
this.with_type_parameter_rib(type_parameters, |this| {
1790+
visit::walk_impl_item(this, impl_item);
1791+
});
1792+
}
1793+
ImplItemKind::Type(ref ty) => {
1794+
// If this is a trait impl, ensure the type
1795+
// exists in trait
1796+
this.check_trait_item(impl_item.ident.name,
1797+
TypeNS,
1798+
impl_item.span,
1799+
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
1800+
1801+
this.visit_ty(ty);
1802+
}
1803+
ImplItemKind::Macro(_) =>
1804+
panic!("unexpanded macro in resolve!"),
17961805
}
1797-
ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
17981806
}
1799-
}
1807+
});
18001808
});
18011809
});
18021810
});

src/librustc_typeck/astconv.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1401,11 +1401,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
14011401

14021402
assert_eq!(opt_self_ty, None);
14031403
tcx.prohibit_type_params(&path.segments);
1404-
let ty = tcx.item_type(def_id);
1405-
if let Some(free_substs) = self.get_free_substs() {
1406-
ty.subst(tcx, free_substs)
1404+
1405+
// FIXME: Self type is not always computed when we are here because type parameter
1406+
// bounds may affect Self type and have to be converted before it.
1407+
let ty = if def_id.is_local() {
1408+
tcx.item_types.borrow().get(&def_id).cloned()
14071409
} else {
1408-
ty
1410+
Some(tcx.item_type(def_id))
1411+
};
1412+
if let Some(ty) = ty {
1413+
if let Some(free_substs) = self.get_free_substs() {
1414+
ty.subst(tcx, free_substs)
1415+
} else {
1416+
ty
1417+
}
1418+
} else {
1419+
tcx.sess.span_err(span, "`Self` type is used before it's determined");
1420+
tcx.types.err
14091421
}
14101422
}
14111423
Def::SelfTy(Some(_), None) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2016 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+
struct S<T = u8>(T);
12+
trait Tr<T = u8> {}
13+
14+
impl Self for S {} //~ ERROR expected trait, found self type `Self`
15+
impl Self::N for S {} //~ ERROR cannot find trait `N` in `Self`
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 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+
struct S<T = u8>(T);
12+
trait Tr<T = u8> {}
13+
14+
impl Tr<Self> for S {} // OK
15+
16+
// FIXME: `Self` cannot be used in bounds because it depends on bounds itself.
17+
impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
18+
impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
19+
impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined
20+
impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined
21+
impl Tr for Self {} //~ ERROR `Self` type is used before it's determined
22+
impl Tr for S<Self> {} //~ ERROR `Self` type is used before it's determined
23+
impl Self {} //~ ERROR `Self` type is used before it's determined
24+
impl S<Self> {} //~ ERROR `Self` type is used before it's determined
25+
26+
fn main() {}
+2-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
error[E0411]: cannot find type `Self` in this scope
1+
error: `Self` type is used before it's determined
22
--> $DIR/issue-23305.rs:15:12
33
|
44
15 | impl ToNbt<Self> {}
5-
| ^^^^ `Self` is only available in traits and impls
6-
7-
error[E0038]: the trait `ToNbt` cannot be made into an object
8-
--> $DIR/issue-23305.rs:15:6
9-
|
10-
15 | impl ToNbt<Self> {}
11-
| ^^^^^^^^^^^ the trait `ToNbt` cannot be made into an object
12-
|
13-
= note: method `new` has no receiver
5+
| ^^^^
146

157
error: aborting due to previous error
168

0 commit comments

Comments
 (0)