From 5363f350887b1e5b5dd21a86f88c8af9d7fea6da Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:25 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/chalk-solve/src/display/bounds.rs | 168 +++++++++ vendor/chalk-solve/src/display/identifiers.rs | 54 +++ vendor/chalk-solve/src/display/items.rs | 503 +++++++++++++++++++++++++ vendor/chalk-solve/src/display/render_trait.rs | 30 ++ vendor/chalk-solve/src/display/state.rs | 352 +++++++++++++++++ vendor/chalk-solve/src/display/stub.rs | 268 +++++++++++++ vendor/chalk-solve/src/display/ty.rs | 303 +++++++++++++++ vendor/chalk-solve/src/display/utils.rs | 51 +++ 8 files changed, 1729 insertions(+) create mode 100644 vendor/chalk-solve/src/display/bounds.rs create mode 100644 vendor/chalk-solve/src/display/identifiers.rs create mode 100644 vendor/chalk-solve/src/display/items.rs create mode 100644 vendor/chalk-solve/src/display/render_trait.rs create mode 100644 vendor/chalk-solve/src/display/state.rs create mode 100644 vendor/chalk-solve/src/display/stub.rs create mode 100644 vendor/chalk-solve/src/display/ty.rs create mode 100644 vendor/chalk-solve/src/display/utils.rs (limited to 'vendor/chalk-solve/src/display') diff --git a/vendor/chalk-solve/src/display/bounds.rs b/vendor/chalk-solve/src/display/bounds.rs new file mode 100644 index 000000000..3c6bfde14 --- /dev/null +++ b/vendor/chalk-solve/src/display/bounds.rs @@ -0,0 +1,168 @@ +//! Writer logic for `where` clauses and other bounds. +//! +//! Contains logic for writing the various forms of `Foo: Bar`. +use std::fmt::{Display, Formatter, Result}; + +use crate::rust_ir::*; +use chalk_ir::{interner::Interner, *}; +use itertools::Itertools; + +use super::{ + display_trait_with_assoc_ty_value, display_type_with_generics, render_trait::RenderAsRust, + state::InternalWriterState, +}; +use crate::split::Split; + +impl RenderAsRust for InlineBound { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + match self { + // Foo: Vec + InlineBound::TraitBound(trait_bound) => trait_bound.fmt(s, f), + // Foo: Iterator + InlineBound::AliasEqBound(eq_bound) => eq_bound.fmt(s, f), + } + } +} + +impl RenderAsRust for TraitBound { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + display_type_with_generics(s, self.trait_id, &self.args_no_self).fmt(f) + } +} + +impl RenderAsRust for AliasEqBound { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + display_trait_with_assoc_ty_value( + s, + s.db().associated_ty_data(self.associated_ty_id), + &self.trait_bound.args_no_self, + &self.parameters, + &self.value, + ) + .fmt(f) + } +} + +impl RenderAsRust for QuantifiedWhereClause { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + let s = &s.add_debrujin_index(None); + if !self.binders.is_empty(interner) { + write!( + f, + "forall<{}> ", + s.binder_var_display(&self.binders).format(", ") + )?; + } + self.skip_binders().fmt(s, f) + } +} + +impl RenderAsRust for QuantifiedInlineBound { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + let s = &s.add_debrujin_index(None); + if !self.binders.is_empty(interner) { + write!( + f, + "forall<{}> ", + s.binder_var_display(&self.binders).format(", ") + )?; + } + self.skip_binders().fmt(s, f) + } +} + +impl RenderAsRust for Vec> { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + write!( + f, + "{}", + self.iter() + .map(|where_clause| { format!("{}{}", s.indent(), where_clause.display(s)) }) + .format(",\n") + )?; + Ok(()) + } +} + +impl RenderAsRust for WhereClause { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + match self { + WhereClause::Implemented(trait_ref) => trait_ref.fmt(s, f), + WhereClause::AliasEq(alias_eq) => alias_eq.fmt(s, f), + WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f), + WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f), + } + } +} + +/// This renders `TraitRef` as a clause in a where clause, as opposed to its +/// usage in other places. +impl RenderAsRust for TraitRef { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + write!( + f, + "{}: {}", + self.self_type_parameter(interner).display(s), + display_type_with_generics( + s, + self.trait_id, + &self.substitution.as_slice(interner)[1..] + ) + ) + } +} + +/// This renders `AliasEq` as a clause in a where clause, as opposed to its +/// usage in other places. +impl RenderAsRust for AliasEq { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // we have: X: Y=D> + // B1, B2, B3, X, A1, A2, A3 are put into alias_eq.alias.substitution + // D is alias_eq.ty + // Z is alias_eq.alias.associated_ty_id + // Y is also packed into alias_eq.alias.associated_ty_id + // Now, we split out A*, Y/Z and B*: + // trait_params is X, A1, A2, A3, + // assoc_type_params is B1, B2, B3, + // assoc_ty_datum stores info about Y and Z. + match &self.alias { + AliasTy::Projection(projection_ty) => { + let (assoc_ty_datum, trait_params, assoc_type_params) = + s.db().split_projection(projection_ty); + // An alternate form might be `<{} as {}<{}>>::{}<{}> = {}` (with same + // parameter ordering). This alternate form would require type equality + // constraints (https://github.com/rust-lang/rust/issues/20041). + write!( + f, + "{}: {}", + trait_params[0].display(s), + display_trait_with_assoc_ty_value( + s, + assoc_ty_datum, + &trait_params[1..], + assoc_type_params, + &self.ty + ), + ) + } + AliasTy::Opaque(opaque) => write!(f, "{}", opaque.display(s)), + } + } +} + +impl RenderAsRust for LifetimeOutlives { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + // a': 'b + write!(f, "{}: {}", self.a.display(s), self.b.display(s)) + } +} + +impl RenderAsRust for TypeOutlives { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + // T: 'a + write!(f, "{}: {}", self.ty.display(s), self.lifetime.display(s)) + } +} diff --git a/vendor/chalk-solve/src/display/identifiers.rs b/vendor/chalk-solve/src/display/identifiers.rs new file mode 100644 index 000000000..81a08d71b --- /dev/null +++ b/vendor/chalk-solve/src/display/identifiers.rs @@ -0,0 +1,54 @@ +//! Writer logic for simple IDs +//! +//! `RenderAsRust` impls for identifiers which are either too small or too +//! shared to belong anywhere else belong here. +use std::fmt::{Formatter, Result}; + +use chalk_ir::interner::Interner; +use chalk_ir::*; + +use super::{render_trait::RenderAsRust, state::InternalWriterState}; + +impl RenderAsRust for AdtId { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // TODO: use debug methods? + write!( + f, + "{}", + s.alias_for_adt_id_name(self.0, s.db().adt_name(*self)) + ) + } +} + +impl RenderAsRust for TraitId { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // TODO: use debug methods? + write!( + f, + "{}", + s.alias_for_id_name(self.0, s.db().trait_name(*self)) + ) + } +} + +impl RenderAsRust for AssocTypeId { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // TODO: use debug methods? + write!( + f, + "{}", + s.alias_for_id_name(self.0, s.db().assoc_type_name(*self)) + ) + } +} + +impl RenderAsRust for OpaqueTyId { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // TODO: use debug methods? + write!( + f, + "{}", + s.alias_for_id_name(self.0, s.db().opaque_type_name(*self)) + ) + } +} diff --git a/vendor/chalk-solve/src/display/items.rs b/vendor/chalk-solve/src/display/items.rs new file mode 100644 index 000000000..00387a07b --- /dev/null +++ b/vendor/chalk-solve/src/display/items.rs @@ -0,0 +1,503 @@ +//! Writer logic for top level items. +//! +//! Contains code specific to top-level items and other structures specific to a +//! single top-level item. + +use std::fmt::{Formatter, Result}; + +use crate::rust_ir::*; +use crate::split::Split; +use chalk_ir::interner::Interner; +use itertools::Itertools; + +use super::{ + display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust, + state::InternalWriterState, +}; + +/// Used in `AdtDatum` and `TraitDatum` to write n flags from a flags struct +/// to a writer. Each flag field turns into an if expression + write!, so we can +/// just list the names and not repeat this pattern over and over. +/// +/// This macro will error if unknown flags are specified. This will also error +/// if any flags are missing. +/// +/// # Usage +/// +/// ```rust,ignore +/// write_flags!(f, self.flags, XFlags { red, green }) +/// ``` +/// +/// Turns into +/// +/// ```rust,ignore +/// match self.flags { +/// XFlags { red, green } => { +/// if red { +/// write!(f, "#[red]")?; +/// } +/// if green { +/// write!(f, "#[green]")?; +/// } +/// } +/// } +/// ``` +macro_rules! write_flags { + ($writer:ident, $val:expr, $struct_name:ident { $($n:ident $(: $extra_arg:tt)?),* }) => { + match $val { + // if any fields are missing, the destructuring will error + $struct_name { + $($n,)* + } => { + $(if $n { + write!($writer, "#[{}]\n", write_flags!(@default $n $(: $extra_arg)*))?; + })* + } + } + }; + (@default $n:ident : $name:literal) => { + $name + }; + (@default $n:ident ) => { + stringify!($n) + }; +} + +impl<'a, I: Interner> RenderAsRust for (&'a GeneratorDatum, &'a GeneratorWitnessDatum) { + fn fmt(&self, _s: &InternalWriterState<'_, I>, _f: &'_ mut Formatter<'_>) -> Result { + unimplemented!() + } +} + +impl RenderAsRust for AdtDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // When support for Self in structs is added, self_binding should be + // changed to Some(0) + let s = &s.add_debrujin_index(None); + let value = self.binders.skip_binders(); + + // flags + write_flags!( + f, + self.flags, + AdtFlags { + // Ordering matters + upstream, + fundamental, + phantom_data + } + ); + + // repr + let repr = s.db().adt_repr(self.id); + + if repr.c { + write!(f, "#[repr(C)]")?; + } + if repr.packed { + write!(f, "#[repr(packed)]")?; + } + if let Some(t) = &repr.int { + write!(f, "#[repr({})]", t.display(s))?; + } + + // name + match self.kind { + AdtKind::Struct => write!(f, "struct {}", self.id.display(s),)?, + AdtKind::Enum => write!(f, "enum {}", self.id.display(s),)?, + AdtKind::Union => write!(f, "union {}", self.id.display(s),)?, + } + write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.binders.binders), ", ")?; + + // where clauses + if !value.where_clauses.is_empty() { + let s = &s.add_indent(); + write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; + } else { + write!(f, " ")?; + } + + // body + write!(f, "{{")?; + let s = &s.add_indent(); + match self.kind { + AdtKind::Struct | AdtKind::Union => { + write_joined_non_empty_list!( + f, + "\n{}\n", + value.variants[0] + .fields + .iter() + .enumerate() + .map(|(idx, field)| { + format!("{}field_{}: {}", s.indent(), idx, field.display(s)) + }), + ",\n" + )?; + } + AdtKind::Enum => { + for (variant_idx, variant) in value.variants.iter().enumerate() { + write!(f, "\n{}variant_{} {{", s.indent(), variant_idx)?; + let s = &s.add_indent(); + write_joined_non_empty_list!( + f, + "\n{}\n", + variant.fields.iter().enumerate().map(|(idx, field)| { + format!("{}field_{}: {}", s.indent(), idx, field.display(s)) + }), + ",\n" + )?; + write!(f, "{}}},", s.indent())?; + } + } + } + write!(f, "}}")?; + Ok(()) + } +} + +impl RenderAsRust for Polarity { + fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + if !self.is_positive() { + write!(f, "!")?; + } + Ok(()) + } +} + +impl RenderAsRust for TraitDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let s = &s.add_debrujin_index(Some(0)); + let value = self.binders.skip_binders(); + + // flags + write_flags!( + f, + self.flags, + TraitFlags { + auto, + marker, + upstream, + fundamental, + non_enumerable, + coinductive + } + ); + + // object safe + if s.db().is_object_safe(self.id) { + writeln!(f, "#[object_safe]")?; + } + + // well-known + if let Some(well_known) = self.well_known { + let name = match well_known { + WellKnownTrait::Sized => "sized", + WellKnownTrait::Copy => "copy", + WellKnownTrait::Clone => "clone", + WellKnownTrait::Drop => "drop", + WellKnownTrait::FnOnce => "fn_once", + WellKnownTrait::FnMut => "fn_mut", + WellKnownTrait::Fn => "fn", + WellKnownTrait::Unsize => "unsize", + WellKnownTrait::Unpin => "unpin", + WellKnownTrait::CoerceUnsized => "coerce_unsized", + WellKnownTrait::DiscriminantKind => "discriminant_kind", + WellKnownTrait::Generator => "generator", + WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn", + WellKnownTrait::Tuple => "tuple_trait", + }; + writeln!(f, "#[lang({})]", name)?; + } + + // trait declaration + let binders = s.binder_var_display(&self.binders.binders).skip(1); + write!(f, "trait {}", self.id.display(s))?; + write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; + + // where clauses + if !value.where_clauses.is_empty() { + let s = &s.add_indent(); + write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; + } else { + write!(f, " ")?; + } + + // body + write!(f, "{{")?; + let s = &s.add_indent(); + write_joined_non_empty_list!( + f, + "\n{}\n", + self.associated_ty_ids.iter().map(|assoc_ty_id| { + let assoc_ty_data = s.db().associated_ty_data(*assoc_ty_id); + format!("{}{}", s.indent(), (*assoc_ty_data).display(s)) + }), + "\n" + )?; + write!(f, "}}")?; + Ok(()) + } +} + +impl RenderAsRust for ImplDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + + let s = &s.add_debrujin_index(None); + let binders = s.binder_var_display(&self.binders.binders); + let value = self.binders.skip_binders(); + + // annotations + // #[upstream] + // ^^^^^^^^^^^ + // impl Foo for Bar where T: Baz { } + if self.impl_type == ImplType::External { + writeln!(f, "#[upstream]")?; + } + + // impl keyword + // impl Foo for Bar where T: Baz { } + // ^^^^ + write!(f, "impl")?; + let trait_ref = &value.trait_ref; + + // generic binders + // impl Foo for Bar where T: Baz + // ^^^ + write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; + + // trait, type and parameters + // impl Foo for Bar where T: Baz { } + // ^^^^^^^^^^^^^^^^^ + let full_trait_name = display_type_with_generics( + s, + trait_ref.trait_id, + // Ignore automatically added Self parameter by skipping first parameter + &trait_ref.substitution.as_slice(interner)[1..], + ); + write!( + f, + " {}{} for {}", + self.polarity.display(s), + full_trait_name, + trait_ref.self_type_parameter(interner).display(s) + )?; + + // where clauses + // impl Foo for Bar where T: Baz { } + // ^^^^^^^^^^^^ + if !value.where_clauses.is_empty() { + let s = &s.add_indent(); + write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?; + } else { + write!(f, " ")?; + } + + // body + // impl Foo for Bar where T: Baz { } + // ^^^ + write!(f, "{{")?; + { + let s = &s.add_indent(); + let assoc_ty_values = self.associated_ty_value_ids.iter().map(|assoc_ty_value| { + s.db() + .associated_ty_value(*assoc_ty_value) + .display(s) + .to_string() + }); + write_joined_non_empty_list!(f, "\n{}\n", assoc_ty_values, "\n")?; + } + write!(f, "}}")?; + Ok(()) + } +} + +impl RenderAsRust for OpaqueTyDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + let s = &s.add_debrujin_index(None); + let bounds = self.bound.skip_binders(); + write!(f, "opaque type {}", self.opaque_ty_id.display(s))?; + write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.bound.binders), ", ")?; + { + let s = &s.add_debrujin_index(Some(0)); + let clauses = bounds.bounds.skip_binders(); + write!( + f, + ": {} = ", + display_self_where_clauses_as_bounds(s, clauses) + )?; + } + write!( + f, + "{};", + s.db().hidden_opaque_type(self.opaque_ty_id).display(s) + )?; + Ok(()) + } +} + +impl RenderAsRust for AssociatedTyDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // In lowering, a completely new empty environment is created for each + // AssociatedTyDatum, and it's given generic parameters for each generic + // parameter that its trait had. We want to map the new binders for + // those generic parameters back into their original names. To do that, + // first find their original names (trait_binder_names), then the names + // they have inside the AssociatedTyDatum (assoc_ty_names_for_trait_params), + // and then add that mapping to the WriterState when writing bounds and + // where clauses. + let trait_datum = s.db().trait_datum(self.trait_id); + // inverted Debrujin indices for the trait's parameters in the trait + // environment + let trait_param_names_in_trait_env = s.binder_var_indices(&trait_datum.binders.binders); + let s = &s.add_debrujin_index(None); + // inverted Debrujin indices for the trait's parameters in the + // associated type environment + let param_names_in_assoc_ty_env = s + .binder_var_indices(&self.binders.binders) + .collect::>(); + // inverted Debrujin indices to render the trait's parameters in the + // associated type environment + let (trait_param_names_in_assoc_ty_env, _) = s + .db() + .split_associated_ty_parameters(¶m_names_in_assoc_ty_env, self); + + let s = &s.add_parameter_mapping( + trait_param_names_in_assoc_ty_env.iter().copied(), + trait_param_names_in_trait_env, + ); + + // rendered names for the associated type's generics in the associated + // type environment + let binder_display_in_assoc_ty = s + .binder_var_display(&self.binders.binders) + .collect::>(); + + let (_, assoc_ty_params) = s + .db() + .split_associated_ty_parameters(&binder_display_in_assoc_ty, self); + write!(f, "type {}", self.id.display(s))?; + write_joined_non_empty_list!(f, "<{}>", assoc_ty_params, ", ")?; + + let datum_bounds = &self.binders.skip_binders(); + + if !datum_bounds.bounds.is_empty() { + write!(f, ": ")?; + } + + // bounds is `A: V, B: D, C = E`? + // type Foo: X + Y + Z; + let bounds = datum_bounds + .bounds + .iter() + .map(|bound| bound.display(s).to_string()) + .format(" + "); + write!(f, "{}", bounds)?; + + // where_clause is 'X: Y, Z: D' + // type Foo<...>: ... where X: Y, Z: D; + + // note: it's a quantified clause b/c we could have `for<'a> T: Foo<'a>` + // within 'where' + if !datum_bounds.where_clauses.is_empty() { + let where_s = &s.add_indent(); + let where_clauses = datum_bounds.where_clauses.display(where_s); + write!(f, "\n{}where\n{}", s.indent(), where_clauses)?; + } + write!(f, ";")?; + Ok(()) + } +} + +impl RenderAsRust for AssociatedTyValue { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // see comments for a similar empty env operation in AssociatedTyDatum's + // impl of RenderAsRust. + let assoc_ty_data = s.db().associated_ty_data(self.associated_ty_id); + let impl_datum = s.db().impl_datum(self.impl_id); + + let impl_param_names_in_impl_env = s.binder_var_indices(&impl_datum.binders.binders); + + let s = &s.add_debrujin_index(None); + let value = self.value.skip_binders(); + + let param_names_in_assoc_ty_value_env = s + .binder_var_indices(&self.value.binders) + .collect::>(); + + let (impl_params_in_assoc_ty_value_env, _assoc_ty_value_params) = s + .db() + .split_associated_ty_value_parameters(¶m_names_in_assoc_ty_value_env, self); + + let s = &s.add_parameter_mapping( + impl_params_in_assoc_ty_value_env.iter().cloned(), + impl_param_names_in_impl_env, + ); + + let display_params = s + .binder_var_display(&self.value.binders) + .collect::>(); + + let (_impl_display, assoc_ty_value_display) = s + .db() + .split_associated_ty_value_parameters(&display_params, self); + + write!(f, "{}type {}", s.indent(), assoc_ty_data.id.display(s))?; + write_joined_non_empty_list!(f, "<{}>", assoc_ty_value_display, ", ")?; + write!(f, " = {};", value.ty.display(s))?; + Ok(()) + } +} + +impl RenderAsRust for FnDefDatum { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + let s = &s.add_debrujin_index(None); + let bound_datum = self.binders.skip_binders(); + + // declaration + // fn foo(arg: u32, arg2: T) -> Result where T: Bar + // ^^^^^^ + write!(f, "fn {}", s.db().fn_def_name(self.id))?; + + // binders + // fn foo(arg: u32, arg2: T) -> Result where T: Bar + // ^^^ + let binders = s.binder_var_display(&self.binders.binders); + write_joined_non_empty_list!(f, "<{}>", binders, ", ")?; + + { + let s = &s.add_debrujin_index(None); + let inputs_and_output = bound_datum.inputs_and_output.skip_binders(); + + // arguments + // fn foo(arg: u32, arg2: T) -> Result where T: Bar + // ^^^^^^^^^^^^^^^^^^^ + let arguments = inputs_and_output + .argument_types + .iter() + .enumerate() + .map(|(idx, arg)| format!("arg_{}: {}", idx, arg.display(s))) + .format(", "); + + write!(f, "({})", arguments)?; + + // return Type + // fn foo(arg: u32, arg2: T) -> Result where T: Bar + // ^^^^^^^^^^^^^ + write!(f, " -> {}", inputs_and_output.return_type.display(s))?; + } + + // where clause + // fn foo(arg: u32, arg2: T) -> Result where T: Bar + // ^^^^^^^^^^^^ + if !bound_datum.where_clauses.is_empty() { + let s = &s.add_indent(); + write!(f, "\nwhere\n{}", bound_datum.where_clauses.display(s))?; + } + + write!(f, ";")?; + + Ok(()) + } +} diff --git a/vendor/chalk-solve/src/display/render_trait.rs b/vendor/chalk-solve/src/display/render_trait.rs new file mode 100644 index 000000000..a565f076c --- /dev/null +++ b/vendor/chalk-solve/src/display/render_trait.rs @@ -0,0 +1,30 @@ +//! `RenderAsRust` trait and related utils. +use std::fmt::{Display, Formatter, Result}; + +use chalk_ir::interner::Interner; + +use super::state::InternalWriterState; + +/// Displays `RenderAsRust` data. +/// +/// This is a utility struct for making `RenderAsRust` nice to use with rust format macros. +pub(in crate::display) struct DisplayRenderAsRust<'a, I: Interner, T> { + s: &'a InternalWriterState<'a, I>, + rar: &'a T, +} + +impl> Display for DisplayRenderAsRust<'_, I, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + self.rar.fmt(self.s, f) + } +} + +pub(in crate::display) trait RenderAsRust { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result; + fn display<'a>(&'a self, s: &'a InternalWriterState<'a, I>) -> DisplayRenderAsRust<'a, I, Self> + where + Self: Sized, + { + DisplayRenderAsRust { s, rar: self } + } +} diff --git a/vendor/chalk-solve/src/display/state.rs b/vendor/chalk-solve/src/display/state.rs new file mode 100644 index 000000000..fed2f5ca5 --- /dev/null +++ b/vendor/chalk-solve/src/display/state.rs @@ -0,0 +1,352 @@ +//! Persistent state passed down between writers. +//! +//! This is essentially `InternalWriterState` and other things supporting that. +use core::hash::Hash; +use std::{ + borrow::Borrow, + collections::BTreeMap, + fmt::{Debug, Display, Formatter, Result}, + marker::PhantomData, + rc::Rc, + sync::{Arc, Mutex}, +}; + +use crate::RustIrDatabase; +use chalk_ir::{interner::Interner, *}; +use indexmap::IndexMap; +use itertools::Itertools; + +/// Like a BoundVar, but with the debrujin index inverted so as to create a +/// canonical name we can use anywhere for each bound variable. +/// +/// In BoundVar, the innermost bound variables have debrujin index `0`, and +/// each further out BoundVar has a debrujin index `1` higher. +/// +/// In InvertedBoundVar, the outermost variables have inverted_debrujin_idx `0`, +/// and the innermost have their depth, not the other way around. +#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)] +pub struct InvertedBoundVar { + /// The inverted debrujin index. Corresponds roughly to an inverted `DebrujinIndex::depth`. + inverted_debrujin_idx: i64, + /// The index within the debrujin index. Corresponds to `BoundVar::index`. + within_idx: IndexWithinBinding, +} + +impl Display for InvertedBoundVar { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "_{}_{}", self.inverted_debrujin_idx, self.within_idx) + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +enum UnifiedId { + AdtId(I::InternedAdtId), + DefId(I::DefId), +} + +#[derive(Debug)] +pub struct IdAliasStore { + /// Map from the DefIds we've encountered to a u32 alias id unique to all ids + /// the same name. + aliases: IndexMap, + /// Map from each name to the next unused u32 alias id. + next_unused_for_name: BTreeMap, +} + +impl Default for IdAliasStore { + fn default() -> Self { + IdAliasStore { + aliases: IndexMap::default(), + next_unused_for_name: BTreeMap::default(), + } + } +} + +impl IdAliasStore { + fn alias_for_id_name(&mut self, id: T, name: String) -> String { + let next_unused_for_name = &mut self.next_unused_for_name; + let alias = *self.aliases.entry(id).or_insert_with(|| { + let next_unused: &mut u32 = next_unused_for_name.entry(name.clone()).or_default(); + let id = *next_unused; + *next_unused += 1; + id + }); + // If there are no conflicts, keep the name the same so that we don't + // need name-agnostic equality in display tests. + if alias == 0 { + name + } else { + format!("{}_{}", name, alias) + } + } +} + +#[derive(Debug)] +struct IdAliases { + id_aliases: IdAliasStore>, +} + +impl Default for IdAliases { + fn default() -> Self { + IdAliases { + id_aliases: IdAliasStore::default(), + } + } +} + +/// Writer state which persists across multiple writes. +/// +/// Currently, this means keeping track of what IDs have been given what names, +/// including deduplication information. +/// +/// This data is stored using interior mutability - clones will point to the same underlying +/// data. +/// +/// Uses a separate type, `P`, for the database stored inside to account for +/// `Arc` or wrapping other storage mediums. +#[derive(Debug)] +pub struct WriterState +where + DB: RustIrDatabase, + P: Borrow, + I: Interner, +{ + pub(super) db: P, + id_aliases: Arc>>, + _phantom: PhantomData, +} + +impl Clone for WriterState +where + DB: RustIrDatabase, + P: Borrow + Clone, + I: Interner, +{ + fn clone(&self) -> Self { + WriterState { + db: self.db.clone(), + id_aliases: self.id_aliases.clone(), + _phantom: PhantomData, + } + } +} + +impl WriterState +where + DB: RustIrDatabase, + P: Borrow, + I: Interner, +{ + pub fn new(db: P) -> Self { + WriterState { + db, + id_aliases: Arc::new(Mutex::new(IdAliases::default())), + _phantom: PhantomData, + } + } + + /// Returns a new version of self containing a wrapped database which + /// references the outer data. + /// + /// `f` will be run on the internal database, and the returned result will + /// wrap the result from `f`. For consistency, `f` should always contain the + /// given database, and must keep the same ID<->item relationships. + pub(super) fn wrap_db_ref<'a, DB2: ?Sized, P2, F>(&'a self, f: F) -> WriterState + where + DB2: RustIrDatabase, + P2: Borrow, + // We need to pass in `&'a P` specifically to guarantee that the `&P` + // can outlive the function body, and thus that it's safe to store `&P` + // in `P2`. + F: FnOnce(&'a P) -> P2, + { + WriterState { + db: f(&self.db), + id_aliases: self.id_aliases.clone(), + _phantom: PhantomData, + } + } + + pub(crate) fn db(&self) -> &DB { + self.db.borrow() + } +} + +/// Writer state for a single write call, persistent only as long as necessary +/// to write a single item. +/// +/// Stores things necessary for . +#[derive(Clone, Debug)] +pub(super) struct InternalWriterState<'a, I: Interner> { + persistent_state: WriterState + 'a, &'a dyn RustIrDatabase>, + indent_level: usize, + debrujin_indices_deep: u32, + // lowered_(inverted_debrujin_idx, index) -> src_correct_(inverted_debrujin_idx, index) + remapping: Rc>, + // the inverted_bound_var which maps to "Self" + self_mapping: Option, +} + +type IndexWithinBinding = usize; + +impl<'a, I: Interner> InternalWriterState<'a, I> { + pub fn new(persistent_state: &'a WriterState) -> Self + where + DB: RustIrDatabase, + P: Borrow, + { + InternalWriterState { + persistent_state: persistent_state + .wrap_db_ref(|db| db.borrow() as &dyn RustIrDatabase), + indent_level: 0, + debrujin_indices_deep: 0, + remapping: Rc::new(BTreeMap::new()), + self_mapping: None, + } + } + + pub(super) fn db(&self) -> &dyn RustIrDatabase { + self.persistent_state.db + } + + pub(super) fn add_indent(&self) -> Self { + InternalWriterState { + indent_level: self.indent_level + 1, + ..self.clone() + } + } + + pub(super) fn indent(&self) -> impl Display { + std::iter::repeat(" ").take(self.indent_level).format("") + } + + pub(super) fn alias_for_adt_id_name(&self, id: I::InternedAdtId, name: String) -> impl Display { + self.persistent_state + .id_aliases + .lock() + .unwrap() + .id_aliases + .alias_for_id_name(UnifiedId::AdtId(id), name) + } + + pub(super) fn alias_for_id_name(&self, id: I::DefId, name: String) -> impl Display { + self.persistent_state + .id_aliases + .lock() + .unwrap() + .id_aliases + .alias_for_id_name(UnifiedId::DefId(id), name) + } + + /// Adds a level of debrujin index, and possibly a "Self" parameter. + /// + /// This should be called whenever recursing into the value within a + /// [`Binders`]. + /// + /// If `self_binding` is `Some`, then it will introduce a new variable named + /// `Self` with the within-debrujin index given within and the innermost + /// debrujian index after increasing debrujin index. + #[must_use = "this returns a new `InternalWriterState`, and does not modify the existing one"] + pub(super) fn add_debrujin_index(&self, self_binding: Option) -> Self { + let mut new_state = self.clone(); + new_state.debrujin_indices_deep += 1; + new_state.self_mapping = self_binding + .map(|idx| new_state.indices_for_introduced_bound_var(idx)) + .or(self.self_mapping); + new_state + } + + /// Adds parameter remapping. + /// + /// Each of the parameters in `lowered_vars` will be mapped to its + /// corresponding variable in `original_vars` when printed through the + /// `InternalWriterState` returned from this method. + /// + /// `lowered_vars` and `original_vars` must have the same length. + pub(super) fn add_parameter_mapping( + &self, + lowered_vars: impl Iterator, + original_vars: impl Iterator, + ) -> Self { + let remapping = self + .remapping + .iter() + .map(|(a, b)| (*a, *b)) + .chain(lowered_vars.zip(original_vars)) + .collect::>(); + + InternalWriterState { + remapping: Rc::new(remapping), + ..self.clone() + } + } + + /// Inverts the debrujin index so as to create a canonical name we can + /// anywhere for each bound variable. + /// + /// See [`InvertedBoundVar`][InvertedBoundVar]. + pub(super) fn invert_debrujin_idx( + &self, + debrujin_idx: u32, + index: IndexWithinBinding, + ) -> InvertedBoundVar { + InvertedBoundVar { + inverted_debrujin_idx: (self.debrujin_indices_deep as i64) - (debrujin_idx as i64), + within_idx: index, + } + } + + pub(super) fn apply_mappings(&self, b: InvertedBoundVar) -> impl Display { + let remapped = self.remapping.get(&b).copied().unwrap_or(b); + if self.self_mapping == Some(remapped) { + "Self".to_owned() + } else { + remapped.to_string() + } + } + + pub(super) fn indices_for_bound_var(&self, b: &BoundVar) -> InvertedBoundVar { + self.invert_debrujin_idx(b.debruijn.depth(), b.index) + } + + pub(super) fn indices_for_introduced_bound_var( + &self, + idx: IndexWithinBinding, + ) -> InvertedBoundVar { + // freshly introduced bound vars will always have debrujin index of 0, + // they're always "innermost". + self.invert_debrujin_idx(0, idx) + } + + pub(super) fn display_bound_var(&self, b: &BoundVar) -> impl Display { + self.apply_mappings(self.indices_for_bound_var(b)) + } + + pub(super) fn name_for_introduced_bound_var(&self, idx: IndexWithinBinding) -> impl Display { + self.apply_mappings(self.indices_for_introduced_bound_var(idx)) + } + + pub(super) fn binder_var_indices<'b>( + &'b self, + binders: &'b VariableKinds, + ) -> impl Iterator + 'b { + binders + .iter(self.db().interner()) + .enumerate() + .map(move |(idx, _param)| self.indices_for_introduced_bound_var(idx)) + } + + pub(super) fn binder_var_display<'b>( + &'b self, + binders: &'b VariableKinds, + ) -> impl Iterator + 'b { + binders + .iter(self.db().interner()) + .zip(self.binder_var_indices(binders)) + .map(move |(parameter, var)| match parameter { + VariableKind::Ty(_) => format!("{}", self.apply_mappings(var)), + VariableKind::Lifetime => format!("'{}", self.apply_mappings(var)), + VariableKind::Const(_ty) => format!("const {}", self.apply_mappings(var)), + }) + } +} diff --git a/vendor/chalk-solve/src/display/stub.rs b/vendor/chalk-solve/src/display/stub.rs new file mode 100644 index 000000000..ec209bc91 --- /dev/null +++ b/vendor/chalk-solve/src/display/stub.rs @@ -0,0 +1,268 @@ +//! Contains a `LoggingIrDatabase` which returns stub versions of everything +//! queried. +use std::sync::Arc; + +use crate::rust_ir::{GeneratorDatum, GeneratorWitnessDatum}; +use crate::{ + rust_ir::{ + AdtDatumBound, AdtKind, AdtVariantDatum, AssociatedTyDatumBound, FnDefDatumBound, + OpaqueTyDatumBound, TraitDatumBound, + }, + RustIrDatabase, +}; +use chalk_ir::{ + interner::Interner, Binders, CanonicalVarKinds, GeneratorId, Substitution, Ty, + UnificationDatabase, VariableKinds, Variances, +}; + +#[derive(Debug)] +pub struct StubWrapper<'a, DB> { + db: &'a DB, +} + +impl<'a, DB> StubWrapper<'a, DB> { + pub fn new(db: &'a DB) -> Self { + StubWrapper { db } + } +} + +impl> UnificationDatabase for StubWrapper<'_, DB> { + fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId) -> Variances { + self.db.unification_database().fn_def_variance(fn_def_id) + } + + fn adt_variance(&self, adt_id: chalk_ir::AdtId) -> Variances { + self.db.unification_database().adt_variance(adt_id) + } +} + +impl> RustIrDatabase for StubWrapper<'_, DB> { + fn custom_clauses(&self) -> Vec> { + self.db.custom_clauses() + } + + fn associated_ty_data( + &self, + ty: chalk_ir::AssocTypeId, + ) -> std::sync::Arc> { + let mut v = (*self.db.associated_ty_data(ty)).clone(); + v.binders = Binders::new( + v.binders.binders.clone(), + AssociatedTyDatumBound { + where_clauses: Vec::new(), + bounds: Vec::new(), + }, + ); + Arc::new(v) + } + + fn trait_datum( + &self, + trait_id: chalk_ir::TraitId, + ) -> std::sync::Arc> { + let mut v = (*self.db.trait_datum(trait_id)).clone(); + v.binders = Binders::new( + v.binders.binders.clone(), + TraitDatumBound { + where_clauses: Vec::new(), + }, + ); + Arc::new(v) + } + + fn adt_datum(&self, adt_id: chalk_ir::AdtId) -> std::sync::Arc> { + let mut v = (*self.db.adt_datum(adt_id)).clone(); + let variants = match v.kind { + AdtKind::Struct | AdtKind::Union => vec![AdtVariantDatum { fields: vec![] }], + AdtKind::Enum => vec![], + }; + v.binders = Binders::new( + v.binders.binders.clone(), + AdtDatumBound { + variants, + where_clauses: Vec::new(), + }, + ); + Arc::new(v) + } + + fn adt_repr(&self, id: chalk_ir::AdtId) -> std::sync::Arc> { + self.db.adt_repr(id) + } + + fn adt_size_align(&self, id: chalk_ir::AdtId) -> Arc { + self.db.adt_size_align(id) + } + + fn fn_def_datum( + &self, + fn_def_id: chalk_ir::FnDefId, + ) -> std::sync::Arc> { + let mut v = (*self.db.fn_def_datum(fn_def_id)).clone(); + v.binders = Binders::new( + v.binders.binders.clone(), + FnDefDatumBound { + inputs_and_output: v.binders.skip_binders().inputs_and_output.clone(), + where_clauses: Vec::new(), + }, + ); + Arc::new(v) + } + + fn impl_datum( + &self, + _impl_id: chalk_ir::ImplId, + ) -> std::sync::Arc> { + unreachable!("impl items should never be stubbed") + } + + fn associated_ty_value( + &self, + _id: crate::rust_ir::AssociatedTyValueId, + ) -> std::sync::Arc> { + unreachable!("associated type values should never be stubbed") + } + + fn opaque_ty_data( + &self, + id: chalk_ir::OpaqueTyId, + ) -> std::sync::Arc> { + let mut v = (*self.db.opaque_ty_data(id)).clone(); + v.bound = Binders::new( + v.bound.binders, + OpaqueTyDatumBound { + bounds: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()), + where_clauses: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()), + }, + ); + Arc::new(v) + } + + fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId) -> chalk_ir::Ty { + // Return a unit since the particular hidden type doesn't matter (If it + // did matter, it would have been recorded) + chalk_ir::TyKind::Tuple(0, Substitution::empty(self.db.interner())) + .intern(self.db.interner()) + } + + fn impls_for_trait( + &self, + _trait_id: chalk_ir::TraitId, + _parameters: &[chalk_ir::GenericArg], + _binders: &CanonicalVarKinds, + ) -> Vec> { + // We panic here because the returned ids may not be collected, + // resulting in unresolvable names. + unimplemented!("stub display code should call this") + } + + fn local_impls_to_coherence_check( + &self, + trait_id: chalk_ir::TraitId, + ) -> Vec> { + self.db.local_impls_to_coherence_check(trait_id) + } + + fn impl_provided_for( + &self, + _auto_trait_id: chalk_ir::TraitId, + _ty: &chalk_ir::TyKind, + ) -> bool { + // We panic here because the returned ids may not be collected, + // resulting in unresolvable names. + unimplemented!("stub display code should call this") + } + + fn well_known_trait_id( + &self, + well_known_trait: crate::rust_ir::WellKnownTrait, + ) -> Option> { + self.db.well_known_trait_id(well_known_trait) + } + + fn program_clauses_for_env( + &self, + environment: &chalk_ir::Environment, + ) -> chalk_ir::ProgramClauses { + self.db.program_clauses_for_env(environment) + } + + fn interner(&self) -> I { + self.db.interner() + } + + fn is_object_safe(&self, trait_id: chalk_ir::TraitId) -> bool { + self.db.is_object_safe(trait_id) + } + + fn closure_kind( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> crate::rust_ir::ClosureKind { + unimplemented!("cannot stub closures") + } + + fn closure_inputs_and_output( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> chalk_ir::Binders> { + unimplemented!("cannot stub closures") + } + + fn closure_upvars( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> chalk_ir::Binders> { + unimplemented!("cannot stub closures") + } + + fn generator_datum(&self, _generator_id: GeneratorId) -> Arc> { + unimplemented!("cannot stub generator") + } + + fn generator_witness_datum( + &self, + _generator_id: GeneratorId, + ) -> Arc> { + unimplemented!("cannot stub generator witness") + } + + fn closure_fn_substitution( + &self, + _closure_id: chalk_ir::ClosureId, + _substs: &chalk_ir::Substitution, + ) -> chalk_ir::Substitution { + unimplemented!("cannot stub closures") + } + + fn unification_database(&self) -> &dyn UnificationDatabase { + self + } + + fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String { + self.db.trait_name(trait_id) + } + + fn adt_name(&self, struct_id: chalk_ir::AdtId) -> String { + self.db.adt_name(struct_id) + } + + fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId) -> String { + self.db.assoc_type_name(assoc_ty_id) + } + + fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId) -> String { + self.db.opaque_type_name(opaque_ty_id) + } + + fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId) -> String { + self.db.fn_def_name(fn_def_id) + } + + fn discriminant_type(&self, ty: Ty) -> Ty { + self.db.discriminant_type(ty) + } +} diff --git a/vendor/chalk-solve/src/display/ty.rs b/vendor/chalk-solve/src/display/ty.rs new file mode 100644 index 000000000..b0186652e --- /dev/null +++ b/vendor/chalk-solve/src/display/ty.rs @@ -0,0 +1,303 @@ +//! Writer logic for types. +//! +//! Contains the highly-recursive logic for writing `TyKind` and its variants. +use std::fmt::{Formatter, Result}; + +use crate::split::Split; +use chalk_ir::{interner::Interner, *}; +use itertools::Itertools; + +use super::{ + display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust, + state::InternalWriterState, +}; + +impl RenderAsRust for TyKind { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + match self { + TyKind::Adt(sid, substitution) => { + write!(f, "{}", sid.display(s))?; + let parameters = substitution.as_slice(interner); + let parameters = parameters.iter().map(|param| param.display(s)); + write_joined_non_empty_list!(f, "<{}>", parameters, ", ") + } + TyKind::AssociatedType(assoc_type_id, substitution) => { + // (Iterator::Item)(x) + // should be written in Rust as ::Item + let datum = s.db().associated_ty_data(*assoc_type_id); + assert!( + substitution + .iter(interner) + .filter_map(move |p| p.ty(interner)) + .count() + >= 1, + "AssociatedType should have at least 1 parameter" + ); + write!( + f, + "<{} as {}>::{}", + substitution + .iter(interner) + .filter_map(move |p| p.ty(interner)) + .next() + .unwrap() + .display(s), + datum.trait_id.display(s), + datum.id.display(s), + )?; + let params = substitution.as_slice(interner); + write_joined_non_empty_list!( + f, + "<{}>", + params[1..].iter().map(|ty| ty.display(s)), + "," + ) + } + TyKind::Scalar(scalar) => write!(f, "{}", scalar.display(s)), + TyKind::Tuple(arity, substitution) => { + write!( + f, + "({}{})", + substitution + .as_slice(interner) + .iter() + .map(|p| p.display(s)) + .format(", "), + if *arity == 1 { + // need trailing single comma + "," + } else { + "" + } + ) + } + TyKind::OpaqueType(opaque_ty_id, substitution) => write!( + f, + "{}", + display_type_with_generics(s, *opaque_ty_id, substitution.as_slice(interner)) + ), + TyKind::Raw(mutability, ty) => match mutability { + Mutability::Mut => write!(f, "*mut {}", ty.display(s)), + Mutability::Not => write!(f, "*const {}", ty.display(s)), + }, + TyKind::Ref(mutability, lifetime, ty) => match mutability { + Mutability::Mut => write!(f, "&{} mut {}", lifetime.display(s), ty.display(s)), + Mutability::Not => write!(f, "&{} {}", lifetime.display(s), ty.display(s)), + }, + TyKind::Str => write!(f, "str"), + TyKind::Slice(ty) => write!(f, "[{}]", ty.display(s)), + TyKind::Error => write!(f, "{{error}}"), + TyKind::Never => write!(f, "!"), + + // FIXME: write out valid types for these variants + TyKind::FnDef(..) => write!(f, ""), + TyKind::Closure(..) => write!(f, ""), + TyKind::Foreign(..) => write!(f, ""), + TyKind::Generator(..) => write!(f, ""), + TyKind::GeneratorWitness(..) => write!(f, ""), + + TyKind::Array(ty, const_) => write!(f, "[{}; {}]", ty.display(s), const_.display(s),), + TyKind::Dyn(dyn_ty) => { + // the lifetime needs to be outside of the bounds, so we + // introduce a new scope for the bounds + { + let s = &s.add_debrujin_index(None); + // dyn_ty.bounds.binders creates a Self binding for the trait + let bounds = dyn_ty.bounds.skip_binders(); + + write!( + f, + "dyn {}", + display_self_where_clauses_as_bounds(s, bounds.as_slice(interner)), + )?; + } + + write!(f, " + {}", dyn_ty.lifetime.display(s))?; + Ok(()) + } + TyKind::BoundVar(bound_var) => write!(f, "{}", s.display_bound_var(bound_var)), + TyKind::InferenceVar(_, _) => write!(f, "_"), + TyKind::Alias(alias_ty) => alias_ty.fmt(s, f), + TyKind::Function(func) => func.fmt(s, f), + TyKind::Placeholder(_) => write!(f, ""), + } + } +} + +impl RenderAsRust for AliasTy { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + match self { + AliasTy::Projection(projection_ty) => projection_ty.fmt(s, f), + AliasTy::Opaque(opaque_ty) => opaque_ty.fmt(s, f), + } + } +} + +impl RenderAsRust for ProjectionTy { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // >::Z + + // Now, we split out A*, Y/Z and B*: + // trait_params is X, A1, A2, A3, + // assoc_type_params is B1, B2, B3, + // assoc_ty_datum stores info about Y and Z. + let (assoc_ty_datum, trait_params, assoc_type_params) = s.db().split_projection(self); + write!( + f, + "<{} as {}>::{}", + trait_params[0].display(s), + display_type_with_generics(s, assoc_ty_datum.trait_id, &trait_params[1..]), + assoc_ty_datum.id.display(s), + )?; + write_joined_non_empty_list!( + f, + "<{}>", + assoc_type_params.iter().map(|param| param.display(s)), + ", " + )?; + Ok(()) + } +} + +impl RenderAsRust for OpaqueTy { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + write!( + f, + "{}", + display_type_with_generics(s, self.opaque_ty_id, self.substitution.as_slice(interner),) + ) + } +} + +impl RenderAsRust for FnPointer { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + let interner = s.db().interner(); + let s = &s.add_debrujin_index(None); + if self.num_binders > 0 { + write!( + f, + "for<{}> ", + (0..self.num_binders) + .map(|n| format!("'{}", s.name_for_introduced_bound_var(n))) + .format(", ") + )?; + } + let parameters = self.substitution.0.as_slice(interner); + write!( + f, + "fn({}) -> {}", + parameters[..parameters.len() - 1] + .iter() + .map(|param| param.display(s)) + .format(", "), + parameters[parameters.len() - 1].display(s), + ) + } +} + +impl RenderAsRust for Scalar { + fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + use chalk_ir::{FloatTy::*, IntTy::*, UintTy::*}; + write!( + f, + "{}", + match self { + Scalar::Bool => "bool", + Scalar::Char => "char", + Scalar::Int(int) => match int { + Isize => "isize", + I8 => "i8", + I16 => "i16", + I32 => "i32", + I64 => "i64", + I128 => "i128", + }, + Scalar::Uint(uint) => match uint { + Usize => "usize", + U8 => "u8", + U16 => "u16", + U32 => "u32", + U64 => "u64", + U128 => "u128", + }, + Scalar::Float(float) => match float { + F32 => "f32", + F64 => "f64", + }, + } + ) + } +} + +impl RenderAsRust for LifetimeData { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + match self { + LifetimeData::BoundVar(v) => write!(f, "'{}", s.display_bound_var(v)), + LifetimeData::InferenceVar(_) => write!(f, "'_"), + LifetimeData::Placeholder(ix) => { + write!(f, "'_placeholder_{}_{}", ix.ui.counter, ix.idx) + } + LifetimeData::Static => write!(f, "'static"), + LifetimeData::Erased => write!(f, "'_"), + // Matching the void ensures at compile time that this code is + // unreachable + LifetimeData::Phantom(void, _) => match *void {}, + } + } +} + +impl RenderAsRust for ConstData { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + write!(f, "{}", self.value.display(s)) + } +} + +impl RenderAsRust for ConstValue { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + match self { + ConstValue::BoundVar(v) => write!(f, "{}", s.display_bound_var(v)), + ConstValue::InferenceVar(_) => write!(f, "_"), + ConstValue::Placeholder(_) => write!(f, ""), + ConstValue::Concrete(value) => write!(f, "{:?}", value.interned), + } + } +} + +impl RenderAsRust for GenericArgData { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + match self { + GenericArgData::Ty(ty) => write!(f, "{}", ty.display(s)), + GenericArgData::Lifetime(lt) => write!(f, "{}", lt.display(s)), + GenericArgData::Const(const_ty) => write!(f, "{}", const_ty.display(s)), + } + } +} + +impl RenderAsRust for Ty { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // delegate to TyKind + self.kind(s.db().interner()).fmt(s, f) + } +} + +impl RenderAsRust for Lifetime { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // delegate to LifetimeData + self.data(s.db().interner()).fmt(s, f) + } +} + +impl RenderAsRust for Const { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { + self.data(s.db().interner()).fmt(s, f) + } +} + +impl RenderAsRust for GenericArg { + fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { + // delegate to GenericArgData + self.data(s.db().interner()).fmt(s, f) + } +} diff --git a/vendor/chalk-solve/src/display/utils.rs b/vendor/chalk-solve/src/display/utils.rs new file mode 100644 index 000000000..306605616 --- /dev/null +++ b/vendor/chalk-solve/src/display/utils.rs @@ -0,0 +1,51 @@ +//! Render utilities which don't belong anywhere else. +use std::fmt::{Display, Formatter, Result}; + +pub fn as_display) -> Result>(f: F) -> impl Display { + struct ClosureDisplay) -> Result>(F); + + impl) -> Result> Display for ClosureDisplay { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + self.0(f) + } + } + + ClosureDisplay(f) +} + +macro_rules! write_joined_non_empty_list { + ($f:expr,$template:tt,$list:expr,$sep:expr) => {{ + let mut x = $list.into_iter().peekable(); + if x.peek().is_some() { + write!($f, $template, x.format($sep)) + } else { + Ok(()) + } + }}; +} + +/// Processes a name given by an [`Interner`][chalk_ir::interner::Interner] debug +/// method into something usable by the `display` module. +/// +/// This is specifically useful when implementing +/// [`RustIrDatabase`][crate::RustIrDatabase] `name_*` methods. +pub fn sanitize_debug_name(func: impl Fn(&mut Formatter<'_>) -> Option) -> String { + use std::fmt::Write; + + // First, write the debug method contents to a String. + let mut debug_out = String::new(); + // ignore if the result is `None`, as we can just as easily tell by looking + // to see if anything was written to `debug_out`. + write!( + debug_out, + "{}", + as_display(|fmt| { func(fmt).unwrap_or(Ok(())) }) + ) + .expect("expected writing to a String to succeed"); + if debug_out.is_empty() { + return "Unknown".to_owned(); + } + + // now the actual sanitization + debug_out.replace(|c: char| !c.is_ascii_alphanumeric(), "_") +} -- cgit v1.2.3