diff --git a/compiler/src/dmd/templatesem.d b/compiler/src/dmd/templatesem.d index 48f1be0519a0..237b597c478f 100644 --- a/compiler/src/dmd/templatesem.d +++ b/compiler/src/dmd/templatesem.d @@ -7183,6 +7183,19 @@ MATCH deduceType(scope RootObject o, scope Scope* sc, scope Type tparam, return; } + // https://github.com/dlang/dmd/issues/19718 + // The argument's safety must satisfy what the parameter type requires; + // an @system (or unmarked) function/delegate cannot match an @safe or + // @trusted parameter type. Without this check, template argument + // deduction only compares parameter lists and ignores the function's + // own attributes, so an unsafe argument can be wrongly deduced to + // match an @safe (or stronger) parameter type. + if (t.trust <= TRUST.system && tp.trust >= TRUST.trusted) + { + result = MATCH.nomatch; + return; + } + foreach (fparam; *tp.parameterList.parameters) { // https://issues.dlang.org/show_bug.cgi?id=2579 diff --git a/compiler/test/fail_compilation/test19718.d b/compiler/test/fail_compilation/test19718.d new file mode 100644 index 000000000000..413f53d86911 --- /dev/null +++ b/compiler/test/fail_compilation/test19718.d @@ -0,0 +1,27 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test19718.d(27): Error: none of the overloads of template `test19718.execute` are callable using argument types `!()(int function(ref Struct rng) @system)` +fail_compilation/test19718.d(15): Candidates are: `execute(T)(T function(ref Struct) @safe dg)` +fail_compilation/test19718.d(21): `execute(T)(T delegate(ref Struct) @safe dg)` +--- +*/ + +struct Struct +{ + int get() { return 1; } +} + +public T execute (T)(T function(ref Struct) @safe dg) +{ + Struct rng; + return dg(rng); +} + +public T execute (T)(T delegate(ref Struct) @safe dg) +{ + Struct rng; + return dg(rng); +} + +auto x = execute((ref Struct rng) { return rng.get(); });