Skip to content

Commit ee1bb3f

Browse files
committed
rollup merge of #19969: aturon/inherit-trait-stab
There is currently no way to specify the stability level for a trait impl produced by `deriving`. This patch is a stopgap solution that: * Turns of stability inheritance for trait impls, and * Uses the stability level of the *trait* if no level is directly specified. That is, manual trait impls may still provide a directly stability level, but `deriving` will use the level of the trait. While not a perfect solution, it should be good enough for 1.0 API stabilization, as we will like *remove* any unwanted impls outright. r? @alexcrichton
2 parents b4f393e + 9bb5380 commit ee1bb3f

File tree

1 file changed

+51
-19
lines changed

1 file changed

+51
-19
lines changed

src/librustc/middle/stability.rs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ struct Annotator {
4343
impl Annotator {
4444
// Determine the stability for a node based on its attributes and inherited
4545
// stability. The stability is recorded in the index and used as the parent.
46-
fn annotate<F>(&mut self, id: NodeId, attrs: &Vec<Attribute>, f: F) where
46+
fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
47+
attrs: &Vec<Attribute>, f: F) where
4748
F: FnOnce(&mut Annotator),
4849
{
4950
match attr::find_stability(attrs.as_slice()) {
@@ -60,7 +61,9 @@ impl Annotator {
6061
}
6162
}
6263
None => {
63-
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
64+
if use_parent {
65+
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
66+
}
6467
f(self);
6568
}
6669
}
@@ -69,11 +72,24 @@ impl Annotator {
6972

7073
impl<'v> Visitor<'v> for Annotator {
7174
fn visit_item(&mut self, i: &Item) {
72-
self.annotate(i.id, &i.attrs, |v| visit::walk_item(v, i));
75+
// FIXME (#18969): the following is a hack around the fact
76+
// that we cannot currently annotate the stability of
77+
// `deriving`. Basically, we do *not* allow stability
78+
// inheritance on trait implementations, so that derived
79+
// implementations appear to be unannotated. This then allows
80+
// derived implementations to be automatically tagged with the
81+
// stability of the trait. This is WRONG, but expedient to get
82+
// libstd stabilized for the 1.0 release.
83+
let use_parent = match i.node {
84+
ast::ItemImpl(_, _, Some(_), _, _) => false,
85+
_ => true,
86+
};
87+
88+
self.annotate(i.id, use_parent, &i.attrs, |v| visit::walk_item(v, i));
7389

7490
if let ast::ItemStruct(ref sd, _) = i.node {
7591
sd.ctor_id.map(|id| {
76-
self.annotate(id, &i.attrs, |_| {})
92+
self.annotate(id, true, &i.attrs, |_| {})
7793
});
7894
}
7995
}
@@ -82,7 +98,7 @@ impl<'v> Visitor<'v> for Annotator {
8298
_: &'v Block, _: Span, _: NodeId) {
8399
if let FkMethod(_, _, meth) = fk {
84100
// Methods are not already annotated, so we annotate it
85-
self.annotate(meth.id, &meth.attrs, |_| {});
101+
self.annotate(meth.id, true, &meth.attrs, |_| {});
86102
}
87103
// Items defined in a function body have no reason to have
88104
// a stability attribute, so we don't recurse.
@@ -101,15 +117,17 @@ impl<'v> Visitor<'v> for Annotator {
101117

102118
TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
103119
};
104-
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
120+
self.annotate(id, true, attrs, |v| visit::walk_trait_item(v, t));
105121
}
106122

107123
fn visit_variant(&mut self, var: &Variant, g: &'v Generics) {
108-
self.annotate(var.node.id, &var.node.attrs, |v| visit::walk_variant(v, var, g))
124+
self.annotate(var.node.id, true, &var.node.attrs,
125+
|v| visit::walk_variant(v, var, g))
109126
}
110127

111128
fn visit_struct_field(&mut self, s: &StructField) {
112-
self.annotate(s.node.id, &s.node.attrs, |v| visit::walk_struct_field(v, s));
129+
self.annotate(s.node.id, true, &s.node.attrs,
130+
|v| visit::walk_struct_field(v, s));
113131
}
114132
}
115133

@@ -123,7 +141,8 @@ impl Index {
123141
},
124142
parent: None
125143
};
126-
annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, |v| visit::walk_crate(v, krate));
144+
annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs,
145+
|v| visit::walk_crate(v, krate));
127146
annotator.index
128147
}
129148
}
@@ -135,16 +154,29 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
135154
match ty::trait_item_of_item(tcx, id) {
136155
Some(ty::MethodTraitItemId(trait_method_id))
137156
if trait_method_id != id => {
138-
lookup(tcx, trait_method_id)
139-
}
140-
_ if is_local(id) => {
141-
tcx.stability.borrow().local.get(&id.node).cloned()
142-
}
143-
_ => {
144-
let stab = csearch::get_stability(&tcx.sess.cstore, id);
145-
let mut index = tcx.stability.borrow_mut();
146-
(*index).extern_cache.insert(id, stab.clone());
147-
stab
157+
return lookup(tcx, trait_method_id)
148158
}
159+
_ => {}
149160
}
161+
162+
let item_stab = if is_local(id) {
163+
tcx.stability.borrow().local.get(&id.node).cloned()
164+
} else {
165+
let stab = csearch::get_stability(&tcx.sess.cstore, id);
166+
let mut index = tcx.stability.borrow_mut();
167+
(*index).extern_cache.insert(id, stab.clone());
168+
stab
169+
};
170+
171+
item_stab.or_else(|| {
172+
if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
173+
// FIXME (#18969): for the time being, simply use the
174+
// stability of the trait to determine the stability of any
175+
// unmarked impls for it. See FIXME above for more details.
176+
177+
lookup(tcx, trait_id)
178+
} else {
179+
None
180+
}
181+
})
150182
}

0 commit comments

Comments
 (0)