on master help sign in
thread BuildID logic through Build.hs

As explained in the NOTE on Details.Local, it is necessary to track the BuildID of the last time the interface changed and the last time the file was compiled. This makes it possible to verify that all files have been compiled AFTER the most recent interface change of their imports in a project with multiple entrypoints such that some files are compiled inconsistently. Fixes https://github.com/elm/compiler/issues/1956

commit884ea201f2c2f6f478df3b311904acb8c02d538a authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 24 Jul 2019, 10:40 (7 years ago) parenta74201c
1 file changed+90−74
builder/src/Build.hs+90−74
builder/src/Build.hs+90−74
@@ -66,19 +66,20 @@ data Env =
6666 , _root :: FilePath
6767 , _pkg :: Pkg.Name
6868 , _srcDirs :: [FilePath]
69+ , _buildID :: Details.BuildID
6970 , _locals :: Map.Map ModuleName.Raw Details.Local
7071 , _foreigns :: Map.Map ModuleName.Raw Details.Foreign
7172 }
7273
7374
7475makeEnv :: Reporting.BKey -> FilePath -> Details.Details -> Env
75−makeEnv key root (Details.Details _ validOutline locals foreigns _) =
76+makeEnv key root (Details.Details _ validOutline buildID locals foreigns _) =
7677 case validOutline of
7778 Details.ValidApp srcDirs ->
78− Env key root Pkg.dummyName (NE.toList srcDirs) locals foreigns
79+ Env key root Pkg.dummyName (NE.toList srcDirs) buildID locals foreigns
7980
8081 Details.ValidPkg pkg _ _ ->
81− Env key root pkg ["src"] locals foreigns
82+ Env key root pkg ["src"] buildID locals foreigns
8283
8384
8485
@@ -238,7 +239,7 @@ crawlDeps env mvar deps blockedValue =
238239
239240
240241crawlModule :: Env -> MVar StatusDict -> DocsNeed -> ModuleName.Raw -> IO Status
241−crawlModule env@(Env _ root pkg srcDirs locals foreigns) mvar docsNeed name =
242+crawlModule env@(Env _ root pkg srcDirs buildID locals foreigns) mvar docsNeed name =
242243 do let fileName = ModuleName.toFilePath name <.> "elm"
243244 let inRoot path = File.exists (root </> path)
244245
@@ -251,18 +252,15 @@ crawlModule env@(Env _ root pkg srcDirs locals foreigns) mvar docsNeed name =
251252 return $ SBadImport $ Import.Ambiguous path [] dep deps
252253
253254 Nothing ->
254− case Map.lookup name locals of
255− Nothing ->
256− crawlFile env mvar docsNeed name path =<< File.getTime path
255+ do newTime <- File.getTime path
256+ case Map.lookup name locals of
257+ Nothing ->
258+ crawlFile env mvar docsNeed name path newTime buildID
257259
258− Just local@(Details.Local oldPath oldTime deps _) ->
259− if path /= oldPath
260− then crawlFile env mvar docsNeed name path =<< File.getTime path
261− else
262− do newTime <- File.getTime path
263− if oldTime /= newTime || needsDocs docsNeed
264− then crawlFile env mvar docsNeed name path newTime
265− else crawlDeps env mvar deps (SCached local)
260+ Just local@(Details.Local oldPath oldTime deps _ lastChange _) ->
261+ if path /= oldPath || oldTime /= newTime || needsDocs docsNeed
262+ then crawlFile env mvar docsNeed name path newTime lastChange
263+ else crawlDeps env mvar deps (SCached local)
266264
267265 p1:p2:ps ->
268266 return $ SBadImport $ Import.AmbiguousLocal p1 p2 ps
@@ -285,8 +283,8 @@ crawlModule env@(Env _ root pkg srcDirs locals foreigns) mvar docsNeed name =
285283 return $ SBadImport Import.NotFound
286284
287285
288−crawlFile :: Env -> MVar StatusDict -> DocsNeed -> ModuleName.Raw -> FilePath -> File.Time -> IO Status
289−crawlFile env@(Env _ root pkg _ _ _) mvar docsNeed expectedName path time =
286+crawlFile :: Env -> MVar StatusDict -> DocsNeed -> ModuleName.Raw -> FilePath -> File.Time -> Details.BuildID -> IO Status
287+crawlFile env@(Env _ root pkg _ buildID _ _) mvar docsNeed expectedName path time lastChange =
290288 do source <- File.readUtf8 (root </> path)
291289
292290 case Parse.fromByteString pkg source of
@@ -302,7 +300,7 @@ crawlFile env@(Env _ root pkg _ _ _) mvar docsNeed expectedName path time =
302300 if expectedName == actualName then
303301 let
304302 deps = map Src.getImportName imports
305− local = Details.Local path time deps (any isMain values)
303+ local = Details.Local path time deps (any isMain values) lastChange buildID
306304 in
307305 crawlDeps env mvar deps (SChanged local source modul docsNeed)
308306 else
@@ -325,7 +323,7 @@ type ResultDict =
325323data Result
326324 = RNew !Details.Local !I.Interface !Opt.LocalGraph !(Maybe Docs.Module)
327325 | RSame !Details.Local !I.Interface !Opt.LocalGraph !(Maybe Docs.Module)
328− | RCached Bool (MVar CachedInterface)
326+ | RCached Bool Details.BuildID (MVar CachedInterface)
329327 | RNotFound Import.Problem
330328 | RProblem Error.Module
331329 | RBlocked
@@ -340,11 +338,11 @@ data CachedInterface
340338
341339
342340checkModule :: Env -> Dependencies -> MVar ResultDict -> ModuleName.Raw -> Status -> IO Result
343−checkModule env@(Env _ root pkg _ _ _) foreigns resultsMVar name status =
341+checkModule env@(Env _ root pkg _ _ _ _) foreigns resultsMVar name status =
344342 case status of
345− SCached local@(Details.Local path time deps hasMain) ->
343+ SCached local@(Details.Local path time deps hasMain lastChange lastCompile) ->
346344 do results <- readMVar resultsMVar
347− depsStatus <- checkDeps root results deps
345+ depsStatus <- checkDeps root results deps lastCompile
348346 case depsStatus of
349347 DepsChange ifaces ->
350348 do source <- File.readUtf8 path
@@ -356,7 +354,7 @@ checkModule env@(Env _ root pkg _ _ _) foreigns resultsMVar name status =
356354
357355 DepsSame _ _ ->
358356 do mvar <- newMVar Unneeded
359− return (RCached hasMain mvar)
357+ return (RCached hasMain lastChange mvar)
360358
361359 DepsBlock ->
362360 return RBlocked
@@ -371,9 +369,9 @@ checkModule env@(Env _ root pkg _ _ _) foreigns resultsMVar name status =
371369 Left err ->
372370 Error.BadSyntax err
373371
374− SChanged local@(Details.Local path time deps _) source modul@(Src.Module _ _ _ imports _ _ _ _ _) docsNeed ->
372+ SChanged local@(Details.Local path time deps _ _ lastCompile) source modul@(Src.Module _ _ _ imports _ _ _ _ _) docsNeed ->
375373 do results <- readMVar resultsMVar
376− depsStatus <- checkDeps root results deps
374+ depsStatus <- checkDeps root results deps lastCompile
377375 case depsStatus of
378376 DepsChange ifaces ->
379377 compile env docsNeed local source ifaces modul
@@ -418,29 +416,45 @@ data DepsStatus
418416 | DepsNotFound (NE.List (ModuleName.Raw, Import.Problem))
419417
420418
421−checkDeps :: FilePath -> ResultDict -> [ModuleName.Raw] -> IO DepsStatus
422−checkDeps root results deps =
423− checkDepsHelp root results deps [] [] [] [] False
419+checkDeps :: FilePath -> ResultDict -> [ModuleName.Raw] -> Details.BuildID -> IO DepsStatus
420+checkDeps root results deps lastCompile =
421+ checkDepsHelp root results deps [] [] [] [] False 0 lastCompile
424422
425423
426424type Dep = (ModuleName.Raw, I.Interface)
427425type CDep = (ModuleName.Raw, MVar CachedInterface)
428426
429427
430−checkDepsHelp :: FilePath -> ResultDict -> [ModuleName.Raw] -> [Dep] -> [Dep] -> [CDep] -> [(ModuleName.Raw,Import.Problem)] -> Bool -> IO DepsStatus
431−checkDepsHelp root results deps new same cached importProblems isBlocked =
428+checkDepsHelp :: FilePath -> ResultDict -> [ModuleName.Raw] -> [Dep] -> [Dep] -> [CDep] -> [(ModuleName.Raw,Import.Problem)] -> Bool -> Details.BuildID -> Details.BuildID -> IO DepsStatus
429+checkDepsHelp root results deps new same cached importProblems isBlocked lastDepChange lastCompile =
432430 case deps of
433431 dep:otherDeps ->
434432 do result <- readMVar (results ! dep)
435433 case result of
436− RNew _ iface _ _ -> checkDepsHelp root results otherDeps ((dep,iface) : new) same cached importProblems isBlocked
437− RSame _ iface _ _ -> checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked
438− RCached _ mvar -> checkDepsHelp root results otherDeps new same ((dep,mvar) : cached) importProblems isBlocked
439− RNotFound prob -> checkDepsHelp root results otherDeps new same cached ((dep,prob) : importProblems) True
440− RProblem _ -> checkDepsHelp root results otherDeps new same cached importProblems True
441− RBlocked -> checkDepsHelp root results otherDeps new same cached importProblems True
442− RForeign iface -> checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked
443− RKernel -> checkDepsHelp root results otherDeps new same cached importProblems isBlocked
434+ RNew (Details.Local _ _ _ _ lastChange _) iface _ _ ->
435+ checkDepsHelp root results otherDeps ((dep,iface) : new) same cached importProblems isBlocked (max lastChange lastDepChange) lastCompile
436+
437+ RSame (Details.Local _ _ _ _ lastChange _) iface _ _ ->
438+ checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked (max lastChange lastDepChange) lastCompile
439+
440+ RCached _ lastChange mvar ->
441+ checkDepsHelp root results otherDeps new same ((dep,mvar) : cached) importProblems isBlocked (max lastChange lastDepChange) lastCompile
442+
443+ RNotFound prob ->
444+ checkDepsHelp root results otherDeps new same cached ((dep,prob) : importProblems) True lastDepChange lastCompile
445+
446+ RProblem _ ->
447+ checkDepsHelp root results otherDeps new same cached importProblems True lastDepChange lastCompile
448+
449+ RBlocked ->
450+ checkDepsHelp root results otherDeps new same cached importProblems True lastDepChange lastCompile
451+
452+ RForeign iface ->
453+ checkDepsHelp root results otherDeps new ((dep,iface) : same) cached importProblems isBlocked lastDepChange lastCompile
454+
455+ RKernel ->
456+ checkDepsHelp root results otherDeps new same cached importProblems isBlocked lastDepChange lastCompile
457+
444458
445459 [] ->
446460 case reverse importProblems of
@@ -451,7 +465,7 @@ checkDepsHelp root results deps new same cached importProblems isBlocked =
451465 if isBlocked then
452466 return $ DepsBlock
453467
454− else if null new then
468+ else if null new && lastDepChange <= lastCompile then
455469 return $ DepsSame same cached
456470
457471 else
@@ -466,7 +480,7 @@ checkDepsHelp root results deps new same cached importProblems isBlocked =
466480
467481
468482toImportErrors :: Env -> ResultDict -> [Src.Import] -> NE.List (ModuleName.Raw, Import.Problem) -> NE.List Import.Error
469−toImportErrors (Env _ _ _ _ locals foreigns) results imports problems =
483+toImportErrors (Env _ _ _ _ _ locals foreigns) results imports problems =
470484 let
471485 knownModules =
472486 Set.unions
@@ -600,12 +614,12 @@ addToGraph name status graph =
600614 let
601615 dependencies =
602616 case status of
603− SCached (Details.Local _ _ deps _) -> deps
604− SChanged (Details.Local _ _ deps _) _ _ _ -> deps
605− SBadImport _ -> []
606− SBadSyntax _ _ _ _ -> []
607− SForeign _ -> []
608− SKernel -> []
617+ SCached (Details.Local _ _ deps _ _ _) -> deps
618+ SChanged (Details.Local _ _ deps _ _ _) _ _ _ -> deps
619+ SBadImport _ -> []
620+ SBadSyntax _ _ _ _ -> []
621+ SForeign _ -> []
622+ SKernel -> []
609623 in
610624 (name, name, dependencies) : graph
611625
@@ -633,9 +647,9 @@ checkUniqueMains insides smains =
633647mainStatusToNamePathPair :: MainStatus -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore FilePath)
634648mainStatusToNamePathPair smain =
635649 case smain of
636− SInside _ -> Nothing
637− SOutsideOk (Details.Local path _ _ _) _ modul -> Just (Src.getName modul, OneOrMore.one path)
638− SOutsideErr _ -> Nothing
650+ SInside _ -> Nothing
651+ SOutsideOk (Details.Local path _ _ _ _ _) _ modul -> Just (Src.getName modul, OneOrMore.one path)
652+ SOutsideErr _ -> Nothing
639653
640654
641655checkOutside :: ModuleName.Raw -> OneOrMore.OneOrMore FilePath -> Either Exit.BuildProjectProblem FilePath
@@ -648,12 +662,12 @@ checkOutside name paths =
648662checkInside :: ModuleName.Raw -> FilePath -> Status -> Either Exit.BuildProjectProblem ()
649663checkInside name p1 status =
650664 case status of
651− SCached (Details.Local p2 _ _ _) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
652− SChanged (Details.Local p2 _ _ _) _ _ _ -> Left (Exit.BP_MainNameDuplicate name p1 p2)
653− SBadImport _ -> Right ()
654− SBadSyntax _ _ _ _ -> Right ()
655− SForeign _ -> Right ()
656− SKernel -> Right ()
665+ SCached (Details.Local p2 _ _ _ _ _) -> Left (Exit.BP_MainNameDuplicate name p1 p2)
666+ SChanged (Details.Local p2 _ _ _ _ _) _ _ _ -> Left (Exit.BP_MainNameDuplicate name p1 p2)
667+ SBadImport _ -> Right ()
668+ SBadSyntax _ _ _ _ -> Right ()
669+ SForeign _ -> Right ()
670+ SKernel -> Right ()
657671
658672
659673
@@ -661,7 +675,7 @@ checkInside name p1 status =
661675
662676
663677compile :: Env -> DocsNeed -> Details.Local -> B.ByteString -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> IO Result
664−compile (Env key root pkg _ _ _) docsNeed local@(Details.Local path time _ _) source ifaces modul =
678+compile (Env key root pkg _ buildID _ _) docsNeed (Details.Local path time deps main lastChange _) source ifaces modul =
665679 case Compile.compile pkg ifaces modul of
666680 Right (Compile.Artifacts canonical annotations objects) ->
667681 do let name = Src.getName modul
@@ -674,12 +688,14 @@ compile (Env key root pkg _ _ _) docsNeed local@(Details.Local path time _ _) so
674688 Just oldi | oldi == iface ->
675689 do -- iface should be fully forced by equality check
676690 Reporting.report key Reporting.BDone
691+ let local = Details.Local path time deps main lastChange buildID
677692 return (RSame local iface objects docs)
678693
679694 _ ->
680695 do -- iface may be lazy still
681696 File.writeBinary elmi iface
682697 Reporting.report key Reporting.BDone
698+ let local = Details.Local path time deps main buildID buildID
683699 return (RNew local iface objects docs)
684700
685701 Left err ->
@@ -692,9 +708,9 @@ compile (Env key root pkg _ _ _) docsNeed local@(Details.Local path time _ _) so
692708
693709
694710writeDetails :: FilePath -> Details.Details -> Map.Map ModuleName.Raw Result -> IO ()
695−writeDetails root (Details.Details time outline locals foreigns extras) results =
711+writeDetails root (Details.Details time outline buildID locals foreigns extras) results =
696712 File.writeBinary (Stuff.details root) $
697− Details.Details time outline (Map.foldrWithKey addNewLocal locals results) foreigns extras
713+ Details.Details time outline buildID (Map.foldrWithKey addNewLocal locals results) foreigns extras
698714
699715
700716addNewLocal :: ModuleName.Raw -> Result -> Map.Map ModuleName.Raw Details.Local -> Map.Map ModuleName.Raw Details.Local
@@ -702,7 +718,7 @@ addNewLocal name result locals =
702718 case result of
703719 RNew local _ _ _ -> Map.insert name local locals
704720 RSame local _ _ _ -> Map.insert name local locals
705− RCached _ _ -> locals
721+ RCached _ _ _ -> locals
706722 RNotFound _ -> locals
707723 RProblem _ -> locals
708724 RBlocked -> locals
@@ -731,7 +747,7 @@ addErrors result errors =
731747 case result of
732748 RNew _ _ _ _ -> errors
733749 RSame _ _ _ _ -> errors
734− RCached _ _ -> errors
750+ RCached _ _ _ -> errors
735751 RNotFound _ -> errors
736752 RProblem e -> e:errors
737753 RBlocked -> errors
@@ -744,7 +760,7 @@ addImportProblems results name problems =
744760 case results ! name of
745761 RNew _ _ _ _ -> problems
746762 RSame _ _ _ _ -> problems
747− RCached _ _ -> problems
763+ RCached _ _ _ -> problems
748764 RNotFound p -> (name, p) : problems
749765 RProblem _ -> problems
750766 RBlocked -> problems
@@ -802,7 +818,7 @@ toDocs result =
802818 case result of
803819 RNew _ _ _ d -> d
804820 RSame _ _ _ d -> d
805− RCached _ _ -> Nothing
821+ RCached _ _ _ -> Nothing
806822 RNotFound _ -> Nothing
807823 RProblem _ -> Nothing
808824 RBlocked -> Nothing
@@ -831,7 +847,7 @@ data ReplArtifacts =
831847fromRepl :: FilePath -> Details.Details -> B.ByteString -> IO (Either Exit.Repl ReplArtifacts)
832848fromRepl root details source =
833849 let
834− env@(Env _ _ pkg _ _ _) = makeEnv Reporting.ignorer root details
850+ env@(Env _ _ pkg _ _ _ _) = makeEnv Reporting.ignorer root details
835851 in
836852 case Parse.fromByteString pkg source of
837853 Left syntaxError ->
@@ -857,12 +873,12 @@ fromRepl root details source =
857873 putMVar rmvar resultMVars
858874 results <- traverse readMVar resultMVars
859875 writeDetails root details results
860− depsStatus <- checkDeps root resultMVars deps
876+ depsStatus <- checkDeps root resultMVars deps 0
861877 finalizeReplArtifacts env source modul depsStatus resultMVars results
862878
863879
864880finalizeReplArtifacts :: Env -> B.ByteString -> Src.Module -> DepsStatus -> ResultDict -> Map.Map ModuleName.Raw Result -> IO (Either Exit.Repl ReplArtifacts)
865−finalizeReplArtifacts env@(Env _ root pkg _ _ _) source modul@(Src.Module _ _ _ imports _ _ _ _ _) depsStatus resultMVars results =
881+finalizeReplArtifacts env@(Env _ root pkg _ _ _ _) source modul@(Src.Module _ _ _ imports _ _ _ _ _) depsStatus resultMVars results =
866882 let
867883 compileInput ifaces =
868884 case Compile.compile pkg ifaces modul of
@@ -958,7 +974,7 @@ findLocation env path =
958974
959975
960976findLoc :: Env -> FilePath -> FilePath -> IO (Either Exit.BuildProjectProblem Location)
961−findLoc (Env _ root _ srcDirs _ _) path absolutePath =
977+findLoc (Env _ root _ srcDirs _ _ _) path absolutePath =
962978 let
963979 (dirs, file) = FP.splitFileName absolutePath
964980 (final, ext) = FP.splitExtension file
@@ -1054,7 +1070,7 @@ data MainStatus
10541070
10551071
10561072crawlMain :: Env -> MVar StatusDict -> MainLocation -> IO MainStatus
1057−crawlMain env@(Env _ _ pkg _ _ _) mvar given =
1073+crawlMain env@(Env _ _ pkg _ buildID _ _) mvar given =
10581074 case given of
10591075 LInside name ->
10601076 do statusMVar <- newEmptyMVar
@@ -1069,7 +1085,7 @@ crawlMain env@(Env _ _ pkg _ _ _) mvar given =
10691085 case Parse.fromByteString pkg source of
10701086 Right modul@(Src.Module _ _ _ imports values _ _ _ _) ->
10711087 do let deps = map Src.getImportName imports
1072− let local = Details.Local path time deps (any isMain values)
1088+ let local = Details.Local path time deps (any isMain values) buildID buildID
10731089 crawlDeps env mvar deps (SOutsideOk local source modul)
10741090
10751091 Left syntaxError ->
@@ -1089,7 +1105,7 @@ data MainResult
10891105
10901106
10911107checkMain :: Env -> ResultDict -> MainStatus -> IO MainResult
1092−checkMain env@(Env _ root _ _ _ _) results pendingMain =
1108+checkMain env@(Env _ root _ _ _ _ _) results pendingMain =
10931109 case pendingMain of
10941110 SInside name ->
10951111 return (RInside name)
@@ -1097,8 +1113,8 @@ checkMain env@(Env _ root _ _ _ _) results pendingMain =
10971113 SOutsideErr err ->
10981114 return (ROutsideErr err)
10991115
1100− SOutsideOk local@(Details.Local path time deps _) source modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
1101− do depsStatus <- checkDeps root results deps
1116+ SOutsideOk local@(Details.Local path time deps _ _ lastCompile) source modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
1117+ do depsStatus <- checkDeps root results deps lastCompile
11021118 case depsStatus of
11031119 DepsChange ifaces ->
11041120 compileOutside env local source ifaces modul
@@ -1118,7 +1134,7 @@ checkMain env@(Env _ root _ _ _ _) results pendingMain =
11181134
11191135
11201136compileOutside :: Env -> Details.Local -> B.ByteString -> Map.Map ModuleName.Raw I.Interface -> Src.Module -> IO MainResult
1121−compileOutside (Env key _ pkg _ _ _) (Details.Local path time _ _) source ifaces modul =
1137+compileOutside (Env key _ pkg _ _ _ _) (Details.Local path time _ _ _ _) source ifaces modul =
11221138 let
11231139 name = Src.getName modul
11241140 in
@@ -1141,7 +1157,7 @@ data Main
11411157
11421158
11431159toArtifacts :: Env -> Dependencies -> Map.Map ModuleName.Raw Result -> NE.List MainResult -> Either Exit.BuildProblem Artifacts
1144−toArtifacts (Env _ _ pkg _ _ _) foreigns results mainResults =
1160+toArtifacts (Env _ _ pkg _ _ _ _) foreigns results mainResults =
11451161 case gatherProblemsOrMains results mainResults of
11461162 Left (NE.List e es) ->
11471163 Left (Exit.BuildBadModules e es)
@@ -1178,7 +1194,7 @@ addInside name result modules =
11781194 case result of
11791195 RNew _ iface objs _ -> Fresh name iface objs : modules
11801196 RSame _ iface objs _ -> Fresh name iface objs : modules
1181− RCached main mvar -> Cached name main mvar : modules
1197+ RCached main _ mvar -> Cached name main mvar : modules
11821198 RNotFound _ -> error (badInside name)
11831199 RProblem _ -> error (badInside name)
11841200 RBlocked -> error (badInside name)