Skip to content

Code fails noImplicitAny check under 1.1.0.0 #833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
paf31 opened this issue Oct 6, 2014 · 13 comments
Closed

Code fails noImplicitAny check under 1.1.0.0 #833

paf31 opened this issue Oct 6, 2014 · 13 comments
Labels
Breaking Change Would introduce errors in existing code By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@paf31
Copy link

paf31 commented Oct 6, 2014

This code used to compile without error under 1.0:

module M {

        export interface T<A> {
            get(): A;
        }

        export function ap<A, B>(f: T<(a: A) => B>, x: T<A>): T<B> {
            return {
                get: () => f.get()(x.get())
            };
        }

        export function map<A, B>(f: (a: A) => B, x: T<A>): T<B> {
            return {
                get: () => f(x.get())
            };
        }

        var x: T<number> = {
            get: () => 0
        };

        var test = ap(ap(map((a: number) => (b: number) => (c: number) => {
                return { a: a, b: b, c: c };
            }, x), x), x);
}

However, under 1.1, I get the following error:

(23,37): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.

I don't see any reason why any subexpression of test should have an inferred type of any.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 6, 2014

This is relates to #641 though it is slightly different.

In 1.0 we used to suppress contextual type propagation for return expression if there are any type annotation on a parameter. so in (c:number) => {} we ignored the contextual type for the return value because c was annotated. in 1.1 we changed that to only do it if you have an explicit return type annotation. the result is that the compiler will try to figure out the contextual type, as the complier is inferring the type for map, that would lead to a cycle, and to break it, the return type will be any.

Note, that this used to happen before in 1.0 as well, but silently. we have added the noImplicitAny reporting for this to give the user some insight in how the compiler is reasoning about the input.

adding an explicit annotation would resolve the issue, also c

var f = (a: number) => (b: number) =>  (c: number) => {
    return { a: a, b: b, c: c };
};
var test = ap(ap(map(f, x), x), x);

another one that would do the trick, but I would not recommend as it is subtle, is using parens around (c:number) => {}, to stop the flow of contextual type.

var test = ap(ap(map((a: number) => (b: number) =>  ((c: number) => {
    return { a: a, b: b, c: c };
}), x), x), x);

@mhegazy mhegazy added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Oct 6, 2014
@paf31
Copy link
Author

paf31 commented Oct 6, 2014

Thanks for the explanation. I would say though that any type system bug which can be fixed by reparenthesizing subexpressions should not be "by design" :)

@mhegazy
Copy link
Contributor

mhegazy commented Oct 6, 2014

I do not believe it is a bug. it is a result of the current design. we have two options, either go into an infinite recursion trying to figure out the type of return statement, or break the loop with some value (any). The parenthesis, is a result of another design decision not to propagate contextual type through expressions, and allowing the user to opt-out of contextual type if they so choose.

@paf31
Copy link
Author

paf31 commented Oct 6, 2014

Where can I find documentation on "contextual types"?

@RyanCavanaugh
Copy link
Member

Section 4.19 of the spec

@danquirk danquirk added the Breaking Change Would introduce errors in existing code label Oct 7, 2014
@mhegazy mhegazy closed this as completed Mar 24, 2015
@zpdDG4gta8XKpMCd
Copy link

is this by design too?

function apply<a, r>(value: a, map: (value: a) => r): r {
    return map(value);
}
function id<a>(value: a) : a { return value; }
var yay = apply(() => ({ x: 0 }), id); // () => any <--- ????


// at the same time

var huh = () => ({ x: 0 }) // () => { x: number } <-- i am all right

// then

function always<a>(value: a): () => a { return () => value; }

var ugh = apply(always({ x: 0 }), id); // () => { x: number } <-- look, i fixed it!

// all this just doesn't make any sense

god, if anything please fix the inference first

@RyanCavanaugh
Copy link
Member

I will let Fred Brooks know that developer time is completely fungible and that it would be plausible to take the intern off his summer project to redesign how generic type inference works.

@paf31
Copy link
Author

paf31 commented Jun 28, 2015

I will let Fred Brooks know that developer time is completely fungible and that it would be plausible to take the intern off his summer project to redesign how generic type inference works.

What is this in response to?

@RyanCavanaugh
Copy link
Member

Aleksey's comment that we should change this instead of doing abstract

@zpdDG4gta8XKpMCd
Copy link

sarcasm, i has it too

seriously, why do new controversial OOP features take precedence over not
working inference let alone anything that supports coding in functional
style?
On Jun 28, 2015 6:20 PM, "Ryan Cavanaugh" notifications@github.com wrote:

Aleksey's comment that we should change this instead of doing abstract


Reply to this email directly or view it on GitHub
#833 (comment)
.

@RyanCavanaugh
Copy link
Member

It's not a matter of precedence.

Choosing not to do abstract will not a) make fixing this any easier or b) free up any resources that are capable of fixing this problem.

@danquirk
Copy link
Member

@Aleksey-Bykov In addition to what's been covered, don't think we haven't spent a lot of time talking about generic type inference over the years. It's not like where inference is now is as far as we thought about it and we just punted on thinking about going any deeper. We'll continually re-evaluate what is and isn't feasible in that part of the system over time, but as Ryan notes, it's not as simple as just choosing to do x instead of y.

@zpdDG4gta8XKpMCd
Copy link

Good to know. Thank you
On Jun 29, 2015 3:43 PM, "Dan Quirk" notifications@github.com wrote:

@Aleksey-Bykov https://github.com/aleksey-bykov In addition to what's
been covered, don't think we haven't spent a lot of time talking about
generic type inference over the years. It's not like where inference is now
is as far as we thought about it and we just punted on thinking about going
any deeper. We'll continually re-evaluate what is and isn't feasible in
that part of the system over time, but as Ryan notes, it's not as simple as
just choosing to do x instead of y.


Reply to this email directly or view it on GitHub
#833 (comment)
.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Breaking Change Would introduce errors in existing code By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

5 participants