Skip to content

Commit 94df3c5

Browse files
committed
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.
1 parent e4c7e2c commit 94df3c5

File tree

1 file changed

+121
-24
lines changed

1 file changed

+121
-24
lines changed

src/librustc_typeck/collect.rs

Lines changed: 121 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use rustc_const_math::ConstInt;
4343
use std::collections::BTreeMap;
4444

4545
use syntax::{abi, ast};
46+
use syntax::ptr::P;
4647
use syntax::codemap::Spanned;
4748
use syntax::symbol::{Symbol, keywords};
4849
use syntax_pos::{Span, DUMMY_SP};
@@ -873,22 +874,32 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
873874
let mut allow_defaults = false;
874875

875876
let no_generics = hir::Generics::empty();
876-
let ast_generics = match node {
877-
NodeTraitItem(item) => &item.generics,
877+
let (ast_generics, opt_inputs) = match node {
878+
NodeTraitItem(item) => {
879+
match item.node {
880+
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
881+
_ => (&item.generics, None)
882+
}
883+
}
878884

879-
NodeImplItem(item) => &item.generics,
885+
NodeImplItem(item) => {
886+
match item.node {
887+
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
888+
_ => (&item.generics, None)
889+
}
890+
}
880891

881892
NodeItem(item) => {
882893
match item.node {
883-
ItemFn(.., ref generics, _) |
884-
ItemImpl(_, _, _, ref generics, ..) => generics,
894+
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
895+
ItemImpl(_, _, _, ref generics, ..) => (generics, None),
885896

886897
ItemTy(_, ref generics) |
887898
ItemEnum(_, ref generics) |
888899
ItemStruct(_, ref generics) |
889900
ItemUnion(_, ref generics) => {
890901
allow_defaults = true;
891-
generics
902+
(generics, None)
892903
}
893904

894905
ItemTrait(_, _, ref generics, ..) => {
@@ -909,22 +920,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
909920
});
910921

911922
allow_defaults = true;
912-
generics
923+
(generics, None)
913924
}
914925

915-
_ => &no_generics
926+
_ => (&no_generics, None)
916927
}
917928
}
918929

919930
NodeForeignItem(item) => {
920931
match item.node {
921-
ForeignItemStatic(..) => &no_generics,
922-
ForeignItemFn(_, _, ref generics) => generics,
923-
ForeignItemType => &no_generics,
932+
ForeignItemStatic(..) => (&no_generics, None),
933+
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
934+
ForeignItemType => (&no_generics, None)
924935
}
925936
}
926937

927-
_ => &no_generics
938+
_ => (&no_generics, None)
928939
};
929940

930941
let has_self = opt_self.is_some();
@@ -981,7 +992,24 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
981992
synthetic: p.synthetic,
982993
}
983994
});
984-
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
995+
996+
let fn_ins = opt_inputs.map(|tys| &tys[..]);
997+
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
998+
let other_type_start = type_start + ast_generics.ty_params.len() as u32;
999+
let mut types: Vec<_> = opt_self.into_iter()
1000+
.chain(types)
1001+
.chain(univ_impl_trait_info.iter().enumerate().map(|(i, info)| {
1002+
ty::TypeParameterDef {
1003+
index: other_type_start + i as u32,
1004+
name: keywords::Invalid.name() /* FIXME(chrisvittal) maybe make not Invalid */,
1005+
def_id: info.def_id,
1006+
has_default: false,
1007+
object_lifetime_default: rl::Set1::Empty,
1008+
pure_wrt_drop: false,
1009+
synthetic: Some(SyntheticTyParamKind::ImplTrait),
1010+
}
1011+
}))
1012+
.collect();
9851013

9861014
// provide junk type parameter defs - the only place that
9871015
// cares about anything but the length is instantiation,
@@ -1337,39 +1365,50 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13371365

13381366
let icx = ItemCtxt::new(tcx, def_id);
13391367
let no_generics = hir::Generics::empty();
1340-
let ast_generics = match node {
1341-
NodeTraitItem(item) => &item.generics,
1368+
let (ast_generics, opt_inputs) = match node {
1369+
NodeTraitItem(item) => {
1370+
match item.node {
1371+
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
1372+
_ => (&item.generics, None)
1373+
}
1374+
}
13421375

1343-
NodeImplItem(item) => &item.generics,
1376+
NodeImplItem(item) => {
1377+
match item.node {
1378+
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
1379+
_ => (&item.generics, None)
1380+
}
1381+
}
13441382

13451383
NodeItem(item) => {
13461384
match item.node {
1347-
ItemFn(.., ref generics, _) |
1385+
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
1386+
13481387
ItemImpl(_, _, _, ref generics, ..) |
13491388
ItemTy(_, ref generics) |
13501389
ItemEnum(_, ref generics) |
13511390
ItemStruct(_, ref generics) |
13521391
ItemUnion(_, ref generics) => {
1353-
generics
1392+
(generics, None)
13541393
}
13551394

13561395
ItemTrait(_, _, ref generics, .., ref items) => {
13571396
is_trait = Some((ty::TraitRef {
13581397
def_id,
13591398
substs: Substs::identity_for_item(tcx, def_id)
13601399
}, items));
1361-
generics
1400+
(generics, None)
13621401
}
13631402

1364-
_ => &no_generics
1403+
_ => (&no_generics, None)
13651404
}
13661405
}
13671406

13681407
NodeForeignItem(item) => {
13691408
match item.node {
1370-
ForeignItemStatic(..) => &no_generics,
1371-
ForeignItemFn(_, _, ref generics) => generics,
1372-
ForeignItemType => &no_generics,
1409+
ForeignItemStatic(..) => (&no_generics, None),
1410+
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
1411+
ForeignItemType => (&no_generics, None),
13731412
}
13741413
}
13751414

@@ -1387,7 +1426,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13871426
};
13881427
}
13891428

1390-
_ => &no_generics
1429+
_ => (&no_generics, None)
13911430
};
13921431

13931432
let generics = tcx.generics_of(def_id);
@@ -1518,6 +1557,19 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
15181557
}))
15191558
}
15201559

1560+
// Add predicates from impl Trait arguments
1561+
let fn_ins = opt_inputs.map(|tys| &tys[..]);
1562+
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
1563+
for info in univ_impl_trait_info.iter() {
1564+
let name = keywords::Invalid.name();
1565+
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
1566+
index += 1;
1567+
let bounds = compute_bounds(&icx, param_ty, info.bounds,
1568+
SizedByDefault::Yes,
1569+
info.span);
1570+
predicates.extend(bounds.predicates(tcx, param_ty));
1571+
}
1572+
15211573
// Subtle: before we store the predicates into the tcx, we
15221574
// sort them so that predicates like `T: Foo<Item=U>` come
15231575
// before uses of `U`. This avoids false ambiguity errors
@@ -1678,3 +1730,48 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
16781730
_ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
16791731
}
16801732
}
1733+
1734+
struct ImplTraitUniversalInfo<'hir> {
1735+
def_id: DefId,
1736+
span: Span,
1737+
bounds: &'hir [hir::TyParamBound],
1738+
}
1739+
1740+
/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal
1741+
/// arguments
1742+
fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1743+
opt_inputs: Option<&'tcx [P<hir::Ty>]>)
1744+
-> Vec<ImplTraitUniversalInfo<'tcx>>
1745+
{
1746+
// A visitor for simply collecting Universally quantified impl Trait arguments
1747+
struct ImplTraitUniversalVisitor<'tcx> {
1748+
items: Vec<&'tcx hir::Ty>
1749+
}
1750+
1751+
impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> {
1752+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1753+
NestedVisitorMap::None
1754+
}
1755+
1756+
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
1757+
if let hir::TyImplTraitUniversal(..) = ty.node {
1758+
self.items.push(ty);
1759+
}
1760+
intravisit::walk_ty(self, ty);
1761+
}
1762+
}
1763+
1764+
let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() };
1765+
opt_inputs.map(|inputs| for t in inputs.iter() {
1766+
visitor.visit_ty(t);
1767+
});
1768+
visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node {
1769+
ImplTraitUniversalInfo {
1770+
def_id: tcx.hir.local_def_id(ty.id),
1771+
span: ty.span,
1772+
bounds: bounds
1773+
}
1774+
} else {
1775+
span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug")
1776+
}).collect()
1777+
}

0 commit comments

Comments
 (0)