eclipse-archived / ceylon

The Ceylon compiler, language module, and command line tools
http://ceylon-lang.org
Apache License 2.0
398 stars 62 forks source link

Warn when type parameter inferred to be Nothing #7384

Open kingjon3377 opened 6 years ago

kingjon3377 commented 6 years ago

I've just spent about an hour tracking down a bug where I was narrowing an Iterable to a type parameter, which it turned out the compiler was inferring to be Nothing. On the rare occasions that I want a type parameter to be Nothing, I always explicitly specify it (either as the default at the definition site, or at the caller), so it would be helpful to me if the compiler would print a warning anytime it inferred a type parameter (or perhaps a type more generally) to be Nothing, similar to the warning it gives about the value nothing or functions or values having the type Nothing.

RossTate commented 6 years ago

Out of curiosity, what was the use case (if it can be shared)?

kingjon3377 commented 6 years ago

The code where the type parameter was incorrectly inferred to be Nothing is in this code to read tab-separated data from a file embedded in the module as a resource:

object fileSplitter {
    {String+} splitOnFirstTab(String line) => line.split('\t'.equals, true, true, 1);
    String->Type lineToEntry<Type>({String+} line, Type(String) factory) =>
        line.first->factory(line.rest.first else "");
    shared Map<String, Type> getFileContents<Type, BroaderType=Type>(String filename,
            BroaderType(String) factory) given Type satisfies BroaderType {
        assert (exists textContent =
            readFileContents(`module strategicprimer.model`, filename));
        return map(textContent.split('\n'.equals).map(splitOnFirstTab)
            .map(shuffle(curry(lineToEntry<BroaderType>))(factory)).narrow<String->Type>());
    }
}

Before I made the type parameter explicit in my commit kingjon3377/strategicprimer-viewer@e2eb545dafe2d165f5949718564143ceec6fcde8, code calling fileSplitter.getFileContents would compile but return an empty Map.

(If you meant my use case for wanting the type parameter to be Nothing, it's a function that asks the user a yes-or-no question, but allows the user to answer "always" or "never" to have future calls automatically return true or false without further interaction, and in some cases allows "quit"; its signature is Boolean|Absent inputBooleanInSeries<Absent=Nothing>(String prompt, <Absent|Boolean?>(String) quitResultFactory).)

RossTate commented 6 years ago

Thanks! That's quite informative.