google / google/closure-compiler

Class templates shadow method templates

Open
#2,973 2 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.