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

Start deprecation period of identical functions in a single module #8429

Merged
merged 6 commits into from
Sep 22, 2020

Conversation

wilzbach
Copy link
Member

@wilzbach wilzbach commented Jul 1, 2018

Initially started in #7577, but reverted in #7969 due to the immediate 2.079 release and a reported issue for it (https://issues.dlang.org/show_bug.cgi?id=18385).

This now officially starts the deprecation period of identical functions in a single module.

The examples provided in 18385 are:

extern (C):

void foo(int) { }
void foo(double) { }

struct S
{
    static void foo(int) {}
    static void foo(double) {}
}

They clearly can't work because the mangling of these functions is the same.
The deprecation period is ten releases after the new deprecation DIP.

Note that the following will still work:

extern (C):

void foo(int) { }
extern(D) void foo(double) { } // OK as it has a different mangling

or:

extern (C):

void foo(int) { }
void foo(double); // duplicate declarations are allowed

See also: #8428

@dlang-bot
Copy link
Contributor

dlang-bot commented Jul 1, 2018

Thanks for your pull request, @wilzbach!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#8429"

@wilzbach wilzbach force-pushed the duplicate-declaration branch from d52e5be to d9ec356 Compare July 1, 2018 21:57
@WalterBright
Copy link
Member

There's the issue of:

void foo();
void foo() { ... }

This is a common pattern in C, should it be allowed in D?

@wilzbach wilzbach force-pushed the duplicate-declaration branch from d9ec356 to 47e756e Compare July 2, 2018 01:50
@wilzbach
Copy link
Member Author

wilzbach commented Jul 2, 2018

This is a common pattern in C, should it be allowed in D?

I don't see a reason to forbid it. Note that this PR doesn't touch this part (see the tests for examples), it will only trigger a deprecation warning when the mangling of two function is equivalent AND both have a body.

@jacob-carlborg
Copy link
Contributor

It's been previously stated that when D interfaces with another language it should follow it's own overloading and lookup rules. Otherwise we would need implement argument dependent lookup for extern(C++) functions.

One use case I could see would be to add overloads so that the D binding allows passing the same values as the C function would allow without requiring casts. For example:

extern (C) void foo(bool);
extern (C) void foo(int);

foo(true);
foo(1);

@jacob-carlborg
Copy link
Contributor

Another use case is, not sure if you're changes cover that:

template Metaclass
{
    extern (Objective-C) interface Class
    {
        extern (C) pragma(mangle, "objc_lookUpClass") static typeof(this) objc_lookUpClass(const(char)* name);
    }
}

extern (Objective-C) NSObject
{
    mixin Metaclass;
}

extern (Objective-C) NSObject
{
    mixin Metaclass;
}

Otherwise calling objc_lookUpClass always requires a cast.

@wilzbach
Copy link
Member Author

wilzbach commented Jul 2, 2018

@jacob-carlborg having duplicate declarations is still completely legal (a previous version of this push tried to deprecate this too, but druntime abused this pattern too).
This PR is just about having two duplicate implementation in the same module.

Another use case is, not sure if you're changes cover that:

Yep that shouldn't be affected by this change, but note that if you meant to add "class" there, having two duplicate classes of the same name was already restricted before this PR: https://run.dlang.io/is/74BDoy

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Jul 2, 2018

This PR is just about having two duplicate implementation in the same module.

Aha, ok. Then I'm fine.

@jacob-carlborg
Copy link
Contributor

I'm a bit unclear on the process, when do we add a changelog entry?

@wilzbach wilzbach force-pushed the duplicate-declaration branch from 47e756e to 85cc64a Compare July 2, 2018 08:51
@wilzbach
Copy link
Member Author

wilzbach commented Jul 2, 2018

I'm a bit unclear on the process, when do we add a changelog entry?

Sorry. I expected more outcry / request for changes on this one. Added the changelog entry now.

@jacob-carlborg
Copy link
Contributor

Is Jenkins disabled? DWT might be affected. But since it’s only a deprecation I think it shouldn’t be a problem.

@wilzbach wilzbach added the Merge:72h no objection -> merge The PR will be merged if there are no objections raised. label Jul 3, 2018
@wilzbach wilzbach force-pushed the duplicate-declaration branch 4 times, most recently from d4e3895 to 80e3ce2 Compare July 8, 2018 22:11
@wilzbach
Copy link
Member Author

wilzbach commented Jul 8, 2018

Is Jenkins disabled? DWT might be affected. But since it’s only a deprecation I think it shouldn’t be a problem.

Yep it's running again, but here's what I locally get:

org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(397,7): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLayoutLine.is_paragraph_start` function org.eclipse.swt.internal.c.pango._PangoLayoutLine.is_paragraph_start(uint v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(394,7)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(398,7): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLayoutLine.resolved_dir` function org.eclipse.swt.internal.c.pango._PangoLayoutLine.resolved_dir(uint v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(395,7)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(524,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_line_break` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_line_break(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(512,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(525,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_mandatory_break` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_mandatory_break(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(513,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(526,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_char_break` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_char_break(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(514,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(527,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_white` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_white(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(515,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(528,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_cursor_position` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_cursor_position(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(516,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(529,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_word_start` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_word_start(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(517,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(530,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_word_end` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_word_end(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(518,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(531,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_boundary` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_boundary(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(519,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(532,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_start` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_start(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(520,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(533,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_end` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_sentence_end(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(521,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(534,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.backspace_deletes_character` function org.eclipse.swt.internal.c.pango._PangoLogAttr.backspace_deletes_character(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(522,6)
org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(535,6): Deprecation: function `org.eclipse.swt.internal.c.pango._PangoLogAttr.is_expandable_space` function org.eclipse.swt.internal.c.pango._PangoLogAttr.is_expandable_space(bool v) cannot be overloaded with another extern(C) function at org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/internal/c/pango.d(523,6)
---
ERROR: This is a compiler bug.
Please report it via https://issues.dlang.org/enter_bug.cgi
with, preferably, a reduced, reproducible example and the information below.
DustMite (https://github.com/CyberShadow/DustMite/wiki) can help with the reduction.
---
DMD v2.081.1-beta.1-186-gd4e3895ee
predefs   VibeCustomMain Have_dwt Have_dwt_base DigitalMars Posix linux ELFv1 LittleEndian D_Version2 all D_SIMD D_InlineAsm_X86_64 X86_64 CRuntime_Glibc D_LP64 D_PIC unittest assert D_HardFloat
binary    /home/seb/dlang/dmd/generated/linux/release/64/dmd
version   v2.081.1-beta.1-186-gd4e3895ee
config    /home/seb/dlang/dmd/generated/linux/release/64/dmd.conf
DFLAGS    -I/home/seb/dlang/dmd/generated/linux/release/64/../../../../../druntime/import -I/home/seb/dlang/dmd/generated/linux/release/64/../../../../../phobos -L-L/home/seb/dlang/dmd/generated/linux/release/64/../../../../../phobos/generated/linux/release/64 -L--export-dynamic -fPIC
---
core.exception.AssertError@dmd/glue.d(774): Assertion failure
----------------
??:? _d_assertp [0x559d1005]
dmd/glue.d:774 _Z25FuncDeclaration_toObjFileP15FuncDeclarationb [0x558f3f0c]
dmd/toobj.d:312 _ZN9toObjFile9ToObjFile5visitEP15FuncDeclaration [0x55901eb0]
dmd/func.d:2369 _ZN15FuncDeclaration6acceptEP7Visitor [0x5584c8d9]
dmd/toobj.d:526 _ZN9toObjFile9ToObjFile5visitEP17StructDeclaration [0x5590264c]
dmd/dstruct.d:589 _ZN17StructDeclaration6acceptEP7Visitor [0x557e8e65]
dmd/toobj.d:731 _ZN9toObjFile9ToObjFile5visitEP17AttribDeclaration [0x55902d01]
dmd/parsetimevisitor.d:67 _ZN16ParseTimeVisitorI10ASTCodegenE5visitEP15LinkDeclaration [0x558d2a4a]
dmd/attrib.d:469 _ZN15LinkDeclaration6acceptEP7Visitor [0x55790205]
dmd/toobj.d:1025 _Z9toObjFileP7Dsymbolb [0x55901e19]
dmd/glue.d:403 _Z10genObjFileP6Moduleb [0x558f3739]
dmd/mars.d:927 int dmd.mars.tryMain(ulong, const(char)**) [0x558855ca]
dmd/mars.d:1078 _Dmain [0x55885f9a]

I will have a look into the segfault, but the deprecations messages are legit as C doesn't mangle its parameters. Try an objdump on this minimal example:

long bitfield;

extern(C):
auto is_paragraph_start(){ return ( bitfield >> 0 ) & 0x01; }
auto is_paragraph_start(uint v ){ bitfield &= ~( 0x01 << 0 ); bitfield |= ( v & 0x01 ) << 0; return is_paragraph_start(); }
``

@jacob-carlborg
Copy link
Contributor

I think there are several functions that have no reason to be extern(C)

@JinShil JinShil removed the Merge:72h no objection -> merge The PR will be merged if there are no objections raised. label Jul 10, 2018
@JinShil
Copy link
Contributor

JinShil commented Jul 10, 2018

Removed the "72h no object -> merge" label as it was applied 7 days ago and this isn't passing the auto tester or Jenkins. I deprecated the auto tester failing test, so let's see if it passes.

@JinShil
Copy link
Contributor

JinShil commented Jul 11, 2018

I'm itching to merge this, but what's going on with Jenkins right now?

@Geod24
Copy link
Member

Geod24 commented Jul 11, 2018

Failure is definitely related, as @wilzbach mentioned above:

core.exception.AssertError@dmd/glue.d(774): Assertion failure
----------------
??:? _d_assertp [0x7500d5]
dmd/glue.d:774 _Z25FuncDeclaration_toObjFileP15FuncDeclarationb [0x673534]
dmd/toobj.d:312 _ZN9toObjFile9ToObjFile5visitEP15FuncDeclaration [0x6814d8]
dmd/func.d:2369 _ZN15FuncDeclaration6acceptEP7Visitor [0x5cd001]
dmd/toobj.d:526 _ZN9toObjFile9ToObjFile5visitEP17StructDeclaration [0x681c74]
dmd/dstruct.d:589 _ZN17StructDeclaration6acceptEP7Visitor [0x56a031]
dmd/toobj.d:1025 _Z9toObjFileP7Dsymbolb [0x681441]
dmd/glue.d:403 _Z10genObjFileP6Moduleb [0x672d61]
dmd/glue.d:156 _Z18obj_write_deferredP7Library [0x6723b4]
dmd/mars.d:947 int dmd.mars.tryMain(ulong, const(char)**) [0x6055b8]
dmd/mars.d:1078 _Dmain [0x605dca]
/var/lib/jenkins/dlang_projects@7/distribution/bin/dmd failed with exit code 1.
script returned exit code 2

@jacob-carlborg
Copy link
Contributor

Should I wait with updating DWT?

@wilzbach
Copy link
Member Author

No feel free to update DWT. Once I have time for this, I will manage to reproduce the segfault from DWT, reduce it and it to the testsuite anyhow.

@JohanEngelen
Copy link
Contributor

Is there another PR for updating the spec?

@MoonlightSentinel
Copy link
Contributor

Thanks!

Copy link
Member

@ibuclaw ibuclaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it won't supplant the existing checks that gdc (and I assume ldc too for the same reason) in the code-gen layer that look for duplication of mangling, and issue a duplicate definition error.

@MoonlightSentinel
Copy link
Contributor

MoonlightSentinel commented Sep 21, 2020

Also not really happy about this deprecation, but if it allows projects a more pleasant transition ...

Should we already define a release for the end of the deprecation and mention it in the error message? (e.g. 2.104)

Copy link
Member

@Geod24 Geod24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, few comments

changelog/duplicate-implementations-deprecation.dd Outdated Show resolved Hide resolved
changelog/duplicate-implementations-deprecation.dd Outdated Show resolved Hide resolved
changelog/duplicate-implementations-deprecation.dd Outdated Show resolved Hide resolved
changelog/duplicate-implementations-deprecation.dd Outdated Show resolved Hide resolved
changelog/duplicate-implementations-deprecation.dd Outdated Show resolved Hide resolved
src/dmd/semantic2.d Outdated Show resolved Hide resolved
fail_compilation/fail2789.d(67): Error: function `fail2789.f_ExternC1()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(66)
fail_compilation/fail2789.d(70): Error: function `fail2789.f_ExternC2(int)` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(69)
fail_compilation/fail2789.d(73): Error: function `fail2789.f_ExternC3()` cannot be overloaded with another `extern(C)` function at fail_compilation/fail2789.d(72)
fail_compilation/fail2789.d(67): Error: function `fail2789.f_ExternC1()` conflicts with previous declaration at fail_compilation\fail2789.d(66)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note, why isn't the file name / line highlighted ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping @MoonlightSentinel . And why the backslash ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because Locs are usually not highlighted in error messages (but we could change that in another PR).

Replaced the backslash

struct S
{
static void foo(int) {}
static void foo(double) {}
Copy link
Contributor

@jacob-carlborg jacob-carlborg Sep 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remind me why this shouldn't be allowed? These two symbols are part of a struct and therefore will get mangled as D symbols, even though the linkage is extern (C).

The changelog entry says: "Note that this change is only relevant for mangling schemes that do no support
overloading". The D mangling scheme does support overloading. Obviously the implementation is not looking at the mangled name when deciding if it should issue a deprecation message or not. Make up your minds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed above, the current behaviour of extern(C) not changing the mangling inside of a struct is a bug because the function still adheres to the C ABI.

The current implementation could cater for that special case but I don't think that it should. Having the deprecation now will allow for a smoother transition when fixing extern(C) inside structs.

@MoonlightSentinel
Copy link
Contributor

@Geod24 Rewrote the changelog and improved the deprecation message.

@BorisCarvajal
Copy link
Member

This pull destroyed compiler diagnostic for conflicts in overload sets created by aliases.

void bar (int s) {}
void foo (int s) {}
alias bar = foo;

void main ()
{
   bar(0);
}

before:

test.d(7): Error: test.foo called with argument types (int) matches both:
test.d(1):     test.foo(int s)
and:
test.d(2):     test.bar(int s)

now:
test.d(2): Error: function test.bar(int s) conflicts with previous declaration at test.d(1)

@rainers
Copy link
Member

rainers commented Dec 26, 2020

When compiling Visual D with 2.095-beta1 I get a lot of deprecation messages due to this change:

  • using std.bitmanip.bitfields with structs compiled as "extern(C)" (from translated Win/VS SDK headers) complain:
import std.bitmanip;
extern(C) struct S
{
	mixin(bitfields!(uint,"cloneGroupId", 16 , uint,"sourceModeInfoIdx", 16));
}
bit.d-mixin-6(7): Deprecation: function bit.S.cloneGroupId cannot overload extern(C) function at bit.d-mixin-6(6)
bit.d-mixin-6(9): Deprecation: function bit.S.sourceModeInfoIdx cannot overload extern(C) function at bit.d-mixin-6(8)
  • classes implementing IUnknown are automatically extern(Windows), and every overload is now deprecated, even for ctors:
interface IUnknown {}
class C : IUnknown
{
	this() {}
	this(int) {}
	
	void fun(int) {}
	void fun(string) {}
}
bit.d(5): Deprecation: constructor bit.C.this cannot overload extern(Windows) function at bit.d(4)
bit.d(8): Deprecation: function bit.C.fun cannot overload extern(Windows) function at bit.d(7)

Is this expected even for non-static member functions?

@jacob-carlborg
Copy link
Contributor

When compiling Visual D with 2.095-beta1 I get a lot of deprecation messages due to this change:

I have the same problem with some of my projects. The reason for the change was to remove the mangling of extern(C) methods and make the transition smoother: #8429 (comment).

But then everyone changed their mind when it comes to remove the actual mangling: #11786.

I don't know what's going on here, it's a mess.

@jacob-carlborg
Copy link
Contributor

Is this expected even for non-static member functions?

The code is probably just looking at the linkage and not the actual mangling.

@MoonlightSentinel
Copy link
Contributor

I'll have a look

@rainers
Copy link
Member

rainers commented Dec 26, 2020

I'm fine with the change for functions with identical mangling. So the change is good for free functions, not so sure about static member functions (with changed mangling), but non-static member functions are not a thing in C, so don't have to obey the same ABI anyway.

@MoonlightSentinel
Copy link
Contributor

This pull destroyed compiler diagnostic for conflicts in overload sets created by aliases.

The false positive hides the actual error. Fix #12053

But then everyone changed their mind when it comes to remove the actual mangling: #11786

Fix to accept the name mangling for (static) member funtions: #12054

UplinkCoder pushed a commit to UplinkCoder/dmd that referenced this pull request Jan 5, 2021
…lang#8429)

Start deprecation period of identical functions in a single module
merged-on-behalf-of: unknown
@ibuclaw
Copy link
Member

ibuclaw commented Dec 26, 2022

This PR caused a regression: https://issues.dlang.org/show_bug.cgi?id=22975

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.