@Nullable
  private <D extends DeclarationDescriptor> D substitute(@Nullable D descriptor) {
    if (descriptor == null) return null;
    if (substitutor.isEmpty()) return descriptor;

    if (substitutedDescriptors == null) {
      substitutedDescriptors = Maps.newHashMap();
    }

    DeclarationDescriptor substituted = substitutedDescriptors.get(descriptor);
    if (substituted == null && !substitutedDescriptors.containsKey(descriptor)) {
      substituted = descriptor.substitute(substitutor);

      //noinspection ConstantConditions
      substitutedDescriptors.put(descriptor, substituted);
    }

    //noinspection unchecked
    return (D) substituted;
  }
 public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
   return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
 }