Re: Limits of implicit conversion of class arrays

2024-03-31 Thread Per Nordlöw via Digitalmars-d-learn
On Thursday, 28 March 2024 at 01:53:52 UTC, Steven Schveighoffer 
wrote:

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```


Yes, it's unsafe, as you can replace an element of `ds` with 
something that has no relation to `Derived`.


This is a suggested change that when _applied_ will make the code 
unsafe yes. But the code in its current form is safe and the 
compiler could be extended to prove it.


Re: Limits of implicit conversion of class arrays

2024-03-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On Monday, 25 March 2024 at 07:16:35 UTC, Per Nordlöw wrote:
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

The first and second is unsound (infamously allowed in Java).


In the general case, yes. But, do you see any errors with the 
code


```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```


Yes, it's unsafe, as you can replace an element of `ds` with 
something that has no relation to `Derived`.




Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of 
the ds slice.


Again, in the general case, yes.

So what is different in this code example compared to the 
general case? Hint: this has overlaps with a missing compiler 
optimization in dmd (and many other statically typed languages) 
enabled by a specific kind of data flow analysis. Which one?


If there is a way to end up with a `Derived` reference to point 
at something that is not a `Derived` *without a cast* in system 
code, or *even with a cast* in safe code, then it is an error. It 
doesn't matter if you aren't actually doing it.


If you know you are not making that mistake, change it to system, 
and cast to inform the compiler that you "know what you are 
doing".


-Steve


Re: Limits of implicit conversion of class arrays

2024-03-25 Thread Per Nordlöw via Digitalmars-d-learn
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

The first and second is unsound (infamously allowed in Java).


In the general case, yes. But, do you see any errors with the code

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of the 
ds slice.


Again, in the general case, yes.

So what is different in this code example compared to the general 
case? Hint: this has overlaps with a missing compiler 
optimization in dmd (and many other statically typed languages) 
enabled by a specific kind of data flow analysis. Which one?


Re: Limits of implicit conversion of class arrays

2024-03-23 Thread FeepingCreature via Digitalmars-d-learn
On Saturday, 23 March 2024 at 11:04:04 UTC, Dmitry Olshansky 
wrote:

On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote:

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


The first and second is unsound (infamously allowed in Java). 
Once you cast the slice you can populate it with Derived2 
objects that are not Derived, hence breaking type safety of the 
ds slice.


—
Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me


Note that it works if the classes are const:

```d
const(Base)[] bs;
const(Derived)[] ds;
bs ~= ds; // pass
bs = ds; // pass
bs = cast(const(Base)[])ds; // pass
```

Exactly because you can't replace existing entries.


Re: Limits of implicit conversion of class arrays

2024-03-23 Thread Dmitry Olshansky via Digitalmars-d-learn

On Saturday, 23 March 2024 at 09:08:45 UTC, Per Nordlöw wrote:

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


The first and second is unsound (infamously allowed in Java). 
Once you cast the slice you can populate it with Derived2 objects 
that are not Derived, hence breaking type safety of the ds slice.


—
Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me



Limits of implicit conversion of class arrays

2024-03-23 Thread Per Nordlöw via Digitalmars-d-learn

Is there a reason why

```d
class Base {}
class Derived : Base {}

@safe pure nothrow unittest {
Base b;
Derived d;
b = d; // pass

Base[] bs;
Derived[] ds;
bs ~= ds; // pass
bs = ds; // fail [1], should pass
bs = cast(Base[])ds; // fail [2], should pass
}
```

fails as

[1]: cannot implicitly convert expression `ds` of type 
`Derived[]` to `Base[]`

[2]: cast from `Derived[]` to `Base[]` not allowed in safe code

?


Re: Implicit conversion of string to array of immutable ubytes

2024-03-22 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, March 23, 2024 12:11:15 AM MDT Per Nordlöw via Digitalmars-d-
learn wrote:
> Why doesn't string implicitly convert to immutable(ubyte)[] in
> @safe mode?

Why would it? They're different types. Their elements happen to have the
same size, but that doesn't mean that they're used for the same thing at
all. And having them be implicitly convertible could cause serious problems
with overloading.

If you want to do that conversion without a cast, then you can just use
std.string.representation (which will do the cast internally).

- Jonathan M Davis






Re: Providing implicit conversion of - memory-safety

2024-01-24 Thread Siarhei Siamashka via Digitalmars-d-learn

On Wednesday, 24 January 2024 at 09:28:57 UTC, Renato wrote:
If you have "widespread" arithmetics which may overflow, 
something like https://dlang.org/phobos/core_checkedint.html is 
useful, yes, but in this case it's overkill.


To make use of this, one needs to already anticipate an 
arithmetic overflow bug at some precise location in the code. But 
this defeats the purpose. Both array bounds checks and arithmetic 
overflow checks are useful when the compiler can perform these 
checks globally for the whole code. To discover bugs even in the 
parts of code, where they were not anticipated.


Re: Providing implicit conversion of - memory-safety

2024-01-24 Thread Renato via Digitalmars-d-learn

On Wednesday, 24 January 2024 at 00:34:19 UTC, bachmeier wrote:

On Tuesday, 23 January 2024 at 21:40:46 UTC, Renato wrote:

While I can understand your frustration, it seems to me D is 
not to blame in this instance because the code is quite 
patently using unsafe constructs (D does not claim to be fully 
safe).


It pretends to be safe. Consider this:

```
void main() {
long y = int.max + 1;
writeln(y);  // -2147483648
long y2 = int.max;
writeln(y2 + 1); // 2147483648
int y3 = y; // Won't compile
}
```

It can only be described as a mess of inconsistency. `int y3 = 
y;` should be an error and it is. `int.max + 1` silently 
turning into a negative value is frankly insane because it's 
the same problem that a few lines below won't compile.



Would something like this work?

```d
double value(T)(T index, double* x) if (is(T : size_t))
```


There's no way to add a template constraint. Many different 
types, most of which I defined myself, could be sent as an 
argument.


that it's almost always a mistake to subract from any unsigned 
type - D scanner correctly warns about that).


It's the inconsistency that's the problem. You have to program 
as if the compiler doesn't catch anything - sometimes it throws 
errors, sometimes it lets stuff through because maybe that's 
what you want. `int y3 = y` in the code above is not 
necessarily an error.


For the record, even Rust allows you to subtract from an unsigned 
type, but it warns you about it and it fails at runtime due to 
the subtraction overflowing (which I believe Rust only checks in 
debug mode - in release mode I believe it would behave like D 
does in this case, but I didn't verify that).


Here's an example program that compiles:

```rust

fn action(n: usize, arr: &[i64]) -> i64 {
if n - 5 < 0 {
0
} else {
arr[n - 5]
}
}

fn main() {
let arr: [i64; 6] = [1,2,3,4,5,6];
println!("{}", action(4, &arr));
}
```

Compiling and running it:

```rust
warning: comparison is useless due to type limits
 --> src/main.rs:3:8
  |
3 | if n - 5 < 0 {
  |^
  |
  = note: `#[warn(unused_comparisons)]` on by default

warning: `playground` (bin "playground") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.49s
 Running `target/debug/playground`
thread 'main' panicked at src/main.rs:3:8:
attempt to subtract with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display 
a backtrace

```

I believe that DScanner also warns about the OP's code (I see 
this warning all the time in my D code)... but again, if you want 
to subtract a number from an unsigned typed variable, you should 
absolutely check first that variable is `>=` that number, in Rust 
or D or any other language.


If you have "widespread" arithmetics which may overflow, 
something like https://dlang.org/phobos/core_checkedint.html is 
useful, yes, but in this case it's overkill.


Some languages, like Pony, have dedicated operators for "safe 
arithmetics" (because they're much slower and are only rarely 
strictly needed):



```
// unsigned wrap-around on overflow
U32.max_value() + 1 == 0

// unsafe operator (undefined behaviour, like with C operators)
U32.max_value() +~ 1 // could be anything!

// safe operator (throws on overflow)
U32.max_value() +? 1
```



Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Renato via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 23:40:55 UTC, Danilo wrote:

How did you make it correct?

Write 2 different versions for `signed` and `unsigned` types?
Or could you utilize `core.checkedint` somehow for checking 
overflow?


```d
double value(T)(T index, double * x) {
bool overflow;
subu(index, 5, overflow);

if (overflow) {
return 0.0;
} else {
return x[index-5];
}
}
```
This is probably only correct for `unsigned` types.


When you have a variable with a "potentially" unsigned type, you 
must not subtract from it unless you're sure the result is not 
going negative. The fixed code only subtracts 5 from `index` 
after checking that `index >= 5`, so it is always safe.


Your previous code was trying to do the same thing incorrectly 
because it just subtracted 5 **first**. This is analogous to 
checking pointers for null before using them.


The type parameter restriction was not necessary, but it was 
added because the code is assuming that the type can be coerced 
to size_t, as it's being used as an index - so it's a good idea 
to make that part of the template's "signature"... even without 
the type limitation, your code wouldn't compile if this was not 
the case (but your error message will probably be much worse).


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread bachmeier via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 23:40:55 UTC, Danilo wrote:

On Tuesday, 23 January 2024 at 17:54:25 UTC, bachmeier wrote:
Here's a reduced version of one of the most bizarre bugs I've 
dealt with in any language. The only reason I didn't move on 
to another language was because I was too busy at the time.


The code allows for initial values if the index is less than 
0, otherwise it returns the element.


```
import std;

double value(T)(T index, double * x) {
  if (index - 5 < 0) {
return 0.0;
  } else {
return x[index-5];
  }
}

void main() {
  double[] v = [1.1, 2.2, 3.3];
  // Works
  writeln(value(3, v.ptr));
  // Lucky: program segfaults
  writeln(value(v.length, v.ptr));
}
```

I noticed this behavior only because the program crashes. Once 
I figured out what was going on, I realized that the thousands 
of lines of code I had already written needed to be checked 
and possibly rewritten. If only I had a compiler to do that 
for me.


How did you make it correct?


The fix is very easy once you realize what's going on. index is 
ulong, so index - 5 is ulong (even though it doesn't make any 
sense). All you have to do is change index to index.to!long and 
the problem is solved.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread bachmeier via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 21:40:46 UTC, Renato wrote:

While I can understand your frustration, it seems to me D is 
not to blame in this instance because the code is quite 
patently using unsafe constructs (D does not claim to be fully 
safe).


It pretends to be safe. Consider this:

```
void main() {
long y = int.max + 1;
writeln(y);  // -2147483648
long y2 = int.max;
writeln(y2 + 1); // 2147483648
int y3 = y; // Won't compile
}
```

It can only be described as a mess of inconsistency. `int y3 = 
y;` should be an error and it is. `int.max + 1` silently turning 
into a negative value is frankly insane because it's the same 
problem that a few lines below won't compile.



Would something like this work?

```d
double value(T)(T index, double* x) if (is(T : size_t))
```


There's no way to add a template constraint. Many different 
types, most of which I defined myself, could be sent as an 
argument.


that it's almost always a mistake to subract from any unsigned 
type - D scanner correctly warns about that).


It's the inconsistency that's the problem. You have to program as 
if the compiler doesn't catch anything - sometimes it throws 
errors, sometimes it lets stuff through because maybe that's what 
you want. `int y3 = y` in the code above is not necessarily an 
error.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Danilo via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 17:54:25 UTC, bachmeier wrote:
Here's a reduced version of one of the most bizarre bugs I've 
dealt with in any language. The only reason I didn't move on to 
another language was because I was too busy at the time.


The code allows for initial values if the index is less than 0, 
otherwise it returns the element.


```
import std;

double value(T)(T index, double * x) {
  if (index - 5 < 0) {
return 0.0;
  } else {
return x[index-5];
  }
}

void main() {
  double[] v = [1.1, 2.2, 3.3];
  // Works
  writeln(value(3, v.ptr));
  // Lucky: program segfaults
  writeln(value(v.length, v.ptr));
}
```

I noticed this behavior only because the program crashes. Once 
I figured out what was going on, I realized that the thousands 
of lines of code I had already written needed to be checked and 
possibly rewritten. If only I had a compiler to do that for me.


How did you make it correct?

Write 2 different versions for `signed` and `unsigned` types?
Or could you utilize `core.checkedint` somehow for checking 
overflow?


```d
double value(T)(T index, double * x) {
bool overflow;
subu(index, 5, overflow);

if (overflow) {
return 0.0;
} else {
return x[index-5];
}
}
```
This is probably only correct for `unsigned` types.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Siarhei Siamashka via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 21:40:46 UTC, Renato wrote:
While I can understand your frustration, it seems to me D is 
not to blame in this instance because the code is quite 
patently using unsafe constructs


I wouldn't blame bachmeier, because many reduced testcases 
distilled from the real code tend to look nonsensical. The 
arithmetic overflows, silent undesirable signed/unsigned casts 
and other pitfalls happen in the `@safe` code too. The use of 
pointers and other unsafe constructs in the provided testcase is 
a red herring.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Renato via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 21:18:53 UTC, bachmeier wrote:
There are two things things that cause the problem. One is the 
use of a template and the other is passing an unsigned type. 
The reason the first parameter uses a template is because there 
are a lot of types I could send as the first argument, and for 
some of them there was a transformation of index (for instance, 
you can pass a date as a long[2], or you can pass another type 
and pull out the length, that sort of thing). It's using a 
pointer because I was working with a C library, and that's how 
the data is stored and passed around.


The data is time series. If after the transformations the index 
is less than zero, it returns 0.0, which is used for all 
pre-sample values. If it's non-negative, return the element at 
that position.


One of the nice things about D is the ability to write this 
kind of code in such a natural and (I thought) intuitive style. 
I really like the way all this comes together. There's really 
no way that code should have been able to do anything wrong. 
What's terribly frustrating is that the compiler had full 
knowledge of what was happening, but by choice it didn't say 
anything, even though D is supposed to prevent these things 
that happen in C.


While I can understand your frustration, it seems to me D is not 
to blame in this instance because the code is quite patently 
using unsafe constructs (D does not claim to be fully safe).


Would something like this work?

```d
double value(T)(T index, double* x) if (is(T : size_t))
{
if (index < 5 || x == null)
{
return 0.0;
}
else
{
return x[index - 5];
}
}

void main()
{
import std.stdio;
import std.range : iota;

double[] ds = [1, 2, 3, 4, 5, 6];
ubyte b = 1;
foreach (_; iota(12))
{
writeln(value(b++, ds.ptr));
}
}
```

This will still read rubbish if the index goes past the actual 
array (because I assume you can't get the exact length from the C 
code? If you can, you should pass that in and do the bounds check 
yourself) but there's no unsigned type mistakes (notice that it's 
almost always a mistake to subract from any unsigned type - D 
scanner correctly warns about that).


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread bachmeier via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 19:27:26 UTC, Renato wrote:
Here's a reduced version of one of the most bizarre bugs I've 
dealt with in any language. The only reason I didn't move on 
to another language was because I was too busy at the time.


The code allows for initial values if the index is less than 
0, otherwise it returns the element.


```
import std;

double value(T)(T index, double * x) {
  if (index - 5 < 0) {
return 0.0;
  } else {
return x[index-5];
  }
}

void main() {
  double[] v = [1.1, 2.2, 3.3];
  // Works
  writeln(value(3, v.ptr));
  // Lucky: program segfaults
  writeln(value(v.length, v.ptr));
}
```

I noticed this behavior only because the program crashes. Once 
I figured out what was going on, I realized that the thousands 
of lines of code I had already written needed to be checked 
and possibly rewritten. If only I had a compiler to do that 
for me.


This code seems to be doing everything it can to run into 
undefined behaviour, though?


Why is `index` of a type T that has no requirements at all 
(when the implementation quite clearly wants `size_t`, or at 
least an unsigned numerical value)? Why is it using a pointer 
for x when clearly you intend to use it as a slice? You 
probably have context that I don't, but I would never expect 
this sort of code to be anywhere near @safe :D


There are two things things that cause the problem. One is the 
use of a template and the other is passing an unsigned type. The 
reason the first parameter uses a template is because there are a 
lot of types I could send as the first argument, and for some of 
them there was a transformation of index (for instance, you can 
pass a date as a long[2], or you can pass another type and pull 
out the length, that sort of thing). It's using a pointer because 
I was working with a C library, and that's how the data is stored 
and passed around.


The data is time series. If after the transformations the index 
is less than zero, it returns 0.0, which is used for all 
pre-sample values. If it's non-negative, return the element at 
that position.


One of the nice things about D is the ability to write this kind 
of code in such a natural and (I thought) intuitive style. I 
really like the way all this comes together. There's really no 
way that code should have been able to do anything wrong. What's 
terribly frustrating is that the compiler had full knowledge of 
what was happening, but by choice it didn't say anything, even 
though D is supposed to prevent these things that happen in C.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Renato via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 17:54:25 UTC, bachmeier wrote:
On Tuesday, 23 January 2024 at 12:34:38 UTC, Nick Treleaven 
wrote:


But I'm strongly in favour of catching any bugs at 
compile-time (and have been since before I discovered D). I 
just object to anyone trying to downgrade the importance of 
automated memory-safety checking.


I'm not downgrading the importance of memory safety. All I'm 
saying is that you can't sell D as a safe language if has bugs 
like this.


Here's a reduced version of one of the most bizarre bugs I've 
dealt with in any language. The only reason I didn't move on to 
another language was because I was too busy at the time.


The code allows for initial values if the index is less than 0, 
otherwise it returns the element.


```
import std;

double value(T)(T index, double * x) {
  if (index - 5 < 0) {
return 0.0;
  } else {
return x[index-5];
  }
}

void main() {
  double[] v = [1.1, 2.2, 3.3];
  // Works
  writeln(value(3, v.ptr));
  // Lucky: program segfaults
  writeln(value(v.length, v.ptr));
}
```

I noticed this behavior only because the program crashes. Once 
I figured out what was going on, I realized that the thousands 
of lines of code I had already written needed to be checked and 
possibly rewritten. If only I had a compiler to do that for me.


This code seems to be doing everything it can to run into 
undefined behaviour, though?


Why is `index` of a type T that has no requirements at all (when 
the implementation quite clearly wants `size_t`, or at least an 
unsigned numerical value)? Why is it using a pointer for x when 
clearly you intend to use it as a slice? You probably have 
context that I don't, but I would never expect this sort of code 
to be anywhere near @safe :D


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread bachmeier via Digitalmars-d-learn

On Tuesday, 23 January 2024 at 12:34:38 UTC, Nick Treleaven wrote:

But I'm strongly in favour of catching any bugs at compile-time 
(and have been since before I discovered D). I just object to 
anyone trying to downgrade the importance of automated 
memory-safety checking.


I'm not downgrading the importance of memory safety. All I'm 
saying is that you can't sell D as a safe language if has bugs 
like this.


Here's a reduced version of one of the most bizarre bugs I've 
dealt with in any language. The only reason I didn't move on to 
another language was because I was too busy at the time.


The code allows for initial values if the index is less than 0, 
otherwise it returns the element.


```
import std;

double value(T)(T index, double * x) {
  if (index - 5 < 0) {
return 0.0;
  } else {
return x[index-5];
  }
}

void main() {
  double[] v = [1.1, 2.2, 3.3];
  // Works
  writeln(value(3, v.ptr));
  // Lucky: program segfaults
  writeln(value(v.length, v.ptr));
}
```

I noticed this behavior only because the program crashes. Once I 
figured out what was going on, I realized that the thousands of 
lines of code I had already written needed to be checked and 
possibly rewritten. If only I had a compiler to do that for me.


Re: Providing implicit conversion of

2024-01-23 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 19:49:19 UTC, Siarhei Siamashka 
wrote:
The two's complement wraparound behavior mandated by the D 
language spec is a non-technical political decision, intended 
to make life easier for the DMD compiler developers, but 
ignoring the needs of the users.


Actually it is for compatibility when porting C code to D.


Re: Providing implicit conversion of - memory-safety

2024-01-23 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 19:11:50 UTC, Siarhei Siamashka 
wrote:
On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven 
wrote:
Memory safety issues are a worse class of bug than arithmetic 
bugs. The latter are reproducible if you feed them the same 
input.


Memory safety bugs are reproducible with the tools like 
`valgrind`.


Not necessarily, valgrind can execute programs too slowly for 
human input, so anything that relies on timing is difficult to 
reproduce. It also uses far more memory, it could be too much 
memory for the system.


Whereas arithmetic overflow bugs are a real PITA to debug. 
Assuming that the incorrect results are even noticed.


You're talking about debugging, whereas I'm saying you often 
don't even have a chance to *notice* memory-safety bugs, because 
they might not even occur on the development system, only on the 
production system.


And even if you know there's a memory-safety problem, you can't 
easily narrow down  where it is (without language support for 
memory-safety). With arithmetic problems it's far easier to 
narrow down which code is causing them.


But I'm strongly in favour of catching any bugs at compile-time 
(and have been since before I discovered D). I just object to 
anyone trying to downgrade the importance of automated 
memory-safety checking.


Re: Providing implicit conversion of

2024-01-22 Thread Danilo via Digitalmars-d-learn

On Monday, 22 January 2024 at 17:15:55 UTC, bachmeier wrote:
I get incorrect results, and when I'm lucky, my program 
segfaults because I accessed something I shouldn't. When I'm 
not, it silently and happily gives me the wrong answer.


Maybe a compiler warning (not error) would help with detecting
the `unsigned into signed` issue, within same size types?

[core.checkedint.negs](https://dlang.org/phobos/core_checkedint.html#.negs) 
probably doesn't help, because `unsigned into signed` is a different issue?


Re: Providing implicit conversion of

2024-01-22 Thread Siarhei Siamashka via Digitalmars-d-learn
On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer 
wrote:

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


There's a hope that OpenD may try to improve the current 
situation. A related discussion can be found here: 
https://github.com/orgs/opendlang/discussions/4



It would also break a lot of existing code.


How did you estimate that it's *a lot* of existing code? As an 
experiment, I tried to patch Druntime and Phobos to avoid signed 
overflows roughly a year ago: 
https://github.com/ssvb/gcc/commits/gdc-ftrapv-phobos-20220209/


And there were not too many places in the code that actually 
needed any fixes. Additionally taking care of unsigned overflows 
would surely require more changes, but I doubt that they are 
going to be big. In most cases encountering an arithmetic 
overflow is unexpected and undesired, it's typically the symptom 
of a bug in the code. Some clever bit-tricks relying on two's 
complement wrap-around exist, but they are: 1) not very common 2) 
can be easily debugged if arithmetic overflows are trapped at 
runtime 3) can be easily patched up. The two's complement 
wraparound behavior mandated by the D language spec is a 
non-technical political decision, intended to make life easier 
for the DMD compiler developers, but ignoring the needs of the 
users.


Re: Providing implicit conversion of

2024-01-22 Thread Siarhei Siamashka via Digitalmars-d-learn

On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven wrote:
Memory safety issues are a worse class of bug than arithmetic 
bugs. The latter are reproducible if you feed them the same 
input.


Memory safety bugs are reproducible with the tools like 
`valgrind`. Whereas arithmetic overflow bugs are a real PITA to 
debug. Assuming that the incorrect results are even noticed.


Re: Providing implicit conversion of

2024-01-22 Thread bachmeier via Digitalmars-d-learn

On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven wrote:

I've said multiple times that it's silly to spend so much time 
on memory safety if the language is going to allow stuff like 
this without a simple way to prevent it.


Memory safety issues are a worse class of bug than arithmetic 
bugs.


The required language changes are pretty small to catch 
arithmetic bugs relative to implementing memory safety. 
Ultimately, you want the compiler to help you catch bugs in any 
form, and I don't think someone that wants memory safety is 
likely to be okay with the type of bugs in this thread.


But for me, arithmetic bugs are a much larger problem than memory 
safety. I mostly use the GC plus calls into well-tested C 
libraries. I get incorrect results, and when I'm lucky, my 
program segfaults because I accessed something I shouldn't. When 
I'm not, it silently and happily gives me the wrong answer.


Re: Providing implicit conversion of

2024-01-22 Thread Nick Treleaven via Digitalmars-d-learn
On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer 
wrote:

The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


It would also break a lot of existing code.


I think the bigger issue is implicit conversion from unsigned to 
signed of the same bit size. In a future edition D could require 
a larger signed type in order to implicitly convert from 
unsigned. That would have caught the `long johnstone =` line.


Also signed should never convert to unsigned, though I don't 
think that's happening here.


Re: Providing implicit conversion of

2024-01-22 Thread bachmeier via Digitalmars-d-learn

On Monday, 22 January 2024 at 06:43:17 UTC, thinkunix wrote:

Gavin Gray via Digitalmars-d-learn wrote:

The following code:

   ulong charlie = 11;
   long johnstone = std.algorithm.comparison.max(0, -charlie);
   writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.



I have no idea what your use case is for this but...
WHY are you doing this??

If you declared charlie as unsigned, why would you then attempt 
to
compare using a negative value?  If you even had the 
possibility that
charlie might be negative, why wouldn't you use a type that can 
accomodate the sign?


I'm sure they would if the compiler had stopped and provided an 
error message to tell them what they were doing. Note that in 
this line


```
long johnstone = std.algorithm.comparison.max(0, -charlie);
```

there is no direct assignment of a negative number to an unsigned 
type. The comparison is carried out as ulong and then there's an 
implicit conversion of a ulong to long, even though that can give 
a very weird result. It's perfectly natural to expect that 
everything will be carried out as a long since that's what's 
specified, or that a language like D will forbid implicit 
conversions if they can possibly give the wrong answer. If you 
change the long to int, the code will no longer compile.


Aside from the general statement that programmers make mistakes, 
D is prone to these issues because of the heavy use of auto, and 
because unsigned types are used for things like the length of an 
array.


Re: Providing implicit conversion of

2024-01-21 Thread Danilo via Digitalmars-d-learn

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.


This returns -1:
```d
import std;

void main() {
ulong charlie = 11;
long johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));
}
```

If you change the result type to `auto johnstone`, it returns 
18446744073709551605:

```d
module app;

import std;

void main() {
ulong charlie = 11;
auto johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));
}
```

So what happens is, max() correctly returns 18446744073709551605,
but if you explicitely receive a `long`, the `ulong` is converted 
to a long,

resulting in -11.

With `auto johnstone` or `ulong johnstone` the result is correct:
```d
import std;

void main() {
ulong charlie = 11;
ulong johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));
}
```

If you take a bigger type, like `Int128`, it is also correct:
```d
import std;

void main() {
ulong charlie = 11;
Int128 johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));
}
```


Re: Providing implicit conversion of

2024-01-21 Thread thinkunix via Digitalmars-d-learn

Gavin Gray via Digitalmars-d-learn wrote:

The following code:

   ulong charlie = 11;
   long johnstone = std.algorithm.comparison.max(0, -charlie);
   writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless of all 
arguments concerning implicit conversions, 1's and 2's complements, 
being efficient, etc).


The language should not allow unary unsigned anything.



I have no idea what your use case is for this but...
WHY are you doing this??

If you declared charlie as unsigned, why would you then attempt to
compare using a negative value?  If you even had the possibility that
charlie might be negative, why wouldn't you use a type that can 
accomodate the sign?


Using the proper type, you get a proper result:

long b = 12;
long n = std.algorithm.comparison.max(0, -b);
long o = std.algorithm.comparison.max(0, b);
writeln("n: ", n);  // prints 0
writeln("o: ", o);  // prints 12

Seems obvious to me, but am I missing something?

scot


Re: Providing implicit conversion of

2024-01-21 Thread bachmeier via Digitalmars-d-learn
On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer 
wrote:

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


It would also break a lot of existing code.

-Steve


Well there was no problem breaking my code for this (which you 
even proposed should be fixed):


```
foreach(int i, v; arr) {
  // i is not an int until you do i.to!int
}
```

The compiler knows it's converting from a ulong to a long:

```
ulong a = -11;
writeln(a);
// 18446744073709551605
long b = a;
writeln(b);
// -11
```

It's impossible for both to be the intended behavior. Anyone 
doing that on purpose (which I suspect is extremely rare) would 
be doing it because they want b equal to 18446744073709551605. I 
don't see why this should be treated the same as an int to long 
conversion because it very much changes the value.


There needs to be a safe arithmetic mode because the current 
behavior of `double j = 10 / 3;` is not what anyone expects and 
is a bug 100% of the time. I've said multiple times that it's 
silly to spend so much time on memory safety if the language is 
going to allow stuff like this without a simple way to prevent it.


Re: Providing implicit conversion of

2024-01-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 
(regardless of all arguments concerning implicit conversions, 
1's and 2's complements, being efficient, etc).


The language should not allow unary unsigned anything.


This is unlikely to get fixed, just due to the nature of D's 
philosophy when it comes to C compatibility.


It would also break a lot of existing code.

-Steve


Providing implicit conversion of

2024-01-21 Thread Gavin Gray via Digitalmars-d-learn

The following code:

  ulong charlie = 11;
  long johnstone = std.algorithm.comparison.max(0, -charlie);
  writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless 
of all arguments concerning implicit conversions, 1's and 2's 
complements, being efficient, etc).


The language should not allow unary unsigned anything.



Re: Implicit conversion of unique chars[] to string

2021-03-23 Thread Per Nordlöw via Digitalmars-d-learn
On Tuesday, 23 March 2021 at 01:07:15 UTC, Steven Schveighoffer 
wrote:
And the answer is complex. You can't accept a const range, 
because they don't work. The only way to have purity infer 
uniqueness is to accept paramters that the result could not 
have come from. Usually this means accepting const and 
returning mutable.


How do we want this to work with and without the presence of 
`return` qualified parameters?


Re: Implicit conversion of unique chars[] to string

2021-03-23 Thread Per Nordlöw via Digitalmars-d-learn
On Tuesday, 23 March 2021 at 01:07:15 UTC, Steven Schveighoffer 
wrote:

const(char)[] x = "foo";
string chained = chainPath(x, "bar").array;


that calls the template overload

ForeachType!Range[] array(Range)(Range r)
if (isIterable!Range && !isAutodecodableString!Range && 
!isInfinite!Range)


should be able to implicitly convert to string because the .array 
expression is inferred `pure`. Or is the compiler pessimistically 
assuming that the slice returned from the .array call may reside 
from a reference reachable from the range parameter `r`?


See for instance

@safe pure unittest
{
import std.path : chainPath;
import std.array : array;
const(char)[] x1 = "foo";
const string x2 = "bar";
auto y1 = chainPath(x1, x2).array;
pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", 
typeof(y1));

auto y2 = chainPath(x2, x1).array;
pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", 
typeof(y2));

}

printing

/home/per/f.d(8,1): Debug: const(char)[]
/home/per/f.d(10,1): Debug: const(char)[]


Re: Implicit conversion of unique chars[] to string

2021-03-22 Thread ag0aep6g via Digitalmars-d-learn

On 23.03.21 02:07, Steven Schveighoffer wrote:

const(char)[] x = "foo";
string chained = chainPath(x, "bar").array;

Error: cannot implicitly convert expression array(chainPath(x, "bar")) 
of type const(char)[] to string


And the answer is complex. You can't accept a const range, because they 
don't work. The only way to have purity infer uniqueness is to accept 
paramters that the result could not have come from. Usually this means 
accepting const and returning mutable.


Ah, right. Purity was a red herring then. If you put a `const(char)[]` 
in and you get a `const(char)[]` out, then the compiler must assume that 
it might be the same one.


We could possibly change `.array` to return a `char[]`. Uniqueness would 
still fail when you pass a `char[]` in, but that could be worked around 
by adding a const temporary.


Re: Implicit conversion of unique chars[] to string

2021-03-22 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/22/21 5:58 PM, ag0aep6g wrote:

On 22.03.21 21:38, Per Nordlöw wrote:

Am I the only one being annoyed by the fact that

 chainPath(...).array

doesn't implicit convert to string despite the array returned from 
.array is allocated by the GC.


Works for me:


import std.array: array;
import std.path: chainPath;
void main()
{
     string chained = chainPath("foo", "bar").array;
}


Uniqueness is being inferred based on purity. If it doesn't work for 
you, then you're probably doing something impure.


He didn't specify clearly on the original post. Yours works because 
everything is a string.


Try

const(char)[] x = "foo";
string chained = chainPath(x, "bar").array;

Error: cannot implicitly convert expression array(chainPath(x, "bar")) 
of type const(char)[] to string


And the answer is complex. You can't accept a const range, because they 
don't work. The only way to have purity infer uniqueness is to accept 
paramters that the result could not have come from. Usually this means 
accepting const and returning mutable.


-Steve


Re: Implicit conversion of unique chars[] to string

2021-03-22 Thread ag0aep6g via Digitalmars-d-learn

On 22.03.21 21:38, Per Nordlöw wrote:

Am I the only one being annoyed by the fact that

     chainPath(...).array

doesn't implicit convert to string despite the array returned from 
.array is allocated by the GC.


Works for me:


import std.array: array;
import std.path: chainPath;
void main()
{
string chained = chainPath("foo", "bar").array;
}


Uniqueness is being inferred based on purity. If it doesn't work for 
you, then you're probably doing something impure.


Re: Implicit conversion of unique chars[] to string

2021-03-22 Thread Per Nordlöw via Digitalmars-d-learn

On Monday, 22 March 2021 at 20:38:36 UTC, Per Nordlöw wrote:

chainPath(...).array


To clarify, for instance, given

  string s;
  const(char)[] c;

all the calls

  chainPath(s, s).array
  chainPath(c, c).array
  chainPath(s, c).array
  chainPath(c, s).array

return a value of type const(char)[].


Implicit conversion of unique chars[] to string

2021-03-22 Thread Per Nordlöw via Digitalmars-d-learn

Am I the only one being annoyed by the fact that

chainPath(...).array

doesn't implicit convert to string despite the array returned 
from .array is allocated by the GC.


Yes, I know that I should do

chainPath(...).array.assumeUnique

but the uniqueness of .array (and in turn implicit conversion to 
immutable) should be inferred by the compiler.


Inference could happen in the same compiler pass that checks 
(will infer) scope qualifiers.


Are there plans for making this happen?

Is having a @unique qualifier motivated for the sake of compiler 
performance to avoid the for need transitive inference across 
function calls?


Re: Disallow implicit "conversion" from alias-types

2020-11-10 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Tuesday, 10 November 2020 at 11:49:19 UTC, Jerry wrote:
On Tuesday, 10 November 2020 at 11:38:30 UTC, Vladimirs 
Nordholm wrote:

Hello.

I am unsure if I am going about this the right way, and if my 
question even makes sense.


In essence what I want is to have two "types" represented by a 
size_t. Here is an example of what I want think I want (but 
might be completely off)


alias Foo = size_t;
alias Bar = size_t;

Foo foo = 4;
Bar bar = foo; // i want some error like
   // "cannot implicitly convert from type Foo 
to Bar"


My best solution is to have the types as classes to force type 
checking.


Is there a better way to do what I want here?


https://dlang.org/library/std/typecons/typedef.html


This is exactly what I need. Thanks!




Re: Disallow implicit "conversion" from alias-types

2020-11-10 Thread Jerry via Digitalmars-d-learn
On Tuesday, 10 November 2020 at 11:38:30 UTC, Vladimirs Nordholm 
wrote:

Hello.

I am unsure if I am going about this the right way, and if my 
question even makes sense.


In essence what I want is to have two "types" represented by a 
size_t. Here is an example of what I want think I want (but 
might be completely off)


alias Foo = size_t;
alias Bar = size_t;

Foo foo = 4;
Bar bar = foo; // i want some error like
   // "cannot implicitly convert from type Foo 
to Bar"


My best solution is to have the types as classes to force type 
checking.


Is there a better way to do what I want here?


https://dlang.org/library/std/typecons/typedef.html


Disallow implicit "conversion" from alias-types

2020-11-10 Thread Vladimirs Nordholm via Digitalmars-d-learn

Hello.

I am unsure if I am going about this the right way, and if my 
question even makes sense.


In essence what I want is to have two "types" represented by a 
size_t. Here is an example of what I want think I want (but might 
be completely off)


alias Foo = size_t;
alias Bar = size_t;

Foo foo = 4;
Bar bar = foo; // i want some error like
   // "cannot implicitly convert from type Foo to 
Bar"


My best solution is to have the types as classes to force type 
checking.


Is there a better way to do what I want here?


Re: Implicit conversion to templatized type

2020-11-06 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Nov 06, 2020 at 03:36:46PM +, Paul Backus via Digitalmars-d-learn 
wrote:
[...]
> User-defined implicit conversions are one of the most error-prone
> features of C++, and have been deliberately excluded from D, with the
> exception of `alias this`.

And Walter is already expressing regret at allowing `alias this`.  I
used to love `alias this`, and still use it in many of my projects, but
over time, I'm also starting to agree with Walter that it was a mistake.
Implicit conversions are generally not a good idea, except in very
narrow, well-defined cases. They are convenient, but lead to problems in
long-term maintenance.


T

-- 
People who are more than casually interested in computers should have at least 
some idea of what the underlying hardware is like. Otherwise the programs they 
write will be pretty weird. -- D. Knuth


Re: Implicit conversion to templatized type

2020-11-06 Thread Paul Backus via Digitalmars-d-learn

On Friday, 6 November 2020 at 15:01:21 UTC, Andrey Zherikov wrote:


But how can I achieve the same result if S1 is a template 
"struct S1(T) {}" and S2 should be convertible to S1!T with any 
T?


Also why neither "opCast"
struct S2 { S1 opCast(T)() const if(is(T == S1)) { return 
S1(); } }

nor suitable ctor
struct S1 { this(const S2 s){} }
are used for implicit conversion?


This is impossible by design. User-defined implicit conversions 
are one of the most error-prone features of C++, and have been 
deliberately excluded from D, with the exception of `alias this`.


Implicit conversion to templatized type

2020-11-06 Thread Andrey Zherikov via Digitalmars-d-learn
There is a way to implicitly convert non-template user type, for 
example:


struct S2
{
@property S1 s1() { return S1(); }
alias s1 this;
}

struct S1 {}

S1 f() { return S2(); }   // implicit conversion from S2 to S1


But how can I achieve the same result if S1 is a template "struct 
S1(T) {}" and S2 should be convertible to S1!T with any T?


Also why neither "opCast"
struct S2 { S1 opCast(T)() const if(is(T == S1)) { return 
S1(); } }

nor suitable ctor
struct S1 { this(const S2 s){} }
are used for implicit conversion?



Re: Docs 6.9.4: Implicit Conversion to bool

2020-03-09 Thread Manfred Nowak via Digitalmars-d-learn
On Monday, 9 March 2020 at 16:44:55 UTC, Steven Schveighoffer 
wrote:

You're not the first person to ask.


Accepted.


Re: Docs 6.9.4: Implicit Conversion to bool

2020-03-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/9/20 11:35 AM, Manfred Nowak wrote:
Having a function `f' overloaded for argument types `bool' and `ulong', 
the specs guarantee, that for `f( 1uL)' the boolean overload of `f' is 
called.


What is this good for?


You're not the first person to ask.

https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1015.md

-Steve


Docs 6.9.4: Implicit Conversion to bool

2020-03-09 Thread Manfred Nowak via Digitalmars-d-learn
Having a function `f' overloaded for argument types `bool' and 
`ulong', the specs guarantee, that for `f( 1uL)' the boolean 
overload of `f' is called.


What is this good for?


Re: Implicit conversion by return

2018-08-08 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, August 8, 2018 2:15:16 AM MDT Hakan Aras via Digitalmars-d-
learn wrote:
> Given this:
>
> struct Num
> {
>  this(int a) {}
> }
>
> Is there any reason why this works:
>
> Num n = 5;
>
> but this doesnt:
>
> Num funk()
> {
>  return 5;
> }
>
>
> I understand that I can construct it explicitely, but that gets
> annoying quickly, especially with templates.

Num n = 5;

doesn't actually do an implict conversion. It's the same as doing

Num n = Num(5);

So, I guess that you could call it implicit construction, but regardless,
it's just a different syntax for calling the constructor. The only way to
create an implicit conversion with a user-defined type in D is to use alias
this, and that only provides a way to implicitly convert _from_ a
user-defined type, not to a type. So, having

Num funk()
{
return 5;
}

work is impossible in D, just like having something like

auto foo(Num n)
{
...
}

foo(5);

work is impossible. If you want to return an int and have it converted to a
Num, then you're going to need to explicitly construct a Num from the int.

- Jonathan M Davis





Re: Implicit conversion by return

2018-08-08 Thread Hakan Aras via Digitalmars-d-learn

On Wednesday, 8 August 2018 at 08:44:03 UTC, Alex wrote:


return typeof(return)(5);


Ah thanks, I was wondering if something like that exists. Still 
though, that's 16 extra characters that dont need to be there.




Re: Implicit conversion by return

2018-08-08 Thread Alex via Digitalmars-d-learn

On Wednesday, 8 August 2018 at 08:15:16 UTC, Hakan Aras wrote:

Given this:

struct Num
{
this(int a) {}
}

Is there any reason why this works:

Num n = 5;

but this doesnt:

Num funk()
{
return 5;
}


I understand that I can construct it explicitely, but that gets 
annoying quickly, especially with templates.


I suppose, this is too slack.

What would work is

Num funk()
{
return typeof(return)(5);
}


Implicit conversion by return

2018-08-08 Thread Hakan Aras via Digitalmars-d-learn

Given this:

struct Num
{
this(int a) {}
}

Is there any reason why this works:

Num n = 5;

but this doesnt:

Num funk()
{
return 5;
}


I understand that I can construct it explicitely, but that gets 
annoying quickly, especially with templates.


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-19 Thread Timoses via Digitalmars-d-learn

On Thursday, 19 July 2018 at 06:35:36 UTC, Simen Kjærås wrote:

On Wednesday, 18 July 2018 at 11:28:54 UTC, Timoses wrote:
But why is a context pointer a problem? Is it problematic 
because the context pointer to the main scope can not 
guarantee `immutable`? E.g. if I happened to use data from 
main in a function of the immutable struct then... well then 
what?
The struct would still be immutable, but what would prevent a 
function from using non-immutable data?


It's a known bug: https://issues.dlang.org/show_bug.cgi?id=18563
In the associated discussion 
(https://forum.dlang.org/thread/p7lp2b$1jod$1...@digitalmars.com), 
Steven Schveighoffer points out that an immutable struct may be 
passed to other threads, which would give one thread access to 
another thread's stack. This could be a good enough reason to 
prevent this kind of conversion, but a better error message 
would still make sense.


--
  Simen


Thanks so much for the pointer, Simen. Interesting discussion.


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-18 Thread Simen Kjærås via Digitalmars-d-learn

On Wednesday, 18 July 2018 at 11:28:54 UTC, Timoses wrote:
But why is a context pointer a problem? Is it problematic 
because the context pointer to the main scope can not guarantee 
`immutable`? E.g. if I happened to use data from main in a 
function of the immutable struct then... well then what?
The struct would still be immutable, but what would prevent a 
function from using non-immutable data?


It's a known bug: https://issues.dlang.org/show_bug.cgi?id=18563
In the associated discussion 
(https://forum.dlang.org/thread/p7lp2b$1jod$1...@digitalmars.com), 
Steven Schveighoffer points out that an immutable struct may be 
passed to other threads, which would give one thread access to 
another thread's stack. This could be a good enough reason to 
prevent this kind of conversion, but a better error message would 
still make sense.


--
  Simen


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-18 Thread Timoses via Digitalmars-d-learn

On Tuesday, 17 July 2018 at 06:24:12 UTC, Simen Kjærås wrote:


That makes sense. The problem is F has a context pointer to the 
main() block, since it's a non-static struct with methods 
inside a block. It doesn't actually use the context pointer for 
anything, so it possibly shouldn't have one, but it does, so we 
have to work around it.


The fix is to mark F as static, or move it outside the main() 
block.


--
  Simen


Thanks for the explanation.

But why is a context pointer a problem? Is it problematic because 
the context pointer to the main scope can not guarantee 
`immutable`? E.g. if I happened to use data from main in a 
function of the immutable struct then... well then what?
The struct would still be immutable, but what would prevent a 
function from using non-immutable data?

E.g. I could do this

int gnumber = 3;

struct F
{
int i;
void fun() immutable
{
gnumber = 5;
}
}

void main ()
{
immutable F f = F();
f.fun;
}

I declared `fun()` to be an immutable function. So calling the 
immutable struct function `F.fun()` changes a module scope int. 
The same could be applied to local data of the main scope, 
however the following fails:


void main ()
{
int mnumber = 3;
struct F
{
int i;
void fun() immutable
{
// Error: immutable function onlineapp.main.F.fun 
cannot access mutable data mnumber

mnumber = 5;
}
}

immutable F f = F();
f.fun;
}

Is this connected why I can't implicitly convert a local struct 
with a context pointer to immutable? What's the reason behind it?


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-16 Thread Simen Kjærås via Digitalmars-d-learn

On Monday, 16 July 2018 at 13:13:53 UTC, Timoses wrote:

On Monday, 16 July 2018 at 12:00:57 UTC, Simen Kjærås wrote:

On Monday, 16 July 2018 at 11:43:03 UTC, Timoses wrote:

Why does this fail?


It doesn't. Not using DMD 2.081.1 under Windows, at least. I 
tried adding a bitfield since you mentioned it, but it 
compiles nicely for me. Which version of DMD are you using, 
and are you having the issues with the exact code you posted 
here?


--
  Simen


https://run.dlang.io/is/Pgs527

I'm on 2.080.1. But above is on latest 2.081.1 I believe.

Note that the bottom code snippet in the original post does 
work, while the first one does not.


That makes sense. The problem is F has a context pointer to the 
main() block, since it's a non-static struct with methods inside 
a block. It doesn't actually use the context pointer for 
anything, so it possibly shouldn't have one, but it does, so we 
have to work around it.


The fix is to mark F as static, or move it outside the main() 
block.


--
  Simen


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-16 Thread Seb via Digitalmars-d-learn

On Monday, 16 July 2018 at 13:13:53 UTC, Timoses wrote:

On Monday, 16 July 2018 at 12:00:57 UTC, Simen Kjærås wrote:

On Monday, 16 July 2018 at 11:43:03 UTC, Timoses wrote:

Why does this fail?


It doesn't. Not using DMD 2.081.1 under Windows, at least. I 
tried adding a bitfield since you mentioned it, but it 
compiles nicely for me. Which version of DMD are you using, 
and are you having the issues with the exact code you posted 
here?


--
  Simen


https://run.dlang.io/is/Pgs527

I'm on 2.080.1. But above is on latest 2.081.1 I believe.

Note that the bottom code snippet in the original post does 
work, while the first one does not.


Yep, run.dlang.io automatically updates itself to the latest 
compiler (you can check this e.g. with -v).


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-16 Thread Timoses via Digitalmars-d-learn

On Monday, 16 July 2018 at 12:00:57 UTC, Simen Kjærås wrote:

On Monday, 16 July 2018 at 11:43:03 UTC, Timoses wrote:

Why does this fail?


It doesn't. Not using DMD 2.081.1 under Windows, at least. I 
tried adding a bitfield since you mentioned it, but it compiles 
nicely for me. Which version of DMD are you using, and are you 
having the issues with the exact code you posted here?


--
  Simen


https://run.dlang.io/is/Pgs527

I'm on 2.080.1. But above is on latest 2.081.1 I believe.

Note that the bottom code snippet in the original post does work, 
while the first one does not.


Re: Implicit conversion of struct with methods to immutable in pure function fails

2018-07-16 Thread Simen Kjærås via Digitalmars-d-learn

On Monday, 16 July 2018 at 11:43:03 UTC, Timoses wrote:

Why does this fail?


It doesn't. Not using DMD 2.081.1 under Windows, at least. I 
tried adding a bitfield since you mentioned it, but it compiles 
nicely for me. Which version of DMD are you using, and are you 
having the issues with the exact code you posted here?


--
  Simen


Implicit conversion of struct with methods to immutable in pure function fails

2018-07-16 Thread Timoses via Digitalmars-d-learn

Why does this fail?

struct F
{
int i;
ushort _x;
void x(ushort v) pure
{_x = v;}
ushort x() const
{ return _x; }
}

immutable F f1 = () pure {
F lf = F();
return lf; }();
// Error: cannot implicitly convert expression delegate () => 
lf() of type F to immutable(F)


F makeF() pure
{
F lf = F();
return lf;
}
immutable F f2 = makeF();
// Error: cannot implicitly convert expression makeF() of 
type F to immutable(F)


Removing the methods in struct F compiles fine.

Background: I have a mixin(bitfields!(...)) in the struct which 
utilizes member functions.



/
Idea:
Just found out that it works when making the struct static. But 
why does that help?


Is it because the compiler wouldn't be able to check whether 
methods in the struct are accessing non-immutable data in the 
enclosing context?

That would not make much sense though because the following works:

// Compiles fine!
int modi = 3;
void main ()
{
static struct F
{
int var() immutable { return modi; } // accessing modi 
from module scope

}
immutable f = () pure { F f = F(); return f; }();
}

So my explanation wouldn't make sense, since why would it be okay 
to use module-scope data and not enclosing context data?


So where does that limitation come from that I implicitly convert 
a nested struct to immutable in a pure function?





Re: Implicit conversion

2018-01-17 Thread Mike Franklin via Digitalmars-d-learn

On Wednesday, 17 January 2018 at 23:15:33 UTC, Jiyan wrote:



I want to convert from ints implicit to a struct type, so for 
example:




I'm not sure what your actual use case is, but based on the 
example, you can just template `useV`.


import std.stdio;

struct use
{
int x;

int toInt()
{
return x;
}

use fromInt(int v)
{
return use(v);
}

alias toInt this; // implicit conversion to int value

this(int v)
{x = v;}
}

void useP(int v)
{
v.writeln;
}

void useV(T)(T v)
{
v.writeln;
}

void main(string[] args)
{
use a = use(2);
//useP(a);
useV(2); // how can i let this work?
}

https://run.dlang.io/is/pJhQJh

Mike



Re: Implicit conversion

2018-01-17 Thread Ali Çehreli via Digitalmars-d-learn

On 01/17/2018 03:15 PM, Jiyan wrote:
> Hello,
>
> I want to convert from ints implicit to a struct type, so for example:
>
> struct use
> {
>  int x;
>
>  int toInt()
>  {
>  return x;
>  }
>
>  use fromInt(int v)
>  {
>  return use(v);
>  }
>
>  alias toInt this; // implicit conversion to int value
>
>  this(int v)
>  {x = v;}
> }
>
> void useP(int v)
> {
>  v.writeln;
> }
>
> void useV(use v)
> {
>  v.writeln;
> }
>
> void main(string[] args)
> {
>  use a = use(2);
>  //useP(a);
>  useV(2); // how can i let this work?
> }
>
> Thanks :)
>

Not possible in D by design.

std.conv.to is smart to use the int-taking constructor, which I think is 
useful in templated code in some cases:


import std.conv : to;
useV(2.to!use);

Ali



Implicit conversion

2018-01-17 Thread Jiyan via Digitalmars-d-learn

Hello,

I want to convert from ints implicit to a struct type, so for 
example:


struct use
{
int x;

int toInt()
{
return x;
}

use fromInt(int v)
{
return use(v);
}

alias toInt this; // implicit conversion to int value

this(int v)
{x = v;}
}

void useP(int v)
{
v.writeln;
}

void useV(use v)
{
v.writeln;
}

void main(string[] args)
{
use a = use(2);
//useP(a);
useV(2); // how can i let this work?
}

Thanks :)



Re: Implicit conversion from const to mutable

2017-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/17 5:28 PM, Balagopal Komarath wrote:

On Thursday, 17 August 2017 at 20:22:09 UTC, Steven Schveighoffer wrote:


This should "work". I don't think your static assert will pass, but 
the main function below should run.


Thanks. But, isn't my static assert testing for exactly this?



I might be wrong. It's hard to tell, because the compiler doesn't work 
with the struct itself.


If I change the alias this to something else, your form of conversion 
does work. But the compiler may recognize that specific form and still 
disallow it. IMO, that would be a further bug.


-Steve


Re: Implicit conversion from const to mutable

2017-08-17 Thread Balagopal Komarath via Digitalmars-d-learn
On Thursday, 17 August 2017 at 20:22:09 UTC, Steven Schveighoffer 
wrote:


This should "work". I don't think your static assert will pass, 
but the main function below should run.


Thanks. But, isn't my static assert testing for exactly this?



Re: Implicit conversion from const to mutable

2017-08-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/17/17 3:24 PM, Balagopal Komarath wrote:
Is it possible to make structs containing slices support implicit 
conversion from const to mutable?


This should "work". I don't think your static assert will pass, but the 
main function below should run.


struct A
{
   int[] a;
   A dup() const
   {
   return A(a.dup);
   }
   alias dup this;
}

void main()
{
const A a;
A a2 = a;
}

However, this results in a segfault as far back as 2.064, and 2.063 
doesn't seem to like it (but maybe because alias this wasn't supported? 
I'm not sure).


https://issues.dlang.org/show_bug.cgi?id=17759

-Steve


Implicit conversion from const to mutable

2017-08-17 Thread Balagopal Komarath via Digitalmars-d-learn
Is it possible to make structs containing slices support implicit 
conversion from const to mutable? I tried adding a postblit that 
dupes the member 'a'. That didn't work.


struct A
{
int[] a;
}

void main()
{
static assert (is(const(A) : A)); // fails
}


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-22 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 10:03:58 UTC, Nicholas Wilson wrote:
As in the function signature of the function you call `ok` or 
`error` in.


Result!(int, SomeEnum) myfunc(bool foo)
{
if(!foo)
return ok(42);
else
return error(SomeEnum.fooHappened);
}

should work.


This is what I've got right now.

--- [module 1]
struct Result(OkType, ErrType)
{
this(OkType ok) pure nothrow
{
isOk = true;
okPayload = ok;
}

this(ErrType error) pure nothrow
{
isOk = false;
errorPayload = error;
}

bool isOk;

union
{
OkType okPayload;
ErrType errorPayload;
}
}

auto ok(T, E)(T payload) { return Result!(T, E)(payload); }
auto error(T, E)(T payload) { return Result!(T, E)(payload); }

--- [module 2]

Result!(string, int) fn(bool shouldErr) {
if (!shouldErr)
return ok("No problem");
return error(0);
}

---

But it can't infer the second parameter.
"template result.ok cannot deduce function from argument types 
!()(string)"




Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread Nicholas Wilson via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:55:41 UTC, David  Zhang wrote:

On Sunday, 21 May 2017 at 09:37:46 UTC, Nicholas Wilson wrote:

On Sunday, 21 May 2017 at 09:29:40 UTC, David  Zhang wrote:
Well then it becomes
 Result!(T, E) ok(T,E) (T t) { return Result(t); }
 Result!(T, E) error(T,E)(E e) { return Result(e); }

and then provided it can be inferred (e.g. from the function 
signature)

it will still work.


But how would it be inferred? Like the `ok` function, `T` could 
be inferred, but E? I'm not sure I understand. If you have to 
specify the types every time, it kinda defeats the purpose. 
With the function signature as it is, you'd have to specify the 
type of the other type (e.g. you'd need to specify E for 
`ok()`).


As in the function signature of the function you call `ok` or 
`error` in.


Result!(int, SomeEnum) myfunc(bool foo)
{
if(!foo)
return ok(42);
else
return error(SomeEnum.fooHappened);
}

should work.


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:37:46 UTC, Nicholas Wilson wrote:

On Sunday, 21 May 2017 at 09:29:40 UTC, David  Zhang wrote:
Well then it becomes
 Result!(T, E) ok(T,E) (T t) { return Result(t); }
 Result!(T, E) error(T,E)(E e) { return Result(e); }

and then provided it can be inferred (e.g. from the function 
signature)

it will still work.


But how would it be inferred? Like the `ok` function, `T` could 
be inferred, but E? I'm not sure I understand. If you have to 
specify the types every time, it kinda defeats the purpose. With 
the function signature as it is, you'd have to specify the type 
of the other type (e.g. you'd need to specify E for `ok()`).


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread Nicholas Wilson via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:29:40 UTC, David  Zhang wrote:

On Sunday, 21 May 2017 at 09:15:56 UTC, Nicholas Wilson wrote:

have free functions

 Result!(T, ErrorEnum) ok(T)(T t) { return Result(t); }
 Result!(T, ErrorEnum) error(T)(ErrorEnum e) { return 
Result(e); }


then go

if (!foo)
return ok(42);
else
return error(Error.fooHappened);


Ah, I think you misread. ErrorEnum is a template type, like 
`T`. There's no ErrorEnum enum specified.


Well then it becomes
 Result!(T, E) ok(T,E) (T t) { return Result(t); }
 Result!(T, E) error(T,E)(E e) { return Result(e); }

and then provided it can be inferred (e.g. from the function 
signature)

it will still work.


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

On Sunday, 21 May 2017 at 09:15:56 UTC, Nicholas Wilson wrote:

have free functions

 Result!(T, ErrorEnum) ok(T)(T t) { return Result(t); }
 Result!(T, ErrorEnum) error(T)(ErrorEnum e) { return 
Result(e); }


then go

if (!foo)
return ok(42);
else
return error(Error.fooHappened);


Ah, I think you misread. ErrorEnum is a template type, like `T`. 
There's no ErrorEnum enum specified.


Re: Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread Nicholas Wilson via Digitalmars-d-learn

On Sunday, 21 May 2017 at 08:44:31 UTC, David  Zhang wrote:

Hi,

I was reading a bit about this in Rust, and their enum type. I 
was wondering if this is replicate-able in D. What I've got 
right now is rather clunky, and involves using


 `typeof(return).ok` and `typeof(return).error)`.

While that's not too bad, it does involve a lot more typing, 
and thus more area for human error.


If you're not familiar with the Result and Option types, it 
allows you to do something like this:


---
Result!(string, ErrorEnum) someFunction(...)
{
return Ok("Hello!");
}

Result!(string, ErrorEnum) someFunction2(...)
{
return Error(ErrorEnum.dummyError);
}
---

I'm not entirely sure it's possible... but I figured I might 
give it a try.


have free functions

 Result!(T, ErrorEnum) ok(T)(T t) { return Result(t); }
 Result!(T, ErrorEnum) error(T)(ErrorEnum e) { return Result(e); }

then go

if (!foo)
return ok(42);
else
return error(Error.fooHappened);



Implicit conversion from 'Ok' to 'Result' type when returning functions

2017-05-21 Thread David Zhang via Digitalmars-d-learn

Hi,

I was reading a bit about this in Rust, and their enum type. I 
was wondering if this is replicate-able in D. What I've got right 
now is rather clunky, and involves using


 `typeof(return).ok` and `typeof(return).error)`.

While that's not too bad, it does involve a lot more typing, and 
thus more area for human error.


If you're not familiar with the Result and Option types, it 
allows you to do something like this:


---
Result!(string, ErrorEnum) someFunction(...)
{
return Ok("Hello!");
}

Result!(string, ErrorEnum) someFunction2(...)
{
return Error(ErrorEnum.dummyError);
}
---

I'm not entirely sure it's possible... but I figured I might give 
it a try.


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-07 Thread Mike Parker via Digitalmars-d-learn
On Tuesday, 7 June 2016 at 22:28:57 UTC, Steven Schveighoffer 
wrote:


It's news to me that while opCast for all other types is for 
explicit

casting, opCast for bool works for implicit casting.


as ag0... mentioned in another thread, opCast is NOT implicitly 
being invoked here, but rather explicitly.


That is:

bool x = someStruct; // error
if(someStruct) // explicit opCast!bool



Documented under 'Boolean Operations' at 
http://dlang.org/spec/operatoroverloading.html#cast


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-07 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/7/16 6:15 PM, Ali Çehreli wrote:

On 06/06/2016 08:28 AM, Adam D. Ruppe wrote:

On Monday, 6 June 2016 at 15:23:50 UTC, chmike wrote:

I would like an implicit conversion of Info to bool that return false
if category_ is null so that I can write


add:

bool opCast(T : bool)() {
   return whatever;
}

to the struct and it should work.


It's news to me that while opCast for all other types is for explicit
casting, opCast for bool works for implicit casting.


as ag0... mentioned in another thread, opCast is NOT implicitly being 
invoked here, but rather explicitly.


That is:

bool x = someStruct; // error
if(someStruct) // explicit opCast!bool

-Steve


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-07 Thread Ali Çehreli via Digitalmars-d-learn

On 06/06/2016 08:28 AM, Adam D. Ruppe wrote:

On Monday, 6 June 2016 at 15:23:50 UTC, chmike wrote:

I would like an implicit conversion of Info to bool that return false
if category_ is null so that I can write


add:

bool opCast(T : bool)() {
   return whatever;
}

to the struct and it should work.


It's news to me that while opCast for all other types is for explicit 
casting, opCast for bool works for implicit casting.


Ali


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-07 Thread Basile B. via Digitalmars-d-learn

On Monday, 6 June 2016 at 15:34:18 UTC, chmike wrote:

On Monday, 6 June 2016 at 15:28:35 UTC, John wrote:
Thank you John and Adam. That was a quick answer !


Too late but another option would have been to put an alias this 
on a bool getter:


struct Info
{
bool getStuff()
{
return true;
}

alias getStuff this;
}


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-06 Thread chmike via Digitalmars-d-learn

On Monday, 6 June 2016 at 15:28:35 UTC, John wrote:
Thank you John and Adam. That was a quick answer !




Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-06 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 6 June 2016 at 15:23:50 UTC, chmike wrote:
I would like an implicit conversion of Info to bool that return 
false if category_ is null so that I can write


add:

bool opCast(T : bool)() {
   return whatever;
}

to the struct and it should work.


Re: Implicit conversion of struct to bool for if (s) operation ?

2016-06-06 Thread John via Digitalmars-d-learn

On Monday, 6 June 2016 at 15:23:50 UTC, chmike wrote:

Hello,

I have a structure with two fields ad defined as

struct Info {
this(int value, Category category)
{
category_ = category;
value_ = category ? value : 0;
}


  // This converts implicitly to bool.
  T opCast(T : bool)() {
  return category_ !is null;
  }


...
private:
Category category_ = null;
int value_ = 0;
}


I would like an implicit conversion of Info to bool that return 
false if category_ is null so that I can write


Info s = foo();
if (s) {
   ...
}

and where

Info s2;
assert(!s2);


See the inserted code above.


Implicit conversion of struct to bool for if (s) operation ?

2016-06-06 Thread chmike via Digitalmars-d-learn

Hello,

I have a structure with two fields ad defined as

struct Info {
this(int value, Category category)
{
category_ = category;
value_ = category ? value : 0;
}
...
private:
Category category_ = null;
int value_ = 0;
}


I would like an implicit conversion of Info to bool that return 
false if category_ is null so that I can write


Info s = foo();
if (s) {
   ...
}

and where

Info s2;
assert(!s2);




Re: Implicit conversion without alias this?

2016-06-03 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, June 03, 2016 16:12:50 maik klein via Digitalmars-d-learn wrote:
> Any ideas?

Well, alias this is the only way that D supports any kind of implicit
conversions for user-defined types. So, if you want to have an implicit
conversion for your type, you're going to have to figure out how to do it
with alias this. If you can't, then you can't have an implicit version.

- Jonathan M Davis



Implicit conversion without alias this?

2016-06-03 Thread maik klein via Digitalmars-d-learn

I have my own version of Algebraic

struct Ok(T){
T value;
}

struct Err(E){
E value;
}

auto ok(T)(auto ref T value){
return Ok!T(value);
}

auto err(E)(auto ref E err){
return Err!E(err);
}

alias Result(T, E) = Algebraic!(Ok!T, Err!E);

I have a constructor and opAssign which allows me to write

Result!(int, string) res = ok(5);

But it seems strange that I can not do the same thing to function 
returns


Result!(int, string) test(){
return ok(5); // Error: cannot implicitly convert expression 
(ok(5)) of type Ok!int to Algebraic!(Ok!int, Err!string)

}

I can not add implicit conversion with alias this from Ok!T to 
Result!(T, ???) because "Ok" doesn't know about the error type.


That is a bit unergonomic because I always seem to need the full 
type


like

auto ok(T, E)(auto ref T value){
return Result!(T, E)(Ok!T(value));
}

I basically try to mirror 
http://rustbyexample.com/std/result.html but I don't think that 
is possible.


Any ideas?





Re: Implicit conversion from string to custom type?

2016-02-14 Thread Ali Çehreli via Digitalmars-d-learn

On 02/14/2016 03:43 PM, Tofu Ninja wrote:

So I wrote a simple ref counted string type because using the built in
strings without the GC is extremely painful. It there any way I can get
strings to implicitly convert to my custom string type?


No, D does not support such implicit conversions.


struct rstring {...}
void fun(rstring s) {...}
...
fun("hello world"); // Currently an error

Would be super nice if it would just call the opAssign when trying to
call fun but I suppose that has some non-obvious problems for why it
does not work that way.


The only way is to be explicit. Three common options:

fun(rstring("hello world"));
fun("hello world".to!rstring);
fun(cast(rstring)"hello world");

Relatedly, user defined types can provide implicit conversions through 
'alias this' but unfortunately, current implementation supports only one 
such operator.


Ali



Implicit conversion from string to custom type?

2016-02-14 Thread Tofu Ninja via Digitalmars-d-learn
So I wrote a simple ref counted string type because using the 
built in strings without the GC is extremely painful. It there 
any way I can get strings to implicitly convert to my custom 
string type?


Some way to make this work...

struct rstring {...}
void fun(rstring s) {...}
...
fun("hello world"); // Currently an error

Would be super nice if it would just call the opAssign when 
trying to call fun but I suppose that has some non-obvious 
problems for why it does not work that way.


Re: Operator implicit conversion difference

2015-11-06 Thread BBaz via Digitalmars-d-learn

On Saturday, 7 November 2015 at 01:10:01 UTC, Ali Çehreli wrote:

On 11/06/2015 04:56 PM, BBaz wrote:

On Thursday, 5 November 2015 at 13:20:26 UTC, ixid wrote:

[...]


What's inconsistent is the integral promotion of the add 
expression

result that stops from 4 bytes int:

---
int a, b;
a += b;
a = a + b;
---

is compiled but according to the specs, a + b result should be 
widened

to long:

http://dlang.org/expression.html#AddExpression

(ubyte, byte) until (uint int) should be widened and (long , 
ulong)

wrapped. This behavior would match the specs better.


You say 'long' but according to integer promotions, a and b 
should both be promoted to 'int' and the result of 'a + b' is 
int:


  http://dlang.org/type.html#integer-promotions

Ali


oh...sorry I thought that the widening was done to the follwing 
type that's bigger, eg byte->short, short->int.


So no inconsistence at all.


Re: Operator implicit conversion difference

2015-11-06 Thread Ali Çehreli via Digitalmars-d-learn

On 11/06/2015 04:56 PM, BBaz wrote:

On Thursday, 5 November 2015 at 13:20:26 UTC, ixid wrote:

This may have been overlooked in my other thread so I wanted to ask
again:

This seems very inconsistent, does a += b not lower to a = a + b? I
guess not based on the below:

ushort a = ushort.max, b = ushort.max;


a += b; // Compiles fine
a = a + b; // Error: cannot implicitly convert expression
(cast(int)a + cast(int)b) of type int to ushort


What's inconsistent is the integral promotion of the add expression
result that stops from 4 bytes int:

---
int a, b;
a += b;
a = a + b;
---

is compiled but according to the specs, a + b result should be widened
to long:

http://dlang.org/expression.html#AddExpression

(ubyte, byte) until (uint int) should be widened and (long , ulong)
wrapped. This behavior would match the specs better.


You say 'long' but according to integer promotions, a and b should both 
be promoted to 'int' and the result of 'a + b' is int:


  http://dlang.org/type.html#integer-promotions

Ali



Re: Operator implicit conversion difference

2015-11-06 Thread BBaz via Digitalmars-d-learn

On Thursday, 5 November 2015 at 13:20:26 UTC, ixid wrote:
This may have been overlooked in my other thread so I wanted to 
ask again:


This seems very inconsistent, does a += b not lower to a = a + 
b? I guess not based on the below:


ushort a = ushort.max, b = ushort.max;


a += b; // Compiles fine
a = a + b; // Error: cannot implicitly convert expression 
(cast(int)a + cast(int)b) of type int to ushort


What's inconsistent is the integral promotion of the add 
expression result that stops from 4 bytes int:


---
int a, b;
a += b;
a = a + b;
---

is compiled but according to the specs, a + b result should be 
widened to long:


http://dlang.org/expression.html#AddExpression

(ubyte, byte) until (uint int) should be widened and (long , 
ulong) wrapped. This behavior would match the specs better.


Re: Preventing implicit conversion

2015-11-05 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, November 05, 2015 09:33:39 ixid via Digitalmars-d-learn wrote:
> In C++ I can add two shorts together without having to use a cast
> to assign the result to one of the two shorts. It just seems
> super clunky not to be able to do basic operations on basic types
> without casts everywhere.

That's why we have value range propagation - so that when the compiler can
prove that the result will fit in the smaller type, it'll let you assign to
it. Perhaps the compiler should do more with that than it currently does,
but it's definitely help reduce the number of casts that are required for
narrowing conversions.

But allowing implicit narrowing conversions is a source of bugs, which is
why languages like D, C#, and Java have all made narrowing conversions
illegal without a cast. Yes, that can be annoying when you need to do math
on a byte or short, and you want the result to end up in a byte or short,
but it prevents bugs. It's a tradeoff. Fortunately, VPR improves the
situation, but we're not going to be able to prevent narrowing bugs while
still allowing implicit narrowing conversions. C/C++ went the route that
requires fewer casts but more easily introduces bugs, whereas D, Java, and
C# went the route where it's harder to introduce bugs but doing arithmetic
on types smaller than int gets a bit annoying. Personally, I think that the
route that D has taken is the better one, but it is a matter of opinion and
priorities.

But if it's important enough to you to not need to cast for arithmetic
operations on small integer types, you can always create a wrapper type that
does all of the casts for you so that you get the implicit conversions.

- Jonathan M Davis



Re: Preventing implicit conversion

2015-11-05 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
On Thursday, 5 November 2015 at 22:15:46 UTC, Dominikus Dittes 
Scherkl wrote:
On Thursday, 5 November 2015 at 13:23:34 UTC, Adam D. Ruppe 
wrote:
On Thursday, 5 November 2015 at 10:07:30 UTC, Dominikus Dittes 
Scherkl wrote:



ubyte d = b + (ubyte)1;

Sorry, should of course be:

ubyte d = b + ubyte(1);

Too much C lately :-/


Re: Preventing implicit conversion

2015-11-05 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Thursday, 5 November 2015 at 13:23:34 UTC, Adam D. Ruppe wrote:
On Thursday, 5 November 2015 at 10:07:30 UTC, Dominikus Dittes 
Scherkl wrote:



ubyte b = 1u;
auto c = b + 1u;

I expect the 1u to be of type ubyte - and also c.


This won't work because of the one-expression rule. In the 
second line, it doesn't know for sure what b is, it just knows 
it is somewhere between 0 and 255. So it assumes the worst, 
that it is 255, and you add one, giving 256... which doesn't 
fit in a byte.
That would be fine - but c is not ushort (which the worst-case 
256 would fit in), not even uint, but int! A signed type! Just 
because of the crazy C interger propagation rules!
And, ok, one needs to accept that auto may not do exactly what I 
wish for, but if I give an exact type that is likely to fit (and 
has to if all operands are of the same type), I expect it to work 
without extra casts:


ubyte d = b + 1u; // doesn't compile
ubyte d = b + (ubyte)1; // works - and overflows to 0 if b is 255


Re: Operator implicit conversion difference

2015-11-05 Thread Ali Çehreli via Digitalmars-d-learn

On 11/05/2015 05:20 AM, ixid wrote:

> This seems very inconsistent, does a += b not lower to a = a + b?

Apparently not:

  http://dlang.org/expression.html#AssignExpression

It says "The right operand is implicitly converted to the type of the 
left operand". So, the rules are different.


Ali



Operator implicit conversion difference

2015-11-05 Thread ixid via Digitalmars-d-learn
This may have been overlooked in my other thread so I wanted to 
ask again:


This seems very inconsistent, does a += b not lower to a = a + b? 
I guess not based on the below:


ushort a = ushort.max, b = ushort.max;


a += b; // Compiles fine
a = a + b; // Error: cannot implicitly convert expression 
(cast(int)a + cast(int)b) of type int to ushort


Re: Preventing implicit conversion

2015-11-05 Thread Adam D. Ruppe via Digitalmars-d-learn
On Thursday, 5 November 2015 at 10:07:30 UTC, Dominikus Dittes 
Scherkl wrote:
And I want to have small number litterals automatically 
choosing the smallest fitting type.


It does, that's the value range propagation at work. Inside one 
expression, if the compiler can prove it fits in a smaller type, 
the explicit cast is not necessary.


ubyte a = 255; // allowed, despite 255 being an int literal
ubyte b = 253L + 2L; // allowed, though I used longs there
ubyte c = 255 + 1; // disallowed, 256 doesn't fit


However, the key there was "in a single expression". If you break 
it into multiple lines with runtime values, the compiler assumes 
the worst:



int i = 254;
int i2 = 1;

ubyte a2 = i + i2; // won't work because it doesn't realize the 
values



But, adding some constant operation can narrow it back down:

ubyte a3 = (i + i2) & 0xff; // but this does because it knows 
anything & 0xff will always fit in a byte



ubyte b = 1u;
auto c = b + 1u;

I expect the 1u to be of type ubyte - and also c.


This won't work because of the one-expression rule. In the second 
line, it doesn't know for sure what b is, it just knows it is 
somewhere between 0 and 255. So it assumes the worst, that it is 
255, and you add one, giving 256... which doesn't fit in a byte. 
It requires the explicit cast or a &0xff or something like that 
to make the bit truncation explicit.




I agree this can be kinda obnoxious (and I think kinda pointless 
if you're dealing with explicitly typed smaller things 
throughout) but knowing what it is actually doing can help a 
little.


Re: Preventing implicit conversion

2015-11-05 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn
And I want to have small number litterals automatically choosing 
the smallest fitting type.


If I write

ubyte b = 1u;
auto c = b + 1u;

I expect the 1u to be of type ubyte - and also c.



Re: Preventing implicit conversion

2015-11-05 Thread Dominikus Dittes Scherkl via Digitalmars-d-learn

On Thursday, 5 November 2015 at 09:33:40 UTC, ixid wrote:

In C++ I can add two shorts together without having to use a 
cast to assign the result to one of the two shorts. It just 
seems super clunky not to be able to do basic operations on 
basic types without casts everywhere.


+1
If automatic shrink is droped from the C legacy stuff, so 
interger propagation should also be dropped (or changed to 
propagate no further than to the actual size of a type). D has a 
far better type system, throw away bad old C habits!


-> this would also make the defect comparison of signed to 
unsigned types visible for small types and hopefully force the 
introduction of the correct comparison!


Re: Preventing implicit conversion

2015-11-05 Thread ixid via Digitalmars-d-learn
On Thursday, 5 November 2015 at 05:41:46 UTC, Jonathan M Davis 
wrote:
On Wednesday, November 04, 2015 21:22:02 ixid via 
Digitalmars-d-learn wrote:
On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin 
wrote:

> On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
>> Is there an elegant way of avoiding implicit conversion to 
>> int when you're using shorter types?

>
> Only with library solution. Implicit conversions are built 
> into language.


Doesn't that seem rather limiting and unnecessary?


Why? You can't affect what conversions do and don't work for 
the built-in types in _any_ language that I've ever used, and 
I've never heard of a language that allowed anything like that. 
If you want different conversion rules, you need to create a 
user-defined type that defines the conversions you want. That's 
pretty normal.


And AFAIK, there aren't very many folks trying to avoid the 
built-in implicit conversions in D, particularly since D 
eliminated the various implicit narrowing conversions that you 
get in C/C++.


- Jonathan M Davis


In C++ I can add two shorts together without having to use a cast 
to assign the result to one of the two shorts. It just seems 
super clunky not to be able to do basic operations on basic types 
without casts everywhere.


Re: Preventing implicit conversion

2015-11-04 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, November 04, 2015 21:22:02 ixid via Digitalmars-d-learn wrote:
> On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin wrote:
> > On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
> >> Is there an elegant way of avoiding implicit conversion to int
> >> when you're using shorter types?
> >
> > Only with library solution. Implicit conversions are built into
> > language.
>
> Doesn't that seem rather limiting and unnecessary?

Why? You can't affect what conversions do and don't work for the built-in
types in _any_ language that I've ever used, and I've never heard of a
language that allowed anything like that. If you want different conversion
rules, you need to create a user-defined type that defines the conversions
you want. That's pretty normal.

And AFAIK, there aren't very many folks trying to avoid the built-in
implicit conversions in D, particularly since D eliminated the various
implicit narrowing conversions that you get in C/C++.

- Jonathan M Davis



Re: Preventing implicit conversion

2015-11-04 Thread Maxim Fomin via Digitalmars-d-learn

On Wednesday, 4 November 2015 at 21:22:04 UTC, ixid wrote:
On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin 
wrote:

On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
Is there an elegant way of avoiding implicit conversion to 
int when you're using shorter types?


Only with library solution. Implicit conversions are built 
into language.


Doesn't that seem rather limiting and unnecessary?


Well, indeed it often produces confusion (this is inherited from 
C for compatibility purpose).


Re: Preventing implicit conversion

2015-11-04 Thread ixid via Digitalmars-d-learn

On Wednesday, 4 November 2015 at 19:09:42 UTC, Maxim Fomin wrote:

On Wednesday, 4 November 2015 at 14:27:49 UTC, ixid wrote:
Is there an elegant way of avoiding implicit conversion to int 
when you're using shorter types?


Only with library solution. Implicit conversions are built into 
language.


Doesn't that seem rather limiting and unnecessary?


  1   2   3   >