-/// T -/// +-- ST0 -/// | -/// +-- ST1 -/// | + -/// | | -/// | +-- T -/// | -/// +-- ST2 -///-/// -/// ST1 is said to "depend" on T because it has T as a sub-type. But -/// because T is recursive, then ST1 is said to depend on a recursive -/// type. Notice however that ST0 does not depend on any recursive -/// type. -/// -/// Now suppose we are comparing T to a type T' that has the same -/// structure with sub-types ST0', ST1' and ST2'. During the -/// comparison of ST1 against ST1', their sub-type T is compared -/// against T'. Because T (resp. T') is a recursive type that is -/// already being compared, the comparison of T against T' (as a -/// subtypes of ST1 and ST1') returns true, meaning they are -/// considered equal. This is done so that we don't enter an infinite -/// recursion. -/// -/// That means ST1 is also deemed equal to ST1'. If we are in the -/// course of the canonicalization of T' and thus if T (as well as as -/// all of its sub-types) is already canonicalized, then the canonical -/// type propagation optimization will make us propagate the canonical -/// type of ST1 onto ST1'. So the canonical type of ST1' will be -/// equal to the canonical type of ST1 as a result of that -/// optmization. -/// -/// But then, later down the road, when ST2 is compared against ST2', -/// let's suppose that we find out that they are different. Meaning -/// that ST2 != ST2'. This means that T != T', i.e, the -/// canonicalization of T' failed for now. But most importantly, it -/// means that the propagation of the canonical type of ST1 to ST1' -/// must now be invalidated. Meaning, ST1' must now be considered as -/// not having any canonical type. -/// -/// In other words, during type canonicalization, if ST1' depends on a -/// recursive type T', its propagated canonical type must be -/// invalidated (set to nullptr) if T' appears to be different from T, -/// a.k.a, the canonicalization of T' temporarily failed. -/// -/// This means that any sub-type that depends on recursive types and -/// that has been the target of the canonical type propagation -/// optimization must be tracked. If the dependant recursive type -/// fails its canonicalization, then the sub-type being compared must -/// have its propagated canonical type cleared. In other words, its -/// propagated canonical type must be cancelled. -/// -/// @} - - -/// If on-the-fly canonicalization is turned on, then this function -/// sets the canonical type of its second parameter to the canonical -/// type of the first parameter. -/// -/// @param lhs_type the type which canonical type to propagate. -/// -/// @param rhs_type the type which canonical type to set. -static bool -maybe_propagate_canonical_type(const type_base& lhs_type, - const type_base& rhs_type) -{ - const environment& env = lhs_type.get_environment(); -#if WITH_DEBUG_TYPE_CANONICALIZATION - if (!env.priv_->use_canonical_type_comparison_) - return false; -#endif - - if (env.do_on_the_fly_canonicalization()) - if (type_base_sptr canonical_type = lhs_type.get_canonical_type()) - if (!rhs_type.get_canonical_type() - && (!rhs_type.priv_->canonical_type_index - || (rhs_type.priv_->canonical_type_index - == canonical_type->priv_->canonical_type_index))) - { -#if WITH_DEBUG_CT_PROPAGATION - ABG_ASSERT(!rhs_type.priv_->canonical_type_index - || (rhs_type.priv_->canonical_type_index - == canonical_type->priv_->canonical_type_index)); -#endif - if (env.priv_->propagate_ct(lhs_type, rhs_type)) - return true; - } - return false; -} - //