code: func (c *Compiler) checkRuleConflicts() {
  	c.RuleTree.DepthFirst(func(node *TreeNode) bool {
  		if len(node.Values) == 0 {
  			return false
  		}
  
  		kinds := map[DocKind]struct{}{}
  		defaultRules := 0
  		arities := map[int]struct{}{}
  
  		for _, rule := range node.Values {
  			r := rule.(*Rule)
  			kinds[r.Head.DocKind()] = struct{}{}
  			arities[len(r.Head.Args)] = struct{}{}
  			if r.Default {
  				defaultRules++
  			}
  		}
  
  		name := Var(node.Key.(String))
  
  		if len(kinds) > 1 || len(arities) > 1 {
  			c.err(NewError(TypeErr, node.Values[0].(*Rule).Loc(), "conflicting rules named %v found", name))
  		}
  
  		if defaultRules > 1 {
  			c.err(NewError(TypeErr, node.Values[0].(*Rule).Loc(), "multiple default rules named %s found", name))
  		}
  
  		return false
  	})
  
  	if c.pathExists != nil {
  		for _, err := range CheckPathConflicts(c, c.pathExists) {
  			c.err(err)
  		}
  	}
  
  	c.ModuleTree.DepthFirst(func(node *ModuleTreeNode) bool {
  		for _, mod := range node.Modules {
  			for _, rule := range mod.Rules {
  				if childNode, ok := node.Children[String(rule.Head.Name)]; ok {
  					for _, childMod := range childNode.Modules {
  						msg := fmt.Sprintf("%v conflicts with rule defined at %v", childMod.Package, rule.Loc())
  						c.err(NewError(TypeErr, mod.Package.Loc(), msg))
  					}
  				}
  			}
  		}
  		return false
  	})
  }
docs: // checkRuleConflicts ensures that rules definitions are not in conflict.