google / google/closure-compiler
Class templates shadow method templates
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
I noticed the following lines in `FunctionTypeBuilder#inferTemplateTypeName`:
```java
ImmutableList.Builder builder = ImmutableList.builder();
builder.addAll(templateTypeNames) // @templates from method's JSDoc
builder.addAll(ownerTypeKeys) // @templates from class's JSDoc
```
This is incorrect - it means that if a class template name is reused on a method, the method one is ignored, which is very surprising. It *should* be a trivial matter to just switch the order of these methods, but unfortunately this breaks `TypeCheckTest#testTemplateType7` and exposes a problem with how we unify generics.
In short, the externs (both prod and test) are written as follows (abbreviated):
```js
/**
* @constructor
* @template T
*/
function Array() {}
/**
* @param {...(T|undefined)} var_args
* @this {IArrayLike}
* @template T
*/
Array.prototype.push = function(var_args) {};
```
Fixing this issue means that the `T` in the `push` extern now refers to a different template type than the one in the class, which should be fine, except that it basically makes type checking this method worthless. The broken test expects an error from
```js
var /** !Array */ query = [];
query.push(1);
```
but with this change, it simply infers `T=(string|number)` and doesn't give an error. IIRC, NTI did this correctly. I'd like to clean up the unification algorithm in OTI, but until then, it's probably better not to stir the pot by "fixing" this shadowing bug.
Contributor guide
Assessment
This issue has not been assessed yet.