Opened 8 months ago

Last modified 5 months ago

#8198 new bug

One-shot mode is buggy w.r.t. hs-boot files

Reported by: parcs Owned by: parcs
Priority: normal Milestone: 7.8.3
Component: Driver Version: 7.7
Keywords: Cc: simonmar
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect warning at compile-time Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Consider

A.hs-boot

module A where

B.hs

module B where

import {-# SOURCE #-} A

Command Line

$ ghc -c A.hs-boot B.hs

B.hs:3:1:
    Bad interface file: A.hi-boot-boot
        A.hi-boot-boot: openBinaryFile: does not exist (No such file or directory)

I expect the modules to get compiled cleanly. Instead I get an error.

Change History (8)

comment:1 Changed 8 months ago by parcs

  • Owner set to parcs

The problem is that when compiling A.hs-boot, module A's hs-boot file is added to the finder cache instead of its corresponding source file. So when the interface file for module A is requested, the finder cache returns "A.hi-boot". It then appends "-boot" to the end of that to get "A.hi-boot-boot".

Since it is assumed that every home-module location in the finder cache corresponds to a source file, the correct solution is to always add the home-module's source-file location to the finder cache, even if the current file happens to be an hs-boot file.

Last edited 8 months ago by parcs (previous) (diff)

comment:2 Changed 5 months ago by simonpj

  • Cc simonmar added

Simon M would you care to comment?

comment:3 Changed 5 months ago by parcs

Here's a patch of the change I'm proposing.

  • compiler/main/DriverPipeline.hs

    diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
    index 44a6fa5..b4f4844 100644
    a b runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0 
    928928        PipeState{hsc_env=hsc_env'} <- getPipeState 
    929929 
    930930  -- Tell the finder cache about this module 
    931         mod <- liftIO $ addHomeModuleToFinder hsc_env' mod_name location 
     931  -- 
     932  -- If we're compiling an hs-boot file in one-shot mode, assume that a 
     933  -- corresponding source file exists in the same directory and add that into 
     934  -- the finder cache instead, to maintain the invariant that locations in the 
     935  -- finder cache correspond to a module's source file only. 
     936        mod <- do 
     937            src_location <- if isHsBoot src_flavour 
     938                                then getLocation HsSrcFile mod_name 
     939                                else return location 
     940            liftIO $ addHomeModuleToFinder hsc_env' mod_name src_location 
    932941 
    933942  -- Make the ModSummary to hand to hscMain 
    934943        let 

comment:4 follow-up: Changed 5 months ago by simonmar

shouldn't we set ml_hs_file to Nothing in this case, rather than assuming that it is in the same location as the hs-boot file?

comment:5 in reply to: ↑ 4 Changed 5 months ago by parcs

Replying to simonmar:

shouldn't we set ml_hs_file to Nothing in this case, rather than assuming that it is in the same location as the hs-boot file?

I think that's a fair assumption since we already assume that hi-boot/o-boot files are in the same directory as their corresponding hi/o files.

Version 0, edited 5 months ago by parcs (next)

comment:6 Changed 5 months ago by simonmar

FC and MLC?

I don't think we make that assumption in one-shot mode. Why make the assumption if we don't need to?

comment:7 Changed 5 months ago by parcs

Sorry, I meant the finder cache and mod location cache. I agree now -- there is no reason to assume that the source module exists in the same directory as the boot module. Does this patch look OK?

  • compiler/main/DriverPipeline.hs

    diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
    index 337778e..0ecb5eb 100644
    a b runPhase (RealPhase (Hsc src_flavour)) input_fn dflags0 
    928928        PipeState{hsc_env=hsc_env'} <- getPipeState 
    929929 
    930930  -- Tell the finder cache about this module 
    931         mod <- liftIO $ addHomeModuleToFinder hsc_env' mod_name location 
     931        mod <- do 
     932            -- We pass in HsSrcFile unconditionally, even if we're compiling a 
     933            -- boot module, because every location in the finder cache 
     934            -- corresponds to a module's source files only. 
     935            src_location0 <- getLocation HsSrcFile mod_name 
     936 
     937            -- However, if we're compiling a boot module then don't make any 
     938            -- assumptions about the location of the source module.  It could 
     939            -- be in a different directory than the boot module. 
     940            let src_location1 
     941                  | isHsBoot src_flavour = src_location0 { ml_hs_file = Nothing } 
     942                  | otherwise            = src_location0 
     943            liftIO $ addHomeModuleToFinder hsc_env' mod_name src_location1 
    932944 
    933945  -- Make the ModSummary to hand to hscMain 
    934946        let 

comment:8 Changed 5 months ago by simonmar

ooh, inline diffs. Funky.

It's not true that "every location in the finder cache corresponds to a module's source files only". In one-shot mode, the finder cache is full of locations that only have .hi files. See findHomeModule, and hi_exts.

I think we should be calling mkHiOnlyModLocation here, because in one-shot mode that is what is normally used to create ModLocations that go in the finder cache.

Note: See TracTickets for help on using tickets.