You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When you create a constant with an non-existent type, and refer to it in another constant, you get an assertion failed error. The compilation would fail either way of course, but since the assertion failure provides no additional information without inspecting the source it's a bit of a hassle to debug. In our case it was just a typo in the type name.
Did a little bit of digging in the source and found out what's going on:
We're failing an assertion in the compilation stage because it thinks that the type of INNER is void
// in compiler.ts// when compiling the INNER identifier used by OUTERif(!this.compileGlobal(<Global>target)){// reports; not yet compiled if a static fieldreturnmodule.unreachable();}lettype=(<Global>target).type;assert(type!=Type.void);//This assertion fails because the type is void
The type ends up being void because of the behaviour of the compileGlobal function:
compileGlobal(global: Global): bool{console.log(global.name)if(global.is(CommonFlags.COMPILED))returntrue;global.set(CommonFlags.COMPILED);assert(global.type==Type.void);//The default type is voidvarmodule=this.module;varinitExpr: ExpressionRef=0;vartypeNode=global.typeNode;varinitializerNode=global.initializerNode;if(!global.is(CommonFlags.RESOLVED)){// Resolve type if annotatedif(typeNode){letresolvedType=this.resolver.resolveType(typeNode,global.parent);// reportsif(!resolvedType)returnfalse;//We get here, fail to resolve the type, and return before setting the type
The false value is then propagated to this statement and is ignored:
caseNodeKind.VARIABLE: {letdeclarations=(<VariableStatement>statement).declarations;for(leti=0,k=declarations.length;i<k;++i){letelement=this.program.getElementByDeclaration(declarations[i]);if(element){assert(element.kind==ElementKind.GLOBAL);if(!element.is(CommonFlags.AMBIENT)&&// delay imports!element.hasDecorator(DecoratorFlags.LAZY))this.compileGlobal(<Global>element);//Here we get false back, and ignore it}}break;}
So we're left with a global with type void despite it actually being of an unresolved type.
I have some questions before looking into this further:
Why doesn't compilation fail when we fail to resolve the type of the global? Are we assuming that the type will be resolved at some point in the future? And if that is a real scenario should we use a special type to represent being not-resolved-yet rather than reusing void?
What is the point of asserting against the void type in compileIdentifierStatement? Wouldn't it just safely fail with a type mismatch later? Here's the output without this assertion for this case:
ERROR TS2304: Cannotfindname'fake'.const INNER: fake=1;~~~~insrc/foo.ts(1,13)ERROR TS2322: Type 'void' is not assignable to type 'i32'.constOUTER: i32=INNER;~~~~~insrc/foo.ts(2,19)
What makes this output nice is that the misspelling is presented in the error output so the user could figure out what they did wrong. The second error is maybe not so clear since INNER being resolved as a void doesn't make any sense to the script author, but it's much better than the current output.
Am I misunderstanding something here?
The text was updated successfully, but these errors were encountered:
If a type isn't found shouldn't it be an any type?
This is the
Also it would be nice edit each assertion to report the range of the error and a simple message. Perhaps I'll take a crack at as I'm sure it'll be useful in the long term and it'll help me understand all the weird edge cases.
When you create a constant with an non-existent type, and refer to it in another constant, you get an assertion failed error. The compilation would fail either way of course, but since the assertion failure provides no additional information without inspecting the source it's a bit of a hassle to debug. In our case it was just a typo in the type name.
Here's a minimal example:
Output upon compilation:
Did a little bit of digging in the source and found out what's going on:
We're failing an assertion in the compilation stage because it thinks that the type of
INNER
isvoid
The type ends up being void because of the behaviour of the compileGlobal function:
The
false
value is then propagated to this statement and is ignored:So we're left with a global with type void despite it actually being of an unresolved type.
I have some questions before looking into this further:
What makes this output nice is that the misspelling is presented in the error output so the user could figure out what they did wrong. The second error is maybe not so clear since INNER being resolved as a void doesn't make any sense to the script author, but it's much better than the current output.
Am I misunderstanding something here?
The text was updated successfully, but these errors were encountered: