// empty
}
}
-
```
-but this won't:
+However, this won't:
```
fn foo(x: Option<String>) {
E0003: r##"
Not-a-Number (NaN) values cannot be compared for equality and hence can never
-match the input to a match expression. To match against NaN values, you should
+match the input to a match expression. So, the following will not compile:
+
+```
+const NAN: f32 = 0.0 / 0.0;
+
+match number {
+ NAN => { /* ... */ },
+ // ...
+}
+```
+
+To match against NaN values, you should
instead use the `is_nan()` method in a guard, like so:
```
"##,
E0038: r####"
+Trait objects like `Box<Trait>` can only be constructed when certain
+requirements are satisfied by the trait in question.
-Trait objects like `Box<Trait>`, can only be constructed when certain
-requirements are obeyed by the trait in question.
-
-Trait objects are a form of dynamic dispatch and use dynamically sized types.
-So, for a given trait `Trait`, when `Trait` is treated as a type, as in
-`Box<Trait>`, the inner type is "unsized". In such cases the boxed pointer is a
-"fat pointer" and contains an extra pointer to a method table for dynamic
-dispatch. This design mandates some restrictions on the types of traits that are
-allowed to be used in trait objects, which are collectively termed as "object
-safety" rules.
+Trait objects are a form of dynamic dispatch and use a dynamically sized type
+for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a
+type, as in `Box<Trait>`, the inner type is "unsized". In such cases the boxed
+pointer is a "fat pointer" that contains an extra pointer to a table of methods
+(among other things) for dynamic dispatch. This design mandates some
+restrictions on the types of traits that are allowed to be used in trait
+objects, which are collectively termed as "object safety" rules.
Attempting to create a trait object for a non object-safe trait will trigger
this error.
-
There are various rules:
### The trait cannot require `Self: Sized`
we cannot create an object of type `Box<Foo>` or `&Foo` since in this case
`Self` would not be `Sized`.
-Generally `Self : Sized` is used to indicate that the trait should not be used
+Generally, `Self : Sized` is used to indicate that the trait should not be used
as a trait object. If the trait comes from your own crate, consider removing
this restriction.
trait Trait {
fn foo(&self) -> Self;
}
+
impl Trait for String {
fn foo(&self) -> Self {
"hi".to_owned()
}
```
-In such a case, the compiler cannot predict the return type of `foo()` in a case
-like the following:
+(Note that `&self` and `&mut self` are okay, it's additional `Self` types which
+cause this problem)
+
+In such a case, the compiler cannot predict the return type of `foo()` in a
+situation like the following:
```
fn call_foo(x: Box<Trait>) {
}
```
-If the offending method isn't actually being called on the trait object, you can
-add a `where Self: Sized` bound on the method:
+If only some methods aren't object-safe, you can add a `where Self: Sized` bound
+on them to mark them as explicitly unavailable to trait objects. The
+functionality will still be available to all other implementers, including
+`Box<Trait>` which is itself sized (assuming you `impl Trait for Box<Trait>`)
```
trait Trait {
}
```
-Now, `foo()` can no longer be called on the trait object, but you will be
-allowed to call other trait methods and construct the trait objects. With such a
-bound, one can still call `foo()` on types implementing that trait that aren't
-behind trait objects.
+Now, `foo()` can no longer be called on a trait object, but you will now be
+allowed to make a trait object, and that will be able to call any object-safe
+methods". With such a bound, one can still call `foo()` on types implementing
+that trait that aren't behind trait objects.
### Method has generic type parameters
// ...
```
-at compile time a table of all implementations of `Trait`, containing pointers
-to the implementation of `foo()` would be generated.
+at compile time each implementation of `Trait` will produce a table containing
+the various methods (and other items) related to the implementation.
-This works fine, but when we the method gains generic parameters, we can have a
+This works fine, but when the method gains generic parameters, we can have a
problem.
Usually, generic parameters get _monomorphized_. For example, if I have
compiler will only generate code for `foo::<bool>()`. When we have additional
type parameters, the number of monomorphized implementations the compiler
generates does not grow drastically, since the compiler will only generate an
-implementation if the function is called with hard substitutions.
+implementation if the function is called with unparametrized substitutions
+(i.e., substitutions where none of the substituted types are themselves
+parametrized).
However, with trait objects we have to make a table containing _every object
that implements the trait_. Now, if it has type parameters, we need to add
-implementations for every type that implements the trait, bloating the table
-quickly.
+implementations for every type that implements the trait, and there could
+theoretically be an infinite number of types.
For example, with
There's no easy fix for this, generally code will need to be refactored so that
you no longer need to derive from `Super<Self>`.
-
"####,
E0079: r##"
Enum variants which contain no data can be given a custom integer
representation. This error indicates that the value provided is not an
integer literal and is therefore invalid.
+
+For example, in the following code,
+
+```
+enum Foo {
+ Q = "32"
+}
+```
+
+we try to set the representation to a string.
+
+There's no general fix for this; if you can work with an integer
+then just set it to one:
+
+```
+enum Foo {
+ Q = 32
+}
+```
+
+however if you actually wanted a mapping between variants
+and non-integer objects, it may be preferable to use a method with
+a match instead:
+
+```
+enum Foo { Q }
+impl Foo {
+ fn get_str(&self) -> &'static str {
+ match *self {
+ Foo::Q => "32",
+ }
+ }
+}
+```
"##,
E0080: r##"
"##,
E0109: r##"
-You tried to give a type parameter to a type which doesn't need it. Erroneous
-code example:
+You tried to give a type parameter to a type which doesn't need it; for example:
```
type X = u32<i32>; // error: type parameters are not allowed on this type
Please check that you used the correct type and recheck its definition. Perhaps
it doesn't need the type parameter.
+
Example:
```
-type X = u32; // ok!
+type X = u32; // this compiles
```
"##,
E0110: r##"
-You tried to give a lifetime parameter to a type which doesn't need it.
-Erroneous code example:
+You tried to give a lifetime parameter to a type which doesn't need it; for
+example:
```
type X = u32<'static>; // error: lifetime parameters are not allowed on
// this type
```
-Please check that you used the correct type and recheck its definition,
-perhaps it doesn't need the lifetime parameter. Example:
+Please check that the correct type was used and recheck its definition; perhaps
+it doesn't need the lifetime parameter. Example:
```
type X = u32; // ok!