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-collections/source/app.d b/examples/rest-collections/source/app.d index d687523fec..53d2a3e979 100644 --- a/examples/rest-collections/source/app.d +++ b/examples/rest-collections/source/app.d @@ -48,7 +48,10 @@ class LocalThreadAPI : ThreadAPI { string[] get() { - return m_data.threads.keys; + static if (__VERSION__ < 2099) { + // NOTE: .keys is not @safe on older compiler versions + return () @trusted { return m_data.threads.keys; } (); + } else return m_data.threads.keys; } } 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/tests/vibe.web.rest.1125/source/app.d b/tests/vibe.web.rest.1125/source/app.d index ed76be6401..1e6b98d056 100644 --- a/tests/vibe.web.rest.1125/source/app.d +++ b/tests/vibe.web.rest.1125/source/app.d @@ -21,6 +21,7 @@ shared static this() } interface ILlama { +@safe: @bodyParam("llama", "llama") string updateLlama(string llama = null); } diff --git a/tests/vibe.web.rest.1140/source/app.d b/tests/vibe.web.rest.1140/source/app.d index dbfc8d4373..2b0d68c78d 100644 --- a/tests/vibe.web.rest.1140/source/app.d +++ b/tests/vibe.web.rest.1140/source/app.d @@ -3,11 +3,13 @@ import vibe.d; interface IOrientDBRoot { +@safe: @property IOrientDBQuery query(); } interface IOrientDBQuery { +@safe: @method(HTTPMethod.GET) @path(":db_name/sql/:query/:result_set_size") Json sql(string _db_name, string _query, int _result_set_size); diff --git a/tests/vibe.web.rest.1230/source/app.d b/tests/vibe.web.rest.1230/source/app.d index 40a80d97d0..1bbc194d98 100644 --- a/tests/vibe.web.rest.1230/source/app.d +++ b/tests/vibe.web.rest.1230/source/app.d @@ -2,6 +2,7 @@ import std.datetime; import vibe.d; interface ITestAPI { +@safe: string postDefault(int value, bool check = true); } diff --git a/tests/vibe.web.rest.1922/source/app.d b/tests/vibe.web.rest.1922/source/app.d index 622c40930a..ea88c12ca8 100644 --- a/tests/vibe.web.rest.1922/source/app.d +++ b/tests/vibe.web.rest.1922/source/app.d @@ -44,6 +44,7 @@ struct AuthInfo { @requiresAuth interface IItemAPI { +@safe: struct CollectionIndices { string item; } @@ -66,6 +67,7 @@ class ItemAPI : IItemAPI { @requiresAuth interface IAuthAPI { +@safe: @noAuth int getNonAuthNumber(int num); @anyAuth int getAuthNumber(AuthInfo info, int num); @anyAuth Collection!IItemAPI items(); diff --git a/tests/vibe.web.rest.2506/source/app.d b/tests/vibe.web.rest.2506/source/app.d index c2659bdd39..6c3054a82a 100644 --- a/tests/vibe.web.rest.2506/source/app.d +++ b/tests/vibe.web.rest.2506/source/app.d @@ -11,6 +11,7 @@ struct TestStruct {int i;} interface IService { +@safe: @safe TestStruct getTest(int sleepsecs); @safe TestStruct getTest2(int sleepsecs); } diff --git a/tests/vibe.web.rest.auth/source/app.d b/tests/vibe.web.rest.auth/source/app.d index 45453bdf4c..1a6e7417da 100644 --- a/tests/vibe.web.rest.auth/source/app.d +++ b/tests/vibe.web.rest.auth/source/app.d @@ -72,6 +72,7 @@ struct Auth { @requiresAuth interface IService { +@safe: @noAuth int getPublic(); @anyAuth int getAny(); @anyAuth int getAnyA(Auth auth); diff --git a/web/vibe/web/rest.d b/web/vibe/web/rest.d index 03f9b14014..f6886d3986 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,30 +1628,26 @@ 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 { - return evaluateOutputModifiers!CFunc( - __traits(getMember, inst, Method)(params), req, res); } (); + auto ret = evaluateOutputModifiers!CFunc( + __traits(getMember, inst, Method)(params), req, res); returnHeaders(); string accept_str; @@ -1670,12 +1666,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