···290290 let name = erl_safe_type_name(to_snake_case(name));
291291292292 // We start the type spec.
293293- builder.type_spec(
293293+ let type_spec = builder.start_type_spec(
294294 *opaque,
295295 &name,
296296 typed_parameters
···349349 builder.end_union_type(union);
350350 }
351351 }
352352+353353+ builder.end_type_spec(type_spec);
352354 }
353355354356 /// Given a constructor this generates its type. For example:
···152152 /// that has yet to be closed.
153153 type FunctionTypeArguments;
154154155155+ /// Represents an open type spec attribute that has yet to be closed after
156156+ /// generating the type it stands for.
157157+ type TypeSpec;
158158+155159 /// Creates a new `ErlangBuilder` data structure to generate Erlang code.
156160 /// If a module name is provided this will also automatically take care of
157161 /// generating the appropriate `-module` annotation at the very beginning.
···339343 /// This starts an Erlang type spec.
340344 /// After this call you're expected to generate a single type; that's going
341345 /// to be the definition of the type.
346346+ /// After that is done you should call `end_type_spec`.
342347 ///
343348 /// For example:
344349 ///
···352357 /// builder.type_variable("A")
353358 /// builder.close_named_type();
354359 ///
355355- /// builder.end_uniont_type(union);
360360+ /// builder.end_union_type(union);
361361+ /// builder.end_type_spec(spec);
356362 /// ```
357363 ///
358364 /// Corresponds to:
···361367 /// -spec wibble(A) :: nil | list(A).
362368 /// ```
363369 ///
364364- fn type_spec<Name: AsRef<str>>(
370370+ fn start_type_spec<Name: AsRef<str>>(
365371 &mut self,
366372 opaque: bool,
367373 name: &str,
368374 type_parameters: impl IntoIterator<Item = Name>,
369369- );
375375+ ) -> Self::TypeSpec;
376376+377377+ fn end_type_spec(&mut self, type_spec: Self::TypeSpec);
370378371379 /// This starts a function type.
372380 /// Any code generated after this is gonna be an argument type of the open
···16861694 type TuplePattern = ();
16871695 type TupleType = ();
16881696 type UnionType = ();
16971697+ type TypeSpec = ();
1689169816901699 fn new(module: Option<ErlangModuleName>) -> Self {
16911700 Self {
···18361845 self.close_currently_open_item();
18371846 }
1838184718391839- fn type_spec<Name: AsRef<str>>(
18481848+ fn start_type_spec<Name: AsRef<str>>(
18401849 &mut self,
18411850 opaque: bool,
18421851 name: &str,
18431852 type_variables: impl IntoIterator<Item = Name>,
18441844- ) {
18531853+ ) -> Self::TypeSpec {
18451854 self.new_top_level_form();
18461855 self.code.push('\n');
18471856 self.code
···18621871 self.position.push(ErlangSourceBuilderPosition::TypeSpec {
18631872 expected: TypeSpecExpectedItem::TypeDefinition,
18641873 });
18741874+ }
18751875+18761876+ fn end_type_spec(&mut self, _type_spec: Self::TypeSpec) {
18771877+ // For the pretty printer type specs do not need any extra book keeping.
18781878+ // Ending one does nothing because the spec is already over and doesn't
18791879+ // change the builder's position.
18651880 }
1866188118671882 fn start_function_type(&mut self) -> Self::FunctionTypeArguments {