title: Proguard stripping out implements interface. Causing java.lang.IncompatibleClassChangeError at runtime
body: <p>After updating dependencies to latest versions we ran into a Runtime crash in release builds because of missing interface implementation </p>
  
  <pre><code>java.lang.IncompatibleClassChangeError: 
  Class 'com.mypackage.app.data.cache.query.user.QueryUserFollowersCountById' 
  does not implement interface 'com.mypackage.app.data.cache.query.Query' 
  in call to 'java.lang.String[] com.mypackage.app.data.cache.query.Query.c()' 
  (declaration of 'com.mypackage.app.data.cache.database.util.Db' 
  appears in /data/app/com.mypackage.app-2/base.apk:classes2.dex)
  </code></pre>
  
  <p>Two days of debugging later, we think the issue is related to Proguard stripping out the 'implements Query' during its shrinking phase. The interface itself is kept as it is used in hundreds of other classes, it is only missing in 3 classes. We also found some RxJava Func0 and Action0 interfaces stripped out in the same way, again in a very few places. Thus the app runs perfectly for 95% of the screens, but obviously crashes where the interface implementation is missing.</p>
  
  <ol>
  <li>We are using Gradle build tools version 3.1.3 but also tried with 3.3.0-alpha03, also tried disabling D8, thus it shouldn't be a build tools issue (also Proguard version 5.3.3 and 6.0.3 behave in the same way in this case)</li>
  <li>The issue appears when bumping Dagger2 from version 2.11 to 2.12 or later, thus it might be related to the amount of fields/methods/classes etc in the app</li>
  <li>The issue remains even when using -dontoptimize, we have gone through Proguard documentation and enabled/disabled almost all relevant flags</li>
  <li><strong>The issue is gone by setting minifyEnabled to false or by using -dontshrink flag for Proguard</strong></li>
  <li>The app uses Multidex, both builds with Dagger 2.11 and Dagger 2.12 end up with 3 classes.dex files. The problematic interface and the implementations are in the same .dex file in both cases.</li>
  <li>For example, there are 5 files in the same package that implement Query, 3 of them have the interface in the resulting bytecode, but 2 files do not. So it should not be related to where the files are placed.</li>
  </ol>
  
  <p><strong>Bytecode when built using Dagger 2.11 or -dontshrink</strong></p>
  
  <pre><code>.class public Lcom/mypackage/app/data/cache/query/user/QueryUserFollowersCountById;
  .super Ljava/lang/Object;
  .source "SourceFile"
  
  # interfaces
  .implements Lcom/mypackage/app/data/cache/query/Query;
  
  # annotations
  .annotation system Ldalvik/annotation/Signature;
      value = {
          "Ljava/lang/Object;",
          "Lcom/mypackage/app/data/cache/query/Query&lt;",
          "Ljava/lang/Integer;",
          "&gt;;"
      }
  .end annotation
  ......
  </code></pre>
  
  <p><strong>Bytecode when built using Dagger 2.12 or later</strong></p>
  
  <pre><code>.class public Lcom/mypackage/app/data/cache/query/user/QueryUserFollowersCountById;
  .super Ljava/lang/Object;
  .source "SourceFile"
  
  # annotations
  .annotation system Ldalvik/annotation/Signature;
      value = {
          "Ljava/lang/Object;"
      }
  .end annotation
  ......
  </code></pre>
  
  <p>We obviously want to use the latest version of Dagger2 and also keep shrinking and optimising our code with Proguard.</p>
  
  <ol>
  <li>How to make sure that Proguard will not strip out implements interface statements?</li>
  <li>Or how to add logging/debugging to Proguard shrinking step?</li>
  </ol>