Commit bba004f2 authored by Edward Z. Yang's avatar Edward Z. Yang

Prevent users from defining instances for abstract classes.

Summary:
Fixes #13068.
Signed-off-by: default avatarEdward Z. Yang <ezyang@cs.stanford.edu>

Test Plan: validate

Reviewers: simonpj, austin, bgamari

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D3254
parent df919fb2
......@@ -520,6 +520,10 @@ doClsInstErrorChecks inst_info
-- In hs-boot files there should be no bindings
; failIfTc (is_boot && not no_binds) badBootDeclErr
-- If not in an hs-boot file, abstract classes cannot have
-- instances declared
; failIfTc (not is_boot && isAbstractClass clas) abstractClassInstErr
-- Handwritten instances of any rejected
-- class is always forbidden
-- #12837
......@@ -535,12 +539,16 @@ doClsInstErrorChecks inst_info
binds = iBinds inst_info
no_binds = isEmptyLHsBinds (ib_binds binds) && null (ib_pragmas binds)
clas_nm = is_cls_nm ispec
clas = is_cls ispec
gen_inst_err = hang (text ("Generic instances can only be "
++ "derived in Safe Haskell.") $+$
text "Replace the following instance:")
2 (pprInstanceHdr ispec)
abstractClassInstErr =
text "Cannot define instance for abstract class" <+> quotes (ppr clas_nm)
-- Report an error or a warning for certain class instances.
-- If we are working on an .hs-boot file, we just report a warning,
-- and ignore the instance. We do this, to give users a chance to fix
......
......@@ -18,6 +18,7 @@ module Class (
classKey, className, classATs, classATItems, classTyCon, classMethods,
classOpItems, classBigSig, classExtraBigSig, classTvsFds, classSCTheta,
classAllSelIds, classSCSelId, classMinimalDef, classHasFds,
isAbstractClass,
naturallyCoherentClass
) where
......@@ -302,6 +303,10 @@ classExtraBigSig (Class {classTyVars = tyvars, classFunDeps = fundeps,
}})
= (tyvars, fundeps, sc_theta, sc_sels, ats, op_stuff)
isAbstractClass :: Class -> Bool
isAbstractClass Class{ classBody = AbstractClass } = True
isAbstractClass _ = False
-- | If a class is "naturally coherent", then we needn't worry at all, in any
-- way, about overlapping/incoherent instances. Just solve the thing!
naturallyCoherentClass :: Class -> Bool
......
module T13068 where
import T13068a
class C a where
f :: a
[1 of 4] Compiling T13068[boot] ( T13068.hs-boot, T13068.o-boot )
[2 of 4] Compiling T13068a ( T13068a.hs, T13068a.o )
T13068a.hs:3:1: error:
• Cannot define instance for abstract class ‘C’
• In the instance declaration for ‘C Int’
module T13068a where
import {-# SOURCE #-} T13068
instance C Int where
import T13068
main = print (f :: Int)
......@@ -424,6 +424,7 @@ test('T12918b', normal, compile_fail, [''])
test('T12921', normal, compile_fail, [''])
test('T12973', normal, compile_fail, [''])
test('StrictBinds', normal, compile_fail, [''])
test('T13068', [extra_files(['T13068.hs', 'T13068a.hs', 'T13068.hs-boot', 'T13068m.hs'])], multimod_compile_fail, ['T13068m', ''])
test('T13105', normal, compile_fail, [''])
test('LevPolyBounded', normal, compile_fail, [''])
test('T13292', normal, multimod_compile, ['T13292', '-v0 -fdefer-type-errors'])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment