Skip to content

Commit 1cbf339

Browse files
committed
Auto merge of #53439 - GuillaumeGomez:generate-blanket-impls-for-reexported-items, r=QuietMisdreavus
Generate blanket implementations for reexported items as well Fixes #53374. r? @QuietMisdreavus
2 parents d0d81b7 + 985da80 commit 1cbf339

File tree

2 files changed

+106
-90
lines changed

2 files changed

+106
-90
lines changed

src/librustdoc/clean/blanket_impl.rs

+88-90
Original file line numberDiff line numberDiff line change
@@ -65,98 +65,96 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
6565
return impls;
6666
}
6767
let ty = self.cx.tcx.type_of(def_id);
68-
if self.cx.access_levels.borrow().is_doc_reachable(def_id) || ty.is_primitive() {
69-
let generics = self.cx.tcx.generics_of(def_id);
70-
let real_name = name.clone().map(|name| Ident::from_str(&name));
71-
let param_env = self.cx.tcx.param_env(def_id);
72-
for &trait_def_id in self.cx.all_traits.iter() {
73-
if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
74-
self.cx.generated_synthetics
75-
.borrow_mut()
76-
.get(&(def_id, trait_def_id))
77-
.is_some() {
78-
continue
79-
}
80-
self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
81-
self.cx.tcx.infer_ctxt().enter(|infcx| {
82-
let t_generics = infcx.tcx.generics_of(impl_def_id);
83-
let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
84-
.expect("Cannot get impl trait");
85-
86-
match trait_ref.self_ty().sty {
87-
ty::TypeVariants::TyParam(_) => {},
88-
_ => return,
89-
}
90-
91-
let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
92-
let ty = ty.subst(infcx.tcx, substs);
93-
let param_env = param_env.subst(infcx.tcx, substs);
94-
95-
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
96-
let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
97-
98-
// Require the type the impl is implemented on to match
99-
// our type, and ignore the impl if there was a mismatch.
100-
let cause = traits::ObligationCause::dummy();
101-
let eq_result = infcx.at(&cause, param_env)
102-
.eq(trait_ref.self_ty(), ty);
103-
if let Ok(InferOk { value: (), obligations }) = eq_result {
104-
// FIXME(eddyb) ignoring `obligations` might cause false positives.
105-
drop(obligations);
106-
107-
let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
108-
cause.clone(),
109-
param_env,
110-
trait_ref.to_predicate(),
111-
));
112-
if !may_apply {
113-
return
114-
}
115-
self.cx.generated_synthetics.borrow_mut()
116-
.insert((def_id, trait_def_id));
117-
let trait_ = hir::TraitRef {
118-
path: get_path_for_type(infcx.tcx,
119-
trait_def_id,
120-
hir::def::Def::Trait),
121-
ref_id: ast::DUMMY_NODE_ID,
122-
hir_ref_id: hir::DUMMY_HIR_ID,
123-
};
124-
let provided_trait_methods =
125-
infcx.tcx.provided_trait_methods(trait_def_id)
126-
.into_iter()
127-
.map(|meth| meth.ident.to_string())
128-
.collect();
129-
130-
let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
131-
let predicates = infcx.tcx.predicates_of(impl_def_id);
132-
133-
impls.push(Item {
134-
source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
135-
name: None,
136-
attrs: Default::default(),
137-
visibility: None,
138-
def_id: self.cx.next_def_id(impl_def_id.krate),
139-
stability: None,
140-
deprecation: None,
141-
inner: ImplItem(Impl {
142-
unsafety: hir::Unsafety::Normal,
143-
generics: (t_generics, &predicates).clean(self.cx),
144-
provided_trait_methods,
145-
trait_: Some(trait_.clean(self.cx)),
146-
for_: ty.clean(self.cx),
147-
items: infcx.tcx.associated_items(impl_def_id)
148-
.collect::<Vec<_>>()
149-
.clean(self.cx),
150-
polarity: None,
151-
synthetic: false,
152-
blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
153-
.clean(self.cx)),
154-
}),
155-
});
68+
let generics = self.cx.tcx.generics_of(def_id);
69+
let real_name = name.clone().map(|name| Ident::from_str(&name));
70+
let param_env = self.cx.tcx.param_env(def_id);
71+
for &trait_def_id in self.cx.all_traits.iter() {
72+
if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
73+
self.cx.generated_synthetics
74+
.borrow_mut()
75+
.get(&(def_id, trait_def_id))
76+
.is_some() {
77+
continue
78+
}
79+
self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
80+
self.cx.tcx.infer_ctxt().enter(|infcx| {
81+
let t_generics = infcx.tcx.generics_of(impl_def_id);
82+
let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
83+
.expect("Cannot get impl trait");
84+
85+
match trait_ref.self_ty().sty {
86+
ty::TypeVariants::TyParam(_) => {},
87+
_ => return,
88+
}
89+
90+
let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
91+
let ty = ty.subst(infcx.tcx, substs);
92+
let param_env = param_env.subst(infcx.tcx, substs);
93+
94+
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
95+
let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
96+
97+
// Require the type the impl is implemented on to match
98+
// our type, and ignore the impl if there was a mismatch.
99+
let cause = traits::ObligationCause::dummy();
100+
let eq_result = infcx.at(&cause, param_env)
101+
.eq(trait_ref.self_ty(), ty);
102+
if let Ok(InferOk { value: (), obligations }) = eq_result {
103+
// FIXME(eddyb) ignoring `obligations` might cause false positives.
104+
drop(obligations);
105+
106+
let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
107+
cause.clone(),
108+
param_env,
109+
trait_ref.to_predicate(),
110+
));
111+
if !may_apply {
112+
return
156113
}
157-
});
114+
self.cx.generated_synthetics.borrow_mut()
115+
.insert((def_id, trait_def_id));
116+
let trait_ = hir::TraitRef {
117+
path: get_path_for_type(infcx.tcx,
118+
trait_def_id,
119+
hir::def::Def::Trait),
120+
ref_id: ast::DUMMY_NODE_ID,
121+
hir_ref_id: hir::DUMMY_HIR_ID,
122+
};
123+
let provided_trait_methods =
124+
infcx.tcx.provided_trait_methods(trait_def_id)
125+
.into_iter()
126+
.map(|meth| meth.ident.to_string())
127+
.collect();
128+
129+
let ty = self.cx.get_real_ty(def_id, def_ctor, &real_name, generics);
130+
let predicates = infcx.tcx.predicates_of(impl_def_id);
131+
132+
impls.push(Item {
133+
source: infcx.tcx.def_span(impl_def_id).clean(self.cx),
134+
name: None,
135+
attrs: Default::default(),
136+
visibility: None,
137+
def_id: self.cx.next_def_id(impl_def_id.krate),
138+
stability: None,
139+
deprecation: None,
140+
inner: ImplItem(Impl {
141+
unsafety: hir::Unsafety::Normal,
142+
generics: (t_generics, &predicates).clean(self.cx),
143+
provided_trait_methods,
144+
trait_: Some(trait_.clean(self.cx)),
145+
for_: ty.clean(self.cx),
146+
items: infcx.tcx.associated_items(impl_def_id)
147+
.collect::<Vec<_>>()
148+
.clean(self.cx),
149+
polarity: None,
150+
synthetic: false,
151+
blanket_impl: Some(infcx.tcx.type_of(impl_def_id)
152+
.clean(self.cx)),
153+
}),
154+
});
155+
}
158156
});
159-
}
157+
});
160158
}
161159
impls
162160
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 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+
#![crate_name = "foo"]
12+
13+
// @has foo/struct.S.html '//h3[@id="impl-Into"]//code' 'impl<T, U> Into for T'
14+
pub struct S2 {}
15+
mod m {
16+
pub struct S {}
17+
}
18+
pub use m::*;

0 commit comments

Comments
 (0)