-tcResultType :: TyCon -> [TyVar] -> ResType Name -> TcM (TyCon, [TcType])
-tcResultType tycon tvs ResTyH98 = return (tycon, mkTyVarTys tvs)
-tcResultType _ _ (ResTyGADT res_ty) = tcLHsConResTy res_ty
-
-tryVanilla :: [TyVar] -> [TcType] -> [TyVar]
--- (tryVanilla tvs tys) returns a permutation of tvs.
--- It tries to re-order the tvs so that it exactly
--- matches the [Type], if that is possible
-tryVanilla tvs (ty:tys) | Just tv <- tcGetTyVar_maybe ty -- The type is a tyvar
- , tv `elem` tvs -- That tyvar is in the list
- = tv : tryVanilla (delete tv tvs) tys
-tryVanilla tvs tys = tvs -- Fall through case
-
+tcResultType :: TyCon
+ -> [TyVar] -- data T a b c = ...
+ -> [TyVar] -- where MkT :: forall a b c. ...
+ -> ResType Name
+ -> TcM ([TyVar], -- Universal
+ [TyVar], -- Existential
+ [(TyVar,Type)], -- Equality predicates
+ TyCon) -- TyCon given in the ResTy
+ -- We don't check that the TyCon given in the ResTy is
+ -- the same as the parent tycon, becuase we are in the middle
+ -- of a recursive knot; so it's postponed until checkValidDataCon
+
+tcResultType decl_tycon tc_tvs dc_tvs ResTyH98
+ = return (tc_tvs, dc_tvs, [], decl_tycon)
+ -- In H98 syntax the dc_tvs are the existential ones
+ -- data T a b c = forall d e. MkT ...
+ -- The {a,b,c} are tc_tvs, and {d,e} are dc_tvs
+
+tcResultType _ tc_tvs dc_tvs (ResTyGADT res_ty)
+ -- E.g. data T a b c where
+ -- MkT :: forall x y z. T (x,y) z z
+ -- Then we generate
+ -- ([a,z,c], [x,y], [a:=:(x,y), c:=:z], T)
+
+ = do { (dc_tycon, res_tys) <- tcLHsConResTy res_ty
+ -- NB: tc_tvs and dc_tvs are distinct
+ ; let univ_tvs = choose_univs [] tc_tvs res_tys
+ -- Each univ_tv is either a dc_tv or a tc_tv
+ ex_tvs = dc_tvs `minusList` univ_tvs
+ eq_spec = [ (tv, ty) | (tv,ty) <- univ_tvs `zip` res_tys,
+ tv `elem` tc_tvs]
+ ; return (univ_tvs, ex_tvs, eq_spec, dc_tycon) }
+ where
+ -- choose_univs uses the res_ty itself if it's a type variable
+ -- and hasn't already been used; otherwise it uses one of the tc_tvs
+ choose_univs used tc_tvs []
+ = ASSERT( null tc_tvs ) []
+ choose_univs used (tc_tv:tc_tvs) (res_ty:res_tys)
+ | Just tv <- tcGetTyVar_maybe res_ty, not (tv `elem` used)
+ = tv : choose_univs (tv:used) tc_tvs res_tys
+ | otherwise
+ = tc_tv : choose_univs used tc_tvs res_tys