[ty] Add `with_type` convenience to display code (#21563)

Code is much more readable.
This commit is contained in:
Aria Desires 2025-11-21 11:36:22 -05:00 committed by GitHub
parent 629258241f
commit a9b3caf181
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 46 additions and 67 deletions

View File

@ -190,6 +190,11 @@ impl<'a, 'b, 'db> TypeWriter<'a, 'b, 'db> {
} }
} }
/// Convenience for `with_detail(TypeDetail::Type(ty))`
fn with_type<'c>(&'c mut self, ty: Type<'db>) -> TypeDetailGuard<'a, 'b, 'c, 'db> {
self.with_detail(TypeDetail::Type(ty))
}
fn join<'c>(&'c mut self, separator: &'static str) -> Join<'a, 'b, 'c, 'db> { fn join<'c>(&'c mut self, separator: &'static str) -> Join<'a, 'b, 'c, 'db> {
Join { Join {
fmt: self, fmt: self,
@ -469,10 +474,8 @@ impl<'db> FmtDetailed<'db> for DisplayType<'db> {
| Type::StringLiteral(_) | Type::StringLiteral(_)
| Type::BytesLiteral(_) | Type::BytesLiteral(_)
| Type::EnumLiteral(_) => { | Type::EnumLiteral(_) => {
f.with_detail(TypeDetail::Type(Type::SpecialForm( f.with_type(Type::SpecialForm(SpecialFormType::Literal))
SpecialFormType::Literal, .write_str("Literal")?;
)))
.write_str("Literal")?;
f.write_char('[')?; f.write_char('[')?;
representation.fmt_detailed(f)?; representation.fmt_detailed(f)?;
f.write_str("]") f.write_str("]")
@ -565,7 +568,7 @@ impl<'db> FmtDetailed<'db> for ClassDisplay<'db> {
f.write_char('.')?; f.write_char('.')?;
} }
} }
f.with_detail(TypeDetail::Type(Type::ClassLiteral(self.class))) f.with_type(Type::ClassLiteral(self.class))
.write_str(self.class.name(self.db))?; .write_str(self.class.name(self.db))?;
if qualification_level == Some(&QualificationLevel::FileAndLineNumber) { if qualification_level == Some(&QualificationLevel::FileAndLineNumber) {
let file = self.class.file(self.db); let file = self.class.file(self.db);
@ -611,14 +614,14 @@ impl Display for DisplayRepresentation<'_> {
impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> { impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result { fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result {
match self.ty { match self.ty {
Type::Dynamic(dynamic) => write!(f.with_detail(TypeDetail::Type(self.ty)), "{dynamic}"), Type::Dynamic(dynamic) => write!(f.with_type(self.ty), "{dynamic}"),
Type::Never => f.with_detail(TypeDetail::Type(self.ty)).write_str("Never"), Type::Never => f.with_type(self.ty).write_str("Never"),
Type::NominalInstance(instance) => { Type::NominalInstance(instance) => {
let class = instance.class(self.db); let class = instance.class(self.db);
match (class, class.known(self.db)) { match (class, class.known(self.db)) {
(_, Some(KnownClass::NoneType)) => f.with_detail(TypeDetail::Type(self.ty)).write_str("None"), (_, Some(KnownClass::NoneType)) => f.with_type(self.ty).write_str("None"),
(_, Some(KnownClass::NoDefaultType)) => f.with_detail(TypeDetail::Type(self.ty)).write_str("NoDefault"), (_, Some(KnownClass::NoDefaultType)) => f.with_type(self.ty).write_str("NoDefault"),
(ClassType::Generic(alias), Some(KnownClass::Tuple)) => alias (ClassType::Generic(alias), Some(KnownClass::Tuple)) => alias
.specialization(self.db) .specialization(self.db)
.tuple(self.db) .tuple(self.db)
@ -642,10 +645,8 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
}, },
Protocol::Synthesized(synthetic) => { Protocol::Synthesized(synthetic) => {
f.write_char('<')?; f.write_char('<')?;
f.with_detail(TypeDetail::Type(Type::SpecialForm( f.with_type(Type::SpecialForm(SpecialFormType::Protocol))
SpecialFormType::Protocol, .write_str("Protocol")?;
)))
.write_str("Protocol")?;
f.write_str(" with members ")?; f.write_str(" with members ")?;
let interface = synthetic.interface(); let interface = synthetic.interface();
let member_list = interface.members(self.db); let member_list = interface.members(self.db);
@ -660,18 +661,16 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
f.write_char('>') f.write_char('>')
} }
}, },
Type::PropertyInstance(_) => f Type::PropertyInstance(_) => f.with_type(self.ty).write_str("property"),
.with_detail(TypeDetail::Type(self.ty))
.write_str("property"),
Type::ModuleLiteral(module) => { Type::ModuleLiteral(module) => {
write!( write!(
f.with_detail(TypeDetail::Type(self.ty)), f.with_type(self.ty),
"<module '{}'>", "<module '{}'>",
module.module(self.db).name(self.db) module.module(self.db).name(self.db)
) )
} }
Type::ClassLiteral(class) => { Type::ClassLiteral(class) => {
let mut f = f.with_detail(TypeDetail::Type(self.ty)); let mut f = f.with_type(self.ty);
f.write_str("<class '")?; f.write_str("<class '")?;
class class
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
@ -679,7 +678,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
f.write_str("'>") f.write_str("'>")
} }
Type::GenericAlias(generic) => { Type::GenericAlias(generic) => {
let mut f = f.with_detail(TypeDetail::Type(self.ty)); let mut f = f.with_type(self.ty);
f.write_str("<class '")?; f.write_str("<class '")?;
generic generic
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
@ -688,7 +687,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
} }
Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() { Type::SubclassOf(subclass_of_ty) => match subclass_of_ty.subclass_of() {
SubclassOfInner::Class(ClassType::NonGeneric(class)) => { SubclassOfInner::Class(ClassType::NonGeneric(class)) => {
f.with_detail(TypeDetail::Type(KnownClass::Type.to_class_literal(self.db))) f.with_type(KnownClass::Type.to_class_literal(self.db))
.write_str("type")?; .write_str("type")?;
f.write_char('[')?; f.write_char('[')?;
class class
@ -697,7 +696,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
f.write_char(']') f.write_char(']')
} }
SubclassOfInner::Class(ClassType::Generic(alias)) => { SubclassOfInner::Class(ClassType::Generic(alias)) => {
f.with_detail(TypeDetail::Type(KnownClass::Type.to_class_literal(self.db))) f.with_type(KnownClass::Type.to_class_literal(self.db))
.write_str("type")?; .write_str("type")?;
f.write_char('[')?; f.write_char('[')?;
alias alias
@ -706,24 +705,19 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
f.write_char(']') f.write_char(']')
} }
SubclassOfInner::Dynamic(dynamic) => { SubclassOfInner::Dynamic(dynamic) => {
f.with_detail(TypeDetail::Type(KnownClass::Type.to_class_literal(self.db))) f.with_type(KnownClass::Type.to_class_literal(self.db))
.write_str("type")?; .write_str("type")?;
f.write_char('[')?; f.write_char('[')?;
write!( write!(f.with_type(Type::Dynamic(dynamic)), "{dynamic}")?;
f.with_detail(TypeDetail::Type(Type::Dynamic(dynamic))),
"{dynamic}"
)?;
f.write_char(']') f.write_char(']')
} }
}, },
Type::SpecialForm(special_form) => { Type::SpecialForm(special_form) => {
write!(f.with_detail(TypeDetail::Type(self.ty)), "{special_form}") write!(f.with_type(self.ty), "{special_form}")
}
Type::KnownInstance(known_instance) => {
write!(f.with_type(self.ty), "{}", known_instance.repr(self.db))
} }
Type::KnownInstance(known_instance) => write!(
f.with_detail(TypeDetail::Type(self.ty)),
"{}",
known_instance.repr(self.db)
),
Type::FunctionLiteral(function) => function Type::FunctionLiteral(function) => function
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
.fmt_detailed(f), .fmt_detailed(f),
@ -748,8 +742,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
.display_with(self.db, self.settings.singleline()) .display_with(self.db, self.settings.singleline())
.fmt_detailed(f)?; .fmt_detailed(f)?;
f.write_char('.')?; f.write_char('.')?;
f.with_detail(TypeDetail::Type(self.ty)) f.with_type(self.ty).write_str(function.name(self.db))?;
.write_str(function.name(self.db))?;
type_parameters.fmt_detailed(f)?; type_parameters.fmt_detailed(f)?;
signature signature
.bind_self(self.db, Some(typing_self_ty)) .bind_self(self.db, Some(typing_self_ty))
@ -845,13 +838,14 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
Type::Intersection(intersection) => intersection Type::Intersection(intersection) => intersection
.display_with(self.db, self.settings.clone()) .display_with(self.db, self.settings.clone())
.fmt_detailed(f), .fmt_detailed(f),
Type::IntLiteral(n) => write!(f.with_detail(TypeDetail::Type(self.ty)), "{n}"), Type::IntLiteral(n) => write!(f.with_type(self.ty), "{n}"),
Type::BooleanLiteral(boolean) => f Type::BooleanLiteral(boolean) => {
.with_detail(TypeDetail::Type(self.ty)) f.with_type(self.ty)
.write_str(if boolean { "True" } else { "False" }), .write_str(if boolean { "True" } else { "False" })
}
Type::StringLiteral(string) => { Type::StringLiteral(string) => {
write!( write!(
f.with_detail(TypeDetail::Type(self.ty)), f.with_type(self.ty),
"{}", "{}",
string.display_with(self.db, self.settings.clone()) string.display_with(self.db, self.settings.clone())
) )
@ -861,14 +855,12 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
// inlay hint, but that seems less useful than the definition of `str` for a variable that is // inlay hint, but that seems less useful than the definition of `str` for a variable that is
// inferred as an *inhabitant* of `LiteralString` (since that variable will just be a string // inferred as an *inhabitant* of `LiteralString` (since that variable will just be a string
// at runtime) // at runtime)
Type::LiteralString => f Type::LiteralString => f.with_type(self.ty).write_str("LiteralString"),
.with_detail(TypeDetail::Type(self.ty))
.write_str("LiteralString"),
Type::BytesLiteral(bytes) => { Type::BytesLiteral(bytes) => {
let escape = AsciiEscape::with_preferred_quote(bytes.value(self.db), Quote::Double); let escape = AsciiEscape::with_preferred_quote(bytes.value(self.db), Quote::Double);
write!( write!(
f.with_detail(TypeDetail::Type(self.ty)), f.with_type(self.ty),
"{}", "{}",
escape.bytes_repr(TripleQuotes::No) escape.bytes_repr(TripleQuotes::No)
) )
@ -883,12 +875,8 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
Type::TypeVar(bound_typevar) => { Type::TypeVar(bound_typevar) => {
write!(f, "{}", bound_typevar.identity(self.db).display(self.db)) write!(f, "{}", bound_typevar.identity(self.db).display(self.db))
} }
Type::AlwaysTruthy => f Type::AlwaysTruthy => f.with_type(self.ty).write_str("AlwaysTruthy"),
.with_detail(TypeDetail::Type(self.ty)) Type::AlwaysFalsy => f.with_type(self.ty).write_str("AlwaysFalsy"),
.write_str("AlwaysTruthy"),
Type::AlwaysFalsy => f
.with_detail(TypeDetail::Type(self.ty))
.write_str("AlwaysFalsy"),
Type::BoundSuper(bound_super) => { Type::BoundSuper(bound_super) => {
f.write_str("<super: ")?; f.write_str("<super: ")?;
Type::from(bound_super.pivot_class(self.db)) Type::from(bound_super.pivot_class(self.db))
@ -901,7 +889,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
f.write_str(">") f.write_str(">")
} }
Type::TypeIs(type_is) => { Type::TypeIs(type_is) => {
f.with_detail(TypeDetail::Type(Type::SpecialForm(SpecialFormType::TypeIs))) f.with_type(Type::SpecialForm(SpecialFormType::TypeIs))
.write_str("TypeIs")?; .write_str("TypeIs")?;
f.write_char('[')?; f.write_char('[')?;
type_is type_is
@ -929,9 +917,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
.fmt_detailed(f), .fmt_detailed(f),
} }
} }
Type::NewTypeInstance(newtype) => f Type::NewTypeInstance(newtype) => f.with_type(self.ty).write_str(newtype.name(self.db)),
.with_detail(TypeDetail::Type(self.ty))
.write_str(newtype.name(self.db)),
} }
} }
} }
@ -982,10 +968,8 @@ pub(crate) struct DisplayTuple<'a, 'db> {
impl<'db> FmtDetailed<'db> for DisplayTuple<'_, 'db> { impl<'db> FmtDetailed<'db> for DisplayTuple<'_, 'db> {
fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result { fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result {
f.with_detail(TypeDetail::Type( f.with_type(KnownClass::Tuple.to_class_literal(self.db))
KnownClass::Tuple.to_class_literal(self.db), .write_str("tuple")?;
))
.write_str("tuple")?;
f.write_char('[')?; f.write_char('[')?;
match self.tuple { match self.tuple {
TupleSpec::Fixed(tuple) => { TupleSpec::Fixed(tuple) => {
@ -1024,10 +1008,8 @@ impl<'db> FmtDetailed<'db> for DisplayTuple<'_, 'db> {
if !tuple.prefix.is_empty() || !tuple.suffix.is_empty() { if !tuple.prefix.is_empty() || !tuple.suffix.is_empty() {
f.write_char('*')?; f.write_char('*')?;
// Might as well link the type again here too // Might as well link the type again here too
f.with_detail(TypeDetail::Type( f.with_type(KnownClass::Tuple.to_class_literal(self.db))
KnownClass::Tuple.to_class_literal(self.db), .write_str("tuple")?;
))
.write_str("tuple")?;
f.write_char('[')?; f.write_char('[')?;
} }
tuple tuple
@ -1218,8 +1200,7 @@ impl<'db> FmtDetailed<'db> for DisplayGenericAlias<'db> {
Some(_) => "]", Some(_) => "]",
}; };
if let Some((name, form)) = prefix_details { if let Some((name, form)) = prefix_details {
f.with_detail(TypeDetail::Type(Type::SpecialForm(form))) f.with_type(Type::SpecialForm(form)).write_str(name)?;
.write_str(name)?;
f.write_char('[')?; f.write_char('[')?;
} }
self.origin self.origin
@ -1890,10 +1871,8 @@ const LITERAL_POLICY: TruncationPolicy = TruncationPolicy {
impl<'db> FmtDetailed<'db> for DisplayLiteralGroup<'db> { impl<'db> FmtDetailed<'db> for DisplayLiteralGroup<'db> {
fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result { fn fmt_detailed(&self, f: &mut TypeWriter<'_, '_, 'db>) -> fmt::Result {
f.with_detail(TypeDetail::Type(Type::SpecialForm( f.with_type(Type::SpecialForm(SpecialFormType::Literal))
SpecialFormType::Literal, .write_str("Literal")?;
)))
.write_str("Literal")?;
f.write_char('[')?; f.write_char('[')?;
let total_entries = self.literals.len(); let total_entries = self.literals.len();