Skip to content

Error when variable is circularly referenced in type annotation #2991

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

Merged
merged 9 commits into from
May 5, 2015

Conversation

ahejlsberg
Copy link
Member

Fixes #2980.

@mhegazy
Copy link
Contributor

mhegazy commented May 1, 2015

👍

error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
// Variable has type annotation that circularly references the variable itself
links.type = unknownType;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the unknown type here as opposed to the 'any' type? What's the mental model i should use for when i should use the 'unknown' type? Thanks! (also a comment in the code explaining this would be useful).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is always an error, i.e. it is something that does not make sense. the other one, the compiler sets to any as it could not find a better type (because of the self reference). the second case is not an error, it is the expected behavior, it is just that if you have --noImplictAny, the compiler warns about cases when it silently gives things an any type.

@ahejlsberg
Copy link
Member Author

Hmm, turns out my fix only fixes it for the first repro in #2980. This one is still an issue:

var varOfAliasedType = func();
function func(): typeAlias { return null; }
type typeAlias = typeof varOfAliasedType;

No error is reported for the example above (and varOfAliasedType is given type any). However, if the first two lines are reversed an error is reported.

The core issue is that we have two rules that are fundamentally at odds: We say variables that circularly reference themselves in their initializers are given type any without an error, whereas type aliases that circularly reference themselves are an error. Depending on which we check first we either get an error or we don't, and then because we cache we don't see the circularity in the second check.

@ahejlsberg
Copy link
Member Author

Latest commits improve circularity detection such that errors are reported on each declaration in a circular chain. This fixes the order dependency issues and also makes it easier for the user to understand the circular causality.

// a new entry with that target and an associated result value of true is pushed on the stack, and the value
// true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
// all entries pushed after it are changed to false, and the value false is returned. The target object has
// no significance other than to provide a unique identity for a particular type resolution result.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice comment! Very clear!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually can you write it in docComment format so that quick info and signature help will display it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to keep it in this format to stay consistent with the rest of the code base.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the comment formats have to be consistent at the expense of usability, but very well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really we should be using doc comments above every function, and every little bit helps.

@JsonFreeman
Copy link
Contributor

I just thought of something interesting, an alternate way to fix this issue. I'm not sure if it's simpler, or if it even works, but it's more similar to the old model, where we track cycles by using the resolvingType sentinel. The idea is this: When chasing references, we would essentially allow the cycle to go through twice. On the first reentry, we detect the reentry, and give an error or not, depending on whether it's a variable initializer. But we allow the recursion to keep going so that we repeat every part of the cycle at least once. On the second reentry, we stop the recursion, and return back out. I'm wondering if this is a cleaner solution.

@JsonFreeman
Copy link
Contributor

This idea would require two sentinel objects, but I think it is simple, and does not rely on us having to be so careful about what object we are passing to the pushTypeResolution method.

@ahejlsberg
Copy link
Member Author

You could probably make something like that work but I doubt it would be simpler. Plus it is technically not in the spirit of lazy initialization of an immutable value because the value actually goes through an observable sequence of changes. I think what we have now is the right solution--or certainly right enough.

ahejlsberg added a commit that referenced this pull request May 5, 2015
Error when variable is circularly referenced in type annotation
@ahejlsberg ahejlsberg merged commit 7b860f5 into master May 5, 2015
@ahejlsberg ahejlsberg deleted the circularVar branch May 5, 2015 20:07
@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
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Type alias circular reference is not detected
6 participants