| Thread overview | ||||||
|---|---|---|---|---|---|---|
|
September 12, 2012 built-in int[] opSliceOpAssign throws? | ||||
|---|---|---|---|---|
| ||||
--------
nothrow void foo1(int[] a)
{
foreach(i; 0..10)
{
a[i] = 5;
a[i] += 5;
}
}
nothrow void foo2(int[] a) //10
{
a[0..10] = 5; //12
a[0..10] += 5; //13
}
--------
main.d(13): Error: _arrayExpSliceAddass_i is not nothrow
main.d(10): Error: function main.foo2 'foo2' is nothrow yet may throw
--------
Making an out of range call in foo2 (after removing nothrow) throws an _ERROR_ in both line 12 and 13 (if commenting 12):
core.exception.RangeError@main(12): Range violation
core.exception.RangeError@main(13): Range violation
Is there any situation where it actually *could* throw an exception?
This is a bug? I did not find any entries in Bug report. Should I report this?
I need to make the above call in a nothrow function. Is there any way to make it work, without any run-time cost?
| ||||
September 12, 2012 Re: built-in int[] opSliceOpAssign throws? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | You are right, slice isn't nothrow, this should may be fixed.
But if you don't assign your dynamic array first, you have a problem: you cannot put elements in a empty dynamic array with arr[i] = val;, you have to use arr ~= val;
This code works:
import std.stdio;
nothrow void foo1(ref int[] a)
{
foreach(i; 0..10)
{
a ~= 5;
a[i] += 5;
}
}
void foo2(ref int[] a) //10
{
a[] = 5; //12, no explicit slice, so the whole array is assigned with 5
a[] += 7; //13
}
void main() {
int[] a;
foo1(a);
foo2(a);
writeln(a);
}
| |||
September 12, 2012 Re: built-in int[] opSliceOpAssign throws? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Wednesday, 12 September 2012 at 09:50:09 UTC, Namespace wrote: > You are right, slice isn't nothrow, this should may be fixed. > But if you don't assign your dynamic array first, you have a problem: you cannot put elements in a empty dynamic array with arr[i] = val;, you have to use arr ~= val; > > This code works: > > import std.stdio; > > nothrow void foo1(ref int[] a) > { > foreach(i; 0..10) > { > a ~= 5; > a[i] += 5; > } > } > > void foo2(ref int[] a) //10 > { > a[] = 5; //12, no explicit slice, so the whole array is assigned with 5 > a[] += 7; //13 > } > > void main() { > int[] a; > > foo1(a); > foo2(a); > > writeln(a); > } I think I foun out what is going on: It is a problem with overlap. According to specs, overlapping arrays are illegal: -------- void main() { int[10] b; b[] = 5; b[0..6] += b[4..10]; //6 b[0..6] = b[4..10]; //7 } -------- Here, Line 7 will produce an "object.Exception@src\rt\arraycat.d(40): overlapping array copy". However, line 6 will produce nothing. Toying with it shows that it produces *unspecified* behavior. So rephrasing my question in 2 questions: 1) Shouldn't "b[0..6] += b[4..10]" throw "something"? 2) Shouldn't the thrown object be an Error (and not an Exception)? | |||
September 12, 2012 Re: built-in int[] opSliceOpAssign throws? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Wednesday, September 12, 2012 11:20:54 monarch_dodra wrote:
> This is a bug? I did not find any entries in Bug report. Should I report this?
>
> I need to make the above call in a nothrow function. Is there any way to make it work, without any run-time cost?
I believe that dup and idup have the same problem, and it definitely needs to be fixed. Regardless, pretty much the only sane way to call a function that throws in a nothrow function is to put a try-catch around it.
try
func();
catch(Exception e)
assert(0, "func threw. That's supposed to be impossible.");
But if you do that, you'd better be sure that it really _can't_ throw (if it can, then you need to actually handle the exception rather than asserting 0).
- Jonathan M Davis
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply