diff --git a/internal/shader/shader.go b/internal/shader/shader.go index b6783c446..c083932bf 100644 --- a/internal/shader/shader.go +++ b/internal/shader/shader.go @@ -315,8 +315,15 @@ func (cs *compileState) parseDecl(b *block, fname string, d ast.Decl) ([]shaderi if !ok { return nil, false } + n := s.Name.Name + for _, t := range b.types { + if t.name == n { + cs.addError(s.Pos(), fmt.Sprintf("%s redeclared in this block", n)) + return nil, false + } + } b.types = append(b.types, typ{ - name: s.Name.Name, + name: n, ir: t, }) } diff --git a/internal/shader/syntax_test.go b/internal/shader/syntax_test.go index a4d01c4e7..a7816f8a6 100644 --- a/internal/shader/syntax_test.go +++ b/internal/shader/syntax_test.go @@ -2381,3 +2381,30 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 { } } } + +func TestTypeRedeclaration(t *testing.T) { + cases := []struct { + stmt string + err bool + }{ + {stmt: "type Foo int; type Foo int", err: true}, + {stmt: "type Foo int; type Foo float", err: true}, + {stmt: "type Foo int; type Bar int", err: false}, + } + + for _, c := range cases { + stmt := c.stmt + src := fmt.Sprintf(`package main + +func Fragment(position vec4, texCoord vec2, color vec4) vec4 { + %s + return position +}`, stmt) + _, err := compileToIR([]byte(src)) + if err == nil && c.err { + t.Errorf("%s must return an error but does not", stmt) + } else if err != nil && !c.err { + t.Errorf("%s must not return nil but returned %v", stmt, err) + } + } +}