+\begin{code}
+tcTyAndClassDecls :: [LTyClDecl Name]
+ -> TcM TcGblEnv -- Input env extended by types and classes
+ -- and their implicit Ids,DataCons
+tcTyAndClassDecls decls
+ = do { -- First check for cyclic type synonysm or classes
+ -- See notes with checkCycleErrs
+ checkCycleErrs decls
+
+ ; let { udecls = map unLoc decls }
+ ; tyclss <- fixM (\ rec_tyclss ->
+ do { lcl_things <- mappM getInitialKind udecls
+ -- Extend the local env with kinds, and
+ -- the global env with the knot-tied results
+ ; let { gbl_things = mkGlobalThings udecls rec_tyclss }
+ ; tcExtendRecEnv gbl_things lcl_things $ do
+
+ -- The local type environment is populated with
+ -- {"T" -> ARecTyCon k, ...}
+ -- and the global type envt with
+ -- {"T" -> ATyCon T, ...}
+ -- where k is T's (unzonked) kind
+ -- T is the loop-tied TyCon itself
+ -- We must populate the environment with the loop-tied T's right
+ -- away, because the kind checker may "fault in" some type
+ -- constructors that recursively mention T
+
+ -- Kind-check the declarations, returning kind-annotated decls
+ { kc_decls <- mappM kcTyClDecl decls
+
+ -- Calculate variances and rec-flag
+ ; let { calc_vrcs = calcTyConArgVrcs rec_tyclss
+ ; calc_rec = calcRecFlags rec_tyclss }
+
+ ; mappM (tcTyClDecl calc_vrcs calc_rec) kc_decls
+ }})
+ -- Finished with knot-tying now
+ -- Extend the environment with the finished things
+ ; tcExtendGlobalEnv tyclss $ do
+
+ -- Perform the validity check
+ { traceTc (text "ready for validity check")
+ ; mappM_ checkValidTyCl decls
+ ; traceTc (text "done")
+
+ -- Add the implicit things;
+ -- we want them in the environment because
+ -- they may be mentioned in interface files
+ ; let { implicit_things = concatMap implicitTyThings tyclss }
+ ; traceTc ((text "Adding" <+> ppr tyclss) $$ (text "and" <+> ppr implicit_things))
+ ; tcExtendGlobalEnv implicit_things getGblEnv
+ }}
+
+mkGlobalThings :: [TyClDecl Name] -- The decls
+ -> [TyThing] -- Knot-tied, in 1-1 correspondence with the decls
+ -> [(Name,TyThing)]
+-- Driven by the Decls, and treating the TyThings lazily
+-- make a TypeEnv for the new things
+mkGlobalThings decls things
+ = map mk_thing (decls `zipLazy` things)
+ where
+ mk_thing (ClassDecl {tcdLName = L _ name}, ~(AClass cl))
+ = (name, AClass cl)
+ mk_thing (decl, ~(ATyCon tc))
+ = (tcdName decl, ATyCon tc)