我们必须放弃 From Trait 以使代码可导航

huangapple go评论69阅读模式
英文:

Must we ditch From Trait to make code navigable

问题

We found the rust From trait is lacking IDE (both PyCharm and vscode) support:

impl From<A> for B {
    fn from(order: A) -> Self {...}  // Impl
}

// order is of Type A
let order: B = order.into();  // Usage

Neither IDE is able to navigate from usage to implementation or vice versa.
If we use

let order = B::from(order);

then navigating from usage to impl is a breeze, but from impl to usage takes vscode 10 seconds on our code base.

If we ditch the From trait altogether, i.e.

impl B {
    pub(crate) fn from(order: A) -> Self {...}
}

then navigating either direction is instantaneous. Our Rust-consultants hate this, but we Rust beginners will understand and maintain the code base so much more efficiently!

Is there a best practice to get IDEs properly navigating (ctrl+left-click and "Go to reference") between From usage and implementation.

英文:

We found the rust From trait is lacking IDE (both PyCharm and vscode) support:

impl From&lt;A&gt; for B {
    fn from(order: A) -&gt; Self {...}  // Impl
}

// order is of Type A
let order: B = order.into();  // Usage

Neither IDE is able to navigate from usage to implementation or vice versa.
If we use

let order = B::from(order);

then navigating from usage to impl is a breeze, but from impl to usage takes vscode 10 seconds on our code base.

If we ditch the From trait altogether, i.e.

impl B {
    pub(crate) fn from(order: A) -&gt; Self {...}
}

then navigating either direction is instantaneous. Our Rust-consultants hate this, but we Rust beginners will understand and maintain the code base so much more efficiently!

Is there a best practice to get IDEs properly navigating (ctrl+left-click and "Go to reference") between From usage and implementation.

答案1

得分: 0

以下是您要翻译的内容:

"Go to X"行为在使用rust-analyzer的VSCode中按我所期望的方式工作,但我可以理解由于From/Into的设计方式可能会令人不满。

.into()方法并不是由From特性提供的,而是由Into特性提供的。之所以实现From似乎允许.into()工作,是因为Into通用实现实现了Into<U> for T where U: From<T>。因此,几乎没有直接实现Into的情况,而是实现了From

在您的IDE中,这意味着导航到.into()几乎总是会将您引导到通用实现,这并不是非常有帮助,但这也是我所期望的。在this issue中有一些关于导航到相关From实现的讨论,尽管目前尚未有任何结果,并且可能必须作为特殊情况处理。

但是,通过::from(_)导航似乎完全正常:例如,在String::from("")上执行"转到实现"将导航到From<&str> for String实现,从那里导航到fn from(...会显示给我所有使用该特定实现的情况。这需要一点时间,但我只在一个中等规模的代码库上进行了测试,所以如果性能对您是个问题,那么您可以提交一个问题。

尽管如此,如果您不想使用From,那么您不需要使用它。如果您依赖于在通用上下文中使用转换,那么将需要一个From实现,因此如果合适的话,我鼓励您提供它。但这并不意味着您必须直接在自己的代码中使用它:如果from_a()into_b()可以提高清晰度,那么请添加它作为一个选项。甚至标准库也这样做(例如,查看String::into_bytesFrom<String> for Vec<u8>)。我不建议使用内在的frominto方法,因为这很容易与特性方法混淆;给它一个更好的名字。

最后,请不要把所有的鸡蛋都放在一个篮子里。特别是对于初学者来说。您的IDE只是可发现性的一个来源:生成的文档以及任何额外的示例、测试和mdbooks共同组成了完整的理解。

英文:

The "Go to X" behavior works both ways as I'd expect in VSCode with rust-analyzer, but I can see how it can be unsatisfying due to how From/Into is designed.

The .into() method is not provided by the From trait, it is provided by the Into trait. The reason that implementing From seems to allow .into() to work is due to Into's generic implementation that implements Into&lt;U&gt; for T where U: From&lt;T&gt;. And because of that behavior, almost nothing implements Into directly and would implement From instead.

What this means in your IDE though is that navigating to .into() will almost always lead you to the generic implementation, which isn't very helpful but its also what I'd expect. There is some discussion in this issue that would propose navigating to the relevant From implementation instead, though nothing has come of it yet and would have to be handled as a special case.

But navigating via ::from(_) appears to work just fine: "Go to implementation" on String::from(&quot;&quot;) for example leads to the From&lt;&amp;str&gt; for String implementation, and navigating from fn from(... there shows me all uses of that particular implementation. It takes a moment but I've only tested on a medium-ish code base so if the performance is a problem for you then you can file an issue.

That all being said, you don't need to use From if you don't want to. A From implementation would be required if you relied on utilizing the conversion in a generic context and thus I would encourage you to provide it anyway if at all appropriate. But that doesn't mean you have to use it directly in your own code: if from_a() or into_b() improves clarity then by all means add that as an option as well. Even the standard library does it (see String::into_bytes vs From&lt;String&gt; for Vec&lt;u8&gt; for example). I wouldn't recommend an inherent from or into method since that would be easily confused with the trait method; give it a better name.

And as a final note, you shouldn't put all your eggs in one basket. Especially as a beginner. Your IDE is only one source of discoverability: the generated documentation and any supplemental examples, tests, and mdbooks work together to form a complete understanding.

huangapple
  • 本文由 发表于 2023年5月21日 15:35:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定