@@ -55,10 +55,9 @@ fn foo(x: Empty) {
55
55
// empty
56
56
}
57
57
}
58
-
59
58
```
60
59
61
- but this won't:
60
+ However, this won't:
62
61
63
62
```
64
63
fn foo(x: Option<String>) {
@@ -71,7 +70,18 @@ fn foo(x: Option<String>) {
71
70
72
71
E0003 : r##"
73
72
Not-a-Number (NaN) values cannot be compared for equality and hence can never
74
- match the input to a match expression. To match against NaN values, you should
73
+ match the input to a match expression. So, the following will not compile:
74
+
75
+ ```
76
+ const NAN: f32 = 0.0 / 0.0;
77
+
78
+ match number {
79
+ NAN => { /* ... */ },
80
+ // ...
81
+ }
82
+ ```
83
+
84
+ To match against NaN values, you should
75
85
instead use the `is_nan()` method in a guard, like so:
76
86
77
87
```
@@ -429,22 +439,20 @@ match 5u32 {
429
439
"## ,
430
440
431
441
E0038 : r####"
442
+ Trait objects like `Box<Trait>` can only be constructed when certain
443
+ requirements are satisfied by the trait in question.
432
444
433
- Trait objects like `Box<Trait>`, can only be constructed when certain
434
- requirements are obeyed by the trait in question.
435
-
436
- Trait objects are a form of dynamic dispatch and use dynamically sized types.
437
- So, for a given trait `Trait`, when `Trait` is treated as a type, as in
438
- `Box<Trait>`, the inner type is "unsized". In such cases the boxed pointer is a
439
- "fat pointer" and contains an extra pointer to a method table for dynamic
440
- dispatch. This design mandates some restrictions on the types of traits that are
441
- allowed to be used in trait objects, which are collectively termed as "object
442
- safety" rules.
445
+ Trait objects are a form of dynamic dispatch and use a dynamically sized type
446
+ for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a
447
+ type, as in `Box<Trait>`, the inner type is "unsized". In such cases the boxed
448
+ pointer is a "fat pointer" that contains an extra pointer to a table of methods
449
+ (among other things) for dynamic dispatch. This design mandates some
450
+ restrictions on the types of traits that are allowed to be used in trait
451
+ objects, which are collectively termed as "object safety" rules.
443
452
444
453
Attempting to create a trait object for a non object-safe trait will trigger
445
454
this error.
446
455
447
-
448
456
There are various rules:
449
457
450
458
### The trait cannot require `Self: Sized`
@@ -463,7 +471,7 @@ trait Foo where Self: Sized {
463
471
we cannot create an object of type `Box<Foo>` or `&Foo` since in this case
464
472
`Self` would not be `Sized`.
465
473
466
- Generally `Self : Sized` is used to indicate that the trait should not be used
474
+ Generally, `Self : Sized` is used to indicate that the trait should not be used
467
475
as a trait object. If the trait comes from your own crate, consider removing
468
476
this restriction.
469
477
@@ -475,6 +483,7 @@ This happens when a trait has a method like the following:
475
483
trait Trait {
476
484
fn foo(&self) -> Self;
477
485
}
486
+
478
487
impl Trait for String {
479
488
fn foo(&self) -> Self {
480
489
"hi".to_owned()
@@ -488,8 +497,11 @@ impl Trait for u8 {
488
497
}
489
498
```
490
499
491
- In such a case, the compiler cannot predict the return type of `foo()` in a case
492
- like the following:
500
+ (Note that `&self` and `&mut self` are okay, it's additional `Self` types which
501
+ cause this problem)
502
+
503
+ In such a case, the compiler cannot predict the return type of `foo()` in a
504
+ situation like the following:
493
505
494
506
```
495
507
fn call_foo(x: Box<Trait>) {
@@ -498,8 +510,10 @@ fn call_foo(x: Box<Trait>) {
498
510
}
499
511
```
500
512
501
- If the offending method isn't actually being called on the trait object, you can
502
- add a `where Self: Sized` bound on the method:
513
+ If only some methods aren't object-safe, you can add a `where Self: Sized` bound
514
+ on them to mark them as explicitly unavailable to trait objects. The
515
+ functionality will still be available to all other implementers, including
516
+ `Box<Trait>` which is itself sized (assuming you `impl Trait for Box<Trait>`)
503
517
504
518
```
505
519
trait Trait {
@@ -508,10 +522,10 @@ trait Trait {
508
522
}
509
523
```
510
524
511
- Now, `foo()` can no longer be called on the trait object, but you will be
512
- allowed to call other trait methods and construct the trait objects. With such a
513
- bound, one can still call `foo()` on types implementing that trait that aren't
514
- behind trait objects.
525
+ Now, `foo()` can no longer be called on a trait object, but you will now be
526
+ allowed to make a trait object, and that will be able to call any object-safe
527
+ methods". With such a bound, one can still call `foo()` on types implementing
528
+ that trait that aren't behind trait objects.
515
529
516
530
### Method has generic type parameters
517
531
@@ -535,10 +549,10 @@ impl Trait for u8 {
535
549
// ...
536
550
```
537
551
538
- at compile time a table of all implementations of `Trait`, containing pointers
539
- to the implementation of `foo()` would be generated .
552
+ at compile time each implementation of `Trait` will produce a table containing
553
+ the various methods (and other items) related to the implementation .
540
554
541
- This works fine, but when we the method gains generic parameters, we can have a
555
+ This works fine, but when the method gains generic parameters, we can have a
542
556
problem.
543
557
544
558
Usually, generic parameters get _monomorphized_. For example, if I have
@@ -555,12 +569,14 @@ implementation on-demand. If you call `foo()` with a `bool` parameter, the
555
569
compiler will only generate code for `foo::<bool>()`. When we have additional
556
570
type parameters, the number of monomorphized implementations the compiler
557
571
generates does not grow drastically, since the compiler will only generate an
558
- implementation if the function is called with hard substitutions.
572
+ implementation if the function is called with unparametrized substitutions
573
+ (i.e., substitutions where none of the substituted types are themselves
574
+ parametrized).
559
575
560
576
However, with trait objects we have to make a table containing _every object
561
577
that implements the trait_. Now, if it has type parameters, we need to add
562
- implementations for every type that implements the trait, bloating the table
563
- quickly .
578
+ implementations for every type that implements the trait, and there could
579
+ theoretically be an infinite number of types .
564
580
565
581
For example, with
566
582
@@ -675,13 +691,46 @@ safe, so they are forbidden when specifying supertraits.
675
691
676
692
There's no easy fix for this, generally code will need to be refactored so that
677
693
you no longer need to derive from `Super<Self>`.
678
-
679
694
"#### ,
680
695
681
696
E0079 : r##"
682
697
Enum variants which contain no data can be given a custom integer
683
698
representation. This error indicates that the value provided is not an
684
699
integer literal and is therefore invalid.
700
+
701
+ For example, in the following code,
702
+
703
+ ```
704
+ enum Foo {
705
+ Q = "32"
706
+ }
707
+ ```
708
+
709
+ we try to set the representation to a string.
710
+
711
+ There's no general fix for this; if you can work with an integer
712
+ then just set it to one:
713
+
714
+ ```
715
+ enum Foo {
716
+ Q = 32
717
+ }
718
+ ```
719
+
720
+ however if you actually wanted a mapping between variants
721
+ and non-integer objects, it may be preferable to use a method with
722
+ a match instead:
723
+
724
+ ```
725
+ enum Foo { Q }
726
+ impl Foo {
727
+ fn get_str(&self) -> &'static str {
728
+ match *self {
729
+ Foo::Q => "32",
730
+ }
731
+ }
732
+ }
733
+ ```
685
734
"## ,
686
735
687
736
E0080 : r##"
@@ -704,33 +753,33 @@ https://doc.rust-lang.org/reference.html#ffi-attributes
704
753
"## ,
705
754
706
755
E0109 : r##"
707
- You tried to give a type parameter to a type which doesn't need it. Erroneous
708
- code example:
756
+ You tried to give a type parameter to a type which doesn't need it; for example:
709
757
710
758
```
711
759
type X = u32<i32>; // error: type parameters are not allowed on this type
712
760
```
713
761
714
762
Please check that you used the correct type and recheck its definition. Perhaps
715
763
it doesn't need the type parameter.
764
+
716
765
Example:
717
766
718
767
```
719
- type X = u32; // ok!
768
+ type X = u32; // this compiles
720
769
```
721
770
"## ,
722
771
723
772
E0110 : r##"
724
- You tried to give a lifetime parameter to a type which doesn't need it.
725
- Erroneous code example:
773
+ You tried to give a lifetime parameter to a type which doesn't need it; for
774
+ example:
726
775
727
776
```
728
777
type X = u32<'static>; // error: lifetime parameters are not allowed on
729
778
// this type
730
779
```
731
780
732
- Please check that you used the correct type and recheck its definition,
733
- perhaps it doesn't need the lifetime parameter. Example:
781
+ Please check that the correct type was used and recheck its definition; perhaps
782
+ it doesn't need the lifetime parameter. Example:
734
783
735
784
```
736
785
type X = u32; // ok!
0 commit comments