Currently, we may initialize a struct with some feature, and use it later. In this case, we must write very ugly code like:
// init foo
#[cfg(feature="foo")]
let foo_builder=...;
#[cfg(feature="foo")] // now we have to duplicating the #[cfg(feature="foo")] since we cannot use brackets
let foo=foo_builder.build();
// ...
// deal with foo
#[cfg(feature="foo")] { // using brackets removed a duplicated `#[cfg(feature="foo")]`
let result = foo.use_it_later();
deal_with(result);
}
A more beautiful code might use brackets to mark what #[cfg(feature="foo")]
affected:
#[cfg(feature="foo")] { // init foo
let foo_builder=...;
let foo=foo_builder.build();
}
// ...
#[cfg(feature="foo")] { // deal with foo
let result = foo.use_it_later();
deal_with(result);
}
But, such code failed to compile, since foo
dropped immeditely after the bracket is closed.
Further, when dealing with unsafe
, same things happened again, we have to wrote:
let result = unsafe {unsafe_fun()};
rather than
unsafe {let result = unsafe_fun()}
If we have a sequence of unsafe function, we have to wrote either
let result1=unsafe{unsafe_fun_1()};
let result2=unsafe{unsafe_fun_2()};
let result3=unsafe{unsafe_fun_3()};
let result4=unsafe{unsafe_fun_4()};
let result5=unsafe{unsafe_fun_5()};
or
let (result1, result2, result3, result4, result5) = unsafe {
let result1=unsafe_fun_1();
let result2=unsafe_fun_2();
let result3=unsafe_fun_3();
let result4=unsafe_fun_4();
let result5=unsafe_fun_5();
(result1, result2, result3, result4, result5)
}
Considering this, I want to propose a new attribute, #[leak]
This attribute could apply to any block, leak all of the variables defined with let
out of the block.
With such option, we may wrote more clearly:
#[leak, cfg(feature="foo")] { // init foo, leak foo and foo_builder outslde the brackets.
let foo_builder=...;
let foo=foo_builder.build();
}
// since `foo` is leaked, we could call `foo.*` directly.
// ...
#[cfg(feature="foo")] { // deal with foo
let result = foo.use_it_later();
deal_with(result);
}
{
#[leak] unsafe {
let result1=unsafe_fun_1();
let result2=unsafe_fun_2();
let result3=unsafe_fun_3();
let result4=unsafe_fun_4();
let result5=unsafe_fun_5();
} // all the 5 results are leaked thus it is usable outside this unsafe block
} // here, all the 5 results are dropped.
Further discussion : fine grained control with leak
- Could the
leak
attribute accept several variables that indicate which variable should be leaked?
#[leak(foo), cfg(feature="foo")] { // init foo, leak foo and foo_builder outslde the brackets.
let foo_builder=...;
let foo=foo_builder.build();
}
foo.usable(); // foo is defined
// foo_builder is not leaked
- Is it possible to leak with
if
clauses
The following code seems clearly enough, but is it worth implement it?
#[leak(foo,bar)]
if flag {
let foo=baz.foo();
let bar=foo.bar();
} else {
let bar=baz.bar();
let foo=bar.foo();
}
I have no idea about the name of the attribute, I tried things like expand
extend
flatten
... Thus if you have a better name, tell me please:)