Reject duplicate top level names
diff --git a/lang/ast/ast.go b/lang/ast/ast.go
index 78a7819..65304af 100644
--- a/lang/ast/ast.go
+++ b/lang/ast/ast.go
@@ -473,6 +473,8 @@
 type Var Node
 
 func (n *Var) AsNode() *Node    { return (*Node)(n) }
+func (n *Var) Filename() string { return n.filename }
+func (n *Var) Line() uint32     { return n.line }
 func (n *Var) Name() t.ID       { return n.id2 }
 func (n *Var) XType() *TypeExpr { return n.lhs.AsTypeExpr() }
 
diff --git a/lang/check/check.go b/lang/check/check.go
index be1c892..a2da22a 100644
--- a/lang/check/check.go
+++ b/lang/check/check.go
@@ -88,15 +88,16 @@
 		resolveUse: resolveUse,
 		reasonMap:  rMap,
 
-		consts:    map[t.QID]*a.Const{},
+		topLevelNames: map[t.ID]a.Kind{
+			t.IDBase: a.KUse,
+		},
+
+		consts:   map[t.QID]*a.Const{},
+		statuses: map[t.QID]*a.Status{},
+		structs:  map[t.QID]*a.Struct{},
+
 		funcs:     map[t.QQID]*a.Func{},
 		localVars: map[t.QQID]typeMap{},
-		statuses:  map[t.QID]*a.Status{},
-		structs:   map[t.QID]*a.Struct{},
-
-		useBaseNames: map[t.ID]struct{}{
-			t.IDBase: struct{}{},
-		},
 
 		builtInSliceFuncs: map[t.QQID]*a.Func{},
 		builtInTableFuncs: map[t.QQID]*a.Func{},
@@ -202,7 +203,6 @@
 	{a.KInvalid, (*Checker).checkInterfacesSatisfied},
 	{a.KStruct, (*Checker).checkFieldMethodCollisions},
 	{a.KInvalid, (*Checker).checkAllTypeChecked},
-	// TODO: check consts, funcs, structs and uses for name collisions.
 }
 
 type reason func(q *checker, n *a.Assert) error
@@ -214,15 +214,20 @@
 	resolveUse func(usePath string) ([]byte, error)
 	reasonMap  reasonMap
 
-	consts    map[t.QID]*a.Const
+	// The topLevelNames map is keyed by the const/status/struct/use
+	// unqualified name (ID, not QID).
+	//
+	// For `use "foo/bar"`, the name is the base name: "bar".
+	topLevelNames map[t.ID]a.Kind
+
+	// These maps are keyed by the const/status/struct name (QID).
+	consts   map[t.QID]*a.Const
+	statuses map[t.QID]*a.Status
+	structs  map[t.QID]*a.Struct
+
+	// These maps are keyed by the func name (QQID).
 	funcs     map[t.QQID]*a.Func
 	localVars map[t.QQID]typeMap
-	statuses  map[t.QID]*a.Status
-	structs   map[t.QID]*a.Struct
-
-	// useBaseNames are the base names of packages referred to by `use
-	// "foo/bar"` lines. The keys are `bar`, not `"foo/bar"`.
-	useBaseNames map[t.ID]struct{}
 
 	builtInSliceFuncs map[t.QQID]*a.Func
 	builtInTableFuncs map[t.QQID]*a.Func
@@ -243,11 +248,14 @@
 	baseName, err := c.tm.Insert(path.Base(filename))
 	if err != nil {
 		return fmt.Errorf("check: cannot resolve `use %s`: %v", usePath.Str(c.tm), err)
+	} else if c.topLevelNames[baseName] != 0 {
+		return &Error{
+			Err:      fmt.Errorf("check: duplicate top level name %q", baseName.Str(c.tm)),
+			Filename: node.AsUse().Filename(),
+			Line:     node.AsUse().Line(),
+		}
 	}
 	filename += ".wuffs"
-	if _, ok := c.useBaseNames[baseName]; ok {
-		return fmt.Errorf("check: duplicate `use \"etc\"` base name %q", baseName.Str(c.tm))
-	}
 
 	if c.resolveUse == nil {
 		return fmt.Errorf("check: cannot resolve a use declaration")
@@ -291,7 +299,7 @@
 			}
 		}
 	}
-	c.useBaseNames[baseName] = struct{}{}
+	c.topLevelNames[baseName] = a.KUse
 	setPlaceholderMBoundsMType(node)
 	return nil
 }
@@ -308,6 +316,16 @@
 			OtherLine:     other.Line(),
 		}
 	}
+	if qid[0] == 0 {
+		if c.topLevelNames[qid[1]] != 0 {
+			return &Error{
+				Err:      fmt.Errorf("check: duplicate top level name %q", qid[1].Str(c.tm)),
+				Filename: n.Filename(),
+				Line:     n.Line(),
+			}
+		}
+		c.topLevelNames[qid[1]] = a.KStatus
+	}
 	c.statuses[qid] = n
 
 	setPlaceholderMBoundsMType(n.AsNode())
@@ -326,6 +344,16 @@
 			OtherLine:     other.Line(),
 		}
 	}
+	if qid[0] == 0 {
+		if c.topLevelNames[qid[1]] != 0 {
+			return &Error{
+				Err:      fmt.Errorf("check: duplicate top level name %q", qid[1].Str(c.tm)),
+				Filename: n.Filename(),
+				Line:     n.Line(),
+			}
+		}
+		c.topLevelNames[qid[1]] = a.KConst
+	}
 	c.consts[qid] = n
 
 	q := &checker{
@@ -398,6 +426,16 @@
 			OtherLine:     other.Line(),
 		}
 	}
+	if qid[0] == 0 {
+		if c.topLevelNames[qid[1]] != 0 {
+			return &Error{
+				Err:      fmt.Errorf("check: duplicate top level name %q", qid[1].Str(c.tm)),
+				Filename: n.Filename(),
+				Line:     n.Line(),
+			}
+		}
+		c.topLevelNames[qid[1]] = a.KStruct
+	}
 	c.structs[qid] = n
 	c.unsortedStructs = append(c.unsortedStructs, n)
 	setPlaceholderMBoundsMType(n.AsNode())
diff --git a/lang/check/type.go b/lang/check/type.go
index a3f8824..7f53b06 100644
--- a/lang/check/type.go
+++ b/lang/check/type.go
@@ -34,6 +34,12 @@
 		name := o.Name()
 		if _, ok := q.localVars[name]; ok {
 			return fmt.Errorf("check: duplicate var %q", name.Str(q.tm))
+		} else if q.c.topLevelNames[name] != 0 {
+			return &Error{
+				Err:      fmt.Errorf("check: var %q shadows top level name", name.Str(q.tm)),
+				Filename: o.Filename(),
+				Line:     o.Line(),
+			}
 		}
 		if err := q.tcheckTypeExpr(o.XType(), 0); err != nil {
 			return err
@@ -366,7 +372,7 @@
 					return nil
 				}
 			}
-			if _, ok := q.c.useBaseNames[id1]; ok {
+			if q.c.topLevelNames[id1] == a.KUse {
 				n.SetConstValue(zero)
 				n.SetMType(typeExprPackage)
 				return nil