void Model::collapse_invalid_paths()

in source/Model.cpp [335:402]


void Model::collapse_invalid_paths(Context& context) {
  if (!method_) {
    return;
  }

  using FieldTypesAccumulator = std::unordered_set<const DexType*>;

  auto is_valid = [this, &context](
                      const FieldTypesAccumulator& previous_field_types,
                      Path::Element field) {
    FieldTypesAccumulator current_field_types;
    for (const auto* previous_field_type : previous_field_types) {
      if (previous_field_type == type::java_lang_Object()) {
        // Object is too generic to determine the set of possible field names.
        continue;
      }

      const auto& cached_types =
          context.field_cache->field_types(previous_field_type, field);
      current_field_types.insert(cached_types.begin(), cached_types.end());
    }

    if (current_field_types.empty()) {
      LOG(5,
          "Model for method `{}` has invalid path element `{}`",
          show(method_),
          show(field));
      return std::make_pair(false, current_field_types);
    }

    return std::make_pair(true, current_field_types);
  };

  auto initial_accumulator = [this](const Root& root) {
    // Leaf ports appear in callee ports. This only applies to caller ports.
    mt_assert(!root.is_leaf_port());

    DexType* MT_NULLABLE root_type = nullptr;
    if (root.is_argument()) {
      root_type = method_->parameter_type(root.parameter_position());
    } else if (root.is_return()) {
      root_type = method_->return_type();
    }

    if (root_type == nullptr) {
      // This can happen when there is an invalid model, e.g. model defined
      // on an argument that does not exist, usually from a model-generator.
      // Returning an empty list of types will collapse all paths.
      ERROR(
          1,
          "Could not find root type for method `{}`, root: `{}`",
          show(method_),
          show(root));
      return FieldTypesAccumulator{};
    }

    return FieldTypesAccumulator{root_type};
  };

  generations_.collapse_invalid_paths<FieldTypesAccumulator>(
      is_valid, initial_accumulator);
  parameter_sources_.collapse_invalid_paths<FieldTypesAccumulator>(
      is_valid, initial_accumulator);
  sinks_.collapse_invalid_paths<FieldTypesAccumulator>(
      is_valid, initial_accumulator);
  propagations_.collapse_invalid_paths<FieldTypesAccumulator>(
      is_valid, initial_accumulator);
}