Wenn eine Bibliothek einen generischen Typ hat Foo<T>
, können nachgeschaltete Kisten normalerweise keine Merkmale darauf implementieren, selbst wenn T
es sich um einen lokalen Typ handelt. Zum Beispiel,
( 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)
}
}
Für ein konkretes Beispiel, das auf dem Spielplatz funktioniert (dh einen Fehler ergibt),
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)
}
}
(Spielplatz)
Dies ermöglicht es dem Kistenautor normalerweise, (pauschale) Implementierungen von Merkmalen hinzuzufügen, ohne nachgeschaltete Kisten zu zerbrechen. Das ist großartig in Fällen, in denen zunächst nicht sicher ist, ob ein Typ ein bestimmtes Merkmal implementieren soll, später jedoch klar wird, dass dies der Fall sein sollte. Zum Beispiel könnten wir einen numerischen Typ haben, der die Merkmale von zunächst nicht implementiert num-traits
. Diese Eigenschaften könnten später hinzugefügt werden, ohne dass eine Änderung erforderlich wäre.
In einigen Fällen möchte der Bibliotheksautor jedoch, dass nachgeschaltete Kisten Merkmale selbst implementieren können. Hier kommt das #[fundamental]
Attribut ins Spiel. Wenn es auf einen Typ gesetzt wird, wird jedes Merkmal, das derzeit nicht für diesen Typ implementiert ist, nicht implementiert (außer bei einer Änderung). Infolgedessen können nachgeschaltete Kisten Merkmale für diesen Typ implementieren, solange ein Typparameter lokal ist (es gibt einige komplizierte Regeln für die Entscheidung, welche Typparameter dafür zählen). Da der Grundtyp ein bestimmtes Merkmal nicht implementiert, kann dieses Merkmal frei implementiert werden, ohne Kohärenzprobleme zu verursachen.
Ist beispielsweise Box<T>
markiert #[fundamental]
, damit der folgende Code (ähnlich der Rc<T>
obigen Version) funktioniert. Box<T>
nicht implementiert Default
(außer T
implementiert Default
), so dass wir davon ausgehen können, dass dies in Zukunft nicht der Fall sein wird, da dies von Box<T>
grundlegender Bedeutung ist. Beachten Sie, dass die Implementierung Default
für Bar
Probleme verursachen würde, da diese Box<Bar>
bereits implementiert sind Default
.
struct Bar;
impl Default for Box<Bar> {
fn default() -> Self {
Box::new(Bar)
}
}
(Spielplatz)
Andererseits können Merkmale auch mit markiert werden #[fundamental]
. Dies hat eine doppelte Bedeutung für grundlegende Typen. Wenn ein Typ derzeit kein grundlegendes Merkmal implementiert, kann davon ausgegangen werden, dass dieser Typ es in Zukunft nicht implementiert (wiederum ohne eine Änderung). Ich bin mir nicht ganz sicher, wie dies in der Praxis angewendet wird. Im Code (unten verlinkt) FnMut
ist er mit dem Hinweis markiert, dass er für Regex benötigt wird (etwas über &str: !FnMut
). Ich konnte nicht finden, wo es in der regex
Kiste verwendet wird oder ob es woanders verwendet wird.
Wenn das Add
Merkmal als grundlegend markiert wäre (was diskutiert wurde), könnte dies theoretisch verwendet werden, um eine Addition zwischen Dingen zu implementieren, die es noch nicht haben. Zum Beispiel das Hinzufügen [MyNumericType; 3]
(punktuell), was in bestimmten Situationen nützlich sein könnte (natürlich [T; N]
würde es auch möglich sein , grundlegend zu machen).
Die primitiven Grundtypen sind &T
, &mut T
(siehe hier für eine Demonstration aller Generika primitive Typen). In der Standardbibliothek Box<T>
und Pin<T>
sind auch als grundlegend gekennzeichnet.
Die Grundzüge in der Standardbibliothek sind Sized
, Fn<T>
, FnMut<T>
, FnOnce<T>
und Generator
.
Beachten Sie, dass das #[fundamental]
Attribut derzeit instabil ist. Das Tracking-Problem ist das Problem Nr. 29635 .
&T
,&mut T
,*const T
,*mut T
,[T; N]
,[T]
,fn
Zeiger und Tupel. Und wenn Sie alle testen (bitte sagen Sie mir, wenn dieser Code keinen Sinn ergibt) , scheinen Referenzen die einzigen grundlegenden primitiven Typen zu sein . Interessant. Mich würde interessieren, warum die anderen es nicht sind, insbesondere rohe Hinweise. Aber das ist wohl nicht der Umfang dieser Frage.