From 5b5219e7c2f5c9abe17b82cb38847a84d87517ca Mon Sep 17 00:00:00 2001 From: aG0aep6G Date: Sun, 18 Aug 2019 20:22:06 +0200 Subject: [PATCH 1/4] fix issue 20138 - is expression not evaluating correctly? When passing a `shared const T` into a `shared U` parameter, then no const conversion is needed to infer `U` as `const int`. Same with `inout int` and `inout const int`. --- src/dmd/dtemplate.d | 7 +++++-- test/compilable/test20138.d | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/compilable/test20138.d diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 6520d728524..5d40e353f57 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -3281,10 +3281,14 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam) case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.const_): case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wild): case X(MODFlags.shared_, MODFlags.shared_ | MODFlags.wildconst): - case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_): // foo(shared(U)) shared(const(T)) => const(T) // foo(shared(U)) shared(inout(T)) => inout(T) // foo(shared(U)) shared(inout(const(T))) => inout(const(T)) + { + *at = t.unSharedOf(); + return MATCH.exact; + } + case X(MODFlags.shared_ | MODFlags.const_, MODFlags.shared_): // foo(shared(const(U))) shared(T) => T { *at = t.unSharedOf(); @@ -3545,7 +3549,6 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param // Found the corresponding parameter tp if (!tp.isTemplateTypeParameter()) goto Lnomatch; - Type at = cast(Type)(*dedtypes)[i]; Type tt; if (ubyte wx = wm ? deduceWildHelper(t, &tt, tparam) : 0) diff --git a/test/compilable/test20138.d b/test/compilable/test20138.d new file mode 100644 index 00000000000..fb915d8c296 --- /dev/null +++ b/test/compilable/test20138.d @@ -0,0 +1,12 @@ +alias C = const int; +static assert(is(shared(C) U == shared U) && is(U == C)); +static assert(is(shared(C) == shared U, U) && is(U == C)); + + +alias I = inout int; +static assert(is(shared(I) U == shared U) && is(U == I)); +static assert(is(shared(I) == shared U, U) && is(U == I)); + +alias IC = inout const int; +static assert(is(shared(IC) U == shared U) && is(U == IC)); +static assert(is(shared(IC) == shared U, U) && is(U == IC)); From 6522b0a9da3d03b3328001d1e0319d4f273cd263 Mon Sep 17 00:00:00 2001 From: aG0aep6G Date: Mon, 19 Aug 2019 01:50:39 +0200 Subject: [PATCH 2/4] fix cases where const/inout/inout(const) are stripped --- src/dmd/dtemplate.d | 16 ++++++++++------ test/compilable/test20138.d | 5 +++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/dmd/dtemplate.d b/src/dmd/dtemplate.d index 5d40e353f57..3e8f34b6270 100644 --- a/src/dmd/dtemplate.d +++ b/src/dmd/dtemplate.d @@ -3248,25 +3248,29 @@ private MATCH deduceTypeHelper(Type t, Type* at, Type tparam) *at = t.mutableOf().unSharedOf(); return MATCH.exact; } + case X(MODFlags.const_, MODFlags.shared_ | MODFlags.const_): + case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild): + case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst): + // foo(const(U)) shared(const(T)) => shared(T) + // foo(inout(U)) shared(inout(T)) => shared(T) + // foo(inout(const(U))) shared(inout(const(T))) => shared(T) + { + *at = t.mutableOf(); + return MATCH.exact; + } case X(MODFlags.const_, 0): case X(MODFlags.const_, MODFlags.wild): case X(MODFlags.const_, MODFlags.wildconst): - case X(MODFlags.const_, MODFlags.shared_ | MODFlags.const_): case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wild): case X(MODFlags.const_, MODFlags.shared_ | MODFlags.wildconst): case X(MODFlags.const_, MODFlags.immutable_): - case X(MODFlags.wild, MODFlags.shared_ | MODFlags.wild): - case X(MODFlags.wildconst, MODFlags.shared_ | MODFlags.wildconst): case X(MODFlags.shared_ | MODFlags.const_, MODFlags.immutable_): // foo(const(U)) T => T // foo(const(U)) inout(T) => T // foo(const(U)) inout(const(T)) => T - // foo(const(U)) shared(const(T)) => shared(T) // foo(const(U)) shared(inout(T)) => shared(T) // foo(const(U)) shared(inout(const(T))) => shared(T) // foo(const(U)) immutable(T) => T - // foo(inout(U)) shared(inout(T)) => shared(T) - // foo(inout(const(U))) shared(inout(const(T))) => shared(T) // foo(shared(const(U))) immutable(T) => T { *at = t.mutableOf(); diff --git a/test/compilable/test20138.d b/test/compilable/test20138.d index fb915d8c296..a470039be47 100644 --- a/test/compilable/test20138.d +++ b/test/compilable/test20138.d @@ -10,3 +10,8 @@ static assert(is(shared(I) == shared U, U) && is(U == I)); alias IC = inout const int; static assert(is(shared(IC) U == shared U) && is(U == IC)); static assert(is(shared(IC) == shared U, U) && is(U == IC)); + +alias S = shared int; +static assert(is(const(S) U == const U) && is(U == shared int)); +static assert(is(inout(S) U == inout U) && is(U == shared int)); +static assert(is(inout(const S) U == inout(const U)) && is(U == shared int)); From 98d27f2574b09869236182dc503f44af4a1389bc Mon Sep 17 00:00:00 2001 From: aG0aep6G Date: Mon, 19 Aug 2019 15:36:31 +0200 Subject: [PATCH 3/4] remove stray newline --- test/compilable/test20138.d | 1 - 1 file changed, 1 deletion(-) diff --git a/test/compilable/test20138.d b/test/compilable/test20138.d index a470039be47..f4626aefbe5 100644 --- a/test/compilable/test20138.d +++ b/test/compilable/test20138.d @@ -2,7 +2,6 @@ alias C = const int; static assert(is(shared(C) U == shared U) && is(U == C)); static assert(is(shared(C) == shared U, U) && is(U == C)); - alias I = inout int; static assert(is(shared(I) U == shared U) && is(U == I)); static assert(is(shared(I) == shared U, U) && is(U == I)); From cc9b34c49edb1b3e012294c0fbbbcf605369c5eb Mon Sep 17 00:00:00 2001 From: aG0aep6G Date: Mon, 19 Aug 2019 15:37:25 +0200 Subject: [PATCH 4/4] add changelog entry for issue 20138 --- changelog/isexpression-const-inout-shared.dd | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 changelog/isexpression-const-inout-shared.dd diff --git a/changelog/isexpression-const-inout-shared.dd b/changelog/isexpression-const-inout-shared.dd new file mode 100644 index 00000000000..dd82e475efe --- /dev/null +++ b/changelog/isexpression-const-inout-shared.dd @@ -0,0 +1,22 @@ +$(I IsExpression)s now correctly match combinations of `const`, `inout`, and `shared`. + +With $(BUGZILLA 20138) fixed, +$(LINK2 $(ROOT_DIR)spec/expression.html#is_expression, $(I IsExpression)s) now +correctly match combinations of the qualifiers `const`, `inout`, and `shared`. + +Examples that failed previously but pass now: + +---- +static assert(is(shared(const int) U == shared U) && is(U == const int)); +static assert(is(shared(inout int) U == inout U) && is(U == shared int)); +---- + +Note that the behavior of code like the following changes: + +---- +static if (is(T U == const U) { ...} +else static if (is(T U == shared const U)) { ... } +---- + +The second case will never be reached, because the first one now matches when +`T` is `shared const`. To get the old behavior, switch the order.