GWT compiler optimization breaks some lambdas

553 views
Skip to first unread message

Ignacio Baca Moreno-Torres

unread,
Oct 24, 2015, 7:40:24 AM10/24/15
to GWT Contributors
There is a bug which optimizations nullify variables which might not be null. I'm trying to reproduce the error outside our app but I can't, I'll continue trying, but for now I going to describe the problem.

return service.get().getBootstrap().bootstrap().doOnNext(data -> {
   
Account account = data.getAccount();
   
if (account == null) auth.get().resetSessionData(false);
   
else auth.get().setSessionData(account, data.getKeychain());
    theme
.get().setCustomization(data.getCustomization());
    analytics
.get().init(data.getAnalyticsUserAccount() + ":" + data.getAnalyticsDomainName());
   
OsmQueryResolver.configureServer(data.getReverseGeocodingUrl());
   
final String user = account == null ? "anonymous" : account.getEmail();
    log
.fine("Bootstrap data loaded successfully (user=" + user + ")");
});
Produces the next js code.
function fie(a) {
    var b;
    null .b1();
    bdf(Tub(a.b.Ee(), 388), false);
    Ujf((b = Tub(a.k.Ee(), 937),
    null .b1(),
    b));
    Tub(a.a.Ee(), 6122).VI(null .b1() + ':' + null .b1());
    Ivg(null .b1());
    U_l(cie, 'Bootstrap data loaded successfully (user=anonymous)')
}
BUT! if compile without optimizations (ex. using draft compile) or if anonymous class is used instead of a lambda, the output js is ok. Next block contains my current working code.
//noinspection Convert2Lambda GWT optimize incompatible
return service.get().getBootstrap().bootstrap().doOnNext(new Action1<EntryPointData>() {
@Override public void call(EntryPointData data) {

The bootstrap method is a call of reactive restygwt service using this proyect https://github.com/ibaca/restygwt-rxadapter. I.e. bootstrap return an Observable which end up making a XMLHttpRequest (a lot of layer in between), and data is a EntryPoint interface, and the implementation received is an overlay.

I know that with this info is almost impossible to discover the problem, but I put here to see if someone else have similar problem, and maybe some gwt compiler developer just seeing that may see where is the problem (improbable). If a get reproduced in a sample project I write back here.

Ignacio Baca Moreno-Torres

unread,
Oct 24, 2015, 7:54:07 AM10/24/15
to GWT Contributors
Other situation producing the same problem. If next code is replaced by lambda and method reference... the next block end up being optimized as if response is always null.
//noinspection Convert2Lambda,Anonymous2MethodRef IGP-1732 gwt optimize incompatible
tracker.add(heads.subscribe(new Action1<SubscriptionResponse>() {
   
@Override public void call(SubscriptionResponse response) {
       
ClientTelemetryStore.this.processResponse(response);
   
}
}));
The processResponse java code.
private void processResponse(SubscriptionResponse response) {
   
Objects.requireNonNull(response, "response required");
   
Objects.requireNonNull(response.getUuid(), "response.uuid required");
   
if (uuid == null) uuid = response.getUuid(); // first response
    else assert uuid.equals(response.getUuid()) : "subscription uuid mismatch";
   
boolean newUnits = false;
   
for (UnitDescriptor xs : response.getUnits()) {
        newUnits
|= processUnitCreate(xs);
   
}
   
for (ProtoUnit xs : response.getData()) {
        processUnitUpdate
(xs);
   
}
   
// accumulate change updates per response
    if (newUnits) tStoresChange.onNext(tStores);
}
And processResponse js code.
function Hak(a, b) {
    var c, d, e, f;
    lWl(b, 'response required');
    lWl(null ._0(), 'response.uuid required');
    a.g = null ._0();
    c = false;
    for (f = null ._0()._0(); f.Nd(); ) {
        d = Vub(f.Od());
        c = c | Iak(a, d)
    }
    for (e = null ._0()._0(); e.Nd(); ) {
        d = Uub(e.Od(), 6163);
        Jak(a, d)
    }
    c && lrm(a.d, a.c)
}

Ray Cromwell

unread,
Oct 24, 2015, 1:52:52 PM10/24/15
to google-web-toolkit-contributors
Does it still happen if you use an anonymous inner class instead of a lambda?

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/9dd3316c-68f5-4ed9-8d8c-c7a34f123109%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Ignacio Baca Moreno-Torres

unread,
Oct 24, 2015, 4:12:04 PM10/24/15
to google-web-toolkit-contributors

Anonymous classes works correctly in both cases.


Roberto Lublinerman

unread,
Oct 24, 2015, 4:30:12 PM10/24/15
to google-web-tool...@googlegroups.com

Are you using a recent snapshot?

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.

Ignacio Baca Moreno-Torres

unread,
Oct 24, 2015, 5:37:30 PM10/24/15
to google-web-tool...@googlegroups.com
This was from 94e45975a06ece1b8d65541aaabf833f9d8c7b07 (6 October 2015 at 04:29:19 GMT+2), I'll try tomorrow with HEAD, but looking the commits looks improbable that the problem has been solved.

Ray Cromwell

unread,
Oct 24, 2015, 10:07:10 PM10/24/15
to google-web-toolkit-contributors
Are you using @JsFunction/JsInterop? Unless the implementation has changed recently, Lambda's are supported in GWT by essentially synthesizing static inner classes, and so if static inner classes work, but lambda's don't, it's really weird. The optimization stages no nothing of lambdas and only see Java classes. The exception is @JsFunction.


Roberto Lublinerman

unread,
Oct 24, 2015, 10:42:10 PM10/24/15
to google-web-tool...@googlegroups.com

The only thing I can think of is that when the class is created for the lambda in gwtastbuilder, the super class or implemented interfaces are not set up correctly.

I'll check later to see if that is there case.

Ignacio Baca Moreno-Torres

unread,
Oct 25, 2015, 5:43:58 AM10/25/15
to GWT Contributors
Recompiled using HEAD dcea13b1d223513418c90c34324ac6929059de3c, with no JsInterop and optimization 1.
function $Xj(a, b) {
    var c, d, e, f;
    JDl(b, 'response required');
    JDl(null .V0(), 'response.uuid required');
    a.g = null .V0();
    c = false;
    for (f = null .V0().V0(); f.Md(); ) {
        d = Irb(f.Nd());
        c = c | _Xj(a, d)
    }
    for (e = null .V0().V0(); e.Md(); ) {
        d = Frb(e.Nd(), 6163);
        aYj(a, d)
    }
    c && B8l(a.d, a.c)
}

net.ltgt.gwt:gwt-maven-plugin configuration
[DEBUG] Configuring mojo 'net.ltgt.gwt.maven:gwt-maven-plugin:1.0-rc-2:compile' with basic configurator -->
[DEBUG] (f) compilerArgs = [-gen, ???/target/gwt/gen]
[DEBUG] (f) deploy = ???/target/gwt/deploy
[DEBUG] (f) draftCompile = false
[DEBUG] (f) extra = ???/target/gwt/extra
[DEBUG] (f) failOnError = true
[DEBUG] (f) forceCompilation = false
[DEBUG] (f) moduleName = com.app.DraftBundle
[DEBUG] (f) optimize = 1
[DEBUG] (f) project = MavenProject: ???/pom.xml
[DEBUG] (f) skipCompilation = false
[DEBUG] (f) sourceLevel = 1.8
[DEBUG] (f) staleMillis = 0
[DEBUG] (f) style = OBFUSCATED
[DEBUG] (f) webappDirectory = ???/target/app
[DEBUG] (f) workDir = ???/target/gwt/work

more context (removed long packages_names)
// Java Code (this lambda) -----v
tracker
.add(heads.subscribe(ClientTelemetryStore.this::processResponse));
// Javascript Output
o9c
(2061, 1, {}, M5j);
_
.$u = function L5j(a) { $Xj(this.a, a) };
var oQc = Fol(o1m, 'ClientTelemetryStore/ClientTelemetryStore$__$Action1$__$instance$ClientTelemetryStore$processResponse__LTelemetrySubscription$SubscriptionResponse_2V$Type', 2061);

And... trying to add this extra context, one more failure come up. This one has appeared after updating to the HEAD dcea13b from 7129828 (sorry, I said to roberto that I was using 94e4597, but I was really using 7129828 7 August 2015 at 13:08:36 GMT+2).

The new nullified method; although this time is an undefined. So repeating; this error came up just updating from 7129828 to dcea13b.
// Java Code                                             (this lambda) -------V
this.store = Suppliers.memoize(() -> from(resources.get()).uniqueIndex(ResourceDescriptor::getType));
// Javasript Output
o9c
(1639, 1, pcm, mRe);
_
.Xd = function lRe(a) { return undefined };
var x0b = Fol(Yum, 'ResourceDescriptor/ResourceRegistry$__$Function$__$static$ResourceDescriptor$getType__LClass_2$Type', 1639);

On Sunday, October 25, 2015 at 3:42:10 AM UTC+1, Roberto Lublinerman wrote:

The only thing I can think of is that when the class is created for the lambda in gwtastbuilder, the super class or implemented interfaces are not set up correctly.

I'll check later to see if that is there case.

On Oct 24, 2015 19:07, "'Ray Cromwell' via GWT Contributors" <google-web-toolkit-contri...@googlegroups.com> wrote:
Are you using @JsFunction/JsInterop? Unless the implementation has changed recently, Lambda's are supported in GWT by essentially synthesizing static inner classes, and so if static inner classes work, but lambda's don't, it's really weird. The optimization stages no nothing of lambdas and only see Java classes. The exception is @JsFunction.

On Sat, Oct 24, 2015 at 2:37 PM, Ignacio Baca Moreno-Torres <ign...@bacamt.com> wrote:
This was from 94e45975a06ece1b8d65541aaabf833f9d8c7b07 (6 October 2015 at 04:29:19 GMT+2), I'll try tomorrow with HEAD, but looking the commits looks improbable that the problem has been solved.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-contributors+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-contributors+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-contributors+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-contributors+unsubscribe@googlegroups.com.

Ignacio Baca Moreno-Torres

unread,
Oct 25, 2015, 7:08:09 AM10/25/15
to GWT Contributors
Next, I show two methods, this.getResource and the 'this' constructor. getResource get wrong because the output never assigns the map variable. And the constructor is showed to see how this.store is assigned. This time, the anonymous class do not solves the problem.

public Collection<ResourceDescriptor<?>> getResources() {
Supplier<Map<Class<?>, ResourceDescriptor<?>>> store = requireNonNull(this.store, "REFXXX store");
Map<Class<?>, ResourceDescriptor<?>> map = requireNonNull(store.get(), "REFXXX store.get()");
return requireNonNull(map.values(),"REFXXX store.get().values()"); 
}

function ILe(a) {
 
var b;
  b
= Erb(PDl(a.a, 'REFXXX store'), 164);
 
Erb(PDl(Erb(b.De(), 82), 'REFXXX store.get()'), 82);
 
return Erb(PDl(undefined, 'REFXXX store.get().values()'), 6)
}

And this is how this.store is initialized (also with lot of requireNotNull to easier matching between java and js)

@Inject
public ResourceRegistry(Provider<Set<ResourceDescriptor<?>>> resources) {
this.store = requireNonNull(Suppliers.memoize(new Supplier<Map<Class<?>, ResourceDescriptor<?>>>() {
@Override public Map<Class<?>, ResourceDescriptor<?>> get() {
Provider<Set<ResourceDescriptor<?>>> ref003 = requireNonNull(resources, "REF003 resources");
Set<ResourceDescriptor<?>> ref004 = requireNonNull(ref003.get(), "REF004 resources.get()");
ImmutableMap<Class<?>, ResourceDescriptor<?>> ref002 = from(ref004).uniqueIndex(
new Function<ResourceDescriptor<?>, Class<?>>() {
@Nullable @Override
public Class<?> apply(@Nullable ResourceDescriptor<?> resourceDescriptor) {
return requireNonNull(resourceDescriptor.getType(), "REF002");
}
});
return requireNonNull(ref002, "REF001");
}
}), "REF000");
}

o9c(2629, 1, Lwm, KLe);
_.De = function LLe() {
    var a, b, c;
    return a = Erb(PDl(this.a, 'REF003 resources'), 38),
    b = Erb(PDl(Erb(a.De(), 62), 'REF004 resources.get()'), 62),
    c = Vu(new $u(b,b), new NLe),
    Erb(PDl(c, 'REF001'), 82)
};
var s_b = Lol(dvm, 'ResourceRegistry/1', 2629);

function MLe(a) {
    return Erb(PDl(a.bw(), 'REF002'), 23)
}

function JLe(a) {
    this.a = Erb(PDl(Th(new KLe(a)), 'REF000'), 164)
}

I think this is the highlighted b.De

var ltb = Lol(Uam, 'Suppliers/MemoizingSupplier', 701);
o9c(702, 1, {
    164: 1,
    702: 1,
    3: 1
}, Xh);
_.zd = function Yh(a) {
    var b;
    if (Mrb(a, 702)) {
        b = Erb(a, 702);
        return Jf(this.a, b.a)
    }
    return false
};
_.De = function Zh() {
    return this.a
}
...

...

Ignacio Baca Moreno-Torres

unread,
Oct 25, 2015, 7:18:01 AM10/25/15
to GWT Contributors
Sorry, this is pretty confusing, just comment that the lamba cases described previously still (in HEAD) get solved when lamdas are changed to anonymous classes.

Ignacio Baca Moreno-Torres

unread,
Oct 25, 2015, 8:23:43 AM10/25/15
to GWT Contributors
function ILe(a) {
 
var b;
  b
= Erb(PDl(a.a, 'REFXXX store'), 164);
 
Erb(PDl(Erb(b.De(), 82), 'REFXXX store.get()'), 82);
 
return Erb(PDl(undefined, 'REFXXX store.get().values()'), 6)
}

This was the actual b.De() function.
u9c(701, 1, { 164: 1, 701: 1, 3: 1 }, Uh);
_
.De = function Vh() {
   
var a;
   
if (!this.b) {
       
if (!this.b) {
            a
= this.a.De();
           
this.c = a;
           
this.b = true;
           
return a
       
}
   
}
   
return this.c
};
_
.Bd = function Wh() { return 'Suppliers.memoize(' + this.a + ')' };
_
.b = false;
var ltb = epl(tbm, 'Suppliers/MemoizingSupplier', 701);

And the highlighted this.a.De() call the Supplier.get(). (this return a,b,c; is pretty obscure!, equivalent to a;b;return c;)
_.De = function RLe() {
   
var a, b, c;
   
return a = Erb(iEl(this.a, 'REF003 resources'), 38),
      b
= Erb(iEl(Erb(a.De(), 62), 'REF004 resources.get()'), 62),
      c
= Vu(new $u(b,b), new TLe),
     
Erb(iEl(c, 'REF001'), 82)
}

Roberto Lublinerman

unread,
Oct 26, 2015, 12:06:47 PM10/26/15
to google-web-tool...@googlegroups.com

Could you compile both working and not working with -style PRETTY.

That would make it easier to map to Java.

To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.

To view this discussion on the web visit
...

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/bd26339f-1852-44dc-8e30-58201f79b284%40googlegroups.com.

Roberto Lublinerman

unread,
Oct 26, 2015, 12:26:33 PM10/26/15
to google-web-tool...@googlegroups.com
Also could you try the equivalent lamda that is not a method reference, i.e

  (parameters) -> this.processResponse(params);

I looked at the way we construct the innerclasses corresponding to lambdas and it looks ok.

It would really help if you could narrow it down to a small reprocase that I can run.

To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.

To view this discussion on the web visit
...

--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/bd26339f-1852-44dc-8e30-58201f79b284%40googlegroups.com.

Ignacio Baca Moreno-Torres

unread,
Oct 26, 2015, 3:27:41 PM10/26/15
to GWT Contributors
Bootstrap using lambda (fail)

// java

return service.get().getBootstrap().bootstrap().doOnNext(data -> {
   
Account account = data.getAccount();
   
if (account == null) auth.get().resetSessionData(false);
   
else auth.get().setSessionData(account, data.getKeychain());
    theme
.get().setCustomization(data.getCustomization());
    analytics
.get().init(data.getAnalyticsUserAccount() + ":" + data.getAnalyticsDomainName());
   
OsmQueryResolver.configureServer(data.getReverseGeocodingUrl());
   
final String user = account == null ? "anonymous" : account.getEmail();
    log
.fine("Bootstrap data loaded successfully (user=" + user + ")");
});
// javascript + pretty
function $lambda$5(this$static) {
   
var lastArg;
   
null .$_nullMethod();
    $resetSessionData
(castTo(this$static.auth.get_1(), 400), false);
    $setCustomization
((lastArg = castTo(this$static.theme.get_1(), 1067),
   
null .$_nullMethod(),
    lastArg
));
    castTo
(this$static.analytics.get_1(), 6137).init_2(null .$_nullMethod() + ':' + null .$_nullMethod());
    configureServer
(null .$_nullMethod());
    $fine_0
(log_3, 'Bootstrap data loaded successfully (user=anonymous)');
}


ProcessResponse using anonymous class (success).

// java

tracker
.add(heads.subscribe(new Action1<SubscriptionResponse>() {
   
@Override public void call(SubscriptionResponse response) {
       
ClientTelemetryStore.this.processResponse(response);
   
}
}));
// Javascript
defineClass
(2064, 1, {}, ClientTelemetryStore$1);
_
.call_0 = function call_145(response) {
    $call_3
(this, castToAllowJso(response, 6180));
};
function $call_3(this$static, response) {
    $processResponse
(this$static.this$01, response);
}
function $processResponse(this$static, response) {
   
var newUnits, xs, xs$iterator, xs$iterator0;
    requireNonNull_0
(response, 'response required');
    requireNonNull_0
(response.uuid, 'response.uuid required’);


ProcessResponse using lambda (fail).

// Java
tracker
.add(heads.subscribe(response -> { ClientTelemetryStore.this.processResponse(response); }));
// Javascript
defineClass
(2063, 1, {}, ClientTelemetryStore$lambda$3$Type);
_
.call_0 = function call_153(arg0) {
    $processResponse
(this.$$outer_0, throwClassCastExceptionUnlessNull(arg0));
};
function $processResponse(this$static, response) {
   
var newUnits, xs, xs$iterator, xs$iterator0;
    requireNonNull_0
(response, 'response required');
    requireNonNull_0
(null .$_nullMethod(), 'response.uuid required');

I did not use pretty style because I thought that this flag produces different result, I tested now and looks like the output is the same, but, I'm pretty sure that some flags changes this issues, optimize is obvious that fixes the problem, but I think that namespace=package also changes the result.

I know that this was easier if we have a sample project, but I can't reproduce! :( You can try, the ResourceRegistry case is plain java + guava. But when you copy to a clean project, the bug disappear.
this.store = Suppliers.memoize(() -> from(resources.get()).uniqueIndex(ResourceDescriptor::getType));
Resource descriptor is an interface with only one implementation where type is a Class<?> type field, a getType return this field. Anyway, I'm still trying to reproduce in a small project.
...

Ignacio Baca Moreno-Torres

unread,
Oct 26, 2015, 3:57:47 PM10/26/15
to GWT Contributors
I said that optimize=0 fix errors, but I just compiled the project a get the same bootstrap+lamba error. But with draftCompile the result looks ok.
// bootstrap case, lambda, pretty, draftCompile
_
.lambda$5 = function lambda$5(data_0){
  $clinit_ApplicationBootstrapper
();
 
var account, user;
 
{
    account
= getAccount__Lshared_user_Account___devirtual$(data_0);
   
if (isNull_2(account))
      castTo
(this.auth.get_1(), 242).resetSessionData(false);
   
else  
      castTo
(this.auth.get_1(), 242).setSessionData(account,getKeychain__LKeychain___devirtual$(data_0));

    castTo
(this.theme.get_1(), 951).setCustomization(getCustomization__LCustomization___devirtual$(data_0));
    castTo
(this.analytics.get_1(),7570).init_13(
        getAnalyticsUserAccount__Ljava_lang_String___devirtual$
(data_0) + ':' +
        getAnalyticsDomainName__Ljava_lang_String___devirtual$
(data_0));
    configureServer
(getReverseGeocodingUrl__Ljava_lang_String___devirtual$(data_0));
    user
= isNull_2(account)?'anonymous':getEmail__Ljava_lang_String___devirtual$(account);
    log_10
.fine('Bootstrap data loaded successfully (user=' + user + ')');
 
}
};
defineClass
(1672, 1, {1:1}, ApplicationBootstrapper$lambda$5$Type);
_
.call_0 = function call_3(arg0){
 
this.$$outer_0.lambda$5(arg0);  
};
var Lclient_ApplicationBootstrapper$lambda$5$Type_2_classLit = createForClass('client', 'ApplicationBootstrapper/lambda$5$Type', 1672, Ljava_lang_Object_2_classLit);
...

Ray Cromwell

unread,
Oct 26, 2015, 4:48:25 PM10/26/15
to google-web-toolkit-contributors
It looks to me like it might be a type inferencing issue Roberto. Remember, the lambda is matched to a SAM interface method. When it synthesizes the implementation, it takes info from JDT about the 'expected type' which is inferred by JDT. I wonder if the type inferred messes up type tightener somehow. Here's something to try, put your lambda into a local var;

e.g.

Function<Foo, Bar> foo = {data -> data.getAccount() etc}
service.get().getBootstrap().bootstrap().doOnNext(foo)

That way you force the param types to what you know they are.

I suppose another thing to try is to declare a type

service.get().getBootstrap().bootstrap().doOnNext(Data data -> .....)

What I'm suspecting is that the compiler is seeing a different type for the parameter somehow and inferring it is never instantiated.



--
You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit-co...@googlegroups.com.

Roberto Lublinerman

unread,
Oct 26, 2015, 5:25:52 PM10/26/15
to google-web-tool...@googlegroups.com
Is the data that flows in the lambda an object created by your Java applications or does it flow from JavaScript?

Roberto Lublinerman

unread,
Oct 26, 2015, 5:39:39 PM10/26/15
to google-web-tool...@googlegroups.com
I did not use pretty style because I thought that this flag produces different result, I tested now and looks like the output is the same, but, I'm pretty sure that some flags changes this issues, optimize is obvious that fixes the problem, but I think that namespace=package also changes the result.

In a nutshell there are optimizations on the Java AST and those are not affected at all by -style or -Xnamespace. Optimizations that are related to types, instantiability, devirtualization, etc, are done in the Java AST.

Some optimizations in that JavaScriptAST might be affected by -style (like DuplicateFunctionRemoval) but those I think they are mostly off. I don't think -Xnamespace has any impact on optimizations.

That said, if you are using JsInterop, and you have a type that is never new'ed in Java, the compiler infers that is not instantiable and assumes it is always null and optimizes accordingly. Types originating from JavaScript need to be marked as JsType so that the compiler is aware and does not assume they are null.


Roberto Lublinerman

unread,
Oct 26, 2015, 5:47:08 PM10/26/15
to google-web-tool...@googlegroups.com
It would be really helpful if you could isolate your problem to a small example.

Ignacio Baca Moreno-Torres

unread,
Oct 27, 2015, 4:17:48 AM10/27/15
to GWT Contributors

Tests:
  • Create a variable with the lambda to fix type inference; did not work.
  • Add a EntryPointDataOverlay.create() factory (not called); did not work.
  • Add EntryPointData data = new EntryPointDataPojo() before lambda; did not work, but now data_0 is not null, but its methods return nulls.
  • Add EntryPointData data = EntryPointDataOverlay.create() before lambda call; did WORK!


I think that with this new info I can create a sample case. Looks like the overlay without constructor/factory calls is the key point. We have lot of that overlays because we are using restygwt that uses overlays as return type, but you only need to add this overlays as a generic parameter in a MethodCallback interface, so the contractor/factory is never used in the application.


Although we are NOT using JsInterop, this comment look the key, thanks, hope next post will be a sample project.

That said, if you are using JsInterop, and you have a type that is never new'ed in Java, the compiler infers that is not instantiable and assumes it is always null and optimizes accordingly. Types originating from JavaScript need to be marked as JsType so that the compiler is aware and does not assume they are null.

Ignacio Baca Moreno-Torres

unread,
Oct 27, 2015, 4:17:47 PM10/27/15
to GWT Contributors
At last! https://github.com/ibaca/gwt-instantiable-inference-bug/blob/master/src/main/java/com/bacamt/ibaca/client/Bug.java

As Roberto said, the problem seems to be the instantiability inference. The project works correctly on draftCompile, but on optimized compile the lambas parameters gets nullified. Alternatively, if you use anonymous classes the code works too (code commented), actually, only an explicit reference to the overlay type is required.

At this point, it appear that the problem was not lambdas :( , but lambdas facilitates to process object only referencing implicit types, which now seems to be the problem. Probably both test that Ray said fixed the problem, but only if the type used was the Overlay type (I didn't test that).

Thanks.

Ignacio Baca Moreno-Torres

unread,
Apr 13, 2016, 3:05:42 PM4/13/16
to GWT Contributors
(just in case someone read this thread) This problem has already been fixed in 2.8.0-SNAPSHOT. Thanks.
Reply all
Reply to author
Forward
0 new messages