1 use proc_macro2
::TokenStream
;
3 use std
::collections
::btree_map
::Entry
;
4 use std
::collections
::{BTreeMap as Map, BTreeSet as Set}
;
5 use syn
::punctuated
::Punctuated
;
6 use syn
::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause}
;
8 pub struct ParamsInScope
<'a
> {
12 impl<'a
> ParamsInScope
<'a
> {
13 pub fn new(generics
: &'a Generics
) -> Self {
15 names
: generics
.type_params().map(|param
| ¶m
.ident
).collect(),
19 pub fn intersects(&self, ty
: &Type
) -> bool
{
20 let mut found
= false;
21 crawl(self, ty
, &mut found
);
26 fn crawl(in_scope
: &ParamsInScope
, ty
: &Type
, found
: &mut bool
) {
27 if let Type
::Path(ty
) = ty
{
28 if ty
.qself
.is_none() {
29 if let Some(ident
) = ty
.path
.get_ident() {
30 if in_scope
.names
.contains(ident
) {
35 for segment
in &ty
.path
.segments
{
36 if let PathArguments
::AngleBracketed(arguments
) = &segment
.arguments
{
37 for arg
in &arguments
.args
{
38 if let GenericArgument
::Type(ty
) = arg
{
39 crawl(in_scope
, ty
, found
);
47 pub struct InferredBounds
{
48 bounds
: Map
<String
, (Set
<String
>, Punctuated
<TokenStream
, Token
![+]>)>,
49 order
: Vec
<TokenStream
>,
53 pub fn new() -> Self {
60 #[allow(clippy::type_repetition_in_bounds, clippy::trait_duplication_in_bounds)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8771
61 pub fn insert(&mut self, ty
: impl ToTokens
, bound
: impl ToTokens
) {
62 let ty
= ty
.to_token_stream();
63 let bound
= bound
.to_token_stream();
64 let entry
= self.bounds
.entry(ty
.to_string());
65 if let Entry
::Vacant(_
) = entry
{
68 let (set
, tokens
) = entry
.or_default();
69 if set
.insert(bound
.to_string()) {
74 pub fn augment_where_clause(&self, generics
: &Generics
) -> WhereClause
{
75 let mut generics
= generics
.clone();
76 let where_clause
= generics
.make_where_clause();
77 for ty
in &self.order
{
78 let (_set
, bounds
) = &self.bounds
[&ty
.to_string()];
79 where_clause
.predicates
.push(parse_quote
!(#ty: #bounds));
81 generics
.where_clause
.unwrap()