Fix pretty-printing of recursive type-alias causing stack overflow.

Fixes #942.
This commit is contained in:
KtorZ 2024-05-16 17:20:26 +02:00
parent b546e42766
commit e87063824c
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
1 changed files with 45 additions and 3 deletions

View File

@ -54,7 +54,7 @@ impl Printer {
}) = typ.alias().as_deref()
{
if let Some(resolved_parameters) = resolve_alias(parameters, annotation, typ) {
return self.type_alias_doc(alias.to_string(), resolved_parameters);
return self.type_alias_doc(typ, alias.to_string(), resolved_parameters);
}
}
@ -92,14 +92,27 @@ impl Printer {
}
}
fn type_alias_doc<'a>(&mut self, alias: String, parameters: Vec<Rc<Type>>) -> Document<'a> {
fn type_alias_doc<'a>(
&mut self,
typ: &Type,
alias: String,
parameters: Vec<Rc<Type>>,
) -> Document<'a> {
let doc = Document::String(alias);
if !parameters.is_empty() {
doc.append(
break_("", "")
.append(concat(Itertools::intersperse(
parameters.iter().map(|t| self.print(t)),
parameters.iter().map(|t| {
// Avoid infinite recursion for recursive types instantiated to
// themselves. For example: type Identity<t> = t
if t.as_ref() == typ {
self.print(typ.clone().set_alias(None).as_ref())
} else {
self.print(t)
}
}),
break_(",", ", "),
)))
.nest(INDENT)
@ -646,6 +659,35 @@ mod tests {
},
"Fuzzer<a>",
);
assert_string!(
Rc::new(Type::Fn {
args: vec![Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: "Bool".to_string(),
args: vec![],
alias: None,
})],
ret: Rc::new(Type::App {
public: true,
contains_opaque: false,
module: "".to_string(),
name: "Bool".to_string(),
args: vec![],
alias: None,
}),
alias: Some(Rc::new(TypeAliasAnnotation {
alias: "Identity".to_string(),
parameters: vec!["t".to_string()],
annotation: Annotation::Var {
location: Span::empty(),
name: "t".to_string(),
},
})),
}),
"Identity<fn(Bool) -> Bool>",
);
}
#[test]