@@ -36,19 +36,42 @@ use syntax::ast_util::{stmt_id};
36
36
/**
37
37
The region maps encode information about region relationships.
38
38
39
- - `scope_map` maps from:
40
- - an expression to the expression or block encoding the maximum
41
- (static) lifetime of a value produced by that expression. This is
42
- generally the innermost call, statement, match, or block.
43
- - a variable or binding id to the block in which that variable is declared.
44
- - `free_region_map` maps from:
45
- - a free region `a` to a list of free regions `bs` such that
46
- `a <= b for all b in bs`
39
+ - `scope_map` maps from a scope id to the enclosing scope id; this is
40
+ usually corresponding to the lexical nesting, though in the case of
41
+ closures the parent scope is the innermost conditinal expression or repeating
42
+ block
43
+
44
+ - `var_map` maps from a variable or binding id to the block in which
45
+ that variable is declared.
46
+
47
+ - `free_region_map` maps from a free region `a` to a list of free
48
+ regions `bs` such that `a <= b for all b in bs`
47
49
- the free region map is populated during type check as we check
48
50
each function. See the function `relate_free_regions` for
49
51
more information.
50
- - `temporary_scopes` includes scopes where cleanups for temporaries occur.
51
- These are statements and loop/fn bodies.
52
+
53
+ - `rvalue_scopes` includes entries for those expressions whose cleanup
54
+ scope is larger than the default. The map goes from the expression
55
+ id to the cleanup scope id. For rvalues not present in this table,
56
+ the appropriate cleanup scope is the innermost enclosing statement,
57
+ conditional expression, or repeating block (see `terminating_scopes`).
58
+
59
+ - `terminating_scopes` is a set containing the ids of each statement,
60
+ or conditional/repeating expression. These scopes are calling "terminating
61
+ scopes" because, when attempting to find the scope of a temporary, by
62
+ default we search up the enclosing scopes until we encounter the
63
+ terminating scope. A conditional/repeating
64
+ expression is one which is not guaranteed to execute exactly once
65
+ upon entering the parent scope. This could be because the expression
66
+ only executes conditionally, such as the expression `b` in `a && b`,
67
+ or because the expression may execute many times, such as a loop
68
+ body. The reason that we distinguish such expressions is that, upon
69
+ exiting the parent scope, we cannot statically know how many times
70
+ the expression executed, and thus if the expression creates
71
+ temporaries we cannot know statically how many such temporaries we
72
+ would have to cleanup. Therefore we ensure that the temporaries never
73
+ outlast the conditional/repeating expression, preventing the need
74
+ for dynamic checks and/or arbitrary amounts of stack space.
52
75
*/
53
76
pub struct RegionMaps {
54
77
priv scope_map : RefCell < HashMap < ast:: NodeId , ast:: NodeId > > ,
@@ -840,7 +863,16 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
840
863
visit:: FkItemFn ( ..) | visit:: FkMethod ( ..) => {
841
864
Context { parent : None , var_parent : None , ..cx}
842
865
}
843
- visit:: FkFnBlock ( ..) => cx
866
+ visit:: FkFnBlock ( ..) => {
867
+ // FIXME(#3696) -- at present we are place the closure body
868
+ // within the region hierarchy exactly where it appears lexically.
869
+ // This is wrong because the closure may live longer
870
+ // than the enclosing expression. We should probably fix this,
871
+ // but the correct fix is a bit subtle, and I am also not sure
872
+ // that the present approach is unsound -- it may not permit
873
+ // any illegal programs. See issue for more details.
874
+ cx
875
+ }
844
876
} ;
845
877
visitor. visit_block ( body, body_cx) ;
846
878
}
0 commit comments