More concretely: you can't both declare security group rules inside a security_group, and also have separate security_group_rule declarations for the same group. Doesn't matter if they're in the same file or not.
Bad:
resource "aws_security_group" "sg" {
ingress { ... port = 80 ... }
}
resource "aws_security_group_rule" "https_too" {
type = "ingress"
from_port = 443
to_port = 443
}
Good:
resource "aws_security_group" "sg" {
# no ingress or egress rules
}
My experience has generally been that it's more predictable to declare anything where there's a resource A, a resource B, and an attach-A-to-B resource always as three separate parts and not as resource "A" { B { ... } }, for exactly the case you describe: if you need to add more rules or attach more devices or whatever else, Terraform's behavior is more obvious when the attachment is separate.