compiler warnings for unconditional recursive calls

  • Thread starter Thread starter cody
  • Start date Start date
C

cody

Why doesn't the compiler give me any warning if it encounters code like
the following:

void foo()
{
// some code here
// foo() ist not nested in a pre-condition loop, some if- or
else- // block and no return statement appears before it.
foo();
}

The compiler should recognize something like that, shouldn't it?
 
cody said:
Why doesn't the compiler give me any warning if it encounters code like
the following:

void foo()
{
// some code here
// foo() ist not nested in a pre-condition loop, some if- or
else- // block and no return statement appears before it.
foo();
}

The compiler should recognize something like that, shouldn't it?

Well, there's nothing in the C# specification to say that it should.
Your criteria wouldn't be enough anyway - what about performing *any*
operation which could result in an exception (beyond running out of
memory or stack)?

I was slightly surprised to see the other day that this is valid too:

public Test()
: this("hello")
{
}

public Test(string x)
: this()
{
}

I believe that's forbidden in Java (I should check it, but I'm too
tired) but that recursive unconditional calls aren't.
 
Hey Jon, you are lightning fast as always :)
comments inline!
Well, there's nothing in the C# specification to say that it should.
Your criteria wouldn't be enough anyway - what about performing *any*
operation which could result in an exception (beyond running out of
memory or stack)?

You are right, an exception could terminate the thing, but I wouldn't
consider it good style, so a warning wouldn't do any harm (if somebody
really wants he can disable this warning for this specific method).

I was slightly surprised to see the other day that this is valid too:

public Test()
: this("hello")
{
}

public Test(string x)
: this()
{
}

I believe that's forbidden in Java (I should check it, but I'm too
tired) but that recursive unconditional calls aren't.

This is very funny. Why is it allowed? This way your class is better
protected from instantiation then by declaring its ctors private :)

Even throwing an Exception from within the ctors doesn't help here
because that code is never reached..
Even if the throw() would be executed before the constructor chaining
then the Exception would also prevent instantiation.

So theoretically the Compiler should warn us:
- That the class can never be instantiated
- The be have unconditional recursion
- That we have unreachable code (when constructors are not empty)
But in reality: Not a single warning.

So you can do nothing with it, besides calling non-void static methods
in the this() call:

public Test()
: this(StaticFunction("hello"))
{
}

Very interesting. If Anders Heijlson and his team thought about this
case while developing the Language?
 
cody said:
You are right, an exception could terminate the thing, but I wouldn't
consider it good style, so a warning wouldn't do any harm (if somebody
really wants he can disable this warning for this specific method).

Hmm... I don't like that kind of warning. I very rarely need to do
anything other than fix my code in order to avoid warnings.

The larger issue, IMO, is the extra specification required in order to
determine what the compiler should do. Just as with the case of
definite assignment, there are bound to be quite a lot of corner cases
to consider...

This is very funny. Why is it allowed? This way your class is better
protected from instantiation then by declaring its ctors private :)

Even throwing an Exception from within the ctors doesn't help here
because that code is never reached..
Even if the throw() would be executed before the constructor chaining
then the Exception would also prevent instantiation.

Indeed. That one's very nasty.
So theoretically the Compiler should warn us:
- That the class can never be instantiated
- The be have unconditional recursion
- That we have unreachable code (when constructors are not empty)
But in reality: Not a single warning.

So you can do nothing with it, besides calling non-void static methods
in the this() call:

public Test()
: this(StaticFunction("hello"))
{
}

Very interesting. If Anders Heijlson and his team thought about this
case while developing the Language?

Not sure - I'll try to find out though. Fortunately it's such a
fundamental problem that if your unit tests *ever* call any of the
cyclical constructors, you're bound to find it very quickly. And yes,
that's exactly how I found mine :)
 
Why doesn't the compiler give me any warning if it encounters code like
the following:

void foo()
{
// some code here
// foo() ist not nested in a pre-condition loop, some if- or
else- // block and no return statement appears before it.
foo();

}

The compiler should recognize something like that, shouldn't it?

Why? It's perfectly cromulant code. Useless, but not in any way
syntactically or grammatically incorrect.
 
cody said:
Why doesn't the compiler give me any warning if it encounters code like
the following:

void foo()
{
// some code here
// foo() ist not nested in a pre-condition loop, some if- or else-
// block and no return statement appears before it.
foo();
}

The compiler should recognize something like that, shouldn't it?

Why? The general case of determining whether code terminates is inhaously
hard (the "halting problem"), and the few specific cases a compiler might be
able to detect are such a timy minority it doesn't seem worth it. If you
really do need to be sure that a method terminates consider implementing a
loop variant of some sort (they're already in Spec#:
http://channel9.msdn.com/wiki/default.aspx/SpecSharp.LoopVariants). If you
really /really/ need to be sure that a method terminates, you probably
shouldn't be using C# but rather something formal like SPARK.
(http://www.praxis-his.com/sparkada/).
 
Back
Top