D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 21209 - scope attribute inference with does not work well with foreach
Summary: scope attribute inference with does not work well with foreach
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 normal
Assignee: No Owner
URL:
Keywords: pull, rejects-valid, safe
Depends on:
Blocks:
 
Reported: 2020-08-29 13:50 UTC by zopsicle
Modified: 2021-06-03 08:00 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description zopsicle 2020-08-29 13:50:33 UTC
The following program does not compile:

---
$ cat main.d
void foo()(const(char)[] cs)
{
    foreach (c; cs)
        bar(c);
}

@safe
void bar(char c)
{
}

@safe
void main()
{
    char[10] cs;
    foo(cs); // line 16
}
$ dmd -dip1000 main.d
main.d(16): Error: reference to local variable `cs` assigned to non-scope parameter `cs` calling example.foo!().foo
---

By manually adding the scope attribute to the cs parameter, the program compiles. But it is expected that DMD infers this from the body of the foo function, as it is a template.

Verified with DMD 2.092.0 and LDC 1.23.0.
Comment 1 Mathias LANG 2021-02-19 06:15:44 UTC
At first I thought it wasn't a bug because the type of `cs` is specified.
However, after changing `foo` to:
```
void foo(T)(T cs)
{
    foreach (c; cs)
        bar(c);
}
```

The error persist. The strangest part is that not calling `bar` from the foreach makes the error go away.
Comment 2 ag0aep6g 2021-02-19 07:30:14 UTC
(In reply to Mathias LANG from comment #1)
> The strangest part is that not calling `bar` from the
> foreach makes the error go away.

That's because `bar` is not `pure`. Without the `bar` call, `foo` becomes `pure` and you're hitting issue 20150 (DMD wrongly assumes that parameters of `pure` functions can always be `scope`).

When not relying on issue 20150, inference of `scope` is very limited. See also issue 20674.
Comment 3 Dennis 2021-06-01 12:50:59 UTC
Worth noting that scope inference also fails on foreach loops of alias sequences:

```
@safe:
void foo(A...)(A args) 
{
    static int x; x++; // force impure for issue 20150
    foreach(a; args) 
    {
        // gets lowered to unrolled loop with `string a = _param_0;`
    }
}

void main() 
{
    scope string x = "hey";
    foo(x);
}
```

Error: scope variable `x` assigned to non-scope parameter `_param_0` calling foo!string.foo
Comment 4 Dlang Bot 2021-06-01 16:05:24 UTC
@dkorpel created dlang/dmd pull request #12620 "Fix issue 21209 - scope attribute inference fails on foreach" fixing this issue:

- fix issue 21209 - scope inference fails with foreach

https://github.com/dlang/dmd/pull/12620
Comment 5 Dlang Bot 2021-06-02 23:58:48 UTC
dlang/dmd pull request #12620 "Fix issue 21209 - scope attribute inference fails on foreach" was merged into master:

- 8e9ea4ef3ae9eb2cad92eeb8d54189dfb108e8b7 by dkorpel:
  Fix issue 21209 - scope inference fails on foreach

https://github.com/dlang/dmd/pull/12620