Skip to content

Commit 9f9376f

Browse files
committed
Check uses of Self in impls in the compiler rather than during expansion
Closes #23909
1 parent 5e30f05 commit 9f9376f

File tree

11 files changed

+326
-219
lines changed

11 files changed

+326
-219
lines changed

src/librustc/middle/astencode.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,11 @@ impl tr for def::Def {
457457
def::DefMethod(did, p) => {
458458
def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
459459
}
460-
def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
460+
def::DefSelfTy(opt_did, impl_ids) => { def::DefSelfTy(opt_did.map(|did| did.tr(dcx)),
461+
impl_ids.map(|(nid1, nid2)| {
462+
(dcx.tr_id(nid1),
463+
dcx.tr_id(nid2))
464+
})) }
461465
def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
462466
def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
463467
def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }

src/librustc/middle/def.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use std::cell::RefCell;
2222
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
2323
pub enum Def {
2424
DefFn(ast::DefId, bool /* is_ctor */),
25-
DefSelfTy(/* trait id */ ast::NodeId),
25+
DefSelfTy(Option<ast::DefId>, // trait id
26+
Option<(ast::NodeId, ast::NodeId)>), // (impl id, self type id)
2627
DefMod(ast::DefId),
2728
DefForeignMod(ast::DefId),
2829
DefStatic(ast::DefId, bool /* is_mutbl */),
@@ -139,18 +140,19 @@ impl Def {
139140
DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
140141
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
141142
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
142-
DefMethod(id, _) | DefConst(id) => {
143+
DefMethod(id, _) | DefConst(id) | DefSelfTy(Some(id), None)=> {
143144
id
144145
}
145146
DefLocal(id) |
146-
DefSelfTy(id) |
147147
DefUpvar(id, _) |
148148
DefRegion(id) |
149-
DefLabel(id) => {
149+
DefLabel(id) |
150+
DefSelfTy(_, Some((_, id))) => {
150151
local_def(id)
151152
}
152153

153-
DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
154+
DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy"),
155+
DefSelfTy(..) => panic!("attempted .def_id() on invalid DefSelfTy"),
154156
}
155157
}
156158

src/librustc_privacy/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
11781178
let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
11791179
// `int` etc. (None doesn't seem to occur.)
11801180
None | Some(def::DefPrimTy(..)) => return false,
1181-
Some(def) => def.def_id()
1181+
Some(def) => def.def_id(),
11821182
};
11831183
// A path can only be private if:
11841184
// it's in this crate...

src/librustc_resolve/lib.rs

+94-83
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
16891689
}
16901690
}
16911691
}
1692-
DefTyParam(..) | DefSelfTy(_) => {
1692+
DefTyParam(..) | DefSelfTy(..) => {
16931693
for rib in ribs {
16941694
match rib.kind {
16951695
NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
@@ -1797,63 +1797,57 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17971797
}
17981798

17991799
ItemDefaultImpl(_, ref trait_ref) => {
1800-
self.with_optional_trait_ref(Some(trait_ref), |_| {});
1800+
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
18011801
}
1802-
ItemImpl(_, _,
1802+
ItemImpl(_,
1803+
_,
18031804
ref generics,
1804-
ref implemented_traits,
1805+
ref opt_trait_ref,
18051806
ref self_type,
18061807
ref impl_items) => {
18071808
self.resolve_implementation(generics,
1808-
implemented_traits,
1809+
opt_trait_ref,
18091810
&**self_type,
1811+
item.id,
18101812
&impl_items[..]);
18111813
}
18121814

18131815
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
18141816
self.check_if_primitive_type_name(name, item.span);
18151817

1816-
// Create a new rib for the self type.
1817-
let mut self_type_rib = Rib::new(ItemRibKind);
1818-
1819-
// plain insert (no renaming, types are not currently hygienic....)
1820-
let name = special_names::type_self;
1821-
self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id)));
1822-
self.type_ribs.push(self_type_rib);
1823-
1824-
// Create a new rib for the trait-wide type parameters.
1825-
self.with_type_parameter_rib(HasTypeParameters(generics,
1826-
TypeSpace,
1827-
NormalRibKind),
1828-
|this| {
1829-
this.visit_generics(generics);
1830-
visit::walk_ty_param_bounds_helper(this, bounds);
1831-
1832-
for trait_item in trait_items {
1833-
// Create a new rib for the trait_item-specific type
1834-
// parameters.
1835-
//
1836-
// FIXME #4951: Do we need a node ID here?
1837-
1838-
let type_parameters = match trait_item.node {
1839-
ast::MethodTraitItem(ref sig, _) => {
1840-
HasTypeParameters(&sig.generics,
1841-
FnSpace,
1842-
MethodRibKind)
1843-
}
1844-
ast::TypeTraitItem(..) => {
1845-
this.check_if_primitive_type_name(trait_item.ident.name,
1846-
trait_item.span);
1847-
NoTypeParameters
1848-
}
1849-
};
1850-
this.with_type_parameter_rib(type_parameters, |this| {
1851-
visit::walk_trait_item(this, trait_item)
1852-
});
1853-
}
1818+
self.with_self_rib(DefSelfTy(Some(local_def(item.id)), None), |this| {
1819+
// Create a new rib for the trait-wide type parameters.
1820+
this.with_type_parameter_rib(HasTypeParameters(generics,
1821+
TypeSpace,
1822+
NormalRibKind),
1823+
|this| {
1824+
this.visit_generics(generics);
1825+
visit::walk_ty_param_bounds_helper(this, bounds);
1826+
1827+
for trait_item in trait_items {
1828+
// Create a new rib for the trait_item-specific type
1829+
// parameters.
1830+
//
1831+
// FIXME #4951: Do we need a node ID here?
1832+
1833+
let type_parameters = match trait_item.node {
1834+
ast::MethodTraitItem(ref sig, _) => {
1835+
HasTypeParameters(&sig.generics,
1836+
FnSpace,
1837+
MethodRibKind)
1838+
}
1839+
ast::TypeTraitItem(..) => {
1840+
this.check_if_primitive_type_name(trait_item.ident.name,
1841+
trait_item.span);
1842+
NoTypeParameters
1843+
}
1844+
};
1845+
this.with_type_parameter_rib(type_parameters, |this| {
1846+
visit::walk_trait_item(this, trait_item)
1847+
});
1848+
}
1849+
});
18541850
});
1855-
1856-
self.type_ribs.pop();
18571851
}
18581852

18591853
ItemMod(_) | ItemForeignMod(_) => {
@@ -2030,8 +2024,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
20302024
visit::walk_generics(self, generics);
20312025
}
20322026

2033-
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
2034-
F: FnOnce(&mut Resolver) -> T,
2027+
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
2028+
where F: FnOnce(&mut Resolver) -> T
20352029
{
20362030
// Handle nested impls (inside fn bodies)
20372031
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
@@ -2044,29 +2038,44 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
20442038
opt_trait_ref: Option<&TraitRef>,
20452039
f: F)
20462040
-> T
2047-
where F: FnOnce(&mut Resolver) -> T,
2041+
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
20482042
{
20492043
let mut new_val = None;
2044+
let mut new_id = None;
20502045
if let Some(trait_ref) = opt_trait_ref {
2051-
match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) {
2052-
Ok(path_res) => {
2053-
self.record_def(trait_ref.ref_id, path_res);
2054-
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
2055-
}
2056-
Err(_) => { /* error was already reported */ }
2046+
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
2047+
&trait_ref.path, 0) {
2048+
assert!(path_res.depth == 0);
2049+
self.record_def(trait_ref.ref_id, path_res);
2050+
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
2051+
new_id = Some(path_res.base_def.def_id());
20572052
}
20582053
visit::walk_trait_ref(self, trait_ref);
20592054
}
20602055
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
2061-
let result = f(self);
2056+
let result = f(self, new_id);
20622057
self.current_trait_ref = original_trait_ref;
20632058
result
20642059
}
20652060

2061+
fn with_self_rib<F>(&mut self, self_def: Def, f: F)
2062+
where F: FnOnce(&mut Resolver)
2063+
{
2064+
let mut self_type_rib = Rib::new(NormalRibKind);
2065+
2066+
// plain insert (no renaming, types are not currently hygienic....)
2067+
let name = special_names::type_self;
2068+
self_type_rib.bindings.insert(name, DlDef(self_def));
2069+
self.type_ribs.push(self_type_rib);
2070+
f(self);
2071+
self.type_ribs.pop();
2072+
}
2073+
20662074
fn resolve_implementation(&mut self,
20672075
generics: &Generics,
20682076
opt_trait_reference: &Option<TraitRef>,
20692077
self_type: &Ty,
2078+
item_id: NodeId,
20702079
impl_items: &[P<ImplItem>]) {
20712080
// If applicable, create a rib for the type parameters.
20722081
self.with_type_parameter_rib(HasTypeParameters(generics,
@@ -2077,40 +2086,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
20772086
this.visit_generics(generics);
20782087

20792088
// Resolve the trait reference, if necessary.
2080-
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| {
2089+
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
20812090
// Resolve the self type.
20822091
this.visit_ty(self_type);
20832092

2084-
this.with_current_self_type(self_type, |this| {
2085-
for impl_item in impl_items {
2086-
match impl_item.node {
2087-
MethodImplItem(ref sig, _) => {
2088-
// If this is a trait impl, ensure the method
2089-
// exists in trait
2090-
this.check_trait_item(impl_item.ident.name,
2091-
impl_item.span);
2092-
2093-
// We also need a new scope for the method-
2094-
// specific type parameters.
2095-
let type_parameters =
2096-
HasTypeParameters(&sig.generics,
2097-
FnSpace,
2098-
MethodRibKind);
2099-
this.with_type_parameter_rib(type_parameters, |this| {
2100-
visit::walk_impl_item(this, impl_item);
2101-
});
2102-
}
2103-
TypeImplItem(ref ty) => {
2104-
// If this is a trait impl, ensure the method
2105-
// exists in trait
2106-
this.check_trait_item(impl_item.ident.name,
2107-
impl_item.span);
2093+
this.with_self_rib(DefSelfTy(trait_id, Some((item_id, self_type.id))), |this| {
2094+
this.with_current_self_type(self_type, |this| {
2095+
for impl_item in impl_items {
2096+
match impl_item.node {
2097+
MethodImplItem(ref sig, _) => {
2098+
// If this is a trait impl, ensure the method
2099+
// exists in trait
2100+
this.check_trait_item(impl_item.ident.name,
2101+
impl_item.span);
2102+
2103+
// We also need a new scope for the method-
2104+
// specific type parameters.
2105+
let type_parameters =
2106+
HasTypeParameters(&sig.generics,
2107+
FnSpace,
2108+
MethodRibKind);
2109+
this.with_type_parameter_rib(type_parameters, |this| {
2110+
visit::walk_impl_item(this, impl_item);
2111+
});
2112+
}
2113+
TypeImplItem(ref ty) => {
2114+
// If this is a trait impl, ensure the method
2115+
// exists in trait
2116+
this.check_trait_item(impl_item.ident.name,
2117+
impl_item.span);
21082118

2109-
this.visit_ty(ty);
2119+
this.visit_ty(ty);
2120+
}
2121+
ast::MacImplItem(_) => {}
21102122
}
2111-
ast::MacImplItem(_) => {}
21122123
}
2113-
}
2124+
});
21142125
});
21152126
});
21162127
});

src/librustc_trans/save/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
248248

249249
def::DefFn(..) => Some(recorder::FnRef),
250250

251-
def::DefSelfTy(_) |
251+
def::DefSelfTy(..) |
252252
def::DefRegion(_) |
253253
def::DefLabel(_) |
254254
def::DefTyParam(..) |

0 commit comments

Comments
 (0)