Re: unimplemented abstract function compiles.

2018-08-13 Thread Jacob Carlborg via Digitalmars-d-learn

On 2018-08-12 19:29, Eric wrote:
I thought it would work the same way as an interface (which must be 
implemented by the direct sub class, otherwise compile error).
But apparently it's possible to implement an abstract function anywhere 
in the class hierarchy. That makes it, in this case, impossible to check 
during compile time.


It will be checked during compile time if the class is referenced during 
compile time. In your example it's not.


The thing is that a library can provide an abstract class which is then 
subclassed and completely implemented by the user of the library. In 
that case you don't want an compile error when you're compiling the 
library but now using the class. One can argue that an abstract class 
always should be marked with "abstract" but that's not currently how the 
language is working.


--
/Jacob Carlborg


Re: unimplemented abstract function compiles.

2018-08-12 Thread ag0aep6g via Digitalmars-d-learn

On 08/12/2018 07:29 PM, Eric wrote:
I thought it would work the same way as an interface (which must be 
implemented by the direct sub class, otherwise compile error).


From the spec text [1], I'd also expect an error. It says: "An abstract 
member function must be overridden by a derived class." And later: 
"Classes become abstract if any of its virtual member functions are 
*declared* abstract or if they are defined within an abstract attribute" 
(emphasis mine).


So, arguably, DMD shouldn't accept your `C` class as abstract. It's not 
marked as abstract itself, and it doesn't have a declaration of an 
abstract method either.


But in cases like this it's more likely that the spec will be changed to 
reflect what DMD does than DMD getting changed to break existing code.


But apparently it's possible to implement an abstract function anywhere 
in the class hierarchy. That makes it, in this case, impossible to check 
during compile time.


You can check it at compile time. The compiler just doesn't do it for 
you proactively. `C` is an abstract class, just like `I` is, and there's 
a trait for that [2]:


static assert(!__traits(isAbstractClass, C));

For nicer syntax, there's also a wrapper around it in std.traits [3]:

import std.traits: isAbstractClass;
static assert(!isAbstractClass!C);

If you want to make sure that your class isn't accidentally abstract, 
you can add an assert like that.



[1] https://dlang.org/spec/attribute.html#abstract
[2] https://dlang.org/spec/traits.html#isAbstractClass
[3] https://dlang.org/phobos/std_traits.html#isAbstractClass


Re: unimplemented abstract function compiles.

2018-08-12 Thread Eric via Digitalmars-d-learn
I thought it would work the same way as an interface (which must 
be implemented by the direct sub class, otherwise compile error).
But apparently it's possible to implement an abstract function 
anywhere in the class hierarchy. That makes it, in this case, 
impossible to check during compile time.


I ran into this while loading objects from a file using 
Object.factory and forgot to implement an abstract function in 
one class.




Re: unimplemented abstract function compiles.

2018-08-11 Thread Nicholas Wilson via Digitalmars-d-learn

On Saturday, 11 August 2018 at 23:12:43 UTC, ag0aep6g wrote:

On 08/11/2018 11:20 PM, rikki cattermole wrote:

On 12/08/2018 8:55 AM, Eric wrote:

Code below compiles while I would not expect it to compile.
Is there a reason that this compiles?

[...]

No bug. You forgot to throw -unittest when you compiled.

[...]

Error: program killed by signal 11


If that's DMD segfaulting, that's definitely a bug.


its not


/tmp/dmd_run2hTpLG(_D9onlineapp17__unittest_L14_C1FZv+0x3a)[0x55d9bba8fe6e]
/tmp/dmd_run2hTpLG(_D9onlineapp9__modtestFZv+0x9)[0x55d9bba8fe81]


That is run.dlang.io running the resulting executable. (I know 
because I've looked a way too many dmd segfaults ;) )


If that's not DMD segfaulting, you're running the program which 
Eric expects not to compile. So there might be a bug (or Eric's 
expectation is wrong).





Re: unimplemented abstract function compiles.

2018-08-11 Thread ag0aep6g via Digitalmars-d-learn

On 08/11/2018 10:55 PM, Eric wrote:

Code below compiles while I would not expect it to compile.
Is there a reason that this compiles?


[...]


class I {
   abstract void f();
}

class C : I {
}

unittest {
   C c = cast(C) Object.factory("C");
   c.f();
}


Not a bug, as far as I see.

You don't get compile-time errors with Object.factory. It works at run 
time, on dynamic values (e.g., a class name entered on the command 
line). You're calling it with a constant string, but the compiler 
doesn't care about that. There's no special handling for that.


Object.factory returns `null` when it can't create the object. And it 
does that in your example, because of the abstract method (and because 
"C" is wrong; the name must be fully qualified). You're supposed to 
check for `null` before attempting to use the object.


If you want a compile-time check, don't use Object.factory. Use `new` 
instead:


C c = new C; /* Error: cannot create instance of abstract class C */


Re: unimplemented abstract function compiles.

2018-08-11 Thread rikki cattermole via Digitalmars-d-learn

On 12/08/2018 11:12 AM, ag0aep6g wrote:

On 08/11/2018 11:20 PM, rikki cattermole wrote:

On 12/08/2018 8:55 AM, Eric wrote:

Code below compiles while I would not expect it to compile.
Is there a reason that this compiles?

[...]

No bug. You forgot to throw -unittest when you compiled.

[...]

Error: program killed by signal 11


If that's DMD segfaulting, that's definitely a bug.

If that's not DMD segfaulting, you're running the program which Eric 
expects not to compile. So there might be a bug (or Eric's expectation 
is wrong).


Eric's is wrong. abstract on a method essentially acts as extern except 
for class methods. Because we're dealing with classes, it won't be hit 
until runtime. Its weird, but at each stage it all kinda makes sense.


Re: unimplemented abstract function compiles.

2018-08-11 Thread ag0aep6g via Digitalmars-d-learn

On 08/11/2018 11:20 PM, rikki cattermole wrote:

On 12/08/2018 8:55 AM, Eric wrote:

Code below compiles while I would not expect it to compile.
Is there a reason that this compiles?

[...]

No bug. You forgot to throw -unittest when you compiled.

[...]

Error: program killed by signal 11


If that's DMD segfaulting, that's definitely a bug.

If that's not DMD segfaulting, you're running the program which Eric 
expects not to compile. So there might be a bug (or Eric's expectation 
is wrong).


Re: unimplemented abstract function compiles.

2018-08-11 Thread rikki cattermole via Digitalmars-d-learn

On 12/08/2018 8:55 AM, Eric wrote:

Code below compiles while I would not expect it to compile.
Is there a reason that this compiles?

Specs are a bit lite on abstract classes.
Only thing I found that would need to allow this is: "19.4 functions 
without bodies" https://dlang.org/spec/function.html#function-declarations

But that's explicitly without the abstract keyword..


class I {
   abstract void f();
}

class C : I {
}

unittest {
   C c = cast(C) Object.factory("C");
   c.f();
}


I also couldn't find anything about this in the issue tracker.


No bug. You forgot to throw -unittest when you compiled.

/tmp/dmd_run2hTpLG(_D4core7runtime18runModuleUnitTestsUZ19unittestSegvHandlerUNbiPSQCk3sys5posix6signal9siginfo_tPvZv+0x38)[0x55d9bba94a40]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x13150)[0x7f970a253150]
/tmp/dmd_run2hTpLG(_D9onlineapp17__unittest_L14_C1FZv+0x3a)[0x55d9bba8fe6e]
/tmp/dmd_run2hTpLG(_D9onlineapp9__modtestFZv+0x9)[0x55d9bba8fe81]
/tmp/dmd_run2hTpLG(_D4core7runtime18runModuleUnitTestsUZ14__foreachbody2MFPS6object10ModuleInfoZi+0x38)[0x55d9bba94a94]
/tmp/dmd_run2hTpLG(_D6object10ModuleInfo7opApplyFMDFPSQBhQBdZiZ9__lambda2MFyPSQCfQCbZi+0x23)[0x55d9bba9098f]
/tmp/dmd_run2hTpLG(_D2rt5minfo17moduleinfos_applyFMDFyPS6object10ModuleInfoZiZ14__foreachbody2MFKSQCz19sections_elf_shared3DSOZi+0x56)[0x55d9bba921ae]
/tmp/dmd_run2hTpLG(_D2rt19sections_elf_shared3DSO7opApplyFMDFKSQBqQBqQyZiZi+0x45)[0x55d9bba9223d]
/tmp/dmd_run2hTpLG(_D2rt5minfo17moduleinfos_applyFMDFyPS6object10ModuleInfoZiZi+0x22)[0x55d9bba9213a]
/tmp/dmd_run2hTpLG(_D6object10ModuleInfo7opApplyFMDFPSQBhQBdZiZi+0x22)[0x55d9bba90966]
/tmp/dmd_run2hTpLG(runModuleUnitTests+0x13e)[0x55d9bba9486a]
/tmp/dmd_run2hTpLG(_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv+0x25)[0x55d9bba90f31]
/tmp/dmd_run2hTpLG(_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv+0x20)[0x55d9bba90eb8]
/tmp/dmd_run2hTpLG(_d_run_main+0x1cf)[0x55d9bba90e23]
/tmp/dmd_run2hTpLG(main+0x22)[0x55d9bba8fea6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f9709a621c1]
/tmp/dmd_run2hTpLG(_start+0x2a)[0x55d9bba8fd4a]
Error: program killed by signal 11