Skip to content

Commit e572d92

Browse files
authored
Merge pull request #194 from dtolnay/parambounds
Move bounds from generic param list to where-clause after 'async_trait bound
2 parents 0b31ad9 + 46c3023 commit e572d92

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

src/expand.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf};
44
use proc_macro2::TokenStream;
55
use quote::{format_ident, quote, quote_spanned, ToTokens};
66
use std::collections::BTreeSet as Set;
7+
use std::mem;
78
use syn::punctuated::Punctuated;
89
use syn::visit_mut::{self, VisitMut};
910
use syn::{
1011
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericParam, Generics, Ident,
11-
ImplItem, Lifetime, Pat, PatIdent, Receiver, ReturnType, Signature, Stmt, Token, TraitItem,
12-
Type, TypeParamBound, TypePath, WhereClause,
12+
ImplItem, Lifetime, LifetimeDef, Pat, PatIdent, Receiver, ReturnType, Signature, Stmt, Token,
13+
TraitItem, Type, TypeParamBound, TypePath, WhereClause,
1314
};
1415

1516
impl ToTokens for Item {
@@ -34,17 +35,18 @@ enum Context<'a> {
3435
}
3536

3637
impl Context<'_> {
37-
fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a GenericParam> {
38+
fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a LifetimeDef> {
3839
let generics = match self {
3940
Context::Trait { generics, .. } => generics,
4041
Context::Impl { impl_generics, .. } => impl_generics,
4142
};
42-
generics.params.iter().filter(move |param| {
43+
generics.params.iter().filter_map(move |param| {
4344
if let GenericParam::Lifetime(param) = param {
44-
used.contains(&param.lifetime)
45-
} else {
46-
false
45+
if used.contains(&param.lifetime) {
46+
return Some(param);
47+
}
4748
}
49+
None
4850
})
4951
}
5052
}
@@ -178,31 +180,42 @@ fn transform_sig(
178180
}
179181
}
180182

181-
for param in sig
182-
.generics
183-
.params
184-
.iter()
185-
.chain(context.lifetimes(&lifetimes.explicit))
186-
{
183+
for param in &mut sig.generics.params {
187184
match param {
188185
GenericParam::Type(param) => {
189-
let param = &param.ident;
190-
let span = param.span();
186+
let param_name = &param.ident;
187+
let span = match param.colon_token.take() {
188+
Some(colon_token) => colon_token.span,
189+
None => param_name.span(),
190+
};
191+
let bounds = mem::replace(&mut param.bounds, Punctuated::new());
191192
where_clause_or_default(&mut sig.generics.where_clause)
192193
.predicates
193-
.push(parse_quote_spanned!(span=> #param: 'async_trait));
194+
.push(parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds));
194195
}
195196
GenericParam::Lifetime(param) => {
196-
let param = &param.lifetime;
197-
let span = param.span();
197+
let param_name = &param.lifetime;
198+
let span = match param.colon_token.take() {
199+
Some(colon_token) => colon_token.span,
200+
None => param_name.span(),
201+
};
202+
let bounds = mem::replace(&mut param.bounds, Punctuated::new());
198203
where_clause_or_default(&mut sig.generics.where_clause)
199204
.predicates
200-
.push(parse_quote_spanned!(span=> #param: 'async_trait));
205+
.push(parse_quote_spanned!(span=> #param: 'async_trait + #bounds));
201206
}
202207
GenericParam::Const(_) => {}
203208
}
204209
}
205210

211+
for param in context.lifetimes(&lifetimes.explicit) {
212+
let param = &param.lifetime;
213+
let span = param.span();
214+
where_clause_or_default(&mut sig.generics.where_clause)
215+
.predicates
216+
.push(parse_quote_spanned!(span=> #param: 'async_trait));
217+
}
218+
206219
if sig.generics.lt_token.is_none() {
207220
sig.generics.lt_token = Some(Token![<](sig.ident.span()));
208221
}

tests/ui/consider-restricting.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ note: captured value is not `Send`
1212
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
1313
help: consider further restricting this bound
1414
|
15-
16 | async fn publish<T + std::marker::Send: IntoUrl>(&self, url: T) {}
16-
| +++++++++++++++++++
15+
16 | async fn publish<T: IntoUrl + std::marker::Send>(&self, url: T) {}
16+
| +++++++++++++++++++
1717

1818
error: future cannot be sent between threads safely
1919
--> tests/ui/consider-restricting.rs:23:40

0 commit comments

Comments
 (0)