std.regex: Fix reassignment of ctRegex wrapper structs

Previously, reassigning such a wrapper resulted in the static immutable
Regex!Char global for that pattern (`staticRe`) to be overwritten by the
global for the new pattern (!). Made possible via alias this and the
logical-const hack.

Proposed fix: keep on allowing reassignments (people are already using
them), but just point to another pattern's global. So use a common
Wrapper struct type wrapping a pointer instead of an empty struct type
per pattern.

Bug reported in https://github.com/ldc-developers/ldc/issues/2961.
This commit is contained in:
Martin Kinkelin 2019-02-02 22:31:16 +01:00
parent 6a759b85f2
commit 5cc7fc5fb2

View file

@ -423,6 +423,16 @@ if (isSomeString!(S))
}
private struct CTRegexWrapper(Char)
{
private immutable(Regex!Char)* re;
// allow code that expects mutable Regex to still work
// we stay "logically const"
@property @trusted ref getRe() const { return *cast(Regex!Char*) re; }
alias getRe this;
}
template ctRegexImpl(alias pattern, string flags=[])
{
import std.regex.internal.backtracking, std.regex.internal.parser;
@ -437,14 +447,7 @@ template ctRegexImpl(alias pattern, string flags=[])
}
static immutable staticRe =
cast(immutable) r.withFactory(new CtfeFactory!(BacktrackingMatcher, Char, func));
struct Wrapper
{
// allow code that expects mutable Regex to still work
// we stay "logically const"
@property @trusted ref getRe() const { return *cast(Regex!Char*)&staticRe; }
alias getRe this;
}
enum wrapper = Wrapper();
enum wrapper = CTRegexWrapper!Char(&staticRe);
}
@safe unittest
@ -457,6 +460,17 @@ template ctRegexImpl(alias pattern, string flags=[])
test(re);
}
@safe unittest
{
auto re = ctRegex!`foo`;
assert(matchFirst("foo", re));
// test reassignment
re = ctRegex!`bar`;
assert(matchFirst("bar", re));
assert(!matchFirst("bar", ctRegex!`foo`));
}
/++
Compile regular expression using CTFE
and generate optimized native machine code for matching it.