为什么对数组的嵌套引用不会强制切片?

问题描述 投票:6回答:1

我从头到尾读了What are Rust's exact auto-dereferencing rules?,但我仍然有一个关于从数组到切片的强制的问题。

让我们考虑以下代码:

let arr: &[i32; 5] = &&&[1, 2, 3, 4, 5];
// let arr: &[i32] = &&&[1, 2, 3, 4, 5]; // Error; expected slice, found reference

我希望&&&[1, 2, 3, 4, 5]有类型,&&&[i32; 5]和解释引用&&[i32; 5] => &[i32; 5] => &[i32; 5] => &[i32],但结果与我的预期不同。

我试着运行以下代码:

let arr: &&&[i32; 5] = &&&[1, 2, 3, 4, 5];
let n = arr.first().unwrap(); // 1

这是正确的代码。 arr的类型被强制为&&&[i32; 5] => &&[i32; 5] => &[i32; 5] => &[i32]并与切片中的first的第一个参数匹配,&self

数组强制切片的条件是什么?我不明白前者和后者代码之间的区别。

我还检查了the documentation in the source code,并猜测上述问题与下面引用的句子有关;

然而,我们有时会沿途进行其他调整和强制,特别是不合规(例如,从[T; n]转换为[T])。

rust dereference coercion
1个回答
7
投票

这种胁迫旨在起作用,但没有实施。

Arrays没有实施Deref,所以胁迫&[T; n] -> &[T]不是一个deref强制,并没有与一个完全相同的方式工作。相反,它被称为“未确定的强制”,因为它将一个大小的类型([T; n])变成一个未大小的类型([T])。

那就是说,language reference(不是规范性的,可能已经过时,但对我而言)列出了可能的强制措施,包括以下内容(强调增加):

  • T_1T_3T_1强迫T_2T_2胁迫T_3(传递案) 请注意,尚未完全支持此功能
  • 如果&T实施&UTDeref<Target = U>
  • TyCtor(T)到TyCtor(U),其中TyCtor(T)是其中之一 &T &mut T *const T *mut T Box<T> 并且T可以从U获得unsized coercion

最后一个子弹,未经证实的强制,是允许&[T; n]强迫&[T]。值得注意的是,这仅描述了一层引用;它没有涵盖&&[T; n] - > &[T]案件(我们也需要Deref强制)。

回到你的非工作范例:

let arr: &[i32] = &&&[1, 2, 3, 4, 5];

预期的强制是&&&[i32; 5] - > &[i32]。我们可以弄清楚这种强制应该如何运作:

  1. &[i32; 5]通过不合格来强迫&[i32];
  2. &&[i32; 5]通过&[i32; 5]强迫Deref;
  3. 因此,&&[i32; 5]通过传递性强迫&[i32]
  4. &&&[i32; 5]通过&&[i32; 5]强迫Deref;
  5. 因此,&&&[i32; 5]通过传递性强迫&[i32]

但事实并非如此。上面的引用暗示了原因:在传递的情况下,它说“请注意,这还没有完全支持”。根据issue #18602的说法,据我所知,“不完全支持”是一种对冲;说“未实现”会更准确。所以,就目前而言,通过传递性的强制是不可能的。显然这个问题不是一个高优先级,可能是因为大小的数组并不常见。 (我怀疑当const泛型登陆时,这可能会成为一种更常见的抱怨,因为这可能会使数组更有用。)

那么为什么arr.first()工作?好吧,用于查找用"auto-dereferencing rules"(点)运算符调用的方法的.是强制规则的扩展。 Autoderef类似于手动解除引用任何次数,直到您使用给定方法获得某些内容(可以强制转换为某种类型)。这意味着您不需要传递性来通过autoderef(RFC 401称为“接收器强制”)来查找方法调用。


Further reading

RFC #401描述了大多数强制的预期语义。这个RFC在5年前就被合并了。从那时起,许多事情都发生了变化,但它仍未完全实现(其跟踪问题是#18469),因此RFC 401无法准确描述Rust的任何过去,现在或未来版本。然而,RFC 401也允许将&&&[i32; 5]强制到&[i32]并且几乎采用相同的逻辑。

Rustonomicon也有关于强制的章节,似乎同意参考书。

© www.soinside.com 2019 - 2024. All rights reserved.