Skip to content

Moar trait object verbiage. #188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions src/expressions/method-call-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,22 @@ let log_pi = pi.unwrap_or(1.0).log(2.72);
```

When resolving method calls on an expression of type `A`, Rust will use the
following order, only looking at methods that are
[visible](visibility-and-privacy.html). If the type of `A` is a type parameter
or `Self` in a trait definitition then steps 2-4 first consider traits from
bounds on the type paramter, then the traits that are in scope. For other
types, only the traits that are in scope are considered.
following order, only looking at methods that are [visible]. If the type of `A`
is a type parameter or `Self` in a trait definitition then steps 2-4 first
consider traits from bounds on the type paramter, then the traits that are in
scope. For other types, only the traits that are in scope are considered.

1. Inherent methods, with receiver of type `A`, `&A`, `&mut A`.
1. Trait methods with receiver of type `A`.
1. Trait methods with receiver of type `&A`.
1. Trait methods with receiver of type `&mut A`.
1. If it's possible, Rust will then repeat steps 1-5 with
`<A as std::ops::Deref>::Target`, and insert a dereference operator.
1. If `A` is now an [array](types.html#array-and-slice-types) type, then
repeat steps 1-4 with the corresponding slice type.
1. If `A` is now an [array] type, then repeat steps 1-4 with the corresponding
slice type.

Note: that in steps 1-4 the receiver is used, not the type of `Self` nor the
type of `A`. For example
Note: In steps 1-4, the receiver is used, not the type of `Self` nor the
type of `A`. For example:

```rust,ignore
// `Self` is `&A`, receiver is `&A`.
Expand All @@ -48,10 +47,21 @@ Another note: this process does not use the mutability or lifetime of the
receiver, or whether `unsafe` methods can currently be called to resolve
methods. These constraints instead lead to compiler errors.

If a step is reached where there is more than one possible method (where
generic methods or traits are considered the same), then it is a compiler
error. These cases require a [more specific
syntax.](expressions/call-expr.html#disambiguating-function-calls) for method
If a step is reached where there is more than one possible method, such as where
generic methods or traits are considered the same, then it is a compiler
error. These cases require a [disambiguating function call syntax] for method
and function invocation.

[IDENTIFIER]: identifiers.html
> Warning: For [trait objects], if there is an inherent method of the same name
> as a trait method, it will give a compiler error when trying to call the
> method in a method call expression. Instead, you can call the method using
> [disambiguating function call syntax], in which case it calls the trait
> method, not the inherent method. There is no way to call the inherent method.
> Just don't define inherent methods on trait objects with the same name a trait
> method and you'll be fine.

[IDENTIFIER]: identifiers.html
[visible]: visibility-and-privacy.html
[array]: types.html#array-and-slice-types
[trait objects]: types.html#trait-objects
[disambiguating function call syntax]: expressions/call-expr.html#disambiguating-function-calls
14 changes: 10 additions & 4 deletions src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,13 +403,19 @@ A *trait object* is an opaque value of another type that implements a set of
traits. The set of traits is made up of an [object safe] *base trait* plus any
number of [auto traits].

Trait objects implement the base trait, its auto traits, and any super traits
of the base trait.

Trait objects are written as the path to the base trait followed by the list
of auto traits all separated by `+`. For example, given a trait `Trait`, the
following are all trait objects: `Trait`, `Trait + Send`, `Trait + Send + Sync`.
of auto traits followed optionally by a lifetime bound all separated by `+`. For
example, given a trait `Trait`, the following are all trait objects: `Trait`,
`Trait + Send`, `Trait + Send + Sync`, `Trait + 'static`,
`Trait + Send + 'static`.

Two trait object types alias each other if the base traits alias each other and
if the sets of auto traits are the same. For example,
`Trait + Send + UnwindSafe` is the same as `Trait + Unwindsafe + Send`.
if the sets of auto traits are the same and the lifetime bounds are the same.
For example, `Trait + Send + UnwindSafe` is the same as
`Trait + Unwindsafe + Send`.

> Warning: With two trait object types, even when the complete set of traits is
> the same, if the base traits differ, the type is different. For example,
Expand Down