Index: src/Validate/NoIdSymbolTable.hpp
===================================================================
--- src/Validate/NoIdSymbolTable.hpp	(revision 0860d9c0c788c565776cbf08f223cede6a4d6ebc)
+++ src/Validate/NoIdSymbolTable.hpp	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
@@ -20,10 +20,19 @@
 namespace Validate {
 
-// A SymbolTable that only has the operations used in the Translate Dimension
-// pass. More importantly, it doesn't have some methods that should no be
+// A SymbolTable that only tracks names relevant to Validate passes.
+// It tracks type names but not identifier names.
+// Some of the canonicalization that occurs before the resolver
+// affects how identifier name errors get reported to the user.
+// The Validate phase needs to chase type names,
+// but it is too early to try tracking identifier names.
+// Identifier skipping is acheived by omitting methods that should not be
 // called by the Pass template (lookupId and addId).
 class NoIdSymbolTable {
 	ast::SymbolTable base;
 public:
+	// All names that are tracked (now) are eligible for collision validation (now).
+	// (Names that are only tracked later get their collision validation then.)
+	NoIdSymbolTable() : base(ast::SymbolTable::ValidateOnAdd) {}
+
 #	define FORWARD_X( func, types_and_names, just_names ) \
 	inline auto func types_and_names -> decltype( base.func just_names ) { \
Index: tests/errors/.expect/scope-type.txt
===================================================================
--- tests/errors/.expect/scope-type.txt	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
+++ tests/errors/.expect/scope-type.txt	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
@@ -0,0 +1,14 @@
+errors/scope-type.cfa:13:1 error: redeclaration of struct thisIsAnError with body
+
+errors/scope-type.cfa:48:1 error: redeclaration of union thisIsAnError_u with body
+
+errors/scope-type.cfa:62:1 error: redeclaration of enum thisIsAnError_e with body
+... with members
+  E0: const instance of enum thisIsAnError_e with body
+
+
+errors/scope-type.cfa:76:1 error: redeclaration of struct thisIsAnError_p with body
+... with parameters
+  Tx: data type
+
+
Index: tests/errors/.expect/scope.txt
===================================================================
--- tests/errors/.expect/scope.txt	(revision 0860d9c0c788c565776cbf08f223cede6a4d6ebc)
+++ tests/errors/.expect/scope.txt	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
@@ -1,4 +1,4 @@
-errors/scope.cfa:2:1 error: duplicate object definition for thisIsAnError: signed int
-errors/scope.cfa:20:1 error: duplicate function definition for butThisIsAnError: function
+errors/scope.cfa:13:1 error: duplicate object definition for thisIsAnError: signed int
+errors/scope.cfa:30:1 error: duplicate function definition for butThisIsAnError: function
 ... with parameters
   double
Index: tests/errors/scope-type.cfa
===================================================================
--- tests/errors/scope-type.cfa	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
+++ tests/errors/scope-type.cfa	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
@@ -0,0 +1,92 @@
+// The type-level analog of errors/scope.
+// Keep harmonized with errors/scope.
+
+#ifdef OMIT_DRIVING_REJECTIONS
+// For manual sanity checking:
+// Leave out the offensive declarations and verify that what's left is accepted.
+#define EXPREJ(...)
+#else 
+#define EXPREJ(...) __VA_ARGS__
+#endif
+
+        struct thisIsAnError {};
+EXPREJ( struct thisIsAnError {}; )
+
+        struct thisIsNotAnError {};
+
+        // There's no type-level analog to overloading at one level:
+        //x    float thisIsNotAnError;
+
+        int thisIsAlsoNotAnError() {
+          struct thisIsNotAnError { int xxx; };
+        }
+
+        // There's no type-level analog to overloading at one level, again:
+        //x    int thisIsAlsoNotAnError( double x ) {
+        //x    }
+
+        struct thisIsStillNotAnError;
+        struct thisIsStillNotAnError;
+
+        // Has analog at type level but would be a repeat (no analog of function vs variable):
+        //x
+        //x    double butThisIsAnError( double ) {
+        //x    }
+        //x
+        //x    double butThisIsAnError( double ) {
+        //x    }
+
+
+
+        //
+        // Repeat the validly harmonized cases, across various type forms
+        //
+
+        // union
+
+        union thisIsAnError_u {};
+EXPREJ( union thisIsAnError_u {}; )
+
+        union thisIsNotAnError_u {};
+
+        int thisIsAlsoNotAnError_u() {
+          union thisIsNotAnError_u { int xxx; };
+        }
+
+        union thisIsStillNotAnError_u;
+        union thisIsStillNotAnError_u;
+
+        // enum
+
+        enum thisIsAnError_e { E0 };
+EXPREJ( enum thisIsAnError_e { E0 }; )
+
+        enum thisIsNotAnError_e { E1 };
+
+        int thisIsAlsoNotAnError_e() {
+          enum thisIsNotAnError_e { E1_xxx };
+        }
+
+        enum thisIsStillNotAnError_e;
+        enum thisIsStillNotAnError_e;
+
+        // polymorphic
+
+        forall(T&)  struct thisIsAnError_p {};
+EXPREJ( forall(Tx&) struct thisIsAnError_p {}; )
+
+        forall(T&)  struct thisIsNotAnError_p {};
+
+        int thisIsAlsoNotAnError_p() {
+          forall(Tx&) struct thisIsNotAnError_p { int xxx; };
+        }
+
+        forall(Tx&) 
+        int thisIsAlsoNotAnError_p2() {
+          struct thisIsNotAnError_p { Tx * xxx; };
+        }
+
+        forall(T&)  struct thisIsStillNotAnError_p;
+      #ifdef SHOW_TRAC_284
+        forall(Tx&) struct thisIsStillNotAnError_p;  // should be accepted, but blocked
+      #endif
Index: tests/errors/scope.cfa
===================================================================
--- tests/errors/scope.cfa	(revision 0860d9c0c788c565776cbf08f223cede6a4d6ebc)
+++ tests/errors/scope.cfa	(revision 4d860ea34731ff1d6c9c167ea3410d0e077fd040)
@@ -1,23 +1,35 @@
-int thisIsAnError;
-int thisIsAnError;
+// Keep harmonized with errors/scope.
 
-int thisIsNotAnError;
-float thisIsNotAnError;
+#ifdef OMIT_DRIVING_REJECTIONS
+// For manual sanity checking:
+// Leave out the offensive declarations and verify that what's left is accepted.
+#define EXPREJ(...)
+#else 
+#define EXPREJ(...) __VA_ARGS__
+#endif
 
-int thisIsAlsoNotAnError() {
-  int thisIsNotAnError;
-}
 
-int thisIsAlsoNotAnError( double x ) {
-}
+        int thisIsAnError;
+EXPREJ( int thisIsAnError; )
 
-double thisIsStillNotAnError( double );
-double thisIsStillNotAnError( double );
+        int thisIsNotAnError;
+        float thisIsNotAnError;
 
-double butThisIsAnError( double ) {
-}
+        int thisIsAlsoNotAnError() {
+          int thisIsNotAnError;
+        }
 
-double butThisIsAnError( double ) {
-}
+        int thisIsAlsoNotAnError( double x ) {
+        }
+
+        double thisIsStillNotAnError( double );
+        double thisIsStillNotAnError( double );
+
+        double butThisIsAnError( double ) {
+        }
+EXPREJ(
+        double butThisIsAnError( double ) {
+        }
+)
 
 // Local Variables: //
