Probably because you didn’t edit the 2-layer initialization of hidden and that was used as h and c.
If you go the route of separating the two, the LSTM case should probably be
 output, (h, cl) = self.rnn(emb,  (h,  c)) 

but you can also define hidden to be the tuple of (h,c) and go with that.
The init_hidden seems relatively correct (even if you’d use weight.new_zeros these days), but your manual definition of hidden isn’t. Maybe you just can inspect the output of init_hidden in an interactive shell and draw your own conclusions.
Best regards
Thomas