Bug 9626 – More precise error message in some cases when failed template constraint

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-01T12:36:11Z
Last change time
2022-02-25T10:38:23Z
Keywords
diagnostic
Assigned to
No Owner
Creator
bearophile_hugs
See also
https://issues.dlang.org/show_bug.cgi?id=11729

Comments

Comment #0 by bearophile_hugs — 2013-03-01T12:36:11Z
This experimental branch of the GCC C++ compiler implements constraints for template arguments, named "concepts lite", that seem very similar to D template constraints: http://isocpp.org/blog/2013/02/concepts-lite-constraining-templates-with-predicates-andrew-sutton-bjarne-s http://concepts.axiomatics.org/~ans/ In that page they show an example of error message: template<Sortable Cont> void sort(Cont& container); list<int> lst = ...; sort(lst); It gives a small amount of readable error messages: error: no matching function for call to ‘sort(list<int>&)’ sort(l); ^ note: candidate is: note: template<Sortable T> void sort(T) void sort(T t) { } ^ note: template constraints not satisfied because note: 'T' is not a/an 'Sortable' type [with T = list<int>] since note: 'declval<T>()[n]' is not valid syntax For a similar wrong D program: import std.container: DList; import std.algorithm: sort; void main() { auto lst = DList!int([10, 3, 14]); sort(lst); // Line 5. } Currently DMD 2.063alpha gives a little worse error messages: test.d(5): Error: template std.algorithm.sort does not match any function template declaration. Candidates are: ...\dmd2\src\phobos\std\algorithm.d(8103): std.algorithm.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!(Range) || hasAssignableElements!(Range)) || ss != SwapStrategy.unstable && hasAssignableElements!(Range)) && isRandomAccessRange!(Range) && hasSlicing!(Range) && hasLength!(Range)) test.d(5): Error: template std.algorithm.sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if ((ss == SwapStrategy.unstable && (hasSwappableElements!(Range) || hasAssignableElements!(Range)) || ss != SwapStrategy.unstable && hasAssignableElements!(Range)) && isRandomAccessRange!(Range) && hasSlicing!(Range) && hasLength!(Range)) cannot deduce template function from argument types !()(DList!(int)) Currently these are the template constraints for std.algorithm.sort: SortedRange!(Range, less) sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range)) || (ss != SwapStrategy.unstable && hasAssignableElements!Range)) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range) /+ Unstable sorting uses the quicksort algorithm, which uses swapAt, which either uses swap(...), requiring swappable elements, or just swaps using assignment. Stable sorting uses TimSort, which needs to copy elements into a buffer, requiring assignable elements. +/ { ... In D template constraints have two (or more) related but different purposes: to exclude one or more templates from the list of possible templates to instantiate, and to restrict a single template to be instantiated correctly (like this sort), to avoid error messages inside the implementation of sort(). Like in the error message generated by that concepts lite compiler, I think it's possible to improve the error message generated by the D compiler for this second usage, when there is only one (or two?) templates available, like in the case of sort(). In this case the compiler, after the current error messages, can print one more error message that shows what parts of the following template constraint have failed: (((ss == SwapStrategy.unstable && (hasSwappableElements!Range || hasAssignableElements!Range)) || (ss != SwapStrategy.unstable && hasAssignableElements!Range)) && isRandomAccessRange!Range && hasSlicing!Range && hasLength!Range) In this case SwapStrategy is unstable. And for a DList!int all the unstable requirements fail: import std.container: DList; import std.range: hasSwappableElements, hasAssignableElements, isRandomAccessRange, hasSlicing, hasLength; void main() { alias Range = DList!int; pragma(msg, hasSwappableElements!Range); pragma(msg, hasAssignableElements!Range); pragma(msg, isRandomAccessRange!Range); pragma(msg, hasSlicing!Range); pragma(msg, hasLength!Range); } Output: false false false false false
Comment #1 by bearophile_hugs — 2013-03-04T15:01:50Z
An example of the problems this enhancement request should help solve. A question from "deed" in D.learn: http://forum.dlang.org/thread/[email protected] > Why randomAccessRange.array() before calling sort? > The std.algorithm.sort doc says: "Sorts a random-access range ..." > > > import std.algorithm, std.array; > > long[] source = [2, 0, 1]; > > auto mapped = source.map!("a * 10"); > assert (isRandomAccessRange!(typeof(mapped))); // Passes. Implies possibility > // to to use std.algorithm.sort? > > auto mappedThenSorted = mapped.sort(); // Error > auto mappedThenSorted = mapped.array.sort(); // Works (and > used in examples) > > > What am I missing in the documentation?
Comment #2 by dfj1esp02 — 2016-04-22T12:18:03Z
void f(int n, T)(T val)if(n==0){} void f1(int n)(int val)if(n==0){} void g() { f!1(1); f1!1(1); } The second instatiation gives good error message: "Error: template instance f1!1 does not match template declaration f1(int n)(int val) if (n == 0)". The first instatiation gives less helpful error message: "Error: template f cannot deduce function from argument types !(1)(int), candidates are:...", but it doesn't look like there's problem with deduction, should report no match. See https://forum.dlang.org/post/[email protected]
Comment #3 by dfj1esp02 — 2016-04-22T12:25:01Z
Even better error message would be "Error: template instance f1!1 does not match template declaration f1(int n)(int val) if (n == 0), because template constraint is not satisfied".
Comment #4 by razvan.nitu1305 — 2022-02-25T10:38:23Z
This has been fixed. Currently, for the bug report I get: test.d(5): Error: none of the overloads of template `std.algorithm.sorting.sort` are callable using argument types `!()(DList!int)` ../phobos/std/algorithm/sorting.d(1925): Candidate is: `sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)` with `less = "a < b", ss = SwapStrategy.unstable, Range = DList!int` must satisfy one of the following constraints: ` hasSwappableElements!Range hasAssignableElements!Range ss != SwapStrategy.unstable`