本文介绍了为什么对数组的嵌套引用不会强制切片?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了从头到尾,但我仍然对从数组到切片的强制转换有疑问。



让我们考虑以下代码:

  let arr:& [i32; 5] =&& [1、2、3、4、5]; 
// //让arr:& [i32] =&& [1、2、3、4、5]; //错误;预期切片,找到参考

我希望&& [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



数组强制转换为切片的条件是什么?我不了解前者和后者的代码之间的区别。



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


解决方案

这种强制性旨在发挥作用,但不起作用


做没有实现 Deref ,因此强制& [T; n]-> & [T] 不是deref强制,因此其工作方式与deref强制相同。取而代之的是,它被称为超大强制。因为它将大小类型( [T; n] )转换为无大小类型( [T] )。 / p>

也就是说,,未完全支持的是套期保值;说未实现会更准确。因此,目前,通过传递性强制转换是完全不可能的。显然,此问题并不是一个高度优先的问题,可能是因为大小不大的阵列并不常见。 (我怀疑当const泛型登陆时,这可能会成为更常见的抱怨,因为这可能会使数组更有用。)


那为什么这样做 arr.first()工作吗?好吧,用于查找用调用的方法。(点)运算符是强制规则的扩展。 Autoderef类似于手动取消引用多次,直到使用给定方法获得某些内容(可以强制转换为某种类型)为止。这意味着您不需要传递性即可通过autoderef(RFC 401称为接收方强制)找到方法调用。




进一步阅读


描述了大多数强制的预期语义。该RFC已于5年前合并。从那时起,许多事情发生了变化,但仍然没有完全实现(其跟踪问题是),因此RFC 401无法准确地描述Rust的任何过去,现在或将来的版本。但是,RFC 401 将允许强制&& [i32; 5] & [i32] ,并且逻辑几乎相同。


也有关于强制的一章,似乎与参考书一致。


I read What are Rust's exact auto-dereferencing rules? from beginning to end, but I still have a question about the coercion from array to slice.

Let us think about the following code:

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

I would expect that &&&[1, 2, 3, 4, 5] has the type, &&&[i32; 5] and dereferences to &&[i32; 5] => &[i32; 5] => &[i32; 5] => &[i32],but the result is different from what I expected.

I tried to run the following code:

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

That's the correct code. The type of arr is coerced to &&&[i32; 5] => &&[i32; 5] => &[i32; 5] => &[i32] and matches to the first argument of first in slice, &self.

What's the condition that arrays coerce to slices? I don't understand the difference between the former and the latter code.

I also checked the documentation in the source code, and guess that the above question has something to do with the sentence cited below;

解决方案

This kind of coercion is intended to work, but not implemented.

Arrays do not implement Deref, so the coercion &[T; n] -> &[T] is not a deref coercion and does not work in quite the same way as one. Instead, it's called an "unsized coercion" because it turns a sized type ([T; n]) into an unsized one ([T]).

That said, the language reference (which is not normative and may be outdated, but bear with me) lists the possible coercions, including the following (emphasis added):

The last bullet, unsized coercion, is what allows &[T; n] to coerce to &[T]. Notably, this only describes one layer of referencing; it doesn't cover the &&[T; n] -> &[T] case (for which we also need Deref coercion).

Back to your non-working example:

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

The intended coercion is &&&[i32; 5] -> &[i32]. We can work out how this coercion ought to work:

  1. &[i32; 5] coerces to &[i32] by unsizing;
  2. &&[i32; 5] coerces to &[i32; 5] by Deref;
  3. therefore, &&[i32; 5] coerces to &[i32] by transitivity.
  4. &&&[i32; 5] coerces to &&[i32; 5] by Deref;
  5. therefore, &&&[i32; 5] coerces to &[i32] by transitivity.

But it doesn't. The quote above hints at why: under the transitive case, it says "Note that this is not fully supported yet". As far as I can tell, according to issue #18602, "not fully supported" is a hedge; it would be more accurate to say "unimplemented". So, for now, coercion via transitivity is not possible at all. Apparently this issue is not a high priority, probably because sized arrays aren't very common. (I suspect this might become a more common complaint when const generics land, since that may make arrays more useful.)

So why does arr.first() work? Well, the "auto-dereferencing rules" used to find methods invoked with the . (dot) operator are an extension of the coercion rules. Autoderef is similar to manually dereferencing any number of times until you get something (that can be coerced to a type) with the given method. This means you don't need transitivity to find method calls through autoderef (which RFC 401 calls "receiver coercion").


Further reading

RFC #401 describes intended semantics of most coercions. This RFC was merged over 5 years ago. Many things have changed since then, but it is still not fully implemented (its tracking issue is #18469), so RFC 401 does not accurately describe any past, present, or future version of Rust. Nevertheless, RFC 401 also would permit coercion of &&&[i32; 5] to &[i32] and by almost the same logic.

The Rustonomicon also has a chapter on coercions and appears to agree with the reference book.

这篇关于为什么对数组的嵌套引用不会强制切片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-08 17:53