From 64d98f8ee037282c35007b64c2649055c56af1db Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:03 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- vendor/chalk-solve-0.87.0/src/split.rs | 199 +++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 vendor/chalk-solve-0.87.0/src/split.rs (limited to 'vendor/chalk-solve-0.87.0/src/split.rs') diff --git a/vendor/chalk-solve-0.87.0/src/split.rs b/vendor/chalk-solve-0.87.0/src/split.rs new file mode 100644 index 000000000..bea24044d --- /dev/null +++ b/vendor/chalk-solve-0.87.0/src/split.rs @@ -0,0 +1,199 @@ +use crate::rust_ir::*; +use crate::RustIrDatabase; +use chalk_ir::interner::Interner; +use chalk_ir::*; +use std::sync::Arc; +use tracing::{debug, instrument}; + +/// Methods for splitting up the projections for associated types from +/// the surrounding context. +pub trait Split: RustIrDatabase { + /// Given a projection of an associated type, split the type + /// parameters into those that come from the *trait* and those + /// that come from the *associated type itself*. So e.g. if you + /// have `(Iterator::Item)`, this would return `([F], [])`, + /// since `Iterator::Item` is not generic and hence doesn't have + /// any type parameters itself. + fn split_projection<'p>( + &self, + projection: &'p ProjectionTy, + ) -> ( + Arc>, + &'p [GenericArg], + &'p [GenericArg], + ) { + let interner = self.interner(); + let ProjectionTy { + associated_ty_id, + ref substitution, + } = *projection; + let parameters = substitution.as_slice(interner); + let associated_ty_data = &self.associated_ty_data(associated_ty_id); + let (trait_params, other_params) = + self.split_associated_ty_parameters(parameters, &**associated_ty_data); + (associated_ty_data.clone(), trait_params, other_params) + } + + /// Given a projection `>::Item`, + /// returns the trait parameters `[P0..Pn]` (see + /// `split_projection`). + fn trait_parameters_from_projection<'p>( + &self, + projection: &'p ProjectionTy, + ) -> &'p [GenericArg] { + let (_, trait_params, _) = self.split_projection(projection); + trait_params + } + + /// Given a projection `>::Item`, + /// returns the trait parameters `[P0..Pn]` (see + /// `split_projection`). + fn trait_ref_from_projection(&self, projection: &ProjectionTy) -> TraitRef { + let interner = self.interner(); + let (associated_ty_data, trait_params, _) = self.split_projection(projection); + TraitRef { + trait_id: associated_ty_data.trait_id, + substitution: Substitution::from_iter(interner, trait_params), + } + } + + /// Given the full set of parameters (or binders) for an + /// associated type *value* (which appears in an impl), splits + /// them into the substitutions for the *impl* and those for the + /// *associated type*. + /// + /// # Example + /// + /// ```ignore (example) + /// impl Iterable for Vec { + /// type Iter<'a>; + /// } + /// ``` + /// + /// in this example, the full set of parameters would be `['x, + /// Y]`, where `'x` is the value for `'a` and `Y` is the value for + /// `T`. + /// + /// # Returns + /// + /// Returns the pair of: + /// + /// * the parameters for the impl (`[Y]`, in our example) + /// * the parameters for the associated type value (`['a]`, in our example) + fn split_associated_ty_value_parameters<'p, P>( + &self, + parameters: &'p [P], + associated_ty_value: &AssociatedTyValue, + ) -> (&'p [P], &'p [P]) { + let interner = self.interner(); + let impl_datum = self.impl_datum(associated_ty_value.impl_id); + let impl_params_len = impl_datum.binders.len(interner); + assert!(parameters.len() >= impl_params_len); + + // the impl parameters are a suffix + // + // [ P0..Pn, Pn...Pm ] + // ^^^^^^^ impl parameters + let split_point = parameters.len() - impl_params_len; + let (other_params, impl_params) = parameters.split_at(split_point); + (impl_params, other_params) + } + + /// Given the full set of parameters for an associated type *value* + /// (which appears in an impl), returns the trait reference + /// and projection that are being satisfied by that value. + /// + /// # Example + /// + /// ```ignore (example) + /// impl Iterable for Vec { + /// type Iter<'a>; + /// } + /// ``` + /// + /// Here we expect the full set of parameters for `Iter`, which + /// would be `['x, Y]`, where `'x` is the value for `'a` and `Y` + /// is the value for `T`. + /// + /// Returns the pair of: + /// + /// * the parameters that apply to the impl (`Y`, in our example) + /// * the projection ` as Iterable>::Iter<'x>` + #[instrument(level = "debug", skip(self, associated_ty_value))] + fn impl_parameters_and_projection_from_associated_ty_value<'p>( + &self, + parameters: &'p [GenericArg], + associated_ty_value: &AssociatedTyValue, + ) -> (&'p [GenericArg], ProjectionTy) { + let interner = self.interner(); + + let impl_datum = self.impl_datum(associated_ty_value.impl_id); + + // Get the trait ref from the impl -- so in our example above + // this would be `Box: Foo`. + let (impl_parameters, atv_parameters) = + self.split_associated_ty_value_parameters(parameters, associated_ty_value); + let trait_ref = { + let opaque_ty_ref = impl_datum.binders.map_ref(|b| &b.trait_ref).cloned(); + debug!(?opaque_ty_ref); + opaque_ty_ref.substitute(interner, impl_parameters) + }; + + // Create the parameters for the projection -- in our example + // above, this would be `['!a, Box]`, corresponding to + // ` as Foo>::Item<'!a>` + let projection_substitution = Substitution::from_iter( + interner, + atv_parameters + .iter() + .chain(trait_ref.substitution.iter(interner)) + .cloned(), + ); + + let projection = ProjectionTy { + associated_ty_id: associated_ty_value.associated_ty_id, + substitution: projection_substitution, + }; + + debug!(?impl_parameters, ?trait_ref, ?projection); + + (impl_parameters, projection) + } + + /// Given the full set of parameters (or binders) for an + /// associated type datum (the one appearing in a trait), splits + /// them into the parameters for the *trait* and those for the + /// *associated type*. + /// + /// # Example + /// + /// ```ignore (example) + /// trait Foo { + /// type Assoc<'a>; + /// } + /// ``` + /// + /// in this example, the full set of parameters would be `['x, + /// Y]`, where `'x` is the value for `'a` and `Y` is the value for + /// `T`. + /// + /// # Returns + /// + /// Returns the tuple of: + /// + /// * the parameters for the impl (`[Y]`, in our example) + /// * the parameters for the associated type value (`['a]`, in our example) + fn split_associated_ty_parameters<'p, P>( + &self, + parameters: &'p [P], + associated_ty_datum: &AssociatedTyDatum, + ) -> (&'p [P], &'p [P]) { + let trait_datum = &self.trait_datum(associated_ty_datum.trait_id); + let trait_num_params = trait_datum.binders.len(self.interner()); + let split_point = parameters.len() - trait_num_params; + let (other_params, trait_params) = parameters.split_at(split_point); + (trait_params, other_params) + } +} + +impl + ?Sized, I: Interner> Split for DB {} -- cgit v1.2.3