From 837027692463c06052874ff6182724dd4c8727a9 Mon Sep 17 00:00:00 2001 From: monarch dodra Date: Mon, 24 Mar 2014 13:41:44 +0000 Subject: [PATCH 1/4] Fix Issue 12449 Undefined format in std.algorithm.max --- std/algorithm.d | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/std/algorithm.d b/std/algorithm.d index 43673fc45..ed7eee502 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -3826,6 +3826,7 @@ unittest result ~= c; } + import std.string : format; assert(equal(result, "abc12def34"d), "Unexpected result: '%s'"d.format(result)); } @@ -7046,8 +7047,8 @@ MinType!T min(T...)(T args) alias a = args[0]; alias b = args[1]; - static assert (is(typeof(a < b)), - format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + static assert (is(typeof(a < b)), {import std.string : format; + return format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof);}()); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7132,8 +7133,8 @@ MaxType!T max(T...)(T args) alias a = args[0]; alias b = args[1]; - static assert (is(typeof(a < b)), - format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + static assert (is(typeof(a < b)), {import std.string : format; + return format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof);}()); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7215,9 +7216,9 @@ minCount(alias pred = "a < b", Range)(Range range) alias UT = Unqual!T; alias RetType = Tuple!(T, size_t); - static assert (is(typeof(RetType(range.front, 1))), - format("Error: Cannot call minCount on a %s, because it is not possible "~ - "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof)); + static assert (is(typeof(RetType(range.front, 1))), {import std.string : format; + return format("Error: Cannot call minCount on a %s, because it is not possible "~ + "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof);}()); enforce(!range.empty, "Can't count elements from an empty range"); size_t occurrences = 1; @@ -7278,9 +7279,12 @@ minCount(alias pred = "a < b", Range)(Range range) return RetType(*p, occurrences); } else + { + import std.string : format; static assert(false, format("Sorry, can't find the minCount of a %s: Don't know how "~ "to keep track of the smallest %s element.", Range.stringof, T.stringof)); + } } /// From 7f76f3fc3a7b6031e1487da1391f6a4d8eaacd4b Mon Sep 17 00:00:00 2001 From: monarch dodra Date: Mon, 24 Mar 2014 16:13:29 +0000 Subject: [PATCH 2/4] Update algorithm.d --- std/algorithm.d | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/std/algorithm.d b/std/algorithm.d index ed7eee502..df34efc59 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -378,6 +378,15 @@ version(unittest) private T* addressOf(T)(ref T val) { return &val; } +// Same as std.string.format, but "self-importing". +// Helps reduce code and un-needed imports, particularly in static asserts. +// Also helps with missing imports errors. +private template algoFormat() +{ + import std.string : format; + alias algoFormat = std.string.format; +} + /** $(D auto map(Range)(Range r) if (isInputRange!(Unqual!Range));) @@ -3102,10 +3111,8 @@ unittest writeln("unittest @", __FILE__, ":", __LINE__, " done."); void compare(string sentence, string[] witness) { - import std.string : format; - auto r = splitter!"a == ' '"(sentence); - assert(equal(r.save, witness), format("got: %(%s, %) expected: %(%s, %)", r, witness)); + assert(equal(r.save, witness), algoFormat("got: %(%s, %) expected: %(%s, %)", r, witness)); } compare(" Mary has a little lamb. ", @@ -3148,11 +3155,9 @@ unittest ]; foreach ( entry ; entries ) { - import std.string : format; - auto a = iota(entry.low, entry.high).filter!"true"(); auto b = splitter!"a%2"(a); - assert(equal!equal(b.save, entry.result), format("got: %(%s, %) expected: %(%s, %)", b, entry.result)); + assert(equal!equal(b.save, entry.result), algoFormat("got: %(%s, %) expected: %(%s, %)", b, entry.result)); } } @@ -3277,7 +3282,7 @@ unittest unittest { import std.conv : text; - import std.string : split, format; + import std.string : split; // Check consistency: // All flavors of split should produce the same results @@ -3291,7 +3296,7 @@ unittest { auto result = split(input, s); - assert(equal(result, split(input, [s])), format(`"[%(%s,%)]"`, split(input, [s]))); + assert(equal(result, split(input, [s])), algoFormat(`"[%(%s,%)]"`, split(input, [s]))); //assert(equal(result, split(input, [s].filter!"true"()))); //Not yet implemented assert(equal(result, split!((a) => a == s)(input)), text(split!((a) => a == s)(input))); @@ -3826,9 +3831,8 @@ unittest result ~= c; } - import std.string : format; assert(equal(result, "abc12def34"d), - "Unexpected result: '%s'"d.format(result)); + "Unexpected result: '%s'"d.algoFormat(result)); } // Issue 8061 @@ -7047,8 +7051,8 @@ MinType!T min(T...)(T args) alias a = args[0]; alias b = args[1]; - static assert (is(typeof(a < b)), {import std.string : format; - return format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof);}()); + static assert (is(typeof(a < b)), + algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7133,8 +7137,8 @@ MaxType!T max(T...)(T args) alias a = args[0]; alias b = args[1]; - static assert (is(typeof(a < b)), {import std.string : format; - return format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof);}()); + static assert (is(typeof(a < b)), + algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7216,9 +7220,9 @@ minCount(alias pred = "a < b", Range)(Range range) alias UT = Unqual!T; alias RetType = Tuple!(T, size_t); - static assert (is(typeof(RetType(range.front, 1))), {import std.string : format; - return format("Error: Cannot call minCount on a %s, because it is not possible "~ - "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof);}()); + static assert (is(typeof(RetType(range.front, 1))), + algoFormat("Error: Cannot call minCount on a %s, because it is not possible "~ + "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof)); enforce(!range.empty, "Can't count elements from an empty range"); size_t occurrences = 1; @@ -7279,12 +7283,9 @@ minCount(alias pred = "a < b", Range)(Range range) return RetType(*p, occurrences); } else - { - import std.string : format; static assert(false, - format("Sorry, can't find the minCount of a %s: Don't know how "~ + algoFormat("Sorry, can't find the minCount of a %s: Don't know how "~ "to keep track of the smallest %s element.", Range.stringof, T.stringof)); - } } /// @@ -12883,14 +12884,12 @@ unittest /// ditto auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges) { - import std.string : format; - /* We implement the n-ary cartesian product by recursively invoking the * binary cartesian product. To make the resulting range nicer, we denest * one level of tuples so that a ternary cartesian product, for example, * returns 3-element tuples instead of nested 2-element tuples. */ - enum string denest = format("tuple(a[0], %(a[1][%d]%|,%))", + enum string denest = algoFormat("tuple(a[0], %(a[1][%d]%|,%))", iota(0, otherRanges.length+1)); return map!denest( cartesianProduct(range1, cartesianProduct(range2, otherRanges)) From 72d78547cf385fd4d3e511130f60a990686b7471 Mon Sep 17 00:00:00 2001 From: monarch dodra Date: Mon, 24 Mar 2014 16:16:19 +0000 Subject: [PATCH 3/4] Update algorithm.d --- std/algorithm.d | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/std/algorithm.d b/std/algorithm.d index df34efc59..e95ec41e8 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -379,12 +379,12 @@ version(unittest) private T* addressOf(T)(ref T val) { return &val; } // Same as std.string.format, but "self-importing". -// Helps reduce code and un-needed imports, particularly in static asserts. +// Helps reduce code and imports, particularly in static asserts. // Also helps with missing imports errors. -private template algoFormat() +private template format() { - import std.string : format; - alias algoFormat = std.string.format; + import std.string : stringformat = format; + alias format = stringformat; } /** @@ -3112,7 +3112,7 @@ unittest void compare(string sentence, string[] witness) { auto r = splitter!"a == ' '"(sentence); - assert(equal(r.save, witness), algoFormat("got: %(%s, %) expected: %(%s, %)", r, witness)); + assert(equal(r.save, witness), format("got: %(%s, %) expected: %(%s, %)", r, witness)); } compare(" Mary has a little lamb. ", @@ -3157,7 +3157,7 @@ unittest { auto a = iota(entry.low, entry.high).filter!"true"(); auto b = splitter!"a%2"(a); - assert(equal!equal(b.save, entry.result), algoFormat("got: %(%s, %) expected: %(%s, %)", b, entry.result)); + assert(equal!equal(b.save, entry.result), format("got: %(%s, %) expected: %(%s, %)", b, entry.result)); } } @@ -3296,7 +3296,7 @@ unittest { auto result = split(input, s); - assert(equal(result, split(input, [s])), algoFormat(`"[%(%s,%)]"`, split(input, [s]))); + assert(equal(result, split(input, [s])), format(`"[%(%s,%)]"`, split(input, [s]))); //assert(equal(result, split(input, [s].filter!"true"()))); //Not yet implemented assert(equal(result, split!((a) => a == s)(input)), text(split!((a) => a == s)(input))); @@ -3832,7 +3832,7 @@ unittest } assert(equal(result, "abc12def34"d), - "Unexpected result: '%s'"d.algoFormat(result)); + "Unexpected result: '%s'"d.format(result)); } // Issue 8061 @@ -7052,7 +7052,7 @@ MinType!T min(T...)(T args) alias b = args[1]; static assert (is(typeof(a < b)), - algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7138,7 +7138,7 @@ MaxType!T max(T...)(T args) alias b = args[1]; static assert (is(typeof(a < b)), - algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7221,7 +7221,7 @@ minCount(alias pred = "a < b", Range)(Range range) alias RetType = Tuple!(T, size_t); static assert (is(typeof(RetType(range.front, 1))), - algoFormat("Error: Cannot call minCount on a %s, because it is not possible "~ + format("Error: Cannot call minCount on a %s, because it is not possible "~ "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof)); enforce(!range.empty, "Can't count elements from an empty range"); @@ -7284,7 +7284,7 @@ minCount(alias pred = "a < b", Range)(Range range) } else static assert(false, - algoFormat("Sorry, can't find the minCount of a %s: Don't know how "~ + format("Sorry, can't find the minCount of a %s: Don't know how "~ "to keep track of the smallest %s element.", Range.stringof, T.stringof)); } @@ -12889,7 +12889,7 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges) * one level of tuples so that a ternary cartesian product, for example, * returns 3-element tuples instead of nested 2-element tuples. */ - enum string denest = algoFormat("tuple(a[0], %(a[1][%d]%|,%))", + enum string denest = format("tuple(a[0], %(a[1][%d]%|,%))", iota(0, otherRanges.length+1)); return map!denest( cartesianProduct(range1, cartesianProduct(range2, otherRanges)) From aec513e5420aa5be2104fb9cbb1a3bfb75c8100a Mon Sep 17 00:00:00 2001 From: monarch dodra Date: Mon, 24 Mar 2014 16:39:56 +0000 Subject: [PATCH 4/4] Revert --- std/algorithm.d | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/std/algorithm.d b/std/algorithm.d index e95ec41e8..95e640745 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -381,10 +381,10 @@ private T* addressOf(T)(ref T val) { return &val; } // Same as std.string.format, but "self-importing". // Helps reduce code and imports, particularly in static asserts. // Also helps with missing imports errors. -private template format() +private template algoFormat() { - import std.string : stringformat = format; - alias format = stringformat; + import std.string : format; + alias algoFormat = std.string.format; } /** @@ -3112,7 +3112,7 @@ unittest void compare(string sentence, string[] witness) { auto r = splitter!"a == ' '"(sentence); - assert(equal(r.save, witness), format("got: %(%s, %) expected: %(%s, %)", r, witness)); + assert(equal(r.save, witness), algoFormat("got: %(%s, %) expected: %(%s, %)", r, witness)); } compare(" Mary has a little lamb. ", @@ -3157,7 +3157,7 @@ unittest { auto a = iota(entry.low, entry.high).filter!"true"(); auto b = splitter!"a%2"(a); - assert(equal!equal(b.save, entry.result), format("got: %(%s, %) expected: %(%s, %)", b, entry.result)); + assert(equal!equal(b.save, entry.result), algoFormat("got: %(%s, %) expected: %(%s, %)", b, entry.result)); } } @@ -3296,7 +3296,7 @@ unittest { auto result = split(input, s); - assert(equal(result, split(input, [s])), format(`"[%(%s,%)]"`, split(input, [s]))); + assert(equal(result, split(input, [s])), algoFormat(`"[%(%s,%)]"`, split(input, [s]))); //assert(equal(result, split(input, [s].filter!"true"()))); //Not yet implemented assert(equal(result, split!((a) => a == s)(input)), text(split!((a) => a == s)(input))); @@ -3832,7 +3832,7 @@ unittest } assert(equal(result, "abc12def34"d), - "Unexpected result: '%s'"d.format(result)); + "Unexpected result: '%s'"d.algoFormat(result)); } // Issue 8061 @@ -7052,7 +7052,7 @@ MinType!T min(T...)(T args) alias b = args[1]; static assert (is(typeof(a < b)), - format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7138,7 +7138,7 @@ MaxType!T max(T...)(T args) alias b = args[1]; static assert (is(typeof(a < b)), - format("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); + algoFormat("Invalid arguments: Cannot compare types %s and %s.", T0.stringof, T1.stringof)); static if (isIntegral!T0 && isIntegral!T1 && (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) @@ -7221,7 +7221,7 @@ minCount(alias pred = "a < b", Range)(Range range) alias RetType = Tuple!(T, size_t); static assert (is(typeof(RetType(range.front, 1))), - format("Error: Cannot call minCount on a %s, because it is not possible "~ + algoFormat("Error: Cannot call minCount on a %s, because it is not possible "~ "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof)); enforce(!range.empty, "Can't count elements from an empty range"); @@ -7284,7 +7284,7 @@ minCount(alias pred = "a < b", Range)(Range range) } else static assert(false, - format("Sorry, can't find the minCount of a %s: Don't know how "~ + algoFormat("Sorry, can't find the minCount of a %s: Don't know how "~ "to keep track of the smallest %s element.", Range.stringof, T.stringof)); } @@ -12889,7 +12889,7 @@ auto cartesianProduct(R1, R2, RR...)(R1 range1, R2 range2, RR otherRanges) * one level of tuples so that a ternary cartesian product, for example, * returns 3-element tuples instead of nested 2-element tuples. */ - enum string denest = format("tuple(a[0], %(a[1][%d]%|,%))", + enum string denest = algoFormat("tuple(a[0], %(a[1][%d]%|,%))", iota(0, otherRanges.length+1)); return map!denest( cartesianProduct(range1, cartesianProduct(range2, otherRanges))