Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Tc/Solver/Dict.hs
    ... ... @@ -263,7 +263,9 @@ in two places:
    263 263
     * In `updInertDicts`, in this module, when adding [G] (?x :: ty), remove any
    
    264 264
       existing [G] (?x :: ty'), regardless of ty'.
    
    265 265
     
    
    266
    -* Wrinkle (SIP1): we must be careful of superclasses.  Consider
    
    266
    +There are wrinkles:
    
    267
    +
    
    268
    +* Wrinkle (SIP1): we must be careful of superclasses (#14218).  Consider
    
    267 269
          f,g :: (?x::Int, C a) => a -> a
    
    268 270
          f v = let ?x = 4 in g v
    
    269 271
     
    
    ... ... @@ -271,24 +273,31 @@ in two places:
    271 273
       We must /not/ solve this from the Given (?x::Int, C a), because of
    
    272 274
       the intervening binding for (?x::Int).  #14218.
    
    273 275
     
    
    274
    -  We deal with this by arranging that when we add [G] (?x::ty) we delete
    
    276
    +  We deal with this by arranging that when we add [G] (?x::ty) we /delete/
    
    275 277
       * from the inert_cans, and
    
    276 278
       * from the inert_solved_dicts
    
    277 279
       any existing [G] (?x::ty) /and/ any [G] D tys, where (D tys) has a superclass
    
    278 280
       with (?x::ty).  See Note [Local implicit parameters] in GHC.Core.Predicate.
    
    279 281
     
    
    280
    -  An important special case is constraint tuples like [G] (% ?x::ty, Eq a %).
    
    281
    -  But it could happen for `class xx => D xx where ...` and the constraint D
    
    282
    -  (?x :: int).  This corner (constraint-kinded variables instantiated with
    
    283
    -  implicit parameter constraints) is not well explored.
    
    282
    +  An very important special case is constraint tuples like [G] (% ?x::ty, Eq a %).
    
    283
    +
    
    284
    +  But it could also happen for `class xx => D xx where ...` and the constraint
    
    285
    +  D (?x :: int); again see Note [Local implicit parameters].  This corner
    
    286
    +  (constraint-kinded variables instantiated with implicit parameter constraints)
    
    287
    +  is not well explored.
    
    284 288
     
    
    285
    -  Example in #14218, and #23761
    
    289
    +  You might worry about whether deleting an /entire/ constraint just because
    
    290
    +  a distant superclass has an implicit parameter might make another Wanted for
    
    291
    +  that constraint un-solvable.  Indeed so. But for constraint tuples it doesn't
    
    292
    +  matter -- their entire payload is their superclasses.  And the other case is
    
    293
    +  the ill-explored corner above.
    
    286 294
     
    
    287 295
       The code that accounts for (SIP1) is in updInertDicts; in particular the call to
    
    288 296
       GHC.Core.Predicate.mentionsIP.
    
    289 297
     
    
    290 298
     * Wrinkle (SIP2): we must apply this update semantics for `inert_solved_dicts`
    
    291
    -  as well as `inert_cans`.
    
    299
    +  as well as `inert_cans` (#23761).
    
    300
    +
    
    292 301
       You might think that wouldn't be necessary, because an element of
    
    293 302
       `inert_solved_dicts` is never an implicit parameter (see
    
    294 303
       Note [Solved dictionaries] in GHC.Tc.Solver.InertSet).
    
    ... ... @@ -301,6 +310,19 @@ in two places:
    301 310
       Now (C (?x::Int)) has a superclass (?x::Int). This may look exotic, but it
    
    302 311
       happens particularly for constraint tuples, like `(% ?x::Int, Eq a %)`.
    
    303 312
     
    
    313
    +* Wrinkle (SIP3)
    
    314
    +  - Note that for the inert dictionaries, `inert_cans`, we must /only/ delete
    
    315
    +    existing /Givens/!  Deleting an existing Wanted led to #26451; we just never
    
    316
    +    solved it!
    
    317
    +
    
    318
    +  - In contrast, the solved dictionaries, `inert_solved_dicts`, are really like
    
    319
    +    Givens; they may be "inherited" from outer scopes, so we must delete any
    
    320
    +    solved dictionaries for this implicit parameter for /both/ Givens /and/
    
    321
    +    Wanteds.
    
    322
    +
    
    323
    +    Otherwise the new Given doesn't properly shadow those inherited solved
    
    324
    +    dictionaries. Test T23761 showed this up.
    
    325
    +
    
    304 326
     Example 1:
    
    305 327
     
    
    306 328
     Suppose we have (typecheck/should_compile/ImplicitParamFDs)
    

  • compiler/GHC/Tc/Solver/Monad.hs
    ... ... @@ -377,28 +377,53 @@ in GHC.Tc.Solver.Dict.
    377 377
     -}
    
    378 378
     
    
    379 379
     updInertDicts :: DictCt -> TcS ()
    
    380
    -updInertDicts dict_ct@(DictCt { di_cls = cls, di_ev = ev, di_tys = tys })
    
    381
    -  = do { traceTcS "Adding inert dict" (ppr dict_ct $$ ppr cls  <+> ppr tys)
    
    382
    -
    
    383
    -       ; if | isGiven ev, Just (str_ty, _) <- isIPPred_maybe cls tys
    
    384
    -            -> -- For [G] ?x::ty, remove any dicts mentioning ?x,
    
    385
    -              --    from /both/ inert_cans /and/ inert_solved_dicts (#23761)
    
    386
    -               -- See (SIP1) and (SIP2) in Note [Shadowing of implicit parameters]
    
    387
    -               updInertSet $ \ inerts@(IS { inert_cans = ics, inert_solved_dicts = solved }) ->
    
    388
    -               inerts { inert_cans         = updDicts (filterDicts (does_not_mention_ip_for str_ty)) ics
    
    389
    -                      , inert_solved_dicts = filterDicts (does_not_mention_ip_for str_ty) solved }
    
    390
    -            | otherwise
    
    391
    -            -> return ()
    
    380
    +updInertDicts dict_ct
    
    381
    +  = do { traceTcS "Adding inert dict" (ppr dict_ct)
    
    382
    +
    
    383
    +       -- For Given implicit parameters (only), delete any existing
    
    384
    +       -- Givens for the same implicit parameter.
    
    385
    +       -- See Note [Shadowing of implicit parameters]
    
    386
    +       ; deleteGivenIPs dict_ct
    
    387
    +
    
    392 388
            -- Add the new constraint to the inert set
    
    393 389
            ; updInertCans (updDicts (addDict dict_ct)) }
    
    390
    +
    
    391
    +deleteGivenIPs :: DictCt -> TcS ()
    
    392
    +-- Special magic when adding a Given implicit parameter to the inert set
    
    393
    +-- For [G] ?x::ty, remove any existing /Givens/ mentioning ?x,
    
    394
    +--    from /both/ inert_cans /and/ inert_solved_dicts (#23761)
    
    395
    +-- See Note [Shadowing of implicit parameters]
    
    396
    +deleteGivenIPs (DictCt { di_cls = cls, di_ev = ev, di_tys = tys })
    
    397
    +  | isGiven ev
    
    398
    +  , Just (str_ty, _) <- isIPPred_maybe cls tys
    
    399
    +  = updInertSet $ \ inerts@(IS { inert_cans = ics, inert_solved_dicts = solved }) ->
    
    400
    +    inerts { inert_cans         = updDicts (filterDicts (keep_can str_ty)) ics
    
    401
    +           , inert_solved_dicts = filterDicts (keep_solved str_ty) solved }
    
    402
    +  | otherwise
    
    403
    +  = return ()
    
    394 404
       where
    
    395
    -    -- Does this class constraint or any of its superclasses mention
    
    396
    -    -- an implicit parameter (?str :: ty) for the given 'str' and any type 'ty'?
    
    397
    -    does_not_mention_ip_for :: Type -> DictCt -> Bool
    
    398
    -    does_not_mention_ip_for str_ty (DictCt { di_cls = cls, di_tys = tys })
    
    399
    -      = not $ mightMentionIP (not . typesAreApart str_ty) (const True) cls tys
    
    400
    -        -- See Note [Using typesAreApart when calling mightMentionIP]
    
    401
    -        -- in GHC.Core.Predicate
    
    405
    +    keep_can, keep_solved :: Type -> DictCt -> Bool
    
    406
    +    -- keep_can: we keep an inert dictionary UNLESS
    
    407
    +    --   (1) it is a Given
    
    408
    +    --   (2) it binds an implicit parameter (?str :: ty) for the given 'str'
    
    409
    +    --       regardless of 'ty', possibly via its superclasses
    
    410
    +    -- The test is a bit conservative, hence `mightMentionIP` and `typesAreApart`
    
    411
    +    -- See Note [Using typesAreApart when calling mightMentionIP]
    
    412
    +    -- in GHC.Core.Predicate
    
    413
    +    --
    
    414
    +    -- keep_solved: same as keep_can, but for /all/ constraints not just Givens
    
    415
    +    --
    
    416
    +    -- Why two functions?  See (SIP3) in Note [Shadowing of implicit parameters]
    
    417
    +    keep_can str (DictCt { di_ev = ev, di_cls = cls, di_tys = tys })
    
    418
    +      = not (isGiven ev                -- (1)
    
    419
    +          && mentions_ip str cls tys)  -- (2)
    
    420
    +    keep_solved str (DictCt { di_cls = cls, di_tys = tys })
    
    421
    +      = not (mentions_ip str cls tys)
    
    422
    +
    
    423
    +    -- mentions_ip: the inert constraint might provide evidence
    
    424
    +    -- for an implicit parameter (?str :: ty) for the given 'str'
    
    425
    +    mentions_ip str cls tys
    
    426
    +      = mightMentionIP (not . typesAreApart str) (const True) cls tys
    
    402 427
     
    
    403 428
     updInertIrreds :: IrredCt -> TcS ()
    
    404 429
     updInertIrreds irred
    

  • testsuite/tests/typecheck/should_compile/T26451.hs
    1
    +{-# LANGUAGE ImplicitParams, TypeFamilies, FunctionalDependencies, ScopedTypeVariables #-}
    
    2
    +
    
    3
    +module T26451 where
    
    4
    +
    
    5
    +type family F a
    
    6
    +type instance F Bool = [Char]
    
    7
    +
    
    8
    +class C a b | b -> a
    
    9
    +instance C Bool Bool
    
    10
    +instance C Char Char
    
    11
    +
    
    12
    +eq :: forall a b. C a b => a -> b -> ()
    
    13
    +eq p q = ()
    
    14
    +
    
    15
    +g :: a -> F a
    
    16
    +g = g
    
    17
    +
    
    18
    +f (x::tx) (y::ty)   -- x :: alpha y :: beta
    
    19
    +  = let ?v = g x   -- ?ip :: F alpha
    
    20
    +      in (?v::[ty], eq x True)
    
    21
    +
    
    22
    +
    
    23
    +{- tx, and ty are unification variables
    
    24
    +
    
    25
    +Inert: [G] dg :: IP "v" (F tx)
    
    26
    +       [W] dw :: IP "v" [ty]
    
    27
    +Work-list: [W] dc1 :: C tx Bool
    
    28
    +           [W] dc2 :: C ty Char
    
    29
    +
    
    30
    +* Solve dc1, we get tx := Bool from fundep
    
    31
    +* Kick out dg
    
    32
    +* Solve dg to get [G] dc : IP "v" [Char]
    
    33
    +* Add that new dg to the inert set: that simply deletes dw!!!
    
    34
    +-}

  • testsuite/tests/typecheck/should_compile/all.T
    ... ... @@ -955,3 +955,4 @@ test('T26376', normal, compile, [''])
    955 955
     test('T26457', normal, compile, [''])
    
    956 956
     test('T17705', normal, compile, [''])
    
    957 957
     test('T14745', normal, compile, [''])
    
    958
    +test('T26451', normal, compile, [''])