[Issue 16222] template failed to infer/coerce types for instantiation

2016-06-30 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16222

--- Comment #2 from Ketmar Dark  ---
(In reply to ag0aep6g from comment #1)
> In your example, you could of course just take a const(char)[] directly,
> without any template parameters. So that isn't a good motivating example to
> change the behavior.

this is common pattern in my code, actually. i want my functions to accept
`string`, `const(char)[]` and `char[]` seamlessly, yet they should not do
unnecessary dups when i need to copy value. that is, there is no need to dup
`string` (obviously), but it's better to dup `char[]` and `const(char)[]`.
without template, i can't tell if `string` or `const(char)[]` was passed.

i was so sure that compiler does conversion of `null` to empty slice that
didn't even checked it beforehand. and today i was caught by the first case.

--


[Issue 16222] template failed to infer/coerce types for instantiation

2016-06-30 Thread via Digitalmars-d-bugs
https://issues.dlang.org/show_bug.cgi?id=16222

ag0ae...@gmail.com changed:

   What|Removed |Added

 CC||ag0ae...@gmail.com

--- Comment #1 from ag0ae...@gmail.com ---
(In reply to Ketmar Dark from comment #0)
> consider the following code:
> 
>   auto test(T : const(char)[]) (T s) { return s.length; }
>   void main () { assert(test(null) == 0); }
> 
> compiling this gives the following error: "no property 'length' for type
> 'typeof(null)'"
> 
> while i see why it complains, i think compiler should convert `null` to
> empty slice here, as i clearly specified the type i want to accept. sure, i
> can workaround this with explicit template constrain... but this is what i
> wanted to avoid in the first place!

The spec [1] isn't clear on this.

The currently implemented behavior of a constraint `T : Foo` is to restrict T
to those types that implicitly convert to Foo, but T is still set as usual
(from an explicit argument or from IFTI).

The behavior you suggest would make it so that T is always set to Foo.
Obviously, this would be a breaking change.

Both approaches are compatible with the examples in the spec, as far as I see.

In your example, you could of course just take a const(char)[] directly,
without any template parameters. So that isn't a good motivating example to
change the behavior.

In favor of the current behavior there is std.exception.assertThrown [2], for
example. It uses a specialization to restrict T to Throwable, but it uses the
(more restricted) passed T in its checks.

> also, another bug with the same `test`:
>   assert(test([]) == 0);
> 
> this time compiler says: "
> template z01.test cannot deduce function from argument types !()(void[]),
> candidates are..."
> 
> i think compiler should convert empty slice to the `immutable(char)[]` here.

Agreed. The empty array literal [] should behave like null and the empty string
literal "" here. I guess this means we need a typeof([]) that implicitly
converts to any T[] (unlike void[]).


[1] http://dlang.org/spec/template.html#parameters_specialization
[2] http://dlang.org/phobos/std_exception.html#.assertThrown

--