Bug 12606 – Mismatch of known array length during dynamic => static array assignment should emit better diagnostics

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-04-21T10:08:00Z
Last change time
2014-04-25T07:58:35Z
Keywords
diagnostic, pull
Assigned to
nobody
Creator
andrej.mitrovich

Comments

Comment #0 by andrej.mitrovich — 2014-04-21T10:08:33Z
----- import std.range; // ok uint[256] arr1 = iota(0, 512).array[0 .. 256]; // diagnostic mentions int[] => uint[256], but no mention of length (128 != 256) uint[256] arr2 = iota(0, 512).array[0 .. 128]; void main() { } ----- The first one is a relatively recent feature, where a slice can be converted to a static array if the length is known. The length is also known for the second declaration, but it's not being taken into account by the diagnostic: Diagnostic: test.d(6): Error: cannot implicitly convert expression ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127]) of type int[] to uint[256] Since the compiler knows the length of the slice it should mention the mismatch of slice lengths when attempting to convert a dynamic array to a static array.
Comment #1 by andrej.mitrovich — 2014-04-21T13:41:38Z
Simplified test-case: ----- uint[2] arr1 = [1, 2, 3][0 .. 2]; uint[2] arr2 = [1, 2, 3][0 .. 3]; void main() { } -----
Comment #2 by andrej.mitrovich — 2014-04-21T13:59:52Z
Kenji: The way I see it, we need some way of returning back information on why some implicit conversion didn't work. For example, in 'implicitConvTo' in the visitor functions 'result' is simply initialized to MATCHnomatch if the dimensions of the two slices don't match. But this isn't propagate back to the caller side. We could vastly improve diagnostics for type mismatches, length mismatches, template instance failures, if we had a way of return back information. I think one way we could do it is to turn the MATCH enum into a struct, which internally holds more state. For example: struct MATCH { /// equivalent to what MATCH was before: MATCHnomatch, MATCHconvert... MATCHLevel level; /// call this to emit informative diagnostic const char*(*error_fp)(); } In internal matching routines the code could do (sorry this is a bit mixed-C/D code syntax): ----- if (e->elements->dim != tsa->dim->toInteger()) { result = MATCH(MATCHnomatch, { return format("Array length mismatch: %s %s", e->elements->dim, tsa->dim->toInteger()); } } ----- So the idea is the routine initializes a pointer, and then the call site can decide whether to call it to extract a diagnostic, or whether to ignore it. For example the 'resolveFuncCall' function typically walks through several template instances before it decides on emitting diagnostics, so having a lazy way of extracting a diagnostic is cruical. On the call site (e.g. 'resolveFuncCall') the code could look like: ----- if (matchresult.level == MATCHnomatch) { error("Failed to match: %s", matchresult.error_fp()); } ----- What do you think about this design? I'm not sure whether we can create delegates in C++ like we can in D though, I'm not too familiar with what's supported there.
Comment #3 by andrej.mitrovich — 2014-04-21T14:00:37Z
(In reply to Andrej Mitrovic from comment #2) > But this isn't propagate back to the caller side. propagated*
Comment #4 by andrej.mitrovich — 2014-04-21T14:01:26Z
(In reply to Andrej Mitrovic from comment #2) > So the idea is the routine initializes a pointer *A function pointer (well, a delegate in this case)
Comment #5 by k.hara.pg — 2014-04-22T01:57:13Z
Comment #6 by k.hara.pg — 2014-04-22T02:09:38Z
(In reply to Andrej Mitrovic from comment #2) > For example, in 'implicitConvTo' in the visitor functions 'result' is simply > initialized to MATCHnomatch if the dimensions of the two slices don't match. > But this isn't propagate back to the caller side. If e->implicitConvTo(t) returns MATCHnomatch, e->implicitCastTo(sc, t) should cause error which represents why e does not match to t. So, the following compiler code form would be sufficient. e = e->implicitCastTo(sc, t); or: if (e->implicitConvTo(t)) { e = e->implicitCastTo(sc, t); assert(e->op != TOKerror); // always succeeds } else { // extra handling for the unmatch, if e and t have known forms. if (...) { error("more better diagnostic for particular case"); e = new ErrorExp(); } // error report for generic case // (if e is already an ErrorExp, no redundant error generated) e = e->implicitCastTo(sc, t); }
Comment #7 by github-bugzilla — 2014-04-25T07:58:34Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/3b74627a464197f526e6b3a9a54334e3ced60fc8 fix Issue 12606 - Mismatch of known array length during dynamic => static array assignment should emit better diagnostics Recognize slice expression on initializer and rhs of assignment https://github.com/D-Programming-Language/dmd/commit/3a50fa40059ae790f783a691b13d4217cf4ac861 Merge pull request #3485 from 9rnsr/fix12606 Issue 12606 - Mismatch of known array length during dynamic => static array assignment should emit better diagnostics