Impl fields resolving, vol.4 [skip ci]
This commit is contained in:
parent
129ff559d1
commit
bf219867b6
2 changed files with 44 additions and 7 deletions
|
@ -7,7 +7,7 @@ pub(crate) mod downcaster;
|
||||||
use std::{any::TypeId, iter, mem};
|
use std::{any::TypeId, iter, mem};
|
||||||
|
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::{quote, format_ident};
|
||||||
use syn::{
|
use syn::{
|
||||||
ext::IdentExt as _,
|
ext::IdentExt as _,
|
||||||
parse::{Parse, ParseBuffer},
|
parse::{Parse, ParseBuffer},
|
||||||
|
@ -105,15 +105,29 @@ pub(crate) trait TypeExt {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn unreferenced(&self) -> &Self;
|
fn unreferenced(&self) -> &Self;
|
||||||
|
|
||||||
/// Iterates mutably over all the lifetime parameters of this [`syn::Type`]
|
/// Iterates mutably over all the lifetime parameters (even implicit) of
|
||||||
/// with the given `func`tion.
|
/// this [`syn::Type`] with the given `func`tion.
|
||||||
fn lifetimes_iter_mut<F: FnMut(&mut syn::Lifetime)>(&mut self, func: &mut F);
|
fn lifetimes_iter_mut<F: FnMut(&mut Option<syn::Lifetime>)>(&mut self, func: &mut F);
|
||||||
|
|
||||||
|
/// Iterates mutably over all the named lifetime parameters (explicit only)
|
||||||
|
/// of this [`syn::Type`] with the given `func`tion.
|
||||||
|
fn named_lifetimes_iter_mut<F: FnMut(&mut syn::Lifetime)>(&mut self, func: &mut F) {
|
||||||
|
self.lifetimes_iter_mut(&mut |lt| {
|
||||||
|
if let Some(lt) = lt {
|
||||||
|
func(lt);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Anonymizes all the lifetime parameters of this [`syn::Type`] (except
|
/// Anonymizes all the lifetime parameters of this [`syn::Type`] (except
|
||||||
/// the `'static` ones), making it suitable for using in contexts with
|
/// the `'static` ones), making it suitable for using in contexts with
|
||||||
/// inferring.
|
/// inferring.
|
||||||
fn lifetimes_anonymized(&mut self);
|
fn lifetimes_anonymized(&mut self);
|
||||||
|
|
||||||
|
/// Lifts all the lifetimes of this [`syn::Type`] (except `'static`) to a
|
||||||
|
/// `for<>` quantifier, preserving the type speciality as much as possible.
|
||||||
|
fn to_hrtb_lifetimes(&self) -> (Option<syn::BoundLifetimes>, syn::Type);
|
||||||
|
|
||||||
/// Returns the topmost [`syn::Ident`] of this [`syn::TypePath`], if any.
|
/// Returns the topmost [`syn::Ident`] of this [`syn::TypePath`], if any.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn topmost_ident(&self) -> Option<&syn::Ident>;
|
fn topmost_ident(&self) -> Option<&syn::Ident>;
|
||||||
|
@ -135,7 +149,7 @@ impl TypeExt for syn::Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lifetimes_iter_mut<F: FnMut(&mut syn::Lifetime)>(&mut self, func: &mut F) {
|
fn lifetimes_iter_mut<F: FnMut(&mut Option<syn::Lifetime>)>(&mut self, func: &mut F) {
|
||||||
use syn::{GenericArgument as GA, Type as T};
|
use syn::{GenericArgument as GA, Type as T};
|
||||||
|
|
||||||
fn iter_path<F: FnMut(&mut syn::Lifetime)>(path: &mut syn::Path, func: &mut F) {
|
fn iter_path<F: FnMut(&mut syn::Lifetime)>(path: &mut syn::Path, func: &mut F) {
|
||||||
|
@ -213,13 +227,36 @@ impl TypeExt for syn::Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lifetimes_anonymized(&mut self) {
|
fn lifetimes_anonymized(&mut self) {
|
||||||
self.lifetimes_iter_mut(&mut |lt| {
|
self.named_lifetimes_iter_mut(&mut |lt| {
|
||||||
if lt.ident != "_" && lt.ident != "static" {
|
if lt.ident != "_" && lt.ident != "static" {
|
||||||
lt.ident = syn::Ident::new("_", Span::call_site());
|
lt.ident = syn::Ident::new("_", Span::call_site());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_hrtb_lifetimes(&self) -> (Option<syn::BoundLifetimes>, syn::Type) {
|
||||||
|
let mut ty = self.clone();
|
||||||
|
let mut lts = vec![];
|
||||||
|
|
||||||
|
let anon_ident = &syn::Ident::new("_", Span::call_site());
|
||||||
|
|
||||||
|
ty.lifetimes_iter_mut(&mut |lt| {
|
||||||
|
let ident = lt.map(|l| l.ident).unwrap_or(anon_ident);
|
||||||
|
if ident != "static" {
|
||||||
|
let ident = format_ident!("__fa_f_{ident}");
|
||||||
|
if !lts.contains(&ident) {
|
||||||
|
lts.push(ident);
|
||||||
|
}
|
||||||
|
*lt = Some(parse_quote! { '#ident })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let for_ = (!lts.is_empty()).then(|| parse_quote! {
|
||||||
|
for< #( #lts ),* >}
|
||||||
|
);
|
||||||
|
(for_, ty)
|
||||||
|
}
|
||||||
|
|
||||||
fn topmost_ident(&self) -> Option<&syn::Ident> {
|
fn topmost_ident(&self) -> Option<&syn::Ident> {
|
||||||
match self.unparenthesized() {
|
match self.unparenthesized() {
|
||||||
syn::Type::Path(p) => Some(&p.path),
|
syn::Type::Path(p) => Some(&p.path),
|
||||||
|
|
|
@ -323,7 +323,7 @@ impl<Operation: ?Sized + 'static> Definition<Operation> {
|
||||||
// Modify lifetime names to omit "lifetime name `'a` shadows a
|
// Modify lifetime names to omit "lifetime name `'a` shadows a
|
||||||
// lifetime name that is already in scope" error.
|
// lifetime name that is already in scope" error.
|
||||||
let mut ty = self.ty.clone();
|
let mut ty = self.ty.clone();
|
||||||
ty.lifetimes_iter_mut(&mut |lt| {
|
ty.named_lifetimes_iter_mut(&mut |lt| {
|
||||||
let ident = lt.ident.unraw();
|
let ident = lt.ident.unraw();
|
||||||
lt.ident = format_ident!("__fa__{ident}");
|
lt.ident = format_ident!("__fa__{ident}");
|
||||||
lifetimes.push(lt.clone());
|
lifetimes.push(lt.clone());
|
||||||
|
|
Loading…
Reference in a new issue