Short answer
The return cancel() must return a valid value, but the declaration of the void run() method declares that run() does not return a value; therefore, return cancel() in run() is an error. The return (without expression) attempts to pass control to the caller and is used when the return type is void ; therefore not a mistake.
Long answer
JLS The *return* Statement section claims
A return statement without an Expression expression is trying to transfer control to the calling method or constructor that contains it. [...] The return statement with an expression must be contained in a method declaration declared to return a value (§8.4) or a compile-time error occurs. The expression must denote a variable or value of some type T, or a compile-time error occurs. Type T must be assigned (§5.2) to the declared method result type or a compile-time error has occurred.
The JLS Method Return Type section reads:
The return type of a method declares the type of the value returned by the method if it returns a value, or indicates that the method is invalid. Declaring a method d1 with a return type R1 is a return type-replaceable for another method d2 with a return type R2, if and only if the following conditions are true: [...] * If R1 is invalid, then R2 is invalid.
JLS Types, Values, and Variables chapter , first paragraph reads:
The Java programming language is a strongly typed language, which means that every variable and every expression has a type that is known at compile time. Types limit the values that a variable can hold (§4.12), or what an expression can express, restrict the operations supported by these values, and determine the value of the operations.
The JLS section of The Kinds of Types and Values reads:
There are two types of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, respectively, two types of data values that can be stored in variables, passed as arguments, returned by methods, and work with: primitive values (§4.2) and reference values (§4.3).
A few more quotes. The JLS Expression Statements section reads:
Unlike C and C ++, the Java programming language only allows certain forms of expression to be used. Note that the Java programming language does not allow "cast to void" -void is not a type
The JLS Method Body section reads:
If a method is declared invalid, then its body should not contain any return statement (§14.17) that has an expression.
And finally, the JLS Method Declarations section reads:
A method declaration either indicates the type of value returned by the method, or uses the void keyword to indicate that the method does not return a value.
Now that we are putting it all together, we can infer the following:
- If the
return contains an expression, the expression must be evaluated with a valid value. - The actual value of the
return expression must be a primitive type or a reference type. void not a valid value type.- A method declared with a return type of
void does not return a value. - The
void run() method does not return a value. - In
run() , return , without expression, will happily pass control to the caller. - In
run() , return some expression is an error because some expression must be a valid value, and run() does not return a value.