Skip to content
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

Tsickle emits bound this generics which trigger jscompiler whitelist conformance checks #1015

Open
DavidSouther opened this issue Apr 15, 2019 · 6 comments

Comments

@DavidSouther
Copy link

m getting a conformance check error with a generic this value:

/**
 * d3 inverts the `this` ownership. buildD3Handler reverts that, so that the
 * passed method is called in the original context with the d3 value as the
 * input.
 */
export function
buildD3Handler<ContextT, SVGEltT extends SVGElement, BoundObjT extends
                   BoundD3T, HandlerRetT>(
    context: ContextT,
    targetMethod: (svgElt: SVGEltT, boundObj: BoundObjT) => HandlerRetT,
    ): d3.ValueFn<SVGEltT, BoundObjT, HandlerRetT> {
  return function(this: SVGEltT, node: BoundObjT) {
    // Here 'this' is a reference to the D3 DOM Node 
    return targetMethod.call(context, this, node);
  };
}

As far as I can tell, this is sensible:

/**                                                                              
 * d3 inverts the `this` ownership. buildD3Handler reverts that, so that the        
 * passed method is called in the original context with the d3 value as the         
 * input.                                                                        
 * @template ContextT, SVGEltT, BoundObjT, HandlerRetT                           
 * @param {ContextT} context                                                     
 * @param {function(SVGEltT, BoundObjT): HandlerRetT} targetMethod               
 * @return {?}                                                                   
 */                                                                              
function buildD3Handler(context, targetMethod) {                                 
    return (/**                                                                  
     * @this {SVGEltT}                                                                                                                                                                                                                                        
     * @param {BoundObjT} node                                                   
     * @return {?}                                                               
     */                                                                          
    function (node) {                                                            
        // Here 'this' is not a reference to TopologyGraphComponent object.         
        return targetMethod.call(context, this, node);                           
    });                                                                          
}

But I am getting:

ERROR - Violation: References to "this" that are typed as "unknown" are not allowed. See https://github.com/google/closure-compiler/wiki/Conformance:-Unknown-type-of-%E2%80%9Cthis%E2%80%9D
@rictic
Copy link
Contributor

rictic commented Apr 18, 2019

I ran into this recently. Adding an explicit cast (e.g. this as SVGEltT}) seems to fix it.

If tsickle automatically emitted the type assertion, both on static methods (because of google/closure-compiler#3340) and when a function has an explicit this type it would do wonders for code legibility.

@mprobst
Copy link
Contributor

mprobst commented Sep 27, 2019

I see - the problem is that SVGEltT is a template parameter, which then is ? inside the method.

@evmar
Copy link
Contributor

evmar commented Sep 27, 2019

The reason Closure cares about what 'this' is at all is so it can consistently rename/DCE against it. For a bounded generic, we could say @this the supertype, since that has all the fields that Closure might care about. In the above that would mean emitting @this {SVGElement}.

@evmar
Copy link
Contributor

evmar commented Sep 27, 2019

I think we do some monkeying with what 'this' refers to already in code like here:

const contextThisTypeBackup = contextThisType;

And in fact we insert explicit casts ourselves, kinda like what @rictic did, in some cases:

* In methods with a templated this type, adds explicit casts to accesses on this.

I suspect it wouldn't be so hard to peek at the this type to see if it's a bounded generic and swap it out when necessary. Contributions welcome!

@mprobst
Copy link
Contributor

mprobst commented Sep 27, 2019 via email

@evmar
Copy link
Contributor

evmar commented Sep 27, 2019

If I followed the bug, this isn't even about generic bounds really. It's that code like

/**
 * @template T
 */
function f() {
  /** @this {T} */
  function f2() {}
}

fails because you can't use a templated type in a this clause. So the generic bounds thing doesn't even help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants