+type DFunId = Id
+data Instance
+ = Instance { is_cls :: Name -- Class name
+
+ -- Used for "rough matching"; see note below
+ , is_tcs :: [Maybe Name] -- Top of type args
+
+ -- Used for "proper matching"; see note
+ , is_tvs :: TyVarSet -- Template tyvars for full match
+ , is_tys :: [Type] -- Full arg types
+
+ , is_dfun :: DFunId
+ , is_flag :: OverlapFlag
+
+ , is_orph :: Maybe OccName }
+
+-- The "rough-match" fields
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~
+-- The is_cls, is_args fields allow a "rough match" to be done
+-- without poking inside the DFunId. Poking the DFunId forces
+-- us to suck in all the type constructors etc it involves,
+-- which is a total waste of time if it has no chance of matching
+-- So the Name, [Maybe Name] fields allow us to say "definitely
+-- does not match", based only on the Name.
+--
+-- In is_tcs,
+-- Nothing means that this type arg is a type variable
+--
+-- (Just n) means that this type arg is a
+-- TyConApp with a type constructor of n.
+-- This is always a real tycon, never a synonym!
+-- (Two different synonyms might match, but two
+-- different real tycons can't.)
+-- NB: newtypes are not transparent, though!
+--
+-- The "proper-match" fields
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~
+-- The is_tvs, is_tys fields are simply cahced values, pulled
+-- out (lazily) from the dfun id. They are cached here simply so
+-- that we don't need to decompose the DFunId each time we want
+-- to match it. The hope is that the fast-match fields mean
+-- that we often never poke th proper-match fields
+--
+-- However, note that:
+-- * is_tvs must be a superset of the free vars of is_tys
+--
+-- * The is_dfun must itself be quantified over exactly is_tvs
+-- (This is so that we can use the matching substitution to
+-- instantiate the dfun's context.)
+--
+-- The "orphan" field
+-- ~~~~~~~~~~~~~~~~~~
+-- An instance is an orphan if its head (after the =>) mentions
+-- nothing defined in this module.
+--
+-- Just n The head mentions n, which is defined in this module
+-- This is used for versioning; the instance decl is
+-- considered part of the defn of n when computing versions
+--
+-- Nothing The head mentions nothing defined in this modle
+--
+-- If a module contains any orphans, then its interface file is read
+-- regardless, so that its instances are not missed.
+--
+-- Functional dependencies worsen the situation a bit. Consider
+-- class C a b | a -> b
+-- In some other module we might have
+-- module M where
+-- data T = ...
+-- instance C Int T where ...
+-- This isn't considered an orphan, so we will only read M's interface
+-- if something from M is used (e.g. T). So there's a risk we'll
+-- miss the improvement from the instance. Workaround: import M.
+
+instanceDFunId :: Instance -> DFunId
+instanceDFunId = is_dfun
+
+setInstanceDFunId :: Instance -> DFunId -> Instance
+setInstanceDFunId ispec dfun
+ = ASSERT( idType dfun `tcEqType` idType (is_dfun ispec) )
+ -- We need to create the cached fields afresh from
+ -- the new dfun id. In particular, the is_tvs in
+ -- the Instance must match those in the dfun!
+ -- We assume that the only thing that changes is
+ -- the quantified type variables, so the other fields
+ -- are ok; hence the assert
+ ispec { is_dfun = dfun, is_tvs = mkVarSet tvs, is_tys = tys }
+ where
+ (tvs, _, _, tys) = tcSplitDFunTy (idType dfun)
+
+instanceRoughTcs :: Instance -> [Maybe Name]
+instanceRoughTcs = is_tcs
+\end{code}
+
+\begin{code}
+instance NamedThing Instance where
+ getName ispec = getName (is_dfun ispec)
+
+instance Outputable Instance where
+ ppr = pprInstance
+
+pprInstance :: Instance -> SDoc
+-- Prints the Instance as an instance declaration
+pprInstance ispec@(Instance { is_flag = flag })
+ = hang (pprInstanceHdr ispec)
+ 2 (ptext SLIT("--") <+> (pprDefnLoc (getSrcLoc ispec)))
+
+-- * pprInstanceHdr is used in VStudio to populate the ClassView tree
+pprInstanceHdr :: Instance -> SDoc
+-- Prints the Instance as an instance declaration
+pprInstanceHdr ispec@(Instance { is_flag = flag })
+ = ptext SLIT("instance") <+> ppr flag
+ <+> sep [pprThetaArrow theta, pprClassPred clas tys]
+ where
+ (_, theta, clas, tys) = instanceHead ispec
+ -- Print without the for-all, which the programmer doesn't write
+
+pprInstances :: [Instance] -> SDoc
+pprInstances ispecs = vcat (map pprInstance ispecs)
+
+instanceHead :: Instance -> ([TyVar], [PredType], Class, [Type])
+instanceHead ispec = tcSplitDFunTy (idType (is_dfun ispec))
+
+mkLocalInstance :: DFunId -> OverlapFlag -> Instance
+-- Used for local instances, where we can safely pull on the DFunId
+mkLocalInstance dfun oflag
+ = Instance { is_flag = oflag, is_dfun = dfun,
+ is_tvs = mkVarSet tvs, is_tys = tys,
+ is_cls = cls_name, is_tcs = roughMatchTcs tys,
+ is_orph = orph }
+ where
+ (tvs, _, cls, tys) = tcSplitDFunTy (idType dfun)
+ mod = nameModule (idName dfun)
+ cls_name = getName cls
+ tycl_names = foldr (unionNameSets . tyClsNamesOfType)
+ (unitNameSet cls_name) tys
+ orph = case filter (nameIsLocalOrFrom mod) (nameSetToList tycl_names) of
+ [] -> Nothing
+ (n:ns) -> Just (getOccName n)
+
+mkImportedInstance :: Name -> [Maybe Name] -> Maybe OccName
+ -> DFunId -> OverlapFlag -> Instance
+-- Used for imported instances, where we get the rough-match stuff
+-- from the interface file
+mkImportedInstance cls mb_tcs orph dfun oflag
+ = Instance { is_flag = oflag, is_dfun = dfun,
+ is_tvs = mkVarSet tvs, is_tys = tys,
+ is_cls = cls, is_tcs = mb_tcs, is_orph = orph }
+ where
+ (tvs, _, _, tys) = tcSplitDFunTy (idType dfun)
+
+roughMatchTcs :: [Type] -> [Maybe Name]
+roughMatchTcs tys = map rough tys
+ where
+ rough ty = case tcSplitTyConApp_maybe ty of
+ Just (tc,_) -> Just (tyConName tc)
+ Nothing -> Nothing
+
+instanceCantMatch :: [Maybe Name] -> [Maybe Name] -> Bool
+-- (instanceCantMatch tcs1 tcs2) returns True if tcs1 cannot
+-- possibly be instantiated to actual, nor vice versa;
+-- False is non-committal
+instanceCantMatch (Just t : ts) (Just a : as) = t/=a || instanceCantMatch ts as
+instanceCantMatch ts as = False -- Safe
+
+---------------------------------------------------
+data OverlapFlag
+ = NoOverlap -- This instance must not overlap another
+
+ | OverlapOk -- Silently ignore this instance if you find a
+ -- more specific one that matches the constraint
+ -- you are trying to resolve
+ --
+ -- Example: constraint (Foo [Int])
+ -- instances (Foo [Int])
+ -- (Foo [a]) OverlapOk
+ -- Since the second instance has the OverlapOk flag,
+ -- the first instance will be chosen (otherwise
+ -- its ambiguous which to choose)
+
+ | Incoherent -- Like OverlapOk, but also ignore this instance
+ -- if it doesn't match the constraint you are
+ -- trying to resolve, but could match if the type variables
+ -- in the constraint were instantiated
+ --
+ -- Example: constraint (Foo [b])
+ -- instances (Foo [Int]) Incoherent
+ -- (Foo [a])
+ -- Without the Incoherent flag, we'd complain that
+ -- instantiating 'b' would change which instance
+ -- was chosen
+
+instance Outputable OverlapFlag where
+ ppr NoOverlap = empty
+ ppr OverlapOk = ptext SLIT("[overlap ok]")
+ ppr Incoherent = ptext SLIT("[incoherent]")