Skip to content

Commit 39849d5

Browse files
First step to generic trait impls
1 parent 54ea8eb commit 39849d5

File tree

3 files changed

+114
-20
lines changed

3 files changed

+114
-20
lines changed

src/librustdoc/clean/auto_trait.rs

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc::{self, hir};
11+
use rustc::hir;
1212
use rustc::traits::{self, auto_trait as auto};
1313
use rustc::ty::{ToPredicate, TypeFoldable};
14+
use rustc::ty::subst::Subst;
15+
use rustc::infer::InferOk;
1416
use std::fmt::Debug;
17+
use syntax_pos::DUMMY_SP;
1518

1619
use super::*;
1720

@@ -82,22 +85,115 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
8285
name: Option<String>,
8386
) -> Vec<Item>
8487
where F: Fn(DefId) -> Def {
88+
let tcx = self.cx.tcx;
89+
let generics = self.cx.tcx.generics_of(def_id);
8590

86-
if ::std::env::var("LOL").is_ok() {
87-
let ty = self.cx.tcx.type_of(def_id);
88-
if let ty::TyAdt(_adt, _) = ty.sty {
89-
let subts = ty::subst::Substs::identity_for_item(self.cx.tcx.clone(), def_id);
90-
self.cx.tcx.infer_ctxt().enter(|infcx| {
91-
for impl_ in infcx.tcx.all_trait_implementations(LOCAL_CRATE).iter() {
92-
let trait_ref = rustc::ty::TraitRef::new(*impl_, subts);
93-
let pred = trait_ref.to_predicate();
94-
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
95-
rustc::ty::ParamEnv::empty(),
96-
pred);
97-
println!("{} => {}",
98-
infcx.tcx.item_name(*impl_).to_string(),
99-
infcx.predicate_may_hold(&obligation));
100-
}
91+
let ty = self.cx.tcx.type_of(def_id);
92+
let mut traits = FxHashMap();
93+
if let ty::TyAdt(_adt, _) = ty.sty {
94+
use std::rc::Rc;
95+
96+
let name = Rc::new(name.clone());
97+
let param_env = self.cx.tcx.param_env(def_id);
98+
for &trait_def_id in self.cx.tcx.all_traits(LOCAL_CRATE).iter() {
99+
let name = name.clone();
100+
self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
101+
let name = name.clone();
102+
self.cx.tcx.infer_ctxt().enter(|infcx| {
103+
let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap();
104+
let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
105+
let ty = ty.subst(infcx.tcx, substs);
106+
let param_env = param_env.subst(infcx.tcx, substs);
107+
108+
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
109+
let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
110+
111+
// Require the type the impl is implemented on to match
112+
// our type, and ignore the impl if there was a mismatch.
113+
let cause = traits::ObligationCause::dummy();
114+
let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty);
115+
if let Ok(InferOk { value: (), obligations }) = eq_result {
116+
// FIXME(eddyb) ignoring `obligations` might cause false positives.
117+
drop(obligations);
118+
119+
let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
120+
cause.clone(),
121+
param_env,
122+
trait_ref.to_predicate(),
123+
));
124+
if may_apply {
125+
// FIXME: add crate's id before the name to avoid removing a
126+
// trait which doesn't exist.
127+
if traits.get(&trait_def_id).is_none() {
128+
/*let generics = (infcx.tcx.generics_of(trait_def_id), &predicates).clean(cx);
129+
get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait)*/
130+
/*if let Some(i) = self.get_auto_trait_impl_for(
131+
def_id,
132+
name.clone(),
133+
generics.clone(),
134+
def_ctor,
135+
trait_def_id,
136+
) {
137+
traits.insert(trait_name, i);
138+
}*/
139+
140+
let path = get_path_for_type(infcx.tcx, def_id, def_ctor);
141+
let mut segments = path.clone().segments.into_vec();
142+
let last = segments.pop().unwrap();
143+
144+
use std::ops::Deref;
145+
let t_name: Option<String> = name.deref().clone();
146+
let real_name = t_name.map(|name| Ident::from_str(&name)).unwrap_or(last.ident);
147+
148+
segments.push(hir::PathSegment::new(
149+
real_name,
150+
self.generics_to_path_params(generics.clone()),
151+
false,
152+
));
153+
let new_path = hir::Path {
154+
span: path.span,
155+
def: path.def,
156+
segments: HirVec::from_vec(segments),
157+
};
158+
let ty = hir::Ty {
159+
id: ast::DUMMY_NODE_ID,
160+
node: hir::Ty_::TyPath(hir::QPath::Resolved(None, P(new_path))),
161+
span: DUMMY_SP,
162+
hir_id: hir::DUMMY_HIR_ID,
163+
};
164+
traits.insert(trait_def_id, Item {
165+
source: Span::empty(),
166+
name: None,
167+
attrs: Default::default(),
168+
visibility: None,
169+
def_id: self.next_def_id(def_id.krate),
170+
stability: None,
171+
deprecation: None,
172+
inner: ImplItem(Impl {
173+
unsafety: hir::Unsafety::Normal,
174+
generics: Generics {
175+
params: generics.params.clean(self.cx),
176+
where_predicates: Vec::new(),
177+
},
178+
provided_trait_methods: FxHashSet(),
179+
trait_: Some(hir::TraitRef {
180+
path,
181+
ref_id: ast::DUMMY_NODE_ID,
182+
}.clean(self.cx)),
183+
184+
//Some(trait_ref.clean(self.cx)),
185+
for_: ty.clean(self.cx),
186+
items: Vec::new(),
187+
polarity: None,
188+
synthetic: true,
189+
})
190+
});
191+
}
192+
//println!("=> {}", infcx.tcx.item_name(trait_def_id).to_string());
193+
}
194+
debug!("{:?} => {}", trait_ref, may_apply);
195+
}
196+
});
101197
});
102198
}
103199
}
@@ -117,9 +213,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
117213
return Vec::new();
118214
}
119215

120-
let tcx = self.cx.tcx;
121-
let generics = self.cx.tcx.generics_of(def_id);
122-
123216
debug!(
124217
"get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}",
125218
def_id, generics
@@ -143,6 +236,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
143236
def_ctor,
144237
tcx.require_lang_item(lang_items::SyncTraitLangItem),
145238
).into_iter())
239+
.chain(traits.into_iter().map(|(_, v)| v))
146240
.collect();
147241

148242
debug!(

src/librustdoc/clean/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,6 @@ impl GenericBound {
15511551
}
15521552

15531553
fn get_trait_type(&self) -> Option<Type> {
1554-
15551554
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
15561555
return Some(trait_.clone());
15571556
}

src/librustdoc/html/render.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,7 @@ where F: Fn(&mut fmt::Formatter) -> fmt::Result {
20822082
impl<'a> fmt::Display for Item<'a> {
20832083
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
20842084
debug_assert!(!self.item.is_stripped());
2085+
println!("=> {:?}", self.item.name);
20852086
// Write the breadcrumb trail header for the top
20862087
write!(fmt, "<h1 class='fqn'><span class='in-band'>")?;
20872088
match self.item.inner {

0 commit comments

Comments
 (0)