From 69714d36e6617800f3edea174f5d6f76c985ad4c Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Mon, 5 Apr 2021 17:13:50 +0200 Subject: Hide Binders internals more --- crates/hir/src/lib.rs | 4 +-- crates/hir/src/semantics.rs | 4 +-- crates/hir_ty/src/diagnostics/expr.rs | 3 ++- crates/hir_ty/src/display.rs | 6 ++--- crates/hir_ty/src/lib.rs | 44 ++++++++----------------------- crates/hir_ty/src/lower.rs | 23 +++++++++------- crates/hir_ty/src/method_resolution.rs | 8 +++--- crates/hir_ty/src/traits/chalk.rs | 43 +++++++++++++++--------------- crates/hir_ty/src/traits/chalk/mapping.rs | 17 +++++++----- crates/hir_ty/src/types.rs | 36 ++++++++++++++++++++++++- crates/hir_ty/src/walk.rs | 8 +++--- 11 files changed, 108 insertions(+), 88 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b14c9a675..ccfe348a4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -702,7 +702,7 @@ impl_from!(Struct, Union, Enum for Adt); impl Adt { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { let subst = db.generic_defaults(self.into()); - subst.iter().any(|ty| ty.value.is_unknown()) + subst.iter().any(|ty| ty.skip_binders().is_unknown()) } /// Turns this ADT into a type. Any type parameters of the ADT will be @@ -1089,7 +1089,7 @@ pub struct TypeAlias { impl TypeAlias { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { let subst = db.generic_defaults(self.id.into()); - subst.iter().any(|ty| ty.value.is_unknown()) + subst.iter().any(|ty| ty.skip_binders().is_unknown()) } pub fn module(self, db: &dyn HirDatabase) -> Module { diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 3bf722d2a..7955bf0b5 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -494,9 +494,9 @@ impl<'db> SemanticsImpl<'db> { fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option { // FIXME: this erases Substs let func = self.resolve_method_call(call)?; - let ty = self.db.value_ty(func.into()); + let (ty, _) = self.db.value_ty(func.into()).into_value_and_skipped_binders(); let resolver = self.analyze(call.syntax()).resolver; - let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?; + let ty = Type::new_with_resolver(self.db, &resolver, ty)?; let mut res = ty.as_callable(self.db)?; res.is_bound_method = true; Some(res) diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 8169b759f..db278d0db 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -245,7 +245,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> { Some(callee) => callee, None => return, }; - let sig = db.callable_item_signature(callee.into()).value; + let sig = + db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0; (sig, args) } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 1108e5a10..2e178e5a8 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -353,7 +353,7 @@ impl HirDisplay for Ty { .as_ref() .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); let bounds = data.subst(parameters); - bounds.value + bounds.into_value_and_skipped_binders().0 } else { Vec::new() } @@ -543,7 +543,7 @@ impl HirDisplay for Ty { .as_ref() .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); let bounds = data.subst(¶meters); - write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; + write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?; // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution } ImplTraitId::AsyncBlockTypeImplTrait(..) => { @@ -630,7 +630,7 @@ impl HirDisplay for Ty { .as_ref() .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); let bounds = data.subst(&opaque_ty.substitution); - write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; + write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?; } ImplTraitId::AsyncBlockTypeImplTrait(..) => { write!(f, "{{async block}}")?; diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index adfdcaa37..61b5cf269 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -118,49 +118,27 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option { } impl Binders { - pub fn new(num_binders: usize, value: T) -> Self { - Self { num_binders, value } - } - pub fn wrap_empty(value: T) -> Self where T: TypeWalk, { - Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } - } - - pub fn as_ref(&self) -> Binders<&T> { - Binders { num_binders: self.num_binders, value: &self.value } - } - - pub fn map(self, f: impl FnOnce(T) -> U) -> Binders { - Binders { num_binders: self.num_binders, value: f(self.value) } - } - - pub fn filter_map(self, f: impl FnOnce(T) -> Option) -> Option> { - Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) - } - - pub fn skip_binders(&self) -> &T { - &self.value - } - - pub fn into_value_and_skipped_binders(self) -> (T, usize) { - (self.value, self.num_binders) + Binders::empty(&Interner, value.shift_bound_vars(DebruijnIndex::ONE)) } } impl Binders<&T> { pub fn cloned(&self) -> Binders { - Binders { num_binders: self.num_binders, value: self.value.clone() } + let (value, binders) = self.into_value_and_skipped_binders(); + Binders::new(binders, value.clone()) } } impl Binders { /// Substitutes all variables. pub fn subst(self, subst: &Substitution) -> T { - assert_eq!(subst.len(&Interner), self.num_binders); - self.value.subst_bound_vars(subst) + let (value, binders) = self.into_value_and_skipped_binders(); + assert_eq!(subst.len(&Interner), binders); + value.subst_bound_vars(subst) } } @@ -334,12 +312,12 @@ impl Ty { /// If this is a `dyn Trait` type, this returns the `Trait` part. fn dyn_trait_ref(&self) -> Option<&TraitRef> { match self.kind(&Interner) { - TyKind::Dyn(dyn_ty) => { - dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { + TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| { + match b.skip_binders() { WhereClause::Implemented(trait_ref) => Some(trait_ref), _ => None, - }) - } + } + }), _ => None, } } @@ -459,7 +437,7 @@ impl Ty { ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), }; - predicates.map(|it| it.value) + predicates.map(|it| it.into_value_and_skipped_binders().0) } TyKind::Placeholder(idx) => { let id = from_placeholder_idx(db, *idx); diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index e9e4e69ad..19465b2ed 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -832,12 +832,15 @@ pub fn associated_type_shorthand_candidates( match res { // FIXME: how to correctly handle higher-ranked bounds here? - TypeNs::SelfType(impl_id) => { - search(db.impl_trait(impl_id)?.value.shift_bound_vars_out(DebruijnIndex::ONE)) - } + TypeNs::SelfType(impl_id) => search( + db.impl_trait(impl_id)? + .into_value_and_skipped_binders() + .0 + .shift_bound_vars_out(DebruijnIndex::ONE), + ), TypeNs::GenericParam(param_id) => { let predicates = db.generic_predicates_for_param(param_id); - let res = predicates.iter().find_map(|pred| match &pred.value.value { + let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() { // FIXME: how to correctly handle higher-ranked bounds here? WhereClause::Implemented(tr) => { search(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) @@ -1088,8 +1091,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS let ctx = TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); - let ret = type_for_adt(db, def.into()); - Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) + let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); + Binders::new(binders, CallableSig::from_params_and_return(params, ret, false)) } /// Build the type of a tuple struct constructor. @@ -1114,8 +1117,8 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) let ctx = TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::>(); - let ret = type_for_adt(db, def.parent.into()); - Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) + let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders(); + Binders::new(binders, CallableSig::from_params_and_return(params, ret, false)) } /// Build the type of a tuple enum variant constructor. @@ -1267,9 +1270,9 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option< let resolver = impl_id.resolver(db.upcast()); let ctx = TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); - let self_ty = db.impl_self_ty(impl_id); + let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); let target_trait = impl_data.target_trait.as_ref()?; - Some(Binders::new(self_ty.num_binders, ctx.lower_trait_ref(target_trait, Some(self_ty.value))?)) + Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?)) } pub(crate) fn return_type_impl_traits( diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 6ace970d1..ad5022808 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -102,11 +102,11 @@ impl TraitImpls { for (_module_id, module_data) in crate_def_map.modules() { for impl_id in module_data.scope.impls() { let target_trait = match db.impl_trait(impl_id) { - Some(tr) => tr.value.hir_trait_id(), + Some(tr) => tr.skip_binders().hir_trait_id(), None => continue, }; let self_ty = db.impl_self_ty(impl_id); - let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); + let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); impls .map .entry(target_trait) @@ -201,7 +201,7 @@ impl InherentImpls { } let self_ty = db.impl_self_ty(impl_id); - if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) { + if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) { map.entry(fp).or_default().push(impl_id); } } @@ -774,7 +774,7 @@ fn transform_receiver_ty( AssocContainerId::ModuleId(_) => unreachable!(), }; let sig = db.callable_item_signature(function_id.into()); - Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) + Some(sig.map(|s| s.params()[0].clone()).subst(&substs)) } pub fn implements_trait( diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index b7388b98c..47867f77e 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -184,10 +184,15 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { .db .return_type_impl_traits(func) .expect("impl trait id without impl traits"); - let data = &datas.value.impl_traits[idx as usize]; + let data = &datas.skip_binders().impl_traits[idx as usize]; let bound = OpaqueTyDatumBound { bounds: make_binders( - data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(), + data.bounds + .skip_binders() + .iter() + .cloned() + .map(|b| b.to_chalk(self.db)) + .collect(), 1, ), where_clauses: make_binders(vec![], 0), @@ -535,7 +540,8 @@ fn impl_def_datum( .impl_trait(impl_id) // ImplIds for impls where the trait ref can't be resolved should never reach Chalk .expect("invalid impl passed to Chalk") - .value; + .into_value_and_skipped_binders() + .0; let impl_data = db.impl_data(impl_id); let generic_params = generics(db.upcast(), impl_id.into()); @@ -605,18 +611,22 @@ fn type_alias_associated_ty_value( _ => panic!("assoc ty value should be in impl"), }; - let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved + let trait_ref = db + .impl_trait(impl_id) + .expect("assoc ty value should not exist") + .into_value_and_skipped_binders() + .0; // we don't return any assoc ty values if the impl'd trait can't be resolved let assoc_ty = db .trait_data(trait_ref.hir_trait_id()) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well - let ty = db.ty(type_alias.into()); - let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; + let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); + let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; let value = rust_ir::AssociatedTyValue { impl_id: impl_id.to_chalk(db), associated_ty_id: to_assoc_type_id(assoc_ty), - value: make_binders(value_bound, ty.num_binders), + value: make_binders(value_bound, binders), }; Arc::new(value) } @@ -628,20 +638,15 @@ pub(crate) fn fn_def_datum_query( ) -> Arc { let callable_def: CallableDefId = from_chalk(db, fn_def_id); let generic_params = generics(db.upcast(), callable_def.into()); - let sig = db.callable_item_signature(callable_def); + let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders(); let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); let bound = rust_ir::FnDefDatumBound { // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway inputs_and_output: make_binders( rust_ir::FnDefInputsAndOutputDatum { - argument_types: sig - .value - .params() - .iter() - .map(|ty| ty.clone().to_chalk(db)) - .collect(), - return_type: sig.value.ret().clone().to_chalk(db), + argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), + return_type: sig.ret().clone().to_chalk(db), } .shifted_in(&Interner), 0, @@ -650,12 +655,8 @@ pub(crate) fn fn_def_datum_query( }; let datum = FnDefDatum { id: fn_def_id, - sig: chalk_ir::FnSig { - abi: (), - safety: chalk_ir::Safety::Safe, - variadic: sig.value.is_varargs, - }, - binders: make_binders(bound, sig.num_binders), + sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs }, + binders: make_binders(bound, binders), }; Arc::new(datum) } diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 67e88ebf4..72458f367 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -93,12 +93,13 @@ impl ToChalk for Ty { TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), TyKind::Dyn(dyn_ty) => { + let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders(); let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( &Interner, - dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), + bounds.interned().iter().cloned().map(|p| p.to_chalk(db)), ); let bounded_ty = chalk_ir::DynTy { - bounds: make_binders(where_clauses, 1), + bounds: make_binders(where_clauses, binders), lifetime: LifetimeData::Static.intern(&Interner), }; chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) @@ -486,13 +487,14 @@ where type Chalk = chalk_ir::Binders; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders { + let (value, binders) = self.into_value_and_skipped_binders(); chalk_ir::Binders::new( chalk_ir::VariableKinds::from_iter( &Interner, std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) - .take(self.num_binders), + .take(binders), ), - self.value.to_chalk(db), + value.to_chalk(db), ) } @@ -537,7 +539,8 @@ pub(super) fn generic_predicate_to_inline_bound( // An InlineBound is like a GenericPredicate, except the self type is left out. // We don't have a special type for this, but Chalk does. let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); - match &pred.value { + let (pred, binders) = pred.as_ref().into_value_and_skipped_binders(); + match pred { WhereClause::Implemented(trait_ref) => { if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in { // we can only convert predicates back to type bounds if they @@ -549,7 +552,7 @@ pub(super) fn generic_predicate_to_inline_bound( .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) .collect(); let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; - Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) + Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), binders)) } WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in { @@ -566,7 +569,7 @@ pub(super) fn generic_predicate_to_inline_bound( associated_ty_id: projection_ty.associated_ty_id, parameters: Vec::new(), // FIXME we don't support generic associated types yet }; - Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) + Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), binders)) } _ => None, } diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs index bac086318..0e3dd511f 100644 --- a/crates/hir_ty/src/types.rs +++ b/crates/hir_ty/src/types.rs @@ -299,7 +299,41 @@ impl Substitution { #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct Binders { pub num_binders: usize, - pub value: T, + value: T, +} + +impl Binders { + pub fn new(num_binders: usize, value: T) -> Self { + Self { num_binders, value } + } + + pub fn empty(_interner: &Interner, value: T) -> Self { + Self { num_binders: 0, value } + } + + pub fn as_ref(&self) -> Binders<&T> { + Binders { num_binders: self.num_binders, value: &self.value } + } + + pub fn map(self, f: impl FnOnce(T) -> U) -> Binders { + Binders { num_binders: self.num_binders, value: f(self.value) } + } + + pub fn filter_map(self, f: impl FnOnce(T) -> Option) -> Option> { + Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) + } + + pub fn skip_binders(&self) -> &T { + &self.value + } + + pub fn into_value_and_skipped_binders(self) -> (T, usize) { + (self.value, self.num_binders) + } + + pub fn skip_binders_mut(&mut self) -> &mut T { + &mut self.value + } } /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs index 5dfd59746..b1e22da0a 100644 --- a/crates/hir_ty/src/walk.rs +++ b/crates/hir_ty/src/walk.rs @@ -139,7 +139,7 @@ impl TypeWalk for Ty { } } TyKind::Dyn(dyn_ty) => { - for p in dyn_ty.bounds.value.interned().iter() { + for p in dyn_ty.bounds.skip_binders().interned().iter() { p.walk(f); } } @@ -167,7 +167,7 @@ impl TypeWalk for Ty { p_ty.substitution.walk_mut_binders(f, binders); } TyKind::Dyn(dyn_ty) => { - for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { + for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) { p.walk_mut_binders(f, binders.shifted_in()); } } @@ -294,7 +294,7 @@ impl TypeWalk for Substitution { impl TypeWalk for Binders { fn walk(&self, f: &mut impl FnMut(&Ty)) { - self.value.walk(f); + self.skip_binders().walk(f); } fn walk_mut_binders( @@ -302,7 +302,7 @@ impl TypeWalk for Binders { f: &mut impl FnMut(&mut Ty, DebruijnIndex), binders: DebruijnIndex, ) { - self.value.walk_mut_binders(f, binders.shifted_in()) + self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in()) } } -- cgit v1.2.3