@@ -111,31 +111,66 @@ public TypeNameChecker(TypeContext ctx, Options options) {
111111 visitor = new TypeNameVisitor ();
112112 }
113113
114+ /** Get the type corresponding to {@code t}; verify that it is well-formed. */
114115 public Type check (TypeName t ) {
116+ Type result = t .acceptVisitor (visitor );
117+ ensureWellFormed (t );
118+ return result ;
119+ }
120+
121+ /**
122+ * Get the type corresponding to {@code t}; verify that it is structurally well-formed, but
123+ * delay full well-formedness checking until a later {@link #ensureWellFormed} call.
124+ */
125+ public Type checkStructure (TypeName t ) {
115126 return t .acceptVisitor (visitor );
116127 }
117128
129+ /** Invoke {@link #check} on each element of a list. */
118130 public Iterable <Type > checkList (Iterable <? extends TypeName > l ) {
119- return IterUtil .mapSnapshot (l , visitor );
131+ Iterable <Type > result = IterUtil .mapSnapshot (l , visitor );
132+ ensureWellFormedList (l );
133+ return result ;
134+ }
135+
136+ /** Invoke {@link #checkStructure} on each element of a list. */
137+ public Iterable <Type > checkStructureForList (Iterable <? extends TypeName > l ) {
138+ Iterable <Type > result = IterUtil .mapSnapshot (l , visitor );
139+ return result ;
120140 }
121141
142+ /**
143+ * Verify that a TypeName that has already been checked is well-formed (according to
144+ * {@link TypeSystem#isWellFormed}).
145+ */
146+ public void ensureWellFormed (TypeName t ) {
147+ if (!ts .isWellFormed (getType (t ))) {
148+ throw new ExecutionError ("malformed.type" , t );
149+ }
150+ }
151+
152+ /** Invoke {@link #ensureWellFormed} on each element of a list. */
153+ public void ensureWellFormedList (Iterable <? extends TypeName > l ) {
154+ for (TypeName t : l ) { ensureWellFormed (t ); }
155+ }
156+
157+
122158 /** Tag the given type parameters with a new VariableType, and set the bounds appropriately. */
123159 public void checkTypeParameters (TypeParameter [] tparams ) {
124160 for (TypeParameter tparam : tparams ) {
125161 setTypeVariable (tparam , new VariableType (new BoundedSymbol (tparam , tparam .getRepresentation ())));
126162 }
127163 TypeNameVisitor v = new TypeNameVisitor ();
128164 for (TypeParameter param : tparams ) {
129- Type firstBound = param .getBound ().acceptVisitor (v );
130- Iterable <Type > restBounds = checkList (param .getInterfaceBounds ());
131- BoundedSymbol bounds = getTypeVariable (param ).symbol ();
132- if (IterUtil .isEmpty (restBounds )) { bounds .initializeUpperBound (firstBound ); }
133- else {
134- bounds .initializeUpperBound (new IntersectionType (IterUtil .compose (firstBound , restBounds )));
165+ Type upperBound = param .getBound ().acceptVisitor (v );
166+ for (Type t : checkList (param .getInterfaceBounds ())) {
167+ upperBound = ts .meet (upperBound , t );
135168 }
169+ BoundedSymbol bounds = getTypeVariable (param ).symbol ();
170+ bounds .initializeUpperBound (upperBound );
136171 bounds .initializeLowerBound (TypeSystem .NULL );
137172 }
138- }
173+ }
139174
140175 private class TypeNameVisitor extends AbstractVisitor <Type > implements Lambda <TypeName , Type > {
141176
@@ -282,7 +317,7 @@ private class TypeNameVisitor extends AbstractVisitor<Type> implements Lambda<Ty
282317 }
283318 catch (AmbiguousNameException e ) { throw new ExecutionError ("ambiguous.name" , node ); }
284319 catch (InvalidTargetException e ) { throw new RuntimeException ("context produced bad type" ); }
285- catch (InvalidTypeArgumentException e ) { throw new ExecutionError ("type.argument" , node ); }
320+ catch (InvalidTypeArgumentException e ) { throw new ExecutionError ("type.argument.arity " , node ); }
286321 catch (UnmatchedLookupException e ) {
287322 if (e .matches () == 0 ) { throw new ExecutionError ("undefined.name.noinfo" , node ); }
288323 else { throw new ExecutionError ("ambiguous.name" , node ); }
0 commit comments