Normalde, bir kütüphane genel bir türe Foo<T>
sahipse T
, bazı yerel türler olsa bile, aşağı akış kasaları üzerinde özellikler uygulayamaz . Örneğin,
( crate_a
)
struct Foo<T>(pub t: T)
( crate_b
)
use crate_a::Foo;
struct Bar;
// This causes an error
impl Clone for Foo<Bar> {
fn clone(&self) -> Self {
Foo(Bar)
}
}
Oyun alanında çalışan somut bir örnek için (yani, bir hata verir),
use std::rc::Rc;
struct Bar;
// This causes an error
// error[E0117]: only traits defined in the current crate
// can be implemented for arbitrary types
impl Default for Rc<Bar> {
fn default() -> Self {
Rc::new(Bar)
}
}
(oyun alanı)
Bu normalde sandık yazarının alt kasaları kırmadan özellik uygulamaları (battaniye) eklemesini sağlar. Bu, başlangıçta bir türün belirli bir özelliği uygulaması gerektiğinden emin olmadığı durumlarda harika, ancak daha sonra olması gerektiği açıktır. Örneğin, başlangıçta özellikleri uygulamayan bir tür sayısal türde olabilir num-traits
. Bu özellikler daha sonra kırılmaya ihtiyaç duyulmadan eklenebilir.
Bununla birlikte, bazı durumlarda, kütüphane yazarı, alt kasaların özellikleri kendileri uygulayabilmesini ister. Bu, #[fundamental]
özelliğin devreye girdiği yerdir . Bir türe yerleştirildiğinde, o tür için şu anda uygulanmayan herhangi bir özellik uygulanmayacaktır (bir kesme değişikliğini engeller). Sonuç olarak, aşağı akış kasaları, bir tür parametresi yerel olduğu sürece bu tür için özellikler uygulayabilir (bunun için hangi tür parametrelerinin sayıldığına karar vermek için bazı karmaşık kurallar vardır). Temel tür belirli bir özelliği uygulamadığından, bu özellik tutarlılık sorunlarına neden olmadan serbestçe uygulanabilir.
Örneğin Box<T>
, işaretlenir #[fundamental]
, bu nedenle aşağıdaki kod ( Rc<T>
yukarıdaki sürüme benzer ) çalışır. Box<T>
uygulamıyor Default
(sürece T
uygular Default
biz değil gelecekte çünkü varsayabiliriz böylece) Box<T>
esastır. Uygulanması unutmayın Default
için Bar
o zamandan beri sorunlara yol açacağını Box<Bar>
zaten uygular Default
.
struct Bar;
impl Default for Box<Bar> {
fn default() -> Self {
Box::new(Bar)
}
}
(oyun alanı)
Öte yandan, özellikler de ile işaretlenebilir #[fundamental]
. Bunun temel türler için ikili bir anlamı vardır. Herhangi bir tür şu anda temel bir özellik uygulamıyorsa, bu türün gelecekte uygulayamayacağı varsayılabilir (yine, bir kırılma değişikliğini engelleme). Bunun pratikte nasıl kullanıldığından tam olarak emin değilim. Kodda (aşağıda bağlantılıdır), FnMut
normal ifade (bir şey hakkında &str: !FnMut
) için gerekli olduğu notu ile temel olarak işaretlenmiştir . regex
Sandıkta nerede kullanıldığını veya başka bir yerde kullanıldığını bulamadım .
Teoride, eğer Add
özellik temel olarak işaretlenmişse (ki bu tartışılmıştır), bu zaten sahip olmayan şeyler arasında ekleme yapmak için kullanılabilir. Örneğin, [MyNumericType; 3]
belirli durumlarda yararlı olabilecek (elbette) eklemek (elbette, [T; N]
temel yapmak da buna izin verecektir).
İlkel temel türleri &T
, &mut T
(bkz burada jenerik ilkel türleri hepsi bir gösteri için). Standart kütüphanede Box<T>
ve Pin<T>
ayrıca temel olarak işaretlenmiştir.
Standart kütüphanede temel özelliklerdir Sized
, Fn<T>
, FnMut<T>
, FnOnce<T>
ve Generator
.
#[fundamental]
Özelliğin şu anda kararsız olduğunu unutmayın . İzleme sorunu 29635 numaralı sorun .
&T
,&mut T
,*const T
,*mut T
,[T; N]
,[T]
,fn
işaretçi ve küpe. Ve hepsini test etmek (lütfen bana bu kodun mantıklı olmadığını söyle) referansların tek temel ilkel türler olduğu anlaşılıyor . İlginç. Diğerlerinin, özellikle de ham göstergelerin neden olmadığının gerekçesini bilmek isterim. Ama bu sorunun kapsamı bu değil sanırım.