gpt4 book ai didi

rust - 一个结构域的析构函数依赖于另一个结构域而没有任何关联

转载 作者:行者123 更新时间:2023-12-03 11:44:26 24 4
gpt4 key购买 nike

我试图提供一个简短的可复制示例,但无法重现我的问题,因此我从主要代码中剥离了大部分内容,从而保留了该错误。
lib.rs

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::{quote};
use syn::{
parse_macro_input, Data, DeriveInput, Field, Fields, Ident,
Type, TypeGenerics,
};

struct IterMapped<Ret, T: Iterator + Clone> {
iter: T,
map_func: Box<dyn FnMut(T::Item) -> Ret>,
}

impl<Ret, T: Iterator + Clone> IterMapped<Ret, T> {
pub fn new(iter: T, map_func: Box<dyn FnMut(T::Item) -> Ret>) -> Self {
IterMapped { iter, map_func }
}
}

enum BuilderField<'a> {
Optional(&'a Field, &'a Type),
Mandatory(&'a Field),
}

struct BuilderData<'a> {
struct_name: &'a Ident,
builder_struct_name: &'a Ident,
ty_generics: &'a TypeGenerics<'a>,
fields_mapped_iter: IterMapped<BuilderField<'a>, syn::punctuated::Iter<'a, Field>>,
}

#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
let derive_input = parse_macro_input!(input as DeriveInput);

let data = &derive_input.data;

let struct_name = &derive_input.ident;
let (impl_generics, ty_generics_temp, where_clause) = derive_input.generics.split_for_impl();

let fields_iter = match data {
Data::Struct(ref data_struct) => match data_struct.fields {
Fields::Named(ref fields_named) => fields_named.named.iter(),
Fields::Unnamed(_) | Fields::Unit => {
panic!()
}
},
_ => panic!()
};

let fields_mapped_iter = IterMapped::new(
fields_iter,
Box::new(|field| BuilderField::Mandatory(field)),
);

let ref ty_generics = ty_generics_temp;
let ref builder_struct_name = Ident::new(
&format!("{}Builder", struct_name),
proc_macro2::Span::call_site(),
);

let mut builder_data = BuilderData {
struct_name,
builder_struct_name,
ty_generics,
fields_mapped_iter,
};

TokenStream::from(quote!())
}
Cargo.toml
[package]
name = "derive_builder"
version = "0.0.0"
edition = "2018"
autotests = false
publish = false

[lib]
proc-macro = true

[dependencies]
syn = "1.0.48"
quote = "1.0.7"
proc-macro2 = "1.0.24"
运行它会产生以下错误:
error[E0716]: temporary value dropped while borrowed
--> builder/src/lib.rs:58:35
|
58 | let ref builder_struct_name = Ident::new(
| ___________________________________^
59 | | &format!("{}Builder", struct_name),
60 | | proc_macro2::Span::call_site(),
61 | | );
| |_____^ creates a temporary which is freed while still in use
...
71 | }
| -
| |
| temporary value is freed at the end of this statement
| borrow might be used here, when `fields_mapped_iter` is dropped and runs the destructor for type `IterMapped<BuilderField<'_>, syn::punctuated::Iter<'_, syn::data::Field>>`
|
= note: consider using a `let` binding to create a longer lived value
我不明白为什么要删除 builder_struct_name的临时效果 fields_mapped_iter。这两个是单独的字段。
如果我将 BuilderData更改为使用生存期 'b,则代码可以编译并正常工作:
struct BuilderData<'a, 'b> {
struct_name: &'a Ident,
builder_struct_name: &'a Ident,
ty_generics: &'a TypeGenerics<'a>,
fields_mapped_iter: IterMapped<BuilderField<'b>, syn::punctuated::Iter<'b, Field>>,
}
☝️将 BuilderData更改为此可以使代码正常工作。
如果我重新排列结构字段的声明顺序,并在设置 let ref builder_struct_name = …fields_iter之前移动 fields_mapped_iter,它会起作用,因为然后将这2个放在 builder_struct_name的温度之前。为什么他们的析构函数依赖 builder_struct_name的temp?

最佳答案

当作用域结束时,将以与声明变量相反的顺序删除变量。因此,BuilderData的生存期参数'a不能超出将builder_struct_name降低到fields_mapped_iter的整个使用生命周期时的范围。但是, syn::punctuated::Iter
要求其类型参数T的生命周期超过其
生存期参数'a

关于rust - 一个结构域的析构函数依赖于另一个结构域而没有任何关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64769867/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com