private ConflictResult doStrictCompare(DataType addedDataType, DataType existingDataType,
			Set<Long> visitedDataTypes) {
		if (addedDataType == existingDataType ||
			!addVisited(existingDataType, addedDataType, visitedDataTypes)) {
			return USE_EXISTING;
		}

		if (existingDataType instanceof Composite && addedDataType instanceof Composite) {
			Composite existingComposite = (Composite) existingDataType;
			Composite addedComposite = (Composite) addedDataType;

			// Check to see if we are adding a default/empty data type
			if ((isCompositeDefault(addedComposite)) && isSizeCompatible(existingComposite, addedComposite)) {
				return USE_EXISTING;
			}
			// Check to see if the existing type is a default/empty data type
			if ((isCompositeDefault(existingComposite)) && isSizeCompatible(addedComposite, existingComposite)) {
				return REPLACE_EXISTING;
			}
			// Check to see if the added type is part of the existing type first to
			// generate more USE_EXISTINGS when possible.
			if (isCompositePart(existingComposite, addedComposite, visitedDataTypes)) {
				return USE_EXISTING;
			}
			// Check to see if the existing type is a part of the added type
			if (isCompositePart(addedComposite, existingComposite, visitedDataTypes)) {
				return REPLACE_EXISTING;
			}

			return RENAME_AND_ADD;
		}

		if (existingDataType instanceof TypeDef && addedDataType instanceof TypeDef) {
			TypeDef addedTypeDef = (TypeDef) addedDataType;
			TypeDef existingTypeDef = (TypeDef) existingDataType;
			return doRelaxedCompare(addedTypeDef.getBaseDataType(), existingTypeDef.getBaseDataType(),
					visitedDataTypes);
		}

		if (existingDataType instanceof Array && addedDataType instanceof Array) {
			Array addedArray = (Array) addedDataType;
			Array existingArray = (Array) existingDataType;

			if (addedArray.getNumElements() != existingArray.getNumElements()
					|| addedArray.getElementLength() != existingArray.getElementLength()) {
				return RENAME_AND_ADD;
			}

			return doRelaxedCompare(addedArray.getDataType(), existingArray.getDataType(), visitedDataTypes);
		}

		if (existingDataType instanceof Pointer && addedDataType instanceof Pointer) {
			return doRelaxedCompare(((Pointer) addedDataType).getDataType(), ((Pointer) existingDataType).getDataType(),
					visitedDataTypes);
		}

		if (existingDataType instanceof FunctionDefinition && addedDataType instanceof FunctionDefinition) {
			return compareFuncDef((FunctionDefinition) addedDataType, (FunctionDefinition) existingDataType,
					visitedDataTypes);
		}

		if (existingDataType instanceof BitFieldDataType && addedDataType instanceof BitFieldDataType) {
			BitFieldDataType existingBF = (BitFieldDataType) existingDataType;
			BitFieldDataType addedBF = (BitFieldDataType) addedDataType;
			if (existingBF.getDeclaredBitSize() != addedBF.getDeclaredBitSize()) {
				return RENAME_AND_ADD;
			}
			return existingBF.getPrimitiveBaseDataType().isEquivalent(addedBF.getPrimitiveBaseDataType()) ? USE_EXISTING
					: RENAME_AND_ADD;
		}

		if (existingDataType.isEquivalent(addedDataType)) {
			return USE_EXISTING;
		}

		return RENAME_AND_ADD;
	}
Returns true if one union is a subset of another union.
<p>
Each component of the candidate partial union must be present in the 'full'
union and must be 'equiv'.
<p>
Order of components is ignored, except for unnamed components, which receive
a default name created using their ordinal position.

@param full             {@link Union} datatype that is expected to be a
                        superset of the next param.
@param part             {@link Union} datatype that is expected to be a
                        subset of the previous param.
@param visitedDataTypes identity map of datatypes to prevent loops.
@return true if part is a subset (or equal) to full.
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/dwarf/DWARFDataTypeConflictHandler.java