Improve error messages for unimplemented interfaces

Using backtips in the message of a static assert means that
the message will get the same syntax highlight as a compiler error message.
This commit is contained in:
Geod24 2020-08-02 20:11:56 +09:00 committed by Mathias LANG
parent e51a019d69
commit a83b6a75e8

View file

@ -414,11 +414,13 @@ template checkInterfaceConformance(T, I) {
static if (functionAttributes!F & FunctionAttribute.property) { static if (functionAttributes!F & FunctionAttribute.property) {
static if (PT.length > 0) { static if (PT.length > 0) {
static if (!is(typeof(mixin("function RT (ref T t)"~attribs~"{ return t."~mem~" = PT.init; }")))) static if (!is(typeof(mixin("function RT (ref T t)"~attribs~"{ return t."~mem~" = PT.init; }"))))
enum impl = T.stringof ~ " does not implement property setter \"" ~ mem ~ "\" of type " ~ FT.stringof; enum impl = "`" ~ T.stringof ~ "` does not implement property setter `" ~
mem ~ "` of type `" ~ FT.stringof ~ "`";
else enum string impl = impl!(i+1); else enum string impl = impl!(i+1);
} else { } else {
static if (!is(typeof(mixin("function RT(ref T t)"~attribs~"{ return t."~mem~"; }")))) static if (!is(typeof(mixin("function RT(ref T t)"~attribs~"{ return t."~mem~"; }"))))
enum impl = T.stringof ~ " does not implement property getter \"" ~ mem ~ "\" of type " ~ FT.stringof; enum impl = "`" ~ T.stringof ~ "` does not implement property getter `" ~
mem ~ "` of type `" ~ FT.stringof ~ "`";
else enum string impl = impl!(i+1); else enum string impl = impl!(i+1);
} }
} else { } else {
@ -427,12 +429,14 @@ template checkInterfaceConformance(T, I) {
static if (mem == "write" && PT.length == 2) { static if (mem == "write" && PT.length == 2) {
auto f = mixin("function void(ref T t, ref PT p)"~attribs~"{ t."~mem~"(p); }"); auto f = mixin("function void(ref T t, ref PT p)"~attribs~"{ t."~mem~"(p); }");
} }
enum impl = T.stringof ~ " does not implement method \"" ~ mem ~ "\" of type " ~ FT.stringof; enum impl = "`" ~ T.stringof ~ "` does not implement method `" ~
mem ~ "` of type `" ~ FT.stringof ~ "`";
} }
else enum string impl = impl!(i+1); else enum string impl = impl!(i+1);
} else { } else {
static if (!is(typeof(mixin("function RT(ref T t, ref PT p)"~attribs~"{ return t."~mem~"(p); }")))) static if (!is(typeof(mixin("function RT(ref T t, ref PT p)"~attribs~"{ return t."~mem~"(p); }"))))
enum impl = T.stringof ~ " does not implement method \"" ~ mem ~ "\" of type " ~ FT.stringof; enum impl = "`" ~ T.stringof ~ "` does not implement method `" ~
mem ~ "` of type `" ~ FT.stringof ~ "`";
else enum string impl = impl!(i+1); else enum string impl = impl!(i+1);
} }
} }
@ -502,7 +506,7 @@ unittest {
} }
static assert(checkInterfaceConformance!(NonOSStruct, OutputStream) == static assert(checkInterfaceConformance!(NonOSStruct, OutputStream) ==
"NonOSStruct does not implement method \"flush\" of type @safe void()"); "`NonOSStruct` does not implement method `flush` of type `@safe void()`");
static struct NonOSStruct2 { static struct NonOSStruct2 {
void write(in ubyte[] bytes) {} // not @safe void write(in ubyte[] bytes) {} // not @safe
@ -515,11 +519,11 @@ unittest {
// With dlang/dmd#11474 it shows up as `in`. // With dlang/dmd#11474 it shows up as `in`.
// Remove when support for v2.093.0 is dropped // Remove when support for v2.093.0 is dropped
static if (checkInterfaceConformance!(NonOSStruct2, OutputStream) != static if (checkInterfaceConformance!(NonOSStruct2, OutputStream) !=
"NonOSStruct2 does not implement method \"write\" of type @safe void(in ubyte[] bytes)") "`NonOSStruct2` does not implement method `write` of type `@safe void(in ubyte[] bytes)`")
{ {
// Fallback to pre-2.092+ // Fallback to pre-2.092+
static assert(checkInterfaceConformance!(NonOSStruct2, OutputStream) == static assert(checkInterfaceConformance!(NonOSStruct2, OutputStream) ==
"NonOSStruct2 does not implement method \"write\" of type @safe void(const(ubyte[]) bytes)"); "`NonOSStruct2` does not implement method `write` of type `@safe void(const(ubyte[]) bytes)`");
} }
} }