19
19
20
20
Currently, the type system is not supposed to allow references to
21
21
escape into object types. However, there are various bugs where it
22
- fails to prevent this from hapenning . Moreover, it is very useful (and
22
+ fails to prevent this from happening . Moreover, it is very useful (and
23
23
frequently necessary) to store a reference into an object. Moreover,
24
24
the current treatment of generic types is in some cases naive and not
25
25
obviously sound.
@@ -105,7 +105,6 @@ Here are some examples:
105
105
106
106
trait IsStatic : 'static { }
107
107
trait Is<'a> : 'a { }
108
- trait IsNothing { }
109
108
110
109
// Type Bounds
111
110
// IsStatic 'static
@@ -124,11 +123,11 @@ default lifetime using the normal rules:
124
123
Box<Writer+Send>, // OK: Send implies 'static
125
124
&'a Writer, // Error: try &'a (Writer+'a)
126
125
}
127
-
126
+
128
127
fn foo(a: Box<Writer>, // OK: Sugar for Box<Writer+'a> where 'a fresh
129
- b: &Writer) // OK: Sugar for &'a (Writer+'b ) where 'a , 'b fresh
128
+ b: &Writer) // OK: Sugar for &'b (Writer+'c ) where 'b , 'c fresh
130
129
{ ... }
131
-
130
+
132
131
This kind of annotation can seem a bit tedious when using object types
133
132
extensively, though type aliases can help quite a bit:
134
133
@@ -138,6 +137,9 @@ extensively, though type aliases can help quite a bit:
138
137
The unresolved questions section discussed possibles ways to lighten
139
138
the burden.
140
139
140
+ See Appendix B for the motivation on why object types are permitted to
141
+ have exactly one lifetime bound.
142
+
141
143
## Specifying relations between lifetimes
142
144
143
145
Currently, when a type or fn has multiple lifetime parameters, there
@@ -155,10 +157,10 @@ them explicitly (and necessary in some cases, see below).
155
157
A * lifetime bound* is written ` 'a:'b ` and it means that "` 'a ` outlives
156
158
` 'b ` ". For example, if ` foo ` were declared like so:
157
159
158
- fn foo<'a , 'b:'a >(...) { ... }
160
+ fn foo<'x , 'y:'x >(...) { ... }
159
161
160
- that would indicate that the lifetime '` a ` was shorter than (or equal
161
- to) ` 'b ` .
162
+ that would indicate that the lifetime '` x ` was shorter than (or equal
163
+ to) ` 'y ` .
162
164
163
165
## The "type must outlive" and well-formedness relation
164
166
@@ -229,7 +231,7 @@ The compiler will infer lifetime bounds on both type parameters and
229
231
region parameters as follows. Within a function or method, we apply
230
232
the wellformedness function ` WF ` to each function or parameter type.
231
233
This yields up a set of relations that must hold. The idea here is
232
- that the caller could have type checked unless the types of the
234
+ that the caller could not have type checked unless the types of the
233
235
arguments were well-formed, so that implies that the callee can assume
234
236
that those well-formedness constraints hold.
235
237
@@ -291,7 +293,7 @@ This RFC has a lot of details. The main implications for end users are:
291
293
arena: &'global Arena
292
294
}
293
295
294
- struct LocalConenxt <'local, 'global:'local> {
296
+ struct LocalContext <'local, 'global:'local> {
295
297
x: &'local mut Context<'global>
296
298
}
297
299
@@ -345,6 +347,9 @@ traverse the type hierarchy deeply to find its origin. This could
345
347
potentially be addressed with better error messages, though our track
346
348
record for lifetime error messages is not very good so far.
347
349
350
+ Also, there is a potential interaction between this sort of inference
351
+ and the description of default trait bounds below.
352
+
348
353
## Default trait bounds
349
354
350
355
When referencing a trait object, it is almost * always* the case that one follows
@@ -358,12 +363,17 @@ certain fixed patterns:
358
363
You might think that we should simply provide some kind of defaults
359
364
that are sensitive to where the ` Trait ` appears. The same is probably
360
365
true of struct type parameters (in other words, ` &'a SomeStruct<'a> `
361
- is a very comon pattern).
366
+ is a very common pattern).
362
367
363
368
However, there are complications:
364
369
365
- - What about a type like ` struct Ref<'a, T> { x: &'a T } ` ? ` Ref<'a, Trait> `
366
- should really work the same way as ` &'a Trait ` .
370
+ - What about a type like ` struct Ref<'a, T:'a> { x: &'a T } ` ? `Ref<'a,
371
+ Trait>` should really work the same way as ` &'a Trait`. One way that
372
+ I can see to do this is to drive the defaulting based on the default
373
+ trait bounds of the ` T ` type parameter -- but if we do that, it is
374
+ both a non-local default (you have to consult the definition of
375
+ ` Ref ` ) and interacts with the potential inference described in the
376
+ previous section.
367
377
- There * are* reasons to want a type like ` Box<Trait+'a> ` . For example,
368
378
the macro parser includes a function like:
369
379
@@ -422,3 +432,39 @@ lifetime `'a` yields a list of `'b:'c` or `X:'d` pairs. For each pair
422
432
423
433
We can then say that ` T outlives 'a ` if all lifetime relations
424
434
returned by ` WF(T:'a) ` hold.
435
+
436
+ # Appendix B: Why object types must have exactly one bound
437
+
438
+ The motivation is that handling multiple bounds is overwhelmingly
439
+ complicated to reason about and implement. In various places,
440
+ constraints arise of the form ` all i. exists j. R[i] <= R[j] ` , where
441
+ ` R ` is a list of lifetimes. This is challenging for lifetime
442
+ inference, since there are many options for it to choose from, and
443
+ thus inference is no longer a fixed-point iteration. Moreover, it
444
+ doesn't seem to add any particular expressiveness.
445
+
446
+ The places where this becomes important are:
447
+
448
+ - Checking lifetime bounds when data is closed over into an object type
449
+ - Subtyping between object types, which would most naturally be
450
+ contravariant in the lifetime bound
451
+
452
+ Similarly, requiring that the "master" bound on object lifetimes outlives
453
+ all other bounds also aids inference. Now, given a type like the
454
+ following:
455
+
456
+ trait Foo<'a> : 'a { }
457
+ trait Bar<'b> : 'b { }
458
+
459
+ ...
460
+
461
+ let x: Box<Foo<'a>+Bar<'b>>
462
+
463
+ the inference engine can create a fresh lifetime variable ` '0 ` for the
464
+ master bound and then say that ` '0:'a ` and ` '0:'b ` . Without the
465
+ requirement that ` '0 ` be a master bound, it would be somewhat unclear
466
+ how ` '0 ` relates to ` 'a ` and ` 'b ` (in fact, there would be no
467
+ necessary relation). But if there is no necessary relation, then when
468
+ closing over data, one would have to ensure that the closed over data
469
+ outlives * all* derivable lifetime bounds, which again creates a
470
+ constraint of the form ` all i. exists j. ` .
0 commit comments