Skip to content

Commit 8e71e97

Browse files
committed
---
yaml --- r: 192501 b: refs/heads/auto c: a1d2e62 h: refs/heads/master i: 192499: f35c876 v: v3
1 parent 338fed4 commit 8e71e97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+982
-310
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1010
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1111
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1212
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
13-
refs/heads/auto: 7e3ee02006ec53ff176fc3490ba01eb2a9c823b8
13+
refs/heads/auto: a1d2e62c1f94930aaab2f9d56b3ee4f34f95369a
1414
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1515
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1616
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/doc/trpl/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* [More Strings](more-strings.md)
2323
* [Patterns](patterns.md)
2424
* [Method Syntax](method-syntax.md)
25+
* [Associated Types](associated-types.md)
2526
* [Closures](closures.md)
2627
* [Iterators](iterators.md)
2728
* [Generics](generics.md)
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
% Associated Types
2+
3+
Associated types are a powerful part of Rust's type system. They're related to
4+
the idea of a 'type family', in other words, grouping multiple types together. That
5+
description is a bit abstract, so let's dive right into an example. If you want
6+
to write a `Graph` trait, you have two types to be generic over: the node type
7+
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
8+
this:
9+
10+
```rust
11+
trait Graph<N, E> {
12+
fn has_edge(&self, &N, &N) -> bool;
13+
fn edges(&self, &N) -> Vec<E>;
14+
// etc
15+
}
16+
```
17+
18+
While this sort of works, it ends up being awkward. For example, any function
19+
that wants to take a `Graph` as a parameter now _also_ needs to be generic over
20+
the `N`ode and `E`dge types too:
21+
22+
```rust,ignore
23+
fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
24+
```
25+
26+
Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
27+
this signature is just a distraction.
28+
29+
What we really want to say is that a certain `E`dge and `N`ode type come together
30+
to form each kind of `Graph`. We can do that with associated types:
31+
32+
```rust
33+
trait Graph {
34+
type N;
35+
type E;
36+
37+
fn has_edge(&self, &Self::N, &Self::N) -> bool;
38+
fn edges(&self, &Self::N) -> Vec<Self::E>;
39+
// etc
40+
}
41+
```
42+
43+
Now, our clients can be abstract over a given `Graph`:
44+
45+
```rust,ignore
46+
fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
47+
```
48+
49+
No need to deal with the `E`dge type here!
50+
51+
Let's go over all this in more detail.
52+
53+
## Defining associated types
54+
55+
Let's build that `Graph` trait. Here's the definition:
56+
57+
```rust
58+
trait Graph {
59+
type N;
60+
type E;
61+
62+
fn has_edge(&self, &Self::N, &Self::N) -> bool;
63+
fn edges(&self, &Self::N) -> Vec<Self::E>;
64+
}
65+
```
66+
67+
Simple enough. Associated types use the `type` keyword, and go inside the body
68+
of the trait, with the functions.
69+
70+
These `type` declarations can have all the same thing as functions do. For example,
71+
if we wanted our `N` type to implement `Display`, so we can print the nodes out,
72+
we could do this:
73+
74+
```rust
75+
use std::fmt;
76+
77+
trait Graph {
78+
type N: fmt::Display;
79+
type E;
80+
81+
fn has_edge(&self, &Self::N, &Self::N) -> bool;
82+
fn edges(&self, &Self::N) -> Vec<Self::E>;
83+
}
84+
```
85+
86+
## Implementing associated types
87+
88+
Just like any trait, traits that use associated types use the `impl` keyword to
89+
provide implementations. Here's a simple implementation of Graph:
90+
91+
```rust
92+
# trait Graph {
93+
# type N;
94+
# type E;
95+
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
96+
# fn edges(&self, &Self::N) -> Vec<Self::E>;
97+
# }
98+
struct Node;
99+
100+
struct Edge;
101+
102+
struct MyGraph;
103+
104+
impl Graph for MyGraph {
105+
type N = Node;
106+
type E = Edge;
107+
108+
fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
109+
true
110+
}
111+
112+
fn edges(&self, n: &Node) -> Vec<Edge> {
113+
Vec::new()
114+
}
115+
}
116+
```
117+
118+
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
119+
gives you an idea of how to implement this kind of thing. We first need three
120+
`struct`s, one for the graph, one for the node, and one for the edge. If it made
121+
more sense to use a different type, that would work as well, we're just going to
122+
use `struct`s for all three here.
123+
124+
Next is the `impl` line, which is just like implementing any other trait.
125+
126+
From here, we use `=` to define our associated types. The name the trait uses
127+
goes on the left of the `=`, and the concrete type we're `impl`ementing this
128+
for goes on the right. Finally, we use the concrete types in our function
129+
declarations.
130+
131+
## Trait objects with associated types
132+
133+
There’s one more bit of syntax we should talk about: trait objects. If you
134+
try to create a trait object from an associated type, like this:
135+
136+
```rust,ignore
137+
# trait Graph {
138+
# type N;
139+
# type E;
140+
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
141+
# fn edges(&self, &Self::N) -> Vec<Self::E>;
142+
# }
143+
# struct Node;
144+
# struct Edge;
145+
# struct MyGraph;
146+
# impl Graph for MyGraph {
147+
# type N = Node;
148+
# type E = Edge;
149+
# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
150+
# true
151+
# }
152+
# fn edges(&self, n: &Node) -> Vec<Edge> {
153+
# Vec::new()
154+
# }
155+
# }
156+
let graph = MyGraph;
157+
let obj = Box::new(graph) as Box<Graph>;
158+
```
159+
160+
You’ll get two errors:
161+
162+
```text
163+
error: the value of the associated type `E` (from the trait `main::Graph`) must
164+
be specified [E0191]
165+
let obj = Box::new(graph) as Box<Graph>;
166+
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167+
24:44 error: the value of the associated type `N` (from the trait
168+
`main::Graph`) must be specified [E0191]
169+
let obj = Box::new(graph) as Box<Graph>;
170+
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
171+
```
172+
173+
We can’t create a trait object like this, becuase we don’t know the associated
174+
types. Instead, we can write this:
175+
176+
```rust
177+
# trait Graph {
178+
# type N;
179+
# type E;
180+
# fn has_edge(&self, &Self::N, &Self::N) -> bool;
181+
# fn edges(&self, &Self::N) -> Vec<Self::E>;
182+
# }
183+
# struct Node;
184+
# struct Edge;
185+
# struct MyGraph;
186+
# impl Graph for MyGraph {
187+
# type N = Node;
188+
# type E = Edge;
189+
# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
190+
# true
191+
# }
192+
# fn edges(&self, n: &Node) -> Vec<Edge> {
193+
# Vec::new()
194+
# }
195+
# }
196+
let graph = MyGraph;
197+
let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
198+
```
199+
200+
The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
201+
type parameter. Same with `E=Edge`. If we didn’t proide this constraint, we
202+
couldn’t be sure which `impl` to match this trait object to.

branches/auto/src/doc/trpl/ownership.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,8 +513,8 @@ Otherwise, it is an error to elide an output lifetime.
513513

514514
### Examples
515515

516-
Here are some examples of functions with elided lifetimes, and the version of
517-
what the elided lifetimes are expand to:
516+
Here are some examples of functions with elided lifetimes. We've paired each
517+
example of an elided lifetime with its expanded form.
518518

519519
```{rust,ignore}
520520
fn print(s: &str); // elided

branches/auto/src/libcollectionstest/btree/set.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,21 @@ struct Counter<'a, 'b> {
4343
}
4444

4545
impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
46-
type Output = bool;
47-
4846
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
4947
assert_eq!(x, self.expected[*self.i]);
5048
*self.i += 1;
5149
true
5250
}
5351
}
5452

53+
impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
54+
type Output = bool;
55+
56+
extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
57+
self.call_mut(args)
58+
}
59+
}
60+
5561
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
5662
// FIXME Replace Counter with `Box<FnMut(_) -> _>`
5763
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,

branches/auto/src/libcore/ops.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,7 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T {
11481148
#[lang="fn"]
11491149
#[stable(feature = "rust1", since = "1.0.0")]
11501150
#[rustc_paren_sugar]
1151+
#[cfg(stage0)]
11511152
pub trait Fn<Args> {
11521153
/// The returned type after the call operator is used.
11531154
type Output;
@@ -1156,10 +1157,21 @@ pub trait Fn<Args> {
11561157
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
11571158
}
11581159

1160+
/// A version of the call operator that takes an immutable receiver.
1161+
#[lang="fn"]
1162+
#[stable(feature = "rust1", since = "1.0.0")]
1163+
#[rustc_paren_sugar]
1164+
#[cfg(not(stage0))]
1165+
pub trait Fn<Args> : FnMut<Args> {
1166+
/// This is called when the call operator is used.
1167+
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
1168+
}
1169+
11591170
/// A version of the call operator that takes a mutable receiver.
11601171
#[lang="fn_mut"]
11611172
#[stable(feature = "rust1", since = "1.0.0")]
11621173
#[rustc_paren_sugar]
1174+
#[cfg(stage0)]
11631175
pub trait FnMut<Args> {
11641176
/// The returned type after the call operator is used.
11651177
type Output;
@@ -1168,6 +1180,16 @@ pub trait FnMut<Args> {
11681180
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
11691181
}
11701182

1183+
/// A version of the call operator that takes a mutable receiver.
1184+
#[lang="fn_mut"]
1185+
#[stable(feature = "rust1", since = "1.0.0")]
1186+
#[rustc_paren_sugar]
1187+
#[cfg(not(stage0))]
1188+
pub trait FnMut<Args> : FnOnce<Args> {
1189+
/// This is called when the call operator is used.
1190+
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
1191+
}
1192+
11711193
/// A version of the call operator that takes a by-value receiver.
11721194
#[lang="fn_once"]
11731195
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1180,6 +1202,7 @@ pub trait FnOnce<Args> {
11801202
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
11811203
}
11821204

1205+
#[cfg(stage0)]
11831206
impl<F: ?Sized, A> FnMut<A> for F
11841207
where F : Fn<A>
11851208
{
@@ -1190,6 +1213,7 @@ impl<F: ?Sized, A> FnMut<A> for F
11901213
}
11911214
}
11921215

1216+
#[cfg(stage0)]
11931217
impl<F,A> FnOnce<A> for F
11941218
where F : FnMut<A>
11951219
{

branches/auto/src/libcore/str/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
2929
use marker::Sized;
3030
use mem;
3131
use num::Int;
32-
use ops::{Fn, FnMut};
32+
use ops::{Fn, FnMut, FnOnce};
3333
use option::Option::{self, None, Some};
3434
use raw::{Repr, Slice};
3535
use result::Result::{self, Ok, Err};
@@ -541,6 +541,7 @@ delegate_iter!{exact u8 : Bytes<'a>}
541541
#[derive(Copy, Clone)]
542542
struct BytesDeref;
543543

544+
#[cfg(stage0)]
544545
impl<'a> Fn<(&'a u8,)> for BytesDeref {
545546
type Output = u8;
546547

@@ -550,6 +551,32 @@ impl<'a> Fn<(&'a u8,)> for BytesDeref {
550551
}
551552
}
552553

554+
#[cfg(not(stage0))]
555+
impl<'a> Fn<(&'a u8,)> for BytesDeref {
556+
#[inline]
557+
extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
558+
*ptr
559+
}
560+
}
561+
562+
#[cfg(not(stage0))]
563+
impl<'a> FnMut<(&'a u8,)> for BytesDeref {
564+
#[inline]
565+
extern "rust-call" fn call_mut(&mut self, (ptr,): (&'a u8,)) -> u8 {
566+
Fn::call(&*self, (ptr,))
567+
}
568+
}
569+
570+
#[cfg(not(stage0))]
571+
impl<'a> FnOnce<(&'a u8,)> for BytesDeref {
572+
type Output = u8;
573+
574+
#[inline]
575+
extern "rust-call" fn call_once(self, (ptr,): (&'a u8,)) -> u8 {
576+
Fn::call(&self, (ptr,))
577+
}
578+
}
579+
553580
/// An iterator over the substrings of a string, separated by `sep`.
554581
struct CharSplits<'a, P: Pattern<'a>> {
555582
/// The slice remaining to be iterated

branches/auto/src/liblog/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ fn init() {
443443
DIRECTIVES = boxed::into_raw(box directives);
444444

445445
// Schedule the cleanup for the globals for when the runtime exits.
446-
rt::at_exit(move || {
446+
let _ = rt::at_exit(move || {
447447
let _g = LOCK.lock();
448448
assert!(!DIRECTIVES.is_null());
449449
let _directives = Box::from_raw(DIRECTIVES);

branches/auto/src/librustc/middle/traits/project.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,10 +789,13 @@ fn confirm_callable_candidate<'cx,'tcx>(
789789
obligation.repr(tcx),
790790
fn_sig.repr(tcx));
791791

792+
// the `Output` associated type is declared on `FnOnce`
793+
let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap();
794+
792795
// Note: we unwrap the binder here but re-create it below (1)
793796
let ty::Binder((trait_ref, ret_type)) =
794797
util::closure_trait_ref_and_return_type(tcx,
795-
obligation.predicate.trait_ref.def_id,
798+
fn_once_def_id,
796799
obligation.predicate.trait_ref.self_ty(),
797800
fn_sig,
798801
flag);

0 commit comments

Comments
 (0)