Missing return statement in a non-void method compiles

I encountered a situation where a non-void method is missing a return statement and the code still compiles. I know that the statements after the while loop are unreachable (dead code) and would never be executed. But why doesn't the compiler even warn about returning something? Or why would a language allow us to have a non-void method having an infinite loop and not returning anything?

public int doNotReturnAnything() {
    while(true) {
        //do something
    }
    //no return statement
}

If I add a break statement (even a conditional one) in the while loop, the compiler complains of the infamous errors: Method does not return a value in Eclipse and Not all code paths return a value in Visual Studio.

public int doNotReturnAnything() {
    while(true) {
        if(mustReturn) break;
        //do something
    }
    //no return statement
}

This is true of both Java and C#.


Solution 1:

Why would a language allow us to have a non-void method having an infinite loop and not returning anything?

The rule for non-void methods is every code path that returns must return a value, and that rule is satisfied in your program: zero out of zero code paths that return do return a value. The rule is not "every non-void method must have a code path that returns".

This enables you to write stub-methods like:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    throw new NotImplementedException(); 
}

That's a non-void method. It has to be a non-void method in order to satisfy the interface. But it seems silly to make this implementation illegal because it does not return anything.

That your method has an unreachable end point because of a goto (remember, a while(true) is just a more pleasant way to write goto) instead of a throw (which is another form of goto) is not relevant.

Why doesn't the compiler even warn about returning something?

Because the compiler has no good evidence that the code is wrong. Someone wrote while(true) and it seems likely that the person who did that knew what they were doing.

Where can I read more about reachability analysis in C#?

See my articles on the subject, here:

ATBG: de facto and de jure reachability

And you might also consider reading the C# specification.

Solution 2:

The Java compiler is smart enough to find the unreachable code ( the code after while loop)

and since its unreachable, there is no point in adding a return statement there (after while ends)

same goes with conditional if

public int get() {
   if(someBoolean) {   
     return 10;
   }
   else {
     return 5;
   }
   // there is no need of say, return 11 here;
}

since the boolean condition someBoolean can only evaluate to either true or false, there is no need to provide a return explicitly after if-else, because that code is unreachable, and Java does not complain about it.

Solution 3:

The compiler knows that the while loop will never stop executing, hence the method will never finish, hence a return statement is not necessary.

Solution 4:

Given your loop is executing on a constant - the compiler knows that it's an infinite loop - meaning the method could never return, anyway.

If you use a variable - the compiler will enforce the rule:

This won't compile:

// Define other methods and classes here
public int doNotReturnAnything() {
    var x = true;

    while(x == true) {
        //do something
    }
    //no return statement - won't compile
}