diff --git a/examples/rest-collections/source/api.d b/examples/rest-collections/source/api.d index a69074332d..4fed5f7144 100644 --- a/examples/rest-collections/source/api.d +++ b/examples/rest-collections/source/api.d @@ -4,11 +4,13 @@ module api; import vibe.web.rest; interface ForumAPI { +@safe: // base path /threads/ Collection!ThreadAPI threads(); } interface ThreadAPI { +@safe: // define the index parameters used to identify the collection items struct CollectionIndices { string _thread_name; @@ -27,6 +29,7 @@ interface ThreadAPI { } interface PostAPI { +@safe: // define the index parameters used to identify the collection items struct CollectionIndices { string _thread_name; diff --git a/examples/rest-js/source/app.d b/examples/rest-js/source/app.d index a18512221b..959ef625cb 100644 --- a/examples/rest-js/source/app.d +++ b/examples/rest-js/source/app.d @@ -6,6 +6,7 @@ import vibe.http.common : HTTPMethod; // Defines a simple RESTful API interface ITest { +@safe: // GET /compute_sum?a=...&b=... @method(HTTPMethod.GET) float computeSum(float a, float b); diff --git a/tests/restclient/source/app.d b/tests/restclient/source/app.d index ead98be2cf..b2d09c3c78 100644 --- a/tests/restclient/source/app.d +++ b/tests/restclient/source/app.d @@ -4,6 +4,7 @@ import vibe.vibe; interface ITestAPI { +@safe: @property ISub sub(); @method(HTTPMethod.POST) @path("other/path") @@ -22,6 +23,7 @@ interface ITestAPI } interface ISub { +@safe: int get(int id); } @@ -49,6 +51,7 @@ class SubAPI : ISub { interface ITestAPICors { +@safe: string getFoo(); string setFoo(); string addFoo(); diff --git a/tests/restcollections/source/app.d b/tests/restcollections/source/app.d index 857c7313da..192b91b146 100644 --- a/tests/restcollections/source/app.d +++ b/tests/restcollections/source/app.d @@ -3,10 +3,12 @@ module app; import vibe.vibe; interface API { +@safe: Collection!ItemAPI items(); } interface ItemAPI { +@safe: struct CollectionIndices { string _item; } @@ -17,6 +19,7 @@ interface ItemAPI { } interface SubItemAPI { +@safe: struct CollectionIndices { string _item; int _index; @@ -29,6 +32,7 @@ interface SubItemAPI { } interface ItemManagerAPI { +@safe: @property string databaseURL(); } diff --git a/web/vibe/web/rest.d b/web/vibe/web/rest.d index 88206e8bf7..e2403c66a3 100644 --- a/web/vibe/web/rest.d +++ b/web/vibe/web/rest.d @@ -1562,8 +1562,8 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)( v = fromRestString!(PT, SerPolicyType)(*pv); } else static if (sparam.kind == ParameterKind.attributed) { static if (!__traits(compiles, () @safe { computeAttributedParameterCtx!(CFunc, pname)(inst, req, res); } ())) - pragma(msg, "Non-@safe @before evaluators are deprecated - annotate evaluator function for parameter "~pname~" of "~T.stringof~"."~Method~" as @safe."); - v = () @trusted { return computeAttributedParameterCtx!(CFunc, pname)(inst, req, res); } (); + static assert(false, "`@before` evaluator for REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`."); + v = computeAttributedParameterCtx!(CFunc, pname)(inst, req, res); } else static if (sparam.kind == ParameterKind.internal) { if (auto pv = fieldname in req.params) v = fromRestString!(PT, DefaultPolicy)(urlDecode(*pv)); @@ -1628,28 +1628,25 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)( import vibe.internal.meta.funcattr; static if (!__traits(compiles, () @safe { __traits(getMember, inst, Method)(params); })) - pragma(msg, "Non-@safe methods are deprecated in REST interfaces - Mark " ~ - T.stringof ~ "." ~ Method ~ " as @safe."); + static assert(false, "REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`."); static if (is(RT == void)) { // TODO: remove after deprecation period - () @trusted { __traits(getMember, inst, Method)(params); } (); + __traits(getMember, inst, Method)(params); returnHeaders(); res.writeBody(cast(ubyte[])null); } else static if (isInputStream!RT) { returnHeaders(); - auto ret = () @trusted { - return evaluateOutputModifiers!CFunc( - __traits(getMember, inst, Method)(params), req, res); } (); + auto ret = evaluateOutputModifiers!CFunc( + __traits(getMember, inst, Method)(params), req, res); res.headers["Content-Type"] = "application/octet-stream"; ret.pipe(res.bodyWriter); } else { // TODO: remove after deprecation period static if (!__traits(compiles, () @safe { evaluateOutputModifiers!Func(RT.init, req, res); } ())) - pragma(msg, "Non-@safe @after evaluators are deprecated - annotate @after evaluator function for " ~ - T.stringof ~ "." ~ Method ~ " as @safe."); + static assert(false, "`@after` evaluator for REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`."); - auto ret = () @trusted { + auto ret = () /*@trusted*/ { return evaluateOutputModifiers!CFunc( __traits(getMember, inst, Method)(params), req, res); } (); returnHeaders(); @@ -1670,12 +1667,9 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)( serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret); })) { - pragma(msg, "Non-@safe serialization of REST return types deprecated - ensure that " ~ - RT.stringof~" is safely serializable."); + static assert(false, "Serialization of return type `"~RT.stringof~"` of REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be `@safe`."); } - () @trusted { - serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret); - }(); + serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret); res.writeBody(serialized_output.data, serializer.contentType); } res.statusCode = HTTPStatus.notAcceptable; // will trigger RestException on the client side