【问题标题】:Update to Rust 1.18 broke compilation: E0034 multiple applicable items in scope for "clone_into"Rust 1.18 的更新破坏了编译:E0034 “clone_into”范围内的多个适用项目
【发布时间】:2017-06-12 14:42:22
【问题描述】:

我有这个简单的sn-p代码,它使用一个arena进行内存分配和一个特征CloneInto,其目的是将一个结构从未知来源克隆到一个Arena中,并随着它的变化调整生命周期:

struct Arena;

impl Arena {
    fn insert<'a, T: 'a>(&'a self, _: T) -> &'a mut T { unimplemented!() }
}

trait CloneInto<'a> {
    type Output: 'a;
    fn clone_into(&self, arena: &'a Arena) -> Self::Output;
}

可以直接使用:

#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
struct Simple<'a> { a: &'a usize }

impl<'a, 'target> CloneInto<'target> for Simple<'a> {
    type Output = Simple<'target>;

    fn clone_into(&self, arena: &'target Arena) -> Simple<'target> {
        Simple { a: arena.insert(*self.a) }
    }
}

fn main() {
    let arena = Arena;
    let _ = Simple { a: &1 }.clone_into(&arena);
}

或者可以,直到更新到 Rust 1.18。现在compiler emits this error

error[E0034]: multiple applicable items in scope
  --> <anon>:25:30
   |
25 |     let _ = Simple { a: &1 }.clone_into(&arena);
   |                              ^^^^^^^^^^ multiple `clone_into` found
   |
note: candidate #1 is defined in an impl of the trait `CloneInto` for the type `Simple<'_>`
  --> <anon>:18:5
   |
18 | /     fn clone_into(&self, arena: &'target Arena) -> Simple<'target> {
19 | |         Simple { a: arena.insert(*self.a) }
20 | |     }
   | |_____^
   = note: candidate #2 is defined in an impl of the trait `std::borrow::ToOwned` for the type `_`

即使我什至不导入stdToOwned

【问题讨论】:

  • ToOwnedprelude 中,所以是的,您正在导入它!
  • @FrancisGagné:说得好。否则不会引起冲突。

标签: rust


【解决方案1】:

这是 Rust 中方法解析如何工作的不幸影响。与其他具有重载功能的语言不同,在 Rust 中,必须明确地解析要调用的函数,而不考虑其参数。

在这种特定情况下,Rust 1.18 在 ToOwned 特征上引入了一个名为 clone_into 的新夜间方法,并且 ToOwned 特征对所有实现 Clone 的类型无条件实现并自动导入(通过 @987654322 @)。

这个方法不能在 stable 上调用的事实没有任何意义;方法先考虑解析,实际使用会报错。

请注意,即使令人讨厌,这种解决方法也有好处:人们通常不清楚当多个似乎可用时选择了哪个重载,或者为什么没有选择预期的重载。由于在明确性方面犯了错误,Rust 让它变得轻而易举。

不幸的是,在这种情况下,这会导致 Simple::clone_into() 变得模棱两可。

没有办法选择退出ToOwned 实现(除非放弃CloneCopy),因此必须切换到使用Fully Qualified Syntax (FQS) 明确调用clone_into

fn main() {
    let arena = Arena;
    let _ = CloneInto::clone_into(&Simple { a: &1 }, &arena);
}

【讨论】:

    猜你喜欢
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    相关资源
    最近更新 更多