【发布时间】:2021-07-07 08:18:37
【问题描述】:
有没有办法获取在 Rust 中初始化值的位置和文件名?我知道file! 和line! 宏,但它们提供了它们最初被调用的位置的信息,我希望从值的初始化位置确定这些信息。比如下面的代码不起作用,但和我想要的差不多:
// Contains a value as well as where this value was initialized
struct Foo {
value : usize,
file : String,
line : u32,
}
impl Foo {
fn new(value : usize) -> Foo {
Foo {
value,
file : String::from(std::file!()),
line : std::line!(),
}
}
}
// Test the result
fn main() {
let foo1 = Foo::new(0);
println!("foo1 created in file \"{}\" line {}",foo1.file,foo1.line);
let foo2 = Foo::new(1);
println!("foo2 created in file \"{}\" line {}",foo2.file,foo2.line);
}
返回
foo1 created in file "src/main.rs" line 12
foo2 created in file "src/main.rs" line 12
其中不包含创建值的正确行号。我也在尝试尽可能透明地执行此操作,以便用户无需为创建的每个值输入宏。至于为什么,我试图在代码中插入一些调试信息,这将有助于用户了解该值是在代码中的哪个位置创建的。
【问题讨论】:
-
我认为这是不可能的,除非您定义自己的过程宏(即使那样它也很不确定,因为很难在其他 crate 中找到类型并由宏定义)。你需要这个功能做什么?当执行恐慌时,它应该出现在问题区域以帮助用户找到问题。如果您定义了一个单独的函数来执行恐慌,您可能需要考虑将其转换为宏。
-
它用于调试,问题是恐慌会给出恐慌的位置,而不是实例化值的位置。我在看一个自动区分代码。在代码中,一个值可能是可微分的,但它并不重要,除非用户要求该值的导数。例如,
abs(0)给出了一个有效值,但它不可微。因此,在派生处理期间会引发恐慌,但随后用户不知道问题发生在代码中的哪个位置。他们只会知道导数处理的位置,这没什么帮助 -
我不确定我是否完全理解你,但听起来你想显示错误发生在被区分的函数的哪个位置,而不是在代码中的哪个位置被定义。我想这会更容易通过返回
Err(x)而不是恐慌来实现,这样当错误沿调用堆栈向上传播时,可以将周围的上下文添加到x。然后,一旦用户解开错误,您就可以使用自定义的Debug实现来突出显示存在问题的部分。 -
是的,我认为有一个误解。我需要原始值实例化发生的位置。尝试这个。想象一个代码,我们在其中创建了一组表示为树的排序值。我们从一个空集开始,然后使用语法
set.insert(x)添加新值。现在,我们可以添加任何值,这不是错误。然而,如果我们调用set.process(),如果集合包含任何,比如零,我们想抛出一个错误。在那个错误中,我们想知道set.insert(0)发生在哪里,但并不真正关心set.process()发生在哪里。正常的恐慌或错误会给出后者。我想要前者。
标签: rust