Jump to page: 1 2 3
Thread overview
[Issue 14035] string concatenation accepts ints in templates
Jan 29, 2015
Kenji Hara
Mar 22, 2015
yebblies
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
yebblies
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
yebblies
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
yebblies
Mar 22, 2015
Kenji Hara
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
Kenji Hara
Mar 22, 2015
yebblies
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
Ketmar Dark
Mar 22, 2015
Kenji Hara
Oct 28, 2022
Nick Treleaven
Dec 17, 2022
Iain Buclaw
January 28, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

hsteoh@quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |accepts-invalid, CTFE
                 CC|                            |hsteoh@quickfur.ath.cx

--
January 29, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|nobody@puremagic.com        |k.hara.pg@gmail.com
           Severity|minor                       |major

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |yebblies@gmail.com
         Resolution|---                         |WONTFIX

--- Comment #1 from yebblies <yebblies@gmail.com> ---
'ln' is a template parameter, so its value is known when semantic is run on the enum's initializer.  Because it is a constant value known to fit in a char type, it is implicitly converted to char and the concatenation succeeds.

You can see the expected error if you move the pragma(msg) line below line 255.

The implicit conversion from int to char is supported for cases like this: "string " ~ ('a' + 1) which would otherwise fail.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

Ketmar Dark <ketmar@ketmar.no-ip.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ketmar@ketmar.no-ip.org

--- Comment #2 from Ketmar Dark <ketmar@ketmar.no-ip.org> ---
the same logic should allow this:

string alice() (usize ln=__LINE__) {
  return "{ int t_"~ln~" = 42; }";
}
pragma(msg, alice!());

yet somehow this is not working. but why? `ln` is known in compile time too!

it's inconsistend and breaking type system. but ok, it's another arcane D knowledge, which can't be logically explained and can be only remembered. one more, one less...

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #3 from yebblies <yebblies@gmail.com> ---
(In reply to Ketmar Dark from comment #2)
> the same logic should allow this:
> 
> string alice() (usize ln=__LINE__) {
>   return "{ int t_"~ln~" = 42; }";
> }
> pragma(msg, alice!());
> 
> yet somehow this is not working. but why? `ln` is known in compile time too!

No, ln is a run-time argument here.  Semantic analysis is run on 'alice' without knowing it will be called from a compile-time context.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #4 from Ketmar Dark <ketmar@ketmar.no-ip.org> ---
ln type is known in both cases. `usize` is `size_t`, if it matters. yet somehow two `ln`s has *different* types. i can see how `(T ln=__LINE__)` can be converted to char, as compiler is free to choose any integral type for `T`, and it can be `ubyte`, if `__LINE__` is sufficiently small. but i specifically wrote `usize`, and i can't see why compiler wants to narrow it in one case, ignoring my explicit type definition, but doesn't want to narrow it in another case.

from programmer's POV both samples should not work if type system is consistent and works as expected. but type system is clearly not consistent, and to use it successfully programmer must know corner cases and compiler internals. something wrong either with language design or with type system here.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #5 from Ketmar Dark <ketmar@ketmar.no-ip.org> ---
i.e. having such template that somehow deduces type for it's argument, despite the explicitly written type, and doing that differently depending of the line where template was instantiated is... very strange. it's the source of hard-to-catch bugs, which type system should *help* to catch. instead it simply doing something i never asked it to do and carefully hides the bug from me. it reminds me INTERCAL language.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #6 from yebblies <yebblies@gmail.com> ---
The type of ln doesn't change.

The template expands to something like

enum uint ln = 4;
enum alice = "{ int t_"~ln~" = 42; }";

As the compiler knows the _value_ for ln, it expands alice's initializer to enum alice = "{ int t_"~4~" = 42; }";

Then, because it knows that 4 can fit in a char, it allows it to become this:

enum alice = "{ int t_"~cast(char)4~" = 42; }";

And then the concatenation is semantically valid.

As I said in my first comment, range propagation is allowed so that code like this will still work:

enum str = "abc" ~ ('a' + 7);

Here ('a' + 7) has type int, but because we know the value at compile time and know it will fit in a char, it is allowed to be narrowed.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #7 from Ketmar Dark <ketmar@ketmar.no-ip.org> ---
the type IS changed. in no way compiler does runtime analysis to allow
converting `size_t` to `char`, it simply rejects such code. yet for
*explicitly* defined type in template compiler — for some unknown reason —
narrows the type. so we actually have THREE types here:
• "runtime `size_t`"
• "compile-time `size_t` which fits to char"
• "compile-time `size_t` which doesn't fit to char"
for another unknown reason they all called `size_t`, which is obviously wrong.

as for your sample with `'a'+1`: 'a' is *literal* here. as i told ealier, i can accept type deduction for literals (it's wrong too in this case, but ok, let's leave it as is). but i can't see why `size_t` has three definitions, and two of that definitions *depends* *on* *instantiation* *line*. it's insane.

--
March 22, 2015
https://issues.dlang.org/show_bug.cgi?id=14035

--- Comment #8 from yebblies <yebblies@gmail.com> ---
Feel free to make your own version of the compiler that works differently.

--
« First   ‹ Prev
1 2 3