First step to generic trait impls
This commit is contained in:
parent
54ea8eb232
commit
39849d5128
3 changed files with 114 additions and 20 deletions
|
@ -8,10 +8,13 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc::{self, hir};
|
use rustc::hir;
|
||||||
use rustc::traits::{self, auto_trait as auto};
|
use rustc::traits::{self, auto_trait as auto};
|
||||||
use rustc::ty::{ToPredicate, TypeFoldable};
|
use rustc::ty::{ToPredicate, TypeFoldable};
|
||||||
|
use rustc::ty::subst::Subst;
|
||||||
|
use rustc::infer::InferOk;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use syntax_pos::DUMMY_SP;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -82,22 +85,115 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
) -> Vec<Item>
|
) -> Vec<Item>
|
||||||
where F: Fn(DefId) -> Def {
|
where F: Fn(DefId) -> Def {
|
||||||
|
let tcx = self.cx.tcx;
|
||||||
|
let generics = self.cx.tcx.generics_of(def_id);
|
||||||
|
|
||||||
if ::std::env::var("LOL").is_ok() {
|
|
||||||
let ty = self.cx.tcx.type_of(def_id);
|
let ty = self.cx.tcx.type_of(def_id);
|
||||||
|
let mut traits = FxHashMap();
|
||||||
if let ty::TyAdt(_adt, _) = ty.sty {
|
if let ty::TyAdt(_adt, _) = ty.sty {
|
||||||
let subts = ty::subst::Substs::identity_for_item(self.cx.tcx.clone(), def_id);
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
let name = Rc::new(name.clone());
|
||||||
|
let param_env = self.cx.tcx.param_env(def_id);
|
||||||
|
for &trait_def_id in self.cx.tcx.all_traits(LOCAL_CRATE).iter() {
|
||||||
|
let name = name.clone();
|
||||||
|
self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
|
||||||
|
let name = name.clone();
|
||||||
self.cx.tcx.infer_ctxt().enter(|infcx| {
|
self.cx.tcx.infer_ctxt().enter(|infcx| {
|
||||||
for impl_ in infcx.tcx.all_trait_implementations(LOCAL_CRATE).iter() {
|
let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap();
|
||||||
let trait_ref = rustc::ty::TraitRef::new(*impl_, subts);
|
let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
|
||||||
let pred = trait_ref.to_predicate();
|
let ty = ty.subst(infcx.tcx, substs);
|
||||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
let param_env = param_env.subst(infcx.tcx, substs);
|
||||||
rustc::ty::ParamEnv::empty(),
|
|
||||||
pred);
|
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
|
||||||
println!("{} => {}",
|
let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
|
||||||
infcx.tcx.item_name(*impl_).to_string(),
|
|
||||||
infcx.predicate_may_hold(&obligation));
|
// Require the type the impl is implemented on to match
|
||||||
|
// our type, and ignore the impl if there was a mismatch.
|
||||||
|
let cause = traits::ObligationCause::dummy();
|
||||||
|
let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty);
|
||||||
|
if let Ok(InferOk { value: (), obligations }) = eq_result {
|
||||||
|
// FIXME(eddyb) ignoring `obligations` might cause false positives.
|
||||||
|
drop(obligations);
|
||||||
|
|
||||||
|
let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
|
||||||
|
cause.clone(),
|
||||||
|
param_env,
|
||||||
|
trait_ref.to_predicate(),
|
||||||
|
));
|
||||||
|
if may_apply {
|
||||||
|
// FIXME: add crate's id before the name to avoid removing a
|
||||||
|
// trait which doesn't exist.
|
||||||
|
if traits.get(&trait_def_id).is_none() {
|
||||||
|
/*let generics = (infcx.tcx.generics_of(trait_def_id), &predicates).clean(cx);
|
||||||
|
get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait)*/
|
||||||
|
/*if let Some(i) = self.get_auto_trait_impl_for(
|
||||||
|
def_id,
|
||||||
|
name.clone(),
|
||||||
|
generics.clone(),
|
||||||
|
def_ctor,
|
||||||
|
trait_def_id,
|
||||||
|
) {
|
||||||
|
traits.insert(trait_name, i);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
let path = get_path_for_type(infcx.tcx, def_id, def_ctor);
|
||||||
|
let mut segments = path.clone().segments.into_vec();
|
||||||
|
let last = segments.pop().unwrap();
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
let t_name: Option<String> = name.deref().clone();
|
||||||
|
let real_name = t_name.map(|name| Ident::from_str(&name)).unwrap_or(last.ident);
|
||||||
|
|
||||||
|
segments.push(hir::PathSegment::new(
|
||||||
|
real_name,
|
||||||
|
self.generics_to_path_params(generics.clone()),
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
let new_path = hir::Path {
|
||||||
|
span: path.span,
|
||||||
|
def: path.def,
|
||||||
|
segments: HirVec::from_vec(segments),
|
||||||
|
};
|
||||||
|
let ty = hir::Ty {
|
||||||
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
node: hir::Ty_::TyPath(hir::QPath::Resolved(None, P(new_path))),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
hir_id: hir::DUMMY_HIR_ID,
|
||||||
|
};
|
||||||
|
traits.insert(trait_def_id, Item {
|
||||||
|
source: Span::empty(),
|
||||||
|
name: None,
|
||||||
|
attrs: Default::default(),
|
||||||
|
visibility: None,
|
||||||
|
def_id: self.next_def_id(def_id.krate),
|
||||||
|
stability: None,
|
||||||
|
deprecation: None,
|
||||||
|
inner: ImplItem(Impl {
|
||||||
|
unsafety: hir::Unsafety::Normal,
|
||||||
|
generics: Generics {
|
||||||
|
params: generics.params.clean(self.cx),
|
||||||
|
where_predicates: Vec::new(),
|
||||||
|
},
|
||||||
|
provided_trait_methods: FxHashSet(),
|
||||||
|
trait_: Some(hir::TraitRef {
|
||||||
|
path,
|
||||||
|
ref_id: ast::DUMMY_NODE_ID,
|
||||||
|
}.clean(self.cx)),
|
||||||
|
|
||||||
|
//Some(trait_ref.clean(self.cx)),
|
||||||
|
for_: ty.clean(self.cx),
|
||||||
|
items: Vec::new(),
|
||||||
|
polarity: None,
|
||||||
|
synthetic: true,
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
//println!("=> {}", infcx.tcx.item_name(trait_def_id).to_string());
|
||||||
|
}
|
||||||
|
debug!("{:?} => {}", trait_ref, may_apply);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,9 +213,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
let tcx = self.cx.tcx;
|
|
||||||
let generics = self.cx.tcx.generics_of(def_id);
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}",
|
"get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}",
|
||||||
def_id, generics
|
def_id, generics
|
||||||
|
@ -143,6 +236,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
||||||
def_ctor,
|
def_ctor,
|
||||||
tcx.require_lang_item(lang_items::SyncTraitLangItem),
|
tcx.require_lang_item(lang_items::SyncTraitLangItem),
|
||||||
).into_iter())
|
).into_iter())
|
||||||
|
.chain(traits.into_iter().map(|(_, v)| v))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
|
|
|
@ -1551,7 +1551,6 @@ impl GenericBound {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_trait_type(&self) -> Option<Type> {
|
fn get_trait_type(&self) -> Option<Type> {
|
||||||
|
|
||||||
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
|
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
|
||||||
return Some(trait_.clone());
|
return Some(trait_.clone());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2082,6 +2082,7 @@ where F: Fn(&mut fmt::Formatter) -> fmt::Result {
|
||||||
impl<'a> fmt::Display for Item<'a> {
|
impl<'a> fmt::Display for Item<'a> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
debug_assert!(!self.item.is_stripped());
|
debug_assert!(!self.item.is_stripped());
|
||||||
|
println!("=> {:?}", self.item.name);
|
||||||
// Write the breadcrumb trail header for the top
|
// Write the breadcrumb trail header for the top
|
||||||
write!(fmt, "<h1 class='fqn'><span class='in-band'>")?;
|
write!(fmt, "<h1 class='fqn'><span class='in-band'>")?;
|
||||||
match self.item.inner {
|
match self.item.inner {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue