Skip to content

Comments

Cross Module renaming#4845

Open
vidit-od wants to merge 2 commits intohaskell:masterfrom
vidit-od:Cross-Module-Renaming
Open

Cross Module renaming#4845
vidit-od wants to merge 2 commits intohaskell:masterfrom
vidit-od:Cross-Module-Renaming

Conversation

@vidit-od
Copy link
Collaborator

@vidit-od vidit-od commented Feb 14, 2026

Fixes #4816

This PR aims at implementing Cross Module Renaming. Recently Cross Module Renaming was made True by default in HLS, but current implementation shows Renaming of an exported name is unsupported and Renaming of an imported name is unsupported when attempting to do so.

The main reason for this was the failWhenImportOrExport function blocking rename whenever any imported or exported variables are renamed.

The current implementation carefully checks and distinguish bw local , exported, imported variables. If cross Module is disabled. Blocks renaming imported and exported variables renaming. The older constrain of having an Explicit export list is still maintained.

The below comment ( link ) also talks about a scenario where relying completely on HieDb can lead to incorrect results when local references and imported/ exported references have same name. Hence Ast is also referred for renaming of local variables.

@vidit-od
Copy link
Collaborator Author

This PR aims at implementing cross module renaming.

It is ready for review and most of the functionality has been check by me manually. Raising this PR to see how the tests perform on various environments.

Will add testcases for this Feature once we can verify old ones work properly.

@vidit-od vidit-od force-pushed the Cross-Module-Renaming branch 4 times, most recently from 9bf809c to 1079ed2 Compare February 14, 2026 09:27
@vidit-od vidit-od force-pushed the Cross-Module-Renaming branch from 1079ed2 to aba72d9 Compare February 14, 2026 09:40
@fendor
Copy link
Collaborator

fendor commented Feb 14, 2026

Could you briefly explain the strategy of the solution? I was under the impression, that the rename feature could entirely rely on hiedb to find references to a Name and replacing them, but it seems like you are doing quite a lot more with the GHC AST directly?

@vidit-od
Copy link
Collaborator Author

Reason for using AST

Implementation with HieDb :
OldCrossNaming-ezgif com-video-to-gif-converter
Here changing the local variable leads to changing of all other variables of same names (Local and Global). The reason for this is HieDB uses OccName for finding references. AST presents absolute truth and should be used to rely on for preventing inconsistencies.

This similar break can be observed in any and all examples where a local variable has same name as imported variable. Although this is a very specific example of : Importing a variable -> having a same name variable as a local variable -> user triggers rename on that variable.

current implementation enables :
NewCrossNaming

IMP : HieDB does cover all of the simpler cases. considering that AST traversal takes comparatively longer time we have to choose b/w faster but little inconsistent implementation vs slower but always correct one ; both version of codes are available with me :)

Hopefully this makes everything clear ! @fendor

exportRefs <- exportNameLocs pm oldNames
isExported <- or <$> mapM (isNameExplicitExported pm) oldNames
let refs = HS.union refs' (HS.fromList exportRefs)
currentModule = fmap unLoc $ hsmodName $ unLoc $ pm_parsed_source pm
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get this from the ModSummary, will allow you to get rid of the Nothing case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure if this is logical / why this is happening but i tried doing what the review recommends by replacing the highlighted code with this code

currentModule = ms_mod $ pm_mod_summary pm
                isLocallyDefined name =
                    case nameModule_maybe name of
                        Nothing -> True
                        Just nameModule -> nameModule == currentModule             

doing this made a lot of testcases flaky. i have tried running almost all of the testcases numerous times and find no logic to why they fail. below is the list of testcases that showed flaky nature;

  • "Data constructor with fields"
  • "Function name"
  • "Realigns do block indentation"

i dont know why this would happen but for all of the above cases we randomly get the below error
"Cannot rename symbol: module has no explicit export list and the symbol is referenced from other modules."

reverting this block to the older version made all of the cases work fine ( Confirmed this multiple times as well )
any guesses why this would happen ?

@wz1000
Copy link
Collaborator

wz1000 commented Feb 16, 2026

Can you offer a overview of what the bug was, and your approach towards fixing it please? It would be good to add this to the commit message as well.

@wz1000
Copy link
Collaborator

wz1000 commented Feb 16, 2026

It would also be good to add the example from #4816 as a regression test.

@vidit-od vidit-od force-pushed the Cross-Module-Renaming branch 3 times, most recently from dc82156 to b9bdde6 Compare February 17, 2026 20:03
Comment on lines +130 to +136
let hasExplicitExportList = isJust (hsmodExports (unLoc $ pm_parsed_source pm))
refFiles <- forM (HS.toList refs) $ \loc -> do
(file, _) <- locToFilePos loc
pure file
let hasExternalRefs = any (/= nfp) refFiles
when ( crossModuleEnabled && not hasExplicitExportList && hasExternalRefs && renamingLocalDeclaration ) $ throwError $ PluginInvalidParams
"Cannot rename symbol: module has no explicit export list and the symbol is referenced from other modules."
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the conditions that define when to show the mentioned error.

CurrentModule -> isLocallyDefined -> renamingLocalDeclaration -> causing the error ?

could this be a possible reason ?

@vidit-od vidit-od force-pushed the Cross-Module-Renaming branch 3 times, most recently from eb4adab to 64e1158 Compare February 18, 2026 07:37
@vidit-od vidit-od force-pushed the Cross-Module-Renaming branch from 64e1158 to bdb31c9 Compare February 18, 2026 07:55
@vidit-od vidit-od requested review from fendor and wz1000 February 18, 2026 09:14
@vidit-od
Copy link
Collaborator Author

  • i have updated the PR description with an overview explanation,
  • also new regression tests including the ones listed in original issue as well as a few more cases have been added.
  • The one review regarding usage of Modsummary has been reverted because of the reasons listed in above conversation.

On a side note: the tests for rename plugin gave me a very hard time. Tho , I dont know if we can do anything about it or not :)

requesting a re-review @wz1000 @fendor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hls-rename-plugin: Rename across modules fails

3 participants