Resolving USR Conflicts
A USR conflict occurs when Periphery finds separate declarations with the same compiler-generated identifier. This can happen when you scan multiple build targets that use the same module name and define overlapping symbols in different source files.
The scan stops with an error beginning:
Declaration conflict detected: a declaration with the USR '...' has already been indexed.The error lists the existing and conflicting declarations, including their source locations and build modules. Use these details to identify which targets contain the declarations.
What is a USR?
Section titled “What is a USR?”A USR (Unified Symbol Resolution) is an identifier the compiler assigns to a declaration, such as a type, function, or property. The compiler records declarations and references to them in the index store. Periphery uses their USRs to connect each reference to the declaration it refers to.
A Swift build target compiles source files into a module. For ordinary Swift types, functions, and properties, the USR encodes the module’s identity as well as the declaration’s name and context. Compiling the same declaration into differently named modules normally produces different USRs.
Periphery requires separate declarations to have unique USRs across all targets included in a scan, so it can reliably connect each reference to the correct declaration.
How can this happen?
Section titled “How can this happen?”Suppose a project has two build targets, TargetA and TargetB. Each compiles its own copy of User.swift, and both use the module name SharedModule:
| Build target | Module name | Source file | Declaration |
|---|---|---|---|
TargetA |
SharedModule |
TargetA/User.swift |
struct User {} |
TargetB |
SharedModule |
TargetB/User.swift |
struct User {} |
Using the same module name is not itself an error. Each target builds successfully on its own: each module contains only one User declaration. However, both declarations have the USR s:12SharedModule4UserV, which violates Periphery’s unique USR requirement when both targets are included in the same scan.
Copying files is one way to create this situation. Independently written declarations can also conflict if their names, signatures, and declaration contexts produce the same USR in identically named modules.
How to resolve the conflict
Section titled “How to resolve the conflict”- Find the affected targets. Compare the source locations and module names listed in the error. In Xcode, check each file’s Target Membership and the targets’ Compile Sources build phases to find which target compiles each declaration.
- Use different module names for the conflicting targets. In Xcode, check the Product Module Name (
PRODUCT_MODULE_NAME) build setting for the affected targets; different target names alone do not guarantee different module names. In the example above, usingModuleAandModuleBas the module names gives the twoUserdeclarations different USRs. Update imports that refer to a renamed module. - Remove unintended copies of shared code. If both targets should use the same implementation, consider moving it into a shared module that both targets import. If a file was accidentally included in a target, remove that target membership.
- Rebuild the index after fixing the configuration. Run the scan with
--clean-build. If you use--skip-buildand--index-store-path, clean and rebuild the project yourself, then point Periphery at the fresh index store.
If the listed declarations do not match your current source or target configuration, try a clean build first: the index store may contain stale build data. See Troubleshooting for more index-store guidance.