Skip to content

Commit 280553c

Browse files
committed
doc: Fix tests in pointer guide
1 parent 6f09d80 commit 280553c

File tree

1 file changed

+58
-51
lines changed

1 file changed

+58
-51
lines changed

doc/guide-pointers.md

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,53 @@ don't need them very often.
1616
"But tutorial!" you may cry. "My co-worker wrote a function that looks like
1717
this:
1818

19-
```rust
19+
~~~rust
2020
fn succ(x: &int) -> int { *x + 1 }
21-
```
21+
~~~
2222

2323
So I wrote this code to try it out:
2424

25-
```rust
25+
~~~rust {.xfail-test}
2626
fn main() {
2727
let number = 5;
2828
let succ_number = succ(number);
2929
println!("{}", succ_number);
3030
}
31-
```
31+
~~~
3232

3333
And now I get an error:
3434

35-
```
35+
~~~ {.notrust}
3636
error: mismatched types: expected `&int` but found `<VI0>` (expected &-ptr but found integral variable)
37-
```
37+
~~~
3838

3939
What gives? It needs a pointer! Therefore I have to use pointers!"
4040

4141
Turns out, you don't. All you need is a reference. Try this on for size:
4242

43-
```rust
43+
~~~rust
44+
# fn succ(x: &int) -> int { *x + 1 }
4445
fn main() {
4546
let number = 5;
4647
let succ_number = succ(&number);
4748
println!("{}", succ_number);
4849
}
49-
```
50+
~~~
5051

5152
It's that easy! One extra little `&` there. This code will run, and print `6`.
5253

5354
That's all you need to know. Your co-worker could have written the function
5455
like this:
5556

56-
```rust
57+
~~~rust
5758
fn succ(x: int) -> int { x + 1 }
5859

5960
fn main() {
6061
let number = 5;
6162
let succ_number = succ(number);
6263
println!("{}", succ_number);
6364
}
64-
```
65+
~~~
6566

6667
No pointers even needed. Then again, this is a simple example. I assume that
6768
your real-world `succ` function is more complicated, and maybe your co-worker
@@ -100,7 +101,8 @@ passing things by reference, or passing things by pointer. In some langauges,
100101
like Java, you can't even have objects without a pointer to them. Therefore, if
101102
you were writing this Rust code:
102103

103-
```rust
104+
~~~rust
105+
# fn transform(p: Point) -> Point { p }
104106
struct Point {
105107
x: int,
106108
y: int,
@@ -112,22 +114,27 @@ fn main() {
112114
println!("{:?}", p1);
113115
}
114116

115-
```
117+
~~~
116118

117119
I think you'd implement `transform` like this:
118120

119-
```rust
121+
~~~rust
122+
# struct Point {
123+
# x: int,
124+
# y: int,
125+
# }
126+
# let p0 = Point { x: 5, y: 10};
120127
fn transform(p: &Point) -> Point {
121128
Point { x: p.x + 1, y: p.y + 1}
122129
}
123130

124131
// and change this:
125132
let p1 = transform(&p0);
126-
```
133+
~~~
127134

128135
This does work, but you don't need to create those references! The better way to write this is simply:
129136

130-
```rust
137+
~~~rust
131138
struct Point {
132139
x: int,
133140
y: int,
@@ -142,7 +149,7 @@ fn main() {
142149
let p1 = transform(p0);
143150
println!("{:?}", p1);
144151
}
145-
```
152+
~~~
146153

147154
But won't this be inefficent? Well, that's a complicated question, but it's
148155
important to know that Rust, like C and C++, store aggregate data types
@@ -175,7 +182,7 @@ trait. Therefore, unboxed traits don't make any sense, and aren't allowed.
175182

176183
Sometimes, you need a recursive data structure. The simplest is known as a 'cons list':
177184

178-
```rust
185+
~~~rust
179186
enum List<T> {
180187
Nil,
181188
Cons(T, ~List<T>),
@@ -185,13 +192,13 @@ fn main() {
185192
let list: List<int> = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
186193
println!("{:?}", list);
187194
}
188-
```
195+
~~~
189196

190197
This prints:
191198

192-
```
199+
~~~ {.notrust}
193200
Cons(1, ~Cons(2, ~Cons(3, ~Nil)))
194-
```
201+
~~~
195202

196203
The inner lists _must_ be an owned pointer, becuase we can't know how many
197204
elements are in the list. Without knowing the length, we don't know the size,
@@ -207,7 +214,7 @@ proved that it's an issue through benchmarks.
207214

208215
For example, this will work:
209216

210-
```rust
217+
~~~rust
211218
struct Point {
212219
x: int,
213220
y: int,
@@ -219,12 +226,12 @@ fn main() {
219226
println(a.x.to_str());
220227
}
221228
}
222-
```
229+
~~~
223230

224231
This struct is tiny, so it's fine. If `Point` were large, this would be more
225232
efficient:
226233

227-
```rust
234+
~~~rust
228235
struct Point {
229236
x: int,
230237
y: int,
@@ -236,7 +243,7 @@ fn main() {
236243
println(a.x.to_str());
237244
}
238245
}
239-
```
246+
~~~
240247

241248
Now it'll be copying a pointer-sized chunk of memory rather than the whole
242249
struct.
@@ -249,7 +256,7 @@ program is very large and complicated.
249256

250257
For example, let's say you're using an owned pointer, and you want to do this:
251258

252-
```rust
259+
~~~rust {.xfail-test}
253260
struct Point {
254261
x: int,
255262
y: int,
@@ -261,22 +268,22 @@ fn main() {
261268
println(b.x.to_str());
262269
println(a.x.to_str());
263270
}
264-
```
271+
~~~
265272

266273
You'll get this error:
267274

268-
```
275+
~~~ {.notrust}
269276
test.rs:10:12: 10:13 error: use of moved value: `a`
270277
test.rs:10 println(a.x.to_str());
271278
^
272279
test.rs:8:8: 8:9 note: `a` moved here because it has type `~Point`, which is moved by default (use `ref` to override)
273280
test.rs:8 let b = a;
274281
^
275-
```
282+
~~~
276283

277284
As the message says, owned pointers only allow for one owner at a time. When you assign `a` to `b`, `a` becomes invalid. Change your code to this, however:
278285

279-
```rust
286+
~~~rust
280287
struct Point {
281288
x: int,
282289
y: int,
@@ -288,14 +295,14 @@ fn main() {
288295
println(b.x.to_str());
289296
println(a.x.to_str());
290297
}
291-
```
298+
~~~
292299

293300
And it works:
294301

295-
```
302+
~~~ {.notrust}
296303
10
297304
10
298-
```
305+
~~~
299306

300307
So why not just use managed pointers everywhere? There are two big drawbacks to
301308
managed pointers:
@@ -315,15 +322,15 @@ data they're pointing to. They're just borrowing it for a while. So in that
315322
sense, they're simple: just keep whatever ownership the data already has. For
316323
example:
317324

318-
```rust
325+
~~~rust
319326
use std::num::sqrt;
320327

321328
struct Point {
322-
x: float,
323-
y: float,
329+
x: f32,
330+
y: f32,
324331
}
325332

326-
fn compute_distance(p1: &Point, p2: &Point) -> float {
333+
fn compute_distance(p1: &Point, p2: &Point) -> f32 {
327334
let x_d = p1.x - p2.x;
328335
let y_d = p1.y - p2.y;
329336

@@ -336,7 +343,7 @@ fn main() {
336343

337344
println!("{:?}", compute_distance(origin, p1));
338345
}
339-
```
346+
~~~
340347

341348
This prints `5.83095189`. You can see that the `compute_distance` function
342349
takes in two borrowed pointers, but we give it a managed and unique pointer. Of
@@ -353,19 +360,19 @@ This theory is called 'region pointers,' and involve a concept called
353360
'lifetimes'. Here's the simple explanation: would you expect this code to
354361
compile?
355362

356-
```rust
363+
~~~rust {.xfail-test}
357364
fn main() {
358365
println(x.to_str());
359366
let x = 5;
360367
}
361-
```
368+
~~~
362369

363370
Probably not. That's becuase you know that the name `x` is valid from where
364371
it's declared to when it goes out of scope. In this case, that's the end of
365372
the `main` function. So you know this code will cause an error. We call this
366373
duration a 'lifetime'. Let's try a more complex example:
367374

368-
```rust
375+
~~~rust
369376
fn main() {
370377
let mut x = ~5;
371378
if(*x < 10) {
@@ -376,13 +383,13 @@ fn main() {
376383
*x = *x - 1;
377384
println!("Oh no: {:?}", x);
378385
}
379-
```
386+
~~~
380387

381388
Here, we're borrowing a pointer to `x` inside of the `if`. The compiler, however,
382389
is able to determine that that pointer will go out of scope without `x` being
383390
mutated, and therefore, lets us pass. This wouldn't work:
384391

385-
```rust
392+
~~~rust {.xfail-test}
386393
fn main() {
387394
let mut x = ~5;
388395
if(*x < 10) {
@@ -395,18 +402,18 @@ fn main() {
395402
*x = *x - 1;
396403
println!("Oh no: {:?}", x);
397404
}
398-
```
405+
~~~
399406

400407
It gives this error:
401408

402-
```
409+
~~~ {.notrust}
403410
test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
404411
test.rs:5 *x = *x - 1;
405412
^~
406413
test.rs:4:16: 4:18 note: borrow of `*x` occurs here
407414
test.rs:4 let y = &x;
408415
^~
409-
```
416+
~~~
410417

411418
As you might guess, this kind of analysis is complex for a human, and therefore
412419
hard for a computer, too! There is an entire [tutorial devoted to borrowed
@@ -421,7 +428,7 @@ managed pointer if you were given one in the first place.
421428

422429
What does that mean? Don't do this:
423430

424-
```rust
431+
~~~rust
425432
fn foo(x: ~int) -> ~int {
426433
return ~*x;
427434
}
@@ -430,11 +437,11 @@ fn main() {
430437
let x = ~5;
431438
let y = foo(x);
432439
}
433-
```
440+
~~~
434441

435442
Do this:
436443

437-
```rust
444+
~~~rust
438445
fn foo(x: ~int) -> int {
439446
return *x;
440447
}
@@ -443,12 +450,12 @@ fn main() {
443450
let x = ~5;
444451
let y = ~foo(x);
445452
}
446-
```
453+
~~~
447454

448455
This gives you flexibility, without sacrificing performance. For example, this will
449456
also work:
450457

451-
```rust
458+
~~~rust
452459
fn foo(x: ~int) -> int {
453460
return *x;
454461
}
@@ -457,7 +464,7 @@ fn main() {
457464
let x = ~5;
458465
let y = @foo(x);
459466
}
460-
```
467+
~~~
461468

462469
You may think that this gives us terrible performance: return a value and then
463470
immediately box it up?!?! Isn't that the worst of both worlds? Rust is smarter

0 commit comments

Comments
 (0)