Alter type collection to collect impl Trait bounds
In ast_generics extraction in generics_of and explicit_predicates_of, also collect inputs if there are any. Then use a Visitor to extract the necessary information from the TyImplTraitUniversal types before extending generics and predicates with the new information.
This commit is contained in:
parent
e4c7e2c99a
commit
94df3c5edf
1 changed files with 121 additions and 24 deletions
|
@ -43,6 +43,7 @@ use rustc_const_math::ConstInt;
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use syntax::{abi, ast};
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
@ -873,22 +874,32 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut allow_defaults = false;
|
||||
|
||||
let no_generics = hir::Generics::empty();
|
||||
let ast_generics = match node {
|
||||
NodeTraitItem(item) => &item.generics,
|
||||
let (ast_generics, opt_inputs) = match node {
|
||||
NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeImplItem(item) => &item.generics,
|
||||
NodeImplItem(item) => {
|
||||
match item.node {
|
||||
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeItem(item) => {
|
||||
match item.node {
|
||||
ItemFn(.., ref generics, _) |
|
||||
ItemImpl(_, _, _, ref generics, ..) => generics,
|
||||
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
|
||||
ItemImpl(_, _, _, ref generics, ..) => (generics, None),
|
||||
|
||||
ItemTy(_, ref generics) |
|
||||
ItemEnum(_, ref generics) |
|
||||
ItemStruct(_, ref generics) |
|
||||
ItemUnion(_, ref generics) => {
|
||||
allow_defaults = true;
|
||||
generics
|
||||
(generics, None)
|
||||
}
|
||||
|
||||
ItemTrait(_, _, ref generics, ..) => {
|
||||
|
@ -909,22 +920,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
});
|
||||
|
||||
allow_defaults = true;
|
||||
generics
|
||||
(generics, None)
|
||||
}
|
||||
|
||||
_ => &no_generics
|
||||
_ => (&no_generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
ForeignItemStatic(..) => (&no_generics, None),
|
||||
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
|
||||
ForeignItemType => (&no_generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
_ => &no_generics
|
||||
_ => (&no_generics, None)
|
||||
};
|
||||
|
||||
let has_self = opt_self.is_some();
|
||||
|
@ -981,7 +992,24 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
synthetic: p.synthetic,
|
||||
}
|
||||
});
|
||||
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
|
||||
|
||||
let fn_ins = opt_inputs.map(|tys| &tys[..]);
|
||||
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
|
||||
let other_type_start = type_start + ast_generics.ty_params.len() as u32;
|
||||
let mut types: Vec<_> = opt_self.into_iter()
|
||||
.chain(types)
|
||||
.chain(univ_impl_trait_info.iter().enumerate().map(|(i, info)| {
|
||||
ty::TypeParameterDef {
|
||||
index: other_type_start + i as u32,
|
||||
name: keywords::Invalid.name() /* FIXME(chrisvittal) maybe make not Invalid */,
|
||||
def_id: info.def_id,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: Some(SyntheticTyParamKind::ImplTrait),
|
||||
}
|
||||
}))
|
||||
.collect();
|
||||
|
||||
// provide junk type parameter defs - the only place that
|
||||
// cares about anything but the length is instantiation,
|
||||
|
@ -1337,20 +1365,31 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let no_generics = hir::Generics::empty();
|
||||
let ast_generics = match node {
|
||||
NodeTraitItem(item) => &item.generics,
|
||||
let (ast_generics, opt_inputs) = match node {
|
||||
NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeImplItem(item) => &item.generics,
|
||||
NodeImplItem(item) => {
|
||||
match item.node {
|
||||
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
|
||||
_ => (&item.generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeItem(item) => {
|
||||
match item.node {
|
||||
ItemFn(.., ref generics, _) |
|
||||
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
|
||||
|
||||
ItemImpl(_, _, _, ref generics, ..) |
|
||||
ItemTy(_, ref generics) |
|
||||
ItemEnum(_, ref generics) |
|
||||
ItemStruct(_, ref generics) |
|
||||
ItemUnion(_, ref generics) => {
|
||||
generics
|
||||
(generics, None)
|
||||
}
|
||||
|
||||
ItemTrait(_, _, ref generics, .., ref items) => {
|
||||
|
@ -1358,18 +1397,18 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
def_id,
|
||||
substs: Substs::identity_for_item(tcx, def_id)
|
||||
}, items));
|
||||
generics
|
||||
(generics, None)
|
||||
}
|
||||
|
||||
_ => &no_generics
|
||||
_ => (&no_generics, None)
|
||||
}
|
||||
}
|
||||
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
ForeignItemStatic(..) => (&no_generics, None),
|
||||
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
|
||||
ForeignItemType => (&no_generics, None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1387,7 +1426,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
};
|
||||
}
|
||||
|
||||
_ => &no_generics
|
||||
_ => (&no_generics, None)
|
||||
};
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
|
@ -1518,6 +1557,19 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}))
|
||||
}
|
||||
|
||||
// Add predicates from impl Trait arguments
|
||||
let fn_ins = opt_inputs.map(|tys| &tys[..]);
|
||||
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
|
||||
for info in univ_impl_trait_info.iter() {
|
||||
let name = keywords::Invalid.name();
|
||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
||||
index += 1;
|
||||
let bounds = compute_bounds(&icx, param_ty, info.bounds,
|
||||
SizedByDefault::Yes,
|
||||
info.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
}
|
||||
|
||||
// Subtle: before we store the predicates into the tcx, we
|
||||
// sort them so that predicates like `T: Foo<Item=U>` come
|
||||
// before uses of `U`. This avoids false ambiguity errors
|
||||
|
@ -1678,3 +1730,48 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
_ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplTraitUniversalInfo<'hir> {
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
bounds: &'hir [hir::TyParamBound],
|
||||
}
|
||||
|
||||
/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal
|
||||
/// arguments
|
||||
fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
opt_inputs: Option<&'tcx [P<hir::Ty>]>)
|
||||
-> Vec<ImplTraitUniversalInfo<'tcx>>
|
||||
{
|
||||
// A visitor for simply collecting Universally quantified impl Trait arguments
|
||||
struct ImplTraitUniversalVisitor<'tcx> {
|
||||
items: Vec<&'tcx hir::Ty>
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||
if let hir::TyImplTraitUniversal(..) = ty.node {
|
||||
self.items.push(ty);
|
||||
}
|
||||
intravisit::walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() };
|
||||
opt_inputs.map(|inputs| for t in inputs.iter() {
|
||||
visitor.visit_ty(t);
|
||||
});
|
||||
visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node {
|
||||
ImplTraitUniversalInfo {
|
||||
def_id: tcx.hir.local_def_id(ty.id),
|
||||
span: ty.span,
|
||||
bounds: bounds
|
||||
}
|
||||
} else {
|
||||
span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug")
|
||||
}).collect()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue