Rust'da “temel tip” nedir?


37

Bir yerde "temel tip" (ve onun niteliği #[fundamental]) terimini aldım ve şimdi bu konuda daha fazla bilgi edinmek istedim. Bazı durumlarda tutarlılık kurallarını rahatlatmakla ilgili belirsiz bir şekilde hatırlıyorum. Bence referans türleri böyle temel türler.

Ne yazık ki, web'de arama yapmak beni çok ileriye götürmedi. Rust referansından bahsetmiyorum (görebildiğim kadarıyla). Ben sadece tuples temel türleri ve niteliği tanıtan RFC yapma hakkında bir sorun buldum . Ancak, RFC'nin temel türler hakkında tek bir paragrafı vardır:

  • Bir #[fundamental]tür Foo, bir battaniye impl uygulamasının Fookırılma değişikliği olduğu türdür . Açıklandığı gibi &ve &muttemeldir. Bu nitelik Box, tutarlılık ile Box aynı &ve aynı &mutşekilde davranarak uygulanacaktır.

İfadeleri anlamakta oldukça zorlanıyorum ve temel türler hakkında bu noktayı anlamak için tam RFC hakkında derinlemesine bilgiye ihtiyacım var gibi geliyor. Birisinin temel türleri biraz daha basit terimlerle açıklayabileceğini umuyordum (elbette çok fazla basitleştirmeden). Bu soru aynı zamanda bulunması kolay bir bilgi parçası olarak da kullanılabilir.

Temel türleri anlamak için, bu soruları cevaplamak istiyorum (elbette ana "onlar ne?" Sorusuna ek olarak):

  • Temel türler temel olmayan türlerden daha fazlasını yapabilir mi?
  • Bir kütüphane yazarı olarak, bazı türlerimi işaretlemekten yararlanabilir miyim #[fundamental]?
  • Çekirdek dilden veya standart kütüphaneden hangi türler esastır?

Yanıtlar:


34

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 Tuygular Defaultbiz değil gelecekte çünkü varsayabiliriz böylece) Box<T>esastır. Uygulanması unutmayın Defaultiçin Baro 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), FnMutnormal ifade (bir şey hakkında &str: !FnMut) için gerekli olduğu notu ile temel olarak işaretlenmiştir . regexSandı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 .


1
Mükemmel cevap! İlkel türler ile ilgili olarak: bir avuç genel ilkel tipi vardır: &T, &mut T, *const T, *mut T, [T; N], [T], fniş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.
Lukas Kalbertodt

1
@LukasKalbertodt İlkel türler hakkında bilgi için teşekkürler. Testlerine ekledim. Referanslar ile işaretçiler arasındaki mantığa gelince , RFC çekme talebinde bu yoruma göz atın.
SCappella

Referans, dengesiz nitelikleri belgelemediğinden, bu yüzden orada bulamadınız.
Havvy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.