September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #9 from Luís Ferreira <contact@lsferreira.net> --- (In reply to Dennis from comment #8) > Reduces to: > > ```D > void main() @safe > { > foreach(ref e; new int[1]) > int* f = &e; > } > ``` Thanks! So, maybe this should also be valid, but more arguable if requires dip1000 internal checks the same way with `ref`, although, spec-wise it should: ``` void main() @safe { foreach(e; new int[1]) int* f = &e; } ``` I removed the `ref`, `f` doesn't escape its own scope, the same way this should compile: ``` void main() @safe { int e; int* f = &e; } ``` -- |
September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #10 from Dominikus Dittes Scherkl <dominikus@scherkl.de> --- (In reply to Luís Ferreira from comment #4) > > Pointers are not allowed in @safe functions at all. > > What are you talking about? They are, its specified in the spec. 20.24.1. Safe Functions. Sorry. I misread your code. And of course the compiler could allow for some more patterns to be considered @safe, but I thought that was intentional so. E.g. the following (a simple self-reference check) is also not considered @safe and I was told that this is intentional without DIP1000: ``` struct Foo { Foo opAssign(const ref Foo f) { if(&f == this) return this; ... } } ``` I'm glad if this is considered a design-flaw that should be fixed. -- |
September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #11 from Dennis <dkorpel@live.nl> --- > the same way this should compile > I'm glad if this is considered a design-flaw that should be fixed. Without `-preview=dip1000` taking the address of local, stack allocated variables is not @safe. This is not going to be fixed, we're not going to add special cases to allow a halfway, in between form of safe stack pointers. It's all or nothing. The question here is whether a `ref` variable counts as a local variable. `ref` parameters freely bind to any lvalue in @safe code, including local variables, so the answer there is yes. A ref loop variable in foreach is a bit more difficult, as it depends on the type of the thing you're iterating over. In theory, in the absence of -preview=dip1000, it can't be a stack pointer when you're iterating over a dynamic array, so this issue's test case can be made `@safe` on the basis of that. On the other hand, there's still the gaping hole that local static arrays can be sliced in `@safe` code without `-preview=dip1000`, and get an unrestricted lifetime. So fixing this issue facilitates more exploitation of that hole (issue 24750). So perhaps we need to make that a deprecation first and then consider adding a special for this, but whether that's worth it depends on the future direction of dip1000 vs Robert's Simple Safe D. -- |
September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #12 from Nick Treleaven <nick@geany.org> --- (In reply to Dennis from comment #8) > Reduces to: > > ```D > void main() @safe > { > foreach(ref e; new int[1]) > int* f = &e; > } > ``` The compiler doesn't know (without optimization or -dip1000) that the program is equivalent to that. It doesn't know below that `f` doesn't escape the scope of foobar somehow. @safe void foobar() { int* f; foreach(ref e; foo) f = &e; } So it seems counter-intuitive to the way D's semantic analysis works to allow this case without -dip1000. -- |
September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #13 from Nick Treleaven <nick@geany.org> --- (In reply to Nick Treleaven from comment #3) > @safe > int* foobar() > { > int* f; > foreach(ref e; foo) > f = &e; // escaping address of foo[0] > return f; > } BTW with dmd git master and -dip1000, the static array escape is now caught: Error: scope variable `f` may not be returned -- |
September 13 [Issue 24754] cannot take address of a member array in a ref foreach | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24754 --- Comment #14 from Dennis <dkorpel@live.nl> --- (In reply to Nick Treleaven from comment #12) > The compiler doesn't know (without optimization or -dip1000) that the > program is equivalent to that. It could, all it needs to know is that typeof(Foo.foo) == typeof(new int[1]) == int[]. > It doesn't know below that `f` doesn't escape > the scope of foobar somehow. Doesn't mattter, `f` may escape, unless it's a `scope int[]`, which doesn't really exist without `-preview=dip1000`. -- |
Copyright © 1999-2021 by the D Language Foundation