在Rust 1.14中,Index特征定义如下:
pub trait Index<Idx> where Idx: ?Sized {
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}
Run Code Online (Sandbox Code Playgroud)
这里放宽Sized了Output类型的隐式绑定?Sized.这是有道理的,因为该index()方法返回一个引用Output.因此,可以使用未实现的类型,这是有用的; 例:
impl<T> Index<Range<usize>> for Vec<T> {
type Output = [T]; // unsized!
fn index(&self, index: Range<usize>) -> &[T] { … } // no problem: &[T] is sized!
}
Run Code Online (Sandbox Code Playgroud)
该Idx类型参数的隐式绑定也轻松,可以无胶.但是Idx作为方法参数使用值,并且使用未定义类型作为参数是不可能的AFAIK.为什么Idx允许不合格?
我有以下Rust程序,我希望它会导致编译错误,因为x稍后会重新分配.但它符合并提供输出.为什么?
fn main() {
let (x, y) = (1, 3);
println!("X is {} and Y is {}", x, y);
let x: i32 = 565;
println!("Now X is {}", x);
}
Run Code Online (Sandbox Code Playgroud) 为什么这个指针算术(没有读取或写入这些指针后面的数据)是segfault的原因?
#![allow(dead_code,unused_variables)]
use std::cell::Cell;
struct Bar<T: ?Sized> {
a: Cell<usize>,
value: T,
}
unsafe fn foo<T: ?Sized>(v: &T) {
let fake: &Bar<T> = std::mem::zeroed();
// segfault on this line
// we are not reading or writing uninitialized data behind the reference,
// but only doing pointer arithmetic. We are not reading or writing
// uninitialized vtable, but only copy the vtable pointer.
let fake_val = &fake.value;
}
fn main() {
use std::any::Any;
let some_ref: &Any = &42 as &Any;
unsafe …Run Code Online (Sandbox Code Playgroud) 我有一个特性,我想为所有实现的类型实现它std::ops::Index.这段代码有效(正如我所料):
use std::ops::Index;
use std::fmt::Display;
trait Foo {
fn foo(&self, i: usize) -> &Display;
}
impl<C> Foo for C
where
C: Index<usize>,
C::Output: Display + Sized,
{
fn foo(&self, i: usize) -> &Display {
&self[i]
}
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
但是,一旦我将一个通用参数引入我的特性,我就会遇到奇怪的生命周期错误.这是代码(Playground):
trait Foo<T> {
fn foo(&self, i: T) -> &Display;
}
impl<C, T> Foo<T> for C
where
C: Index<T>,
C::Output: Display + Sized,
{
fn foo(&self, i: T) -> &Display {
&self[i]
}
}
Run Code Online (Sandbox Code Playgroud)
而奇怪的错误(显然这是一个错误,在略有不同的版本中重复三次): …
尝试将impl添加Add<char> for String到标准库时遇到了这个问题。但是我们可以轻松地复制它,而无需操作员恶作剧。我们从这个开始:
trait MyAdd<Rhs> {
fn add(self, rhs: Rhs) -> Self;
}
impl MyAdd<&str> for String {
fn add(mut self, rhs: &str) -> Self {
self.push_str(rhs);
self
}
}
Run Code Online (Sandbox Code Playgroud)
很简单。这样,将编译以下代码:
let a = String::from("a");
let b = String::from("b");
MyAdd::add(a, &b);
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,第二个参数表达式(&b)具有类型&String。然后将其反强制执行&str,然后函数调用起作用。
但是,让我们尝试添加以下内容:
impl MyAdd<char> for String {
fn add(mut self, rhs: char) -> Self {
self.push(rhs);
self
}
}
Run Code Online (Sandbox Code Playgroud)
(操场上的一切)
现在,MyAdd::add(a, &b)上面的表达式导致以下错误:
error[E0277]: the trait bound …Run Code Online (Sandbox Code Playgroud) let mut item = vec!["2", "3", "5"];
Run Code Online (Sandbox Code Playgroud)
我想连接该向量的第一个和第二个索引并替换为零索引的值。
item[0] = item[0] + item[1];
Run Code Online (Sandbox Code Playgroud)
但由于向量元素的类型&str以及连接后得到的结果是String,Rust 不允许我更新向量的值。
我想执行另一个进程,通常想等到它完成。假设我们在线程 T1 中生成并等待进程:
let child = Command::new("rustc").spawn().unwrap();
child.wait();
Run Code Online (Sandbox Code Playgroud)
现在,如果发生特殊事件(线程 T0 正在等待),我想终止生成的进程:
if let Ok(event) = special_event_notifier.recv() {
child.kill();
}
Run Code Online (Sandbox Code Playgroud)
但我看不出有什么办法可以做到这一点:两者kill都wait采用可变引用Child,因此是互斥的。打电话之后wait就没有人可以再参考了child。
我找到了wait-timeout箱子,但我想知道是否还有其他方法。
这是一个冗长的例子,因为我无法进一步减少它.铁锈游乐场
use std::marker::PhantomData;
use std::ops::{Add, Sub, Mul, Div};
pub trait Scalar
: Sized + Copy + Add<Self, Output = Self> + Sub<Self, Output = Self> + Mul<Self, Output = Self> + Div<Self, Output = Self>
{}
impl Scalar for u32 {}
pub struct ScalarVal<T>(T) where T: Scalar;
pub trait Pixel: Sized {
type ScalarType: Scalar;
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Gray<BaseTypeP>
where BaseTypeP: Scalar
{
intensity: BaseTypeP,
}
impl<BaseTypeP> Pixel for Gray<BaseTypeP>
where BaseTypeP: Scalar
{
type …Run Code Online (Sandbox Code Playgroud) 下面是mod文档给出的例子syn::parse。
enum Item {
Struct(ItemStruct),
Enum(ItemEnum),
}
struct ItemStruct {
struct_token: Token![struct],
ident: Ident,
brace_token: token::Brace,
fields: Punctuated<Field, Token![,]>,
}
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
input.parse().map(Item::Struct) // <-- here
} else if lookahead.peek(Token![enum]) {
input.parse().map(Item::Enum) // <-- and here
} else {
Err(lookahead.error())
}
}
}
Run Code Online (Sandbox Code Playgroud)
是input.parse().map(Item::Struct)有效的普通 Rust 语法(看起来不是Item::Struct函数),还是库的一种特殊语法proc_macro?如果是后者,是否有proc_macro具体语法规则的文档?
我有一个带有两个类型参数的结构,其中一个具有默认类型:
use std::marker::PhantomData;
struct Foo<T, F = ()>(PhantomData<(T, F)>);
impl<T, F> Foo<T, F> {
fn new() -> Self { Self(PhantomData) }
fn foo(&self, _: T) {}
}
let foo = Foo::new();
foo.foo(0u32);
Run Code Online (Sandbox Code Playgroud)
上面的代码导致:
error[E0282]: type annotations needed
--> src/main.rs:17:15
|
17 | let foo = Foo::new();
| --- ^^^^^^^^ cannot infer type for `F`
| |
| consider giving `foo` a type
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这里不使用默认类型。请注意,let foo: Foo<u32> = Foo::new();已经说过了-无需指定参数F。但是为什么要指定T?所以我已经很困惑。
但是后来我想起了所有这些HashMap!定义为struct HashMap<K, V, S …