Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #20763 - Inconsistent handling of type + value in typeof expressions #20798

Merged
merged 2 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -14769,11 +14769,16 @@
return true;
}

// FIXME: Existing code relies on adding / subtracting types in typeof() expressions:
// alias I = ulong; alias U = typeof(I + 1u);
// https://github.com/dlang/dmd/issues/20763
if (op == EXP.add || op == EXP.min)
if ((op == EXP.add || op == EXP.min) && e.isTypeExp())
{
// @@@DEPRECATED_2.121@@@
// Deprecated in 2.111
// In 2.121, remove this branch to let `checkValue` raise the error
deprecation(e.loc, "type `%s` has no value", e.toChars);
thewilsonator marked this conversation as resolved.
Show resolved Hide resolved
if (!e.type.isOpaqueType)
deprecationSupplemental(e.loc, "perhaps use `%s.init`", e.toChars);

Check warning on line 14779 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L14777-L14779

Added lines #L14777 - L14779 were not covered by tests
return false;
}

return e.checkValue();
}
Expand Down Expand Up @@ -14844,6 +14849,8 @@
if (auto te = e.isTypeExp())
{
error(e.loc, "type `%s` has no value", e.toChars());
if (!e.type.isOpaqueType)
errorSupplemental(e.loc, "perhaps use `%s.init`", e.toChars());
return true;
}

Expand Down
12 changes: 12 additions & 0 deletions compiler/src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -7609,6 +7609,18 @@
return false;
}

/// Returns: whether `t` is a struct/class/enum without a body
bool isOpaqueType(Type t)
{
if (auto te = t.isTypeEnum())
return te.sym.members is null;

Check warning on line 7616 in compiler/src/dmd/typesem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/typesem.d#L7616

Added line #L7616 was not covered by tests
if (auto ts = t.isTypeStruct())
return ts.sym.members is null;
if (auto tc = t.isTypeClass())
return tc.sym.members is null;
return false;

Check warning on line 7621 in compiler/src/dmd/typesem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/typesem.d#L7619-L7621

Added lines #L7619 - L7621 were not covered by tests
}


/******************************* Private *****************************************/

Expand Down
7 changes: 4 additions & 3 deletions compiler/test/fail_compilation/b17285.d
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/b17285.d(14): Error: type `ONE` has no value
fail_compilation/b17285.d(14): Error: type `TWO` has no value
fail_compilation/b17285.d(14): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
fail_compilation/b17285.d(15): Error: type `ONE` has no value
fail_compilation/b17285.d(15): perhaps use `ONE.init`
fail_compilation/b17285.d(15): Error: type `TWO` has no value
fail_compilation/b17285.d(15): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
---
*/

Expand Down
3 changes: 2 additions & 1 deletion compiler/test/fail_compilation/ice9545.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
/*
TEST_OUTPUT:
----
fail_compilation/ice9545.d(13): Error: type `int` has no value
fail_compilation/ice9545.d(14): Error: type `int` has no value
fail_compilation/ice9545.d(14): perhaps use `int.init`
----
*/

Expand Down
31 changes: 31 additions & 0 deletions compiler/test/fail_compilation/test20763.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
REQUIRED_ARGS: -de

TEST_OUTPUT:
---
fail_compilation/test20763.d(25): Deprecation: type `ulong` has no value
fail_compilation/test20763.d(25): perhaps use `ulong.init`
fail_compilation/test20763.d(26): Deprecation: type `ulong` has no value
fail_compilation/test20763.d(26): perhaps use `ulong.init`
fail_compilation/test20763.d(27): Error: type `ulong` has no value
fail_compilation/test20763.d(27): perhaps use `ulong.init`
fail_compilation/test20763.d(28): Error: type `ulong` has no value
fail_compilation/test20763.d(28): perhaps use `ulong.init`
fail_compilation/test20763.d(29): Error: type `ulong` has no value
fail_compilation/test20763.d(29): perhaps use `ulong.init`
fail_compilation/test20763.d(30): Error: type `ulong` has no value
fail_compilation/test20763.d(30): perhaps use `ulong.init`
---
*/

// https://github.com/dlang/dmd/issues/20763
void test()
{
alias I = ulong;
alias U0 = typeof(I + 1u);
alias U1 = typeof(1 - I);
alias U2 = typeof(+I);
alias U3 = typeof(I * 1);
alias U4 = typeof(I << 1);
alias U5 = typeof(I | 1);
}
Loading