From b15152c430237d6850ec709ac75aab269c4b7dee Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 20:14:21 +0200 Subject: Add TyBuilder --- crates/hir_ty/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 4c3d904bf..a8ddb43f5 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -810,6 +810,12 @@ impl TypeWalk for CallableSig { } } +struct TyBuilder {} + +impl TyBuilder { + +} + impl Ty { pub fn unit() -> Self { TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) -- cgit v1.2.3 From b0fe3d929f6f8764f371970b9f9ca9e7c415dafd Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 20:22:59 +0200 Subject: Add TyBuilder::unit() and TyExt::is_unit() --- crates/hir_ty/src/chalk_ext.rs | 13 +++++++++++++ crates/hir_ty/src/diagnostics/expr.rs | 4 ++-- crates/hir_ty/src/display.rs | 7 ++++--- crates/hir_ty/src/infer/expr.rs | 22 +++++++++++----------- crates/hir_ty/src/lib.rs | 10 +++++----- crates/hir_ty/src/op.rs | 4 ++-- crates/hir_ty/src/traits/chalk.rs | 4 ++-- 7 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 crates/hir_ty/src/chalk_ext.rs (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs new file mode 100644 index 000000000..b7463366b --- /dev/null +++ b/crates/hir_ty/src/chalk_ext.rs @@ -0,0 +1,13 @@ +//! Various extensions traits for Chalk types. + +use crate::{Interner, Ty, TyKind}; + +pub trait TyExt { + fn is_unit(&self) -> bool; +} + +impl TyExt for Ty { + fn is_unit(&self) -> bool { + matches!(self.kind(&Interner), TyKind::Tuple(0, _)) + } +} diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index ad1259b34..8169b759f 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -15,7 +15,7 @@ use crate::{ MissingPatFields, RemoveThisSemicolon, }, utils::variant_data, - AdtId, InferenceResult, Interner, Ty, TyKind, + AdtId, InferenceResult, Interner, TyExt, TyKind, }; pub(crate) use hir_def::{ @@ -423,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { None => return, }; - if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { + if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty { return; } diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 97f1092c6..eb82e1a11 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -19,7 +19,8 @@ use crate::{ db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, - ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, + ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyExt, TyKind, + WhereClause, }; pub struct HirFormatter<'a> { @@ -423,7 +424,7 @@ impl HirDisplay for Ty { f.write_joined(sig.params(), ", ")?; write!(f, ")")?; let ret = sig.ret(); - if *ret != Ty::unit() { + if !ret.is_unit() { let ret_display = ret.into_displayable( f.db, f.max_size, @@ -663,7 +664,7 @@ impl HirDisplay for CallableSig { } write!(f, ")")?; let ret = self.ret(); - if *ret != Ty::unit() { + if !ret.is_unit() { let ret_display = ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); write!(f, " -> {}", ret_display)?; diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index dd3914ec3..db8aeead2 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -23,7 +23,7 @@ use crate::{ traits::{chalk::from_chalk, FnTrait, InEnvironment}, utils::{generics, variant_data, Generics}, AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, - Substitution, TraitRef, Ty, TyKind, + Substitution, TraitRef, Ty, TyBuilder, TyKind, }; use super::{ @@ -138,7 +138,7 @@ impl<'a> InferenceContext<'a> { both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); let else_ty = match else_branch { Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), - None => Ty::unit(), + None => TyBuilder::unit(), }; both_arms_diverge &= self.diverges; @@ -193,7 +193,7 @@ impl<'a> InferenceContext<'a> { break_ty: self.table.new_type_var(), label: label.map(|label| self.body[label].name.clone()), }); - self.infer_expr(*body, &Expectation::has_type(Ty::unit())); + self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); let ctxt = self.breakables.pop().expect("breakable stack broken"); if ctxt.may_break { @@ -217,11 +217,11 @@ impl<'a> InferenceContext<'a> { *condition, &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), ); - self.infer_expr(*body, &Expectation::has_type(Ty::unit())); + self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); let _ctxt = self.breakables.pop().expect("breakable stack broken"); // the body may not run, so it diverging doesn't mean we diverge self.diverges = Diverges::Maybe; - Ty::unit() + TyBuilder::unit() } Expr::For { iterable, body, pat, label } => { let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); @@ -236,11 +236,11 @@ impl<'a> InferenceContext<'a> { self.infer_pat(*pat, &pat_ty, BindingMode::default()); - self.infer_expr(*body, &Expectation::has_type(Ty::unit())); + self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); let _ctxt = self.breakables.pop().expect("breakable stack broken"); // the body may not run, so it diverging doesn't mean we diverge self.diverges = Diverges::Maybe; - Ty::unit() + TyBuilder::unit() } Expr::Lambda { body, args, ret_type, arg_types } => { assert_eq!(args.len(), arg_types.len()); @@ -360,7 +360,7 @@ impl<'a> InferenceContext<'a> { let val_ty = if let Some(expr) = expr { self.infer_expr(*expr, &Expectation::none()) } else { - Ty::unit() + TyBuilder::unit() }; let last_ty = @@ -386,7 +386,7 @@ impl<'a> InferenceContext<'a> { if let Some(expr) = expr { self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); } else { - let unit = Ty::unit(); + let unit = TyBuilder::unit(); self.coerce(&unit, &self.return_ty.clone()); } TyKind::Never.intern(&Interner) @@ -828,8 +828,8 @@ impl<'a> InferenceContext<'a> { // we don't even make an attempt at coercion self.table.new_maybe_never_var() } else { - self.coerce(&Ty::unit(), &expected.coercion_target()); - Ty::unit() + self.coerce(&TyBuilder::unit(), &expected.coercion_target()); + TyBuilder::unit() } }; ty diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index a8ddb43f5..b6173d87c 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -23,6 +23,7 @@ pub mod diagnostics; mod tests; #[cfg(test)] mod test_db; +mod chalk_ext; use std::{iter, mem, sync::Arc}; @@ -42,6 +43,7 @@ use crate::{ }; pub use autoderef::autoderef; +pub use chalk_ext::TyExt; pub use infer::{could_unify, InferenceResult, InferenceVar}; pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, @@ -813,14 +815,12 @@ impl TypeWalk for CallableSig { struct TyBuilder {} impl TyBuilder { - -} - -impl Ty { - pub fn unit() -> Self { + pub fn unit() -> Ty { TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) } +} +impl Ty { pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { TyKind::Adt(AdtId(adt), substs).intern(&Interner) } diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index 8533e1ed8..90dd31a35 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs @@ -2,12 +2,12 @@ use chalk_ir::TyVariableKind; use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; -use crate::{Interner, Scalar, Ty, TyKind}; +use crate::{Interner, Scalar, Ty, TyBuilder, TyKind}; pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { match op { BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), - BinaryOp::Assignment { .. } => Ty::unit(), + BinaryOp::Assignment { .. } => TyBuilder::unit(), BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { match lhs_ty.kind(&Interner) { TyKind::Scalar(Scalar::Int(_)) diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index fbac51b05..36a397990 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -22,7 +22,7 @@ use crate::{ to_assoc_type_id, to_chalk_trait_id, utils::generics, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, - TraitRef, Ty, TyKind, WhereClause, + TraitRef, Ty, TyBuilder, TyKind, WhereClause, }; use mapping::{ convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, @@ -300,7 +300,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { _closure_id: chalk_ir::ClosureId, _substs: &chalk_ir::Substitution, ) -> chalk_ir::Binders> { - let ty = Ty::unit().to_chalk(self.db); + let ty = TyBuilder::unit().to_chalk(self.db); make_binders(ty, 0) } fn closure_fn_substitution( -- cgit v1.2.3 From e6f007d9a8e676c4af5731001b211ca7a52bce16 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 20:27:57 +0200 Subject: Move Ty::fn_ptr to TyBuilder --- crates/hir_ty/src/infer/coerce.rs | 9 +++++---- crates/hir_ty/src/lib.rs | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index d887e21a2..744f30a93 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -8,7 +8,8 @@ use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; use hir_def::lang_item::LangItemTarget; use crate::{ - autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind, + autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, + TyBuilder, TyKind, }; use super::{InEnvironment, InferenceContext}; @@ -44,8 +45,8 @@ impl<'a> InferenceContext<'a> { // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); - let ptr_ty1 = Ty::fn_ptr(sig1); - let ptr_ty2 = Ty::fn_ptr(sig2); + let ptr_ty1 = TyBuilder::fn_ptr(sig1); + let ptr_ty2 = TyBuilder::fn_ptr(sig2); self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) } else { cov_mark::hit!(coerce_merge_fail_fallback); @@ -95,7 +96,7 @@ impl<'a> InferenceContext<'a> { (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { None => return false, Some(sig) => { - from_ty = Ty::fn_ptr(sig); + from_ty = TyBuilder::fn_ptr(sig); } }, diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index b6173d87c..fd44efa07 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -818,14 +818,8 @@ impl TyBuilder { pub fn unit() -> Ty { TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) } -} - -impl Ty { - pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { - TyKind::Adt(AdtId(adt), substs).intern(&Interner) - } - pub fn fn_ptr(sig: CallableSig) -> Self { + pub fn fn_ptr(sig: CallableSig) -> Ty { TyKind::Function(FnPointer { num_args: sig.params().len(), sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, @@ -833,6 +827,12 @@ impl Ty { }) .intern(&Interner) } +} + +impl Ty { + pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { + TyKind::Adt(AdtId(adt), substs).intern(&Interner) + } pub fn builtin(builtin: BuiltinType) -> Self { match builtin { -- cgit v1.2.3 From 620769f32276bb7e8c580eae2c91ee535a06d9f8 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 21:29:49 +0200 Subject: Add TyBuilder::adt --- crates/hir_ty/src/infer/expr.rs | 27 +++++-------- crates/hir_ty/src/infer/pat.rs | 26 ++++-------- crates/hir_ty/src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++--- crates/hir_ty/src/lower.rs | 9 +++-- 4 files changed, 104 insertions(+), 45 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index db8aeead2..5eb07126e 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -539,17 +539,10 @@ impl<'a> InferenceContext<'a> { Expr::Box { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); if let Some(box_) = self.resolve_boxed_box() { - let mut sb = - Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); - sb = sb.push(inner_ty); - match self.db.generic_defaults(box_.into()).get(1) { - Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { - sb = sb.push(alloc_ty.value.clone()); - } - _ => (), - } - sb = sb.fill(repeat_with(|| self.table.new_type_var())); - Ty::adt_ty(box_, sb.build()) + TyBuilder::adt(self.db, box_) + .push(inner_ty) + .fill_with_defaults(self.db, || self.table.new_type_var()) + .build() } else { self.err_ty() } @@ -639,31 +632,31 @@ impl<'a> InferenceContext<'a> { let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); match (range_type, lhs_ty, rhs_ty) { (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { - Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), + Some(adt) => TyBuilder::adt(self.db, adt).build(), None => self.err_ty(), }, (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { - Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), + Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), None => self.err_ty(), }, (RangeOp::Inclusive, None, Some(ty)) => { match self.resolve_range_to_inclusive() { - Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), + Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), None => self.err_ty(), } } (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { - Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), + Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), None => self.err_ty(), }, (RangeOp::Inclusive, Some(_), Some(ty)) => { match self.resolve_range_inclusive() { - Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), + Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), None => self.err_ty(), } } (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { - Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), + Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), None => self.err_ty(), }, (RangeOp::Inclusive, _, None) => self.err_ty(), diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 10df8d8cb..5b70d5e5a 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -13,9 +13,8 @@ use hir_expand::name::Name; use super::{BindingMode, Expectation, InferenceContext}; use crate::{ - lower::lower_to_chalk_mutability, - utils::{generics, variant_data}, - Interner, Substitution, Ty, TyKind, + lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, + TyKind, }; impl<'a> InferenceContext<'a> { @@ -246,23 +245,12 @@ impl<'a> InferenceContext<'a> { }; let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); - let mut sb = Substitution::build_for_generics(&generics( - self.db.upcast(), - box_adt.into(), - )); - sb = sb.push(inner_ty); - if sb.remaining() == 1 { - sb = sb.push(match alloc_ty { - Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, - _ => match self.db.generic_defaults(box_adt.into()).get(1) { - Some(alloc_ty) if !alloc_ty.value.is_unknown() => { - alloc_ty.value.clone() - } - _ => self.table.new_type_var(), - }, - }); + let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty); + + if let Some(alloc_ty) = alloc_ty { + b = b.push(alloc_ty); } - Ty::adt_ty(box_adt, sb.build()) + b.fill_with_defaults(self.db, || self.table.new_type_var()).build() } None => self.err_ty(), }, diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index fd44efa07..afe5424d6 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -812,9 +812,59 @@ impl TypeWalk for CallableSig { } } -struct TyBuilder {} +pub struct TyBuilder { + data: D, + vec: SmallVec<[GenericArg; 2]>, + param_count: usize, +} + +impl TyBuilder { + fn new(data: D, param_count: usize) -> TyBuilder { + TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) } + } + + fn build_internal(self) -> (D, Substitution) { + assert_eq!(self.vec.len(), self.param_count); + // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form + let subst = Substitution(self.vec); + (self.data, subst) + } + + pub fn push(mut self, arg: impl CastTo) -> Self { + self.vec.push(arg.cast(&Interner)); + self + } + + fn remaining(&self) -> usize { + self.param_count - self.vec.len() + } + + pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { + self.fill( + (starting_from..) + .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), + ) + } + + pub fn fill_with_unknown(self) -> Self { + self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) + } + + pub fn fill(mut self, filler: impl Iterator>) -> Self { + self.vec.extend(filler.take(self.remaining()).casted(&Interner)); + assert_eq!(self.remaining(), 0); + self + } + + pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { + assert!(self.vec.is_empty()); + assert!(parent_substs.len(&Interner) <= self.param_count); + self.vec.extend(parent_substs.iter(&Interner).cloned()); + self + } +} -impl TyBuilder { +impl TyBuilder<()> { pub fn unit() -> Ty { TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) } @@ -829,11 +879,38 @@ impl TyBuilder { } } -impl Ty { - pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { - TyKind::Adt(AdtId(adt), substs).intern(&Interner) +impl TyBuilder { + pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder { + let generics = generics(db.upcast(), adt.into()); + let param_count = generics.len(); + TyBuilder::new(adt, param_count) } + pub fn fill_with_defaults( + mut self, + db: &dyn HirDatabase, + mut fallback: impl FnMut() -> Ty, + ) -> Self { + let defaults = db.generic_defaults(self.data.into()); + for default_ty in defaults.iter().skip(self.vec.len()) { + if default_ty.skip_binders().is_unknown() { + self.vec.push(fallback().cast(&Interner)); + } else { + // each default can depend on the previous parameters + let subst_so_far = Substitution(self.vec.clone()); + self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); + } + } + self + } + + pub fn build(self) -> Ty { + let (adt, subst) = self.build_internal(); + TyKind::Adt(AdtId(adt), subst).intern(&Interner) + } +} + +impl Ty { pub fn builtin(builtin: BuiltinType) -> Self { match builtin { BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index e60d7c730..5e2024f0a 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -36,7 +36,7 @@ use crate::{ AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, - TyKind, TypeWalk, WhereClause, + TyBuilder, TyKind, TypeWalk, WhereClause, }; #[derive(Debug)] @@ -1141,9 +1141,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - } fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders { - let generics = generics(db.upcast(), adt.into()); - let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); - Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) + let b = TyBuilder::adt(db, adt); + let num_binders = b.remaining(); + let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); + Binders::new(num_binders, ty) } fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { -- cgit v1.2.3 From 2ead65190ecaf1096a998d88d4aab8505ce88afa Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 21:32:22 +0200 Subject: Move Ty::builtin to TyBuilder --- crates/hir_ty/src/lib.rs | 34 +++++++++++++++++----------------- crates/hir_ty/src/lower.rs | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index afe5424d6..be6fe5016 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -877,6 +877,23 @@ impl TyBuilder<()> { }) .intern(&Interner) } + + pub fn builtin(builtin: BuiltinType) -> Ty { + match builtin { + BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), + BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), + BuiltinType::Str => TyKind::Str.intern(&Interner), + BuiltinType::Int(t) => { + TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) + } + BuiltinType::Uint(t) => { + TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) + } + BuiltinType::Float(t) => { + TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) + } + } + } } impl TyBuilder { @@ -911,23 +928,6 @@ impl TyBuilder { } impl Ty { - pub fn builtin(builtin: BuiltinType) -> Self { - match builtin { - BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), - BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), - BuiltinType::Str => TyKind::Str.intern(&Interner), - BuiltinType::Int(t) => { - TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) - } - BuiltinType::Uint(t) => { - TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) - } - BuiltinType::Float(t) => { - TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) - } - } - } - pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self.kind(&Interner) { TyKind::Ref(mutability, ty) => Some((ty, *mutability)), diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 5e2024f0a..762b226e6 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -1216,7 +1216,7 @@ impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for V /// namespace. pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders { match def { - TyDefId::BuiltinType(it) => Binders::new(0, Ty::builtin(it)), + TyDefId::BuiltinType(it) => Binders::new(0, TyBuilder::builtin(it)), TyDefId::AdtId(it) => type_for_adt(db, it), TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), } -- cgit v1.2.3 From cd227f581e0c20d6b9ee81a3982509a9f6b2f67f Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 21:50:52 +0200 Subject: Add and start using TraitRef and ProjectionTy builders --- crates/hir_ty/src/infer.rs | 8 +++----- crates/hir_ty/src/infer/path.rs | 16 ++++------------ crates/hir_ty/src/lib.rs | 29 +++++++++++++++++++++++++++++ crates/hir_ty/src/method_resolution.rs | 8 +++----- 4 files changed, 39 insertions(+), 22 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b871594bd..b208d821d 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -42,7 +42,7 @@ use super::{ }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, - to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, + to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, }; // This lint has a false positive here. See the link below for details. @@ -409,16 +409,14 @@ impl<'a> InferenceContext<'a> { _ => panic!("resolve_associated_type called with non-associated type"), }; let ty = self.table.new_type_var(); - let substs = Substitution::build_for_def(self.db, res_assoc_ty) + let trait_ref = TyBuilder::trait_ref(self.db, trait_) .push(inner_ty) .fill(params.iter().cloned()) .build(); - let trait_ref = - TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; let alias_eq = AliasEq { alias: AliasTy::Projection(ProjectionTy { associated_ty_id: to_assoc_type_id(res_assoc_ty), - substitution: substs, + substitution: trait_ref.substitution.clone(), }), ty: ty.clone(), }; diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 1ba15f737..282dd499f 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -10,9 +10,7 @@ use hir_def::{ }; use hir_expand::name::Name; -use crate::{ - method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId, -}; +use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; use super::{ExprOrPatId, InferenceContext, TraitRef}; @@ -254,18 +252,12 @@ impl<'a> InferenceContext<'a> { } AssocContainerId::TraitId(trait_) => { // we're picking this method - let trait_substs = Substitution::build_for_def(self.db, trait_) + let trait_ref = TyBuilder::trait_ref(self.db, trait_) .push(ty.clone()) .fill(std::iter::repeat_with(|| self.table.new_type_var())) .build(); - self.push_obligation( - TraitRef { - trait_id: to_chalk_trait_id(trait_), - substitution: trait_substs.clone(), - } - .cast(&Interner), - ); - Some(trait_substs) + self.push_obligation(trait_ref.clone().cast(&Interner)); + Some(trait_ref.substitution) } AssocContainerId::ModuleId(_) => None, }; diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index be6fe5016..e586d73d8 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -927,6 +927,35 @@ impl TyBuilder { } } +impl TyBuilder { + pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder { + let generics = generics(db.upcast(), trait_id.into()); + let param_count = generics.len(); + TyBuilder::new(trait_id, param_count) + } + + pub fn build(self) -> TraitRef { + let (trait_id, substitution) = self.build_internal(); + TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } + } +} + +impl TyBuilder { + pub fn assoc_type_projection( + db: &dyn HirDatabase, + type_alias: TypeAliasId, + ) -> TyBuilder { + let generics = generics(db.upcast(), type_alias.into()); + let param_count = generics.len(); + TyBuilder::new(type_alias, param_count) + } + + pub fn build(self) -> ProjectionTy { + let (type_alias, substitution) = self.build_internal(); + ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution } + } +} + impl Ty { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self.kind(&Interner) { diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index c093fce20..b9cc081e8 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -19,10 +19,9 @@ use crate::{ db::HirDatabase, from_foreign_def_id, primitive::{self, FloatTy, IntTy, UintTy}, - to_chalk_trait_id, utils::all_super_traits, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, - InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, + InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind, TypeWalk, }; @@ -813,7 +812,7 @@ fn generic_implements_goal( self_ty: Canonical, ) -> Canonical> { let mut kinds = self_ty.binders.interned().to_vec(); - let substs = super::Substitution::build_for_def(db, trait_) + let trait_ref = TyBuilder::trait_ref(db, trait_) .push(self_ty.value) .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) .build(); @@ -822,9 +821,8 @@ fn generic_implements_goal( chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), UniverseIndex::ROOT, )) - .take(substs.len(&Interner) - 1), + .take(trait_ref.substitution.len(&Interner) - 1), ); - let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; let obligation = trait_ref.cast(&Interner); Canonical { binders: CanonicalVarKinds::from_iter(&Interner, kinds), -- cgit v1.2.3 From 66fec39aa04ea59ac39d52f0872c0a6c52a27e35 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 21:56:18 +0200 Subject: More TyBuilder use --- crates/hir_ty/src/autoderef.rs | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index c859f9491..70c56cc45 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -13,11 +13,9 @@ use log::{info, warn}; use crate::{ db::HirDatabase, - to_assoc_type_id, to_chalk_trait_id, traits::{InEnvironment, Solution}, - utils::generics, - AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, - ProjectionTy, Substitution, TraitRef, Ty, TyKind, + AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty, + TyBuilder, TyKind, }; const AUTODEREF_RECURSION_LIMIT: usize = 10; @@ -57,21 +55,20 @@ fn deref_by_trait( }; let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; - let generic_params = generics(db.upcast(), target.into()); - if generic_params.len() != 1 { - // the Target type + Deref trait should only have one generic parameter, - // namely Deref's Self type - return None; - } + let projection = { + let b = TyBuilder::assoc_type_projection(db, target); + if b.remaining() != 1 { + // the Target type + Deref trait should only have one generic parameter, + // namely Deref's Self type + return None; + } + b.push(ty.goal.value.clone()).build() + }; // FIXME make the Canonical / bound var handling nicer - let parameters = - Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); - // Check that the type implements Deref at all - let trait_ref = - TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; + let trait_ref = projection.trait_ref(db); let implements_goal = Canonical { binders: ty.goal.binders.clone(), value: InEnvironment { @@ -84,11 +81,8 @@ fn deref_by_trait( } // Now do the assoc type projection - let projection = AliasEq { - alias: AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(target), - substitution: parameters, - }), + let alias_eq = AliasEq { + alias: AliasTy::Projection(projection), ty: TyKind::BoundVar(BoundVar::new( DebruijnIndex::INNERMOST, ty.goal.binders.len(&Interner), @@ -96,9 +90,7 @@ fn deref_by_trait( .intern(&Interner), }; - let obligation = projection.cast(&Interner); - - let in_env = InEnvironment { goal: obligation, environment: ty.environment }; + let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment }; let canonical = Canonical { value: in_env, -- cgit v1.2.3 From 77333a571ffb401a6765bbc80dea082ad08238d9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 21:59:13 +0200 Subject: More TyBuilder use --- crates/hir_ty/src/infer/coerce.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 744f30a93..ed8c677a8 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -8,7 +8,7 @@ use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; use hir_def::lang_item::LangItemTarget; use crate::{ - autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, + autoderef, traits::Solution, Interner, Ty, TyBuilder, TyKind, }; @@ -131,18 +131,15 @@ impl<'a> InferenceContext<'a> { _ => return None, }; - let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); - if generic_params.len() != 2 { - // The CoerceUnsized trait should have two generic params: Self and T. - return None; - } + let trait_ref = { + let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait); + if b.remaining() != 2 { + // The CoerceUnsized trait should have two generic params: Self and T. + return None; + } + b.push(from_ty.clone()).push(to_ty.clone()).build() + }; - let substs = Substitution::build_for_generics(&generic_params) - .push(from_ty.clone()) - .push(to_ty.clone()) - .build(); - let trait_ref = - TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); let canonicalizer = self.canonicalizer(); -- cgit v1.2.3 From 5d2b488aeb17410aec3b89eac69038c51f332448 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 22:18:02 +0200 Subject: Replace remaining uses of Substitution::build_for_def --- crates/hir_ty/src/infer.rs | 3 +-- crates/hir_ty/src/infer/coerce.rs | 5 +--- crates/hir_ty/src/infer/path.rs | 2 +- crates/hir_ty/src/lib.rs | 46 ++++++++++++++++++++++++++++------ crates/hir_ty/src/method_resolution.rs | 6 ++--- 5 files changed, 44 insertions(+), 18 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b208d821d..caafeccb8 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -514,10 +514,9 @@ impl<'a> InferenceContext<'a> { } } TypeNs::TypeAliasId(it) => { - let substs = Substitution::build_for_def(self.db, it) + let ty = TyBuilder::def_ty(self.db, it.into()) .fill(std::iter::repeat_with(|| self.table.new_type_var())) .build(); - let ty = self.db.ty(it.into()).subst(&substs); let variant = ty_variant(&ty); forbid_unresolved_segments((ty, variant), unresolved) } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index ed8c677a8..028a4d568 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -7,10 +7,7 @@ use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; use hir_def::lang_item::LangItemTarget; -use crate::{ - autoderef, traits::Solution, Interner, Ty, - TyBuilder, TyKind, -}; +use crate::{autoderef, traits::Solution, Interner, Ty, TyBuilder, TyKind}; use super::{InEnvironment, InferenceContext}; diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 282dd499f..c9219776b 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -243,7 +243,7 @@ impl<'a> InferenceContext<'a> { }; let substs = match container { AssocContainerId::ImplId(impl_id) => { - let impl_substs = Substitution::build_for_def(self.db, impl_id) + let impl_substs = TyBuilder::subst_for_def(self.db, impl_id) .fill(iter::repeat_with(|| self.table.new_type_var())) .build(); let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index e586d73d8..75bf8bcd9 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -28,7 +28,10 @@ mod chalk_ext; use std::{iter, mem, sync::Arc}; use base_db::salsa; -use chalk_ir::cast::{CastTo, Caster}; +use chalk_ir::{ + cast::{CastTo, Caster}, + interner::HasInterner, +}; use hir_def::{ builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, @@ -490,13 +493,6 @@ impl Substitution { ) } - pub fn build_for_def(db: &dyn HirDatabase, def: impl Into) -> SubstsBuilder { - let def = def.into(); - let params = generics(db.upcast(), def); - let param_count = params.len(); - Substitution::builder(param_count) - } - pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { Substitution::builder(generic_params.len()) } @@ -894,6 +890,18 @@ impl TyBuilder<()> { } } } + + pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into) -> TyBuilder<()> { + let def = def.into(); + let params = generics(db.upcast(), def); + let param_count = params.len(); + TyBuilder::new((), param_count) + } + + pub fn build(self) -> Substitution { + let ((), subst) = self.build_internal(); + subst + } } impl TyBuilder { @@ -956,6 +964,28 @@ impl TyBuilder { } } +impl> TyBuilder> { + fn subst_binders(b: Binders) -> Self { + let param_count = b.num_binders; + TyBuilder::new(b, param_count) + } + + pub fn build(self) -> T { + let (b, subst) = self.build_internal(); + b.subst(&subst) + } +} + +impl TyBuilder> { + pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder> { + TyBuilder::subst_binders(db.ty(def.into())) + } + + pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder> { + TyBuilder::subst_binders(db.impl_self_ty(def)) + } +} + impl Ty { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self.kind(&Interner) { diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index b9cc081e8..a76586f0c 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -709,7 +709,7 @@ pub(crate) fn inherent_impl_substs( ) -> Option { // we create a var for each type parameter of the impl; we need to keep in // mind here that `self_ty` might have vars of its own - let vars = Substitution::build_for_def(db, impl_id) + let vars = TyBuilder::subst_for_def(db, impl_id) .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) .build(); let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); @@ -760,13 +760,13 @@ fn transform_receiver_ty( self_ty: &Canonical, ) -> Option { let substs = match function_id.lookup(db.upcast()).container { - AssocContainerId::TraitId(_) => Substitution::build_for_def(db, function_id) + AssocContainerId::TraitId(_) => TyBuilder::subst_for_def(db, function_id) .push(self_ty.value.clone()) .fill_with_unknown() .build(), AssocContainerId::ImplId(impl_id) => { let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; - Substitution::build_for_def(db, function_id) + TyBuilder::subst_for_def(db, function_id) .use_parent_substs(&impl_substs) .fill_with_unknown() .build() -- cgit v1.2.3 From eaa03ef4465765a16951faa54dd8ebc53095e2c8 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 22:28:10 +0200 Subject: Some more TyBuilder use --- crates/hir_ty/src/infer/expr.rs | 54 +++++++++++++++++++---------------------- crates/hir_ty/src/lib.rs | 4 --- 2 files changed, 25 insertions(+), 33 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 5eb07126e..9f5624eb0 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -19,11 +19,11 @@ use crate::{ lower::lower_to_chalk_mutability, method_resolution, op, primitive::{self, UintTy}, - to_assoc_type_id, to_chalk_trait_id, + to_chalk_trait_id, traits::{chalk::from_chalk, FnTrait, InEnvironment}, utils::{generics, variant_data, Generics}, - AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, - Substitution, TraitRef, Ty, TyBuilder, TyKind, + AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Rawness, Scalar, Substitution, + TraitRef, Ty, TyBuilder, TyKind, }; use super::{ @@ -73,38 +73,34 @@ impl<'a> InferenceContext<'a> { let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; let output_assoc_type = self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; - let generic_params = generics(self.db.upcast(), fn_once_trait.into()); - if generic_params.len() != 2 { - return None; - } - let mut param_builder = Substitution::builder(num_args); let mut arg_tys = vec![]; - for _ in 0..num_args { - let arg = self.table.new_type_var(); - param_builder = param_builder.push(arg.clone()); - arg_tys.push(arg); - } - let parameters = param_builder.build(); + let parameters = Substitution::builder(num_args) + .fill(repeat_with(|| { + let arg = self.table.new_type_var(); + arg_tys.push(arg.clone()); + arg + })) + .build(); let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); - let substs = - Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); + + let projection = { + let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type); + if b.remaining() != 2 { + return None; + } + b.push(ty.clone()).push(arg_ty).build() + }; let trait_env = self.trait_env.env.clone(); - let implements_fn_trait: DomainGoal = - TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } - .cast(&Interner); - let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { - goal: implements_fn_trait.clone(), + let obligation = InEnvironment { + goal: projection.trait_ref(self.db).cast(&Interner), environment: trait_env, - }); - if self.db.trait_solve(krate, goal.value).is_some() { - self.push_obligation(implements_fn_trait); - let output_proj_ty = crate::ProjectionTy { - associated_ty_id: to_assoc_type_id(output_assoc_type), - substitution: substs, - }; - let return_ty = self.normalize_projection_ty(output_proj_ty); + }; + let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone()); + if self.db.trait_solve(krate, canonical.value).is_some() { + self.push_obligation(obligation.goal); + let return_ty = self.normalize_projection_ty(projection); Some((arg_tys, return_ty)) } else { None diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 75bf8bcd9..b37566958 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -493,10 +493,6 @@ impl Substitution { ) } - pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { - Substitution::builder(generic_params.len()) - } - fn builder(param_count: usize) -> SubstsBuilder { SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } } -- cgit v1.2.3 From ac8fee006a4858230fe22dfdb5647a3d0e19bb64 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 22:45:31 +0200 Subject: Use TyBuilder in another place --- crates/hir_ty/src/lower.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 762b226e6..644a2eed5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -860,10 +860,9 @@ pub fn associated_type_shorthand_candidates( if generics.params.types[param_id.local_id].provenance == TypeParamProvenance::TraitSelf { - let trait_ref = TraitRef { - trait_id: to_chalk_trait_id(trait_id), - substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), - }; + let trait_ref = TyBuilder::trait_ref(db, trait_id) + .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) + .build(); return search(trait_ref); } } -- cgit v1.2.3 From 505ca65216e7d1ea87a235170106338272b36a10 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 3 Apr 2021 22:47:29 +0200 Subject: Remove CallableSig::from_substs --- crates/hir_ty/src/lib.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index b37566958..27ebb7b7c 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -754,7 +754,7 @@ impl CallableSig { pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { CallableSig { - // FIXME: what to do about lifetime params? + // FIXME: what to do about lifetime params? -> return PolyFnSig params_and_return: fn_ptr .substs .clone() @@ -767,16 +767,6 @@ impl CallableSig { } } - pub fn from_substs(substs: &Substitution) -> CallableSig { - CallableSig { - params_and_return: substs - .iter(&Interner) - .map(|arg| arg.assert_ty_ref(&Interner).clone()) - .collect(), - is_varargs: false, - } - } - pub fn params(&self) -> &[Ty] { &self.params_and_return[0..self.params_and_return.len() - 1] } -- cgit v1.2.3 From 584d1c9e5bc39402e2855d0ffa9394ae5a066060 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 4 Apr 2021 12:48:10 +0200 Subject: Replace last uses of SubstsBuilder by TyBuilder --- crates/hir_ty/src/infer/expr.rs | 3 +- crates/hir_ty/src/infer/path.rs | 5 +-- crates/hir_ty/src/infer/unify.rs | 13 +++----- crates/hir_ty/src/lib.rs | 66 ++++++++++------------------------------ 4 files changed, 23 insertions(+), 64 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 9f5624eb0..c584a2c08 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -75,14 +75,13 @@ impl<'a> InferenceContext<'a> { self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; let mut arg_tys = vec![]; - let parameters = Substitution::builder(num_args) + let arg_ty = TyBuilder::tuple(num_args) .fill(repeat_with(|| { let arg = self.table.new_type_var(); arg_tys.push(arg.clone()); arg })) .build(); - let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); let projection = { let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type); diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index c9219776b..d55ae4900 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -93,16 +93,13 @@ impl<'a> InferenceContext<'a> { ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), }; - let ty = self.db.value_ty(typable); - // self_subst is just for the parent let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); let substs = ctx.substs_from_path(path, typable, true); - let full_substs = Substitution::builder(substs.len(&Interner)) + let ty = TyBuilder::value_ty(self.db, typable) .use_parent_substs(&parent_substs) .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) .build(); - let ty = ty.subst(&full_substs); Some(ty) } diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index d2496db3b..a04b935ef 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -186,14 +186,11 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { ); } } - Some( - Substitution::builder(tys.binders.len(&Interner)) - .fill( - vars.iter(&Interner) - .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), - ) - .build(), - ) + Some(Substitution::from_iter( + &Interner, + vars.iter(&Interner) + .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), + )) } #[derive(Clone, Debug)] diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 27ebb7b7c..f99b70f2b 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -492,10 +492,6 @@ impl Substitution { .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), ) } - - fn builder(param_count: usize) -> SubstsBuilder { - SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } - } } /// Return an index of a parameter in the generic type parameter list by it's id. @@ -503,52 +499,6 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option { generics(db.upcast(), id.parent).param_idx(id) } -#[derive(Debug, Clone)] -pub struct SubstsBuilder { - vec: Vec, - param_count: usize, -} - -impl SubstsBuilder { - pub fn build(self) -> Substitution { - assert_eq!(self.vec.len(), self.param_count); - Substitution::from_iter(&Interner, self.vec) - } - - pub fn push(mut self, ty: impl CastTo) -> Self { - self.vec.push(ty.cast(&Interner)); - self - } - - fn remaining(&self) -> usize { - self.param_count - self.vec.len() - } - - pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { - self.fill( - (starting_from..) - .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), - ) - } - - pub fn fill_with_unknown(self) -> Self { - self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) - } - - pub fn fill(mut self, filler: impl Iterator>) -> Self { - self.vec.extend(filler.take(self.remaining()).casted(&Interner)); - assert_eq!(self.remaining(), 0); - self - } - - pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { - assert!(self.vec.is_empty()); - assert!(parent_substs.len(&Interner) <= self.param_count); - self.vec.extend(parent_substs.iter(&Interner).cloned()); - self - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct Binders { pub num_binders: usize, @@ -921,6 +871,18 @@ impl TyBuilder { } } +struct Tuple(usize); +impl TyBuilder { + pub fn tuple(size: usize) -> TyBuilder { + TyBuilder::new(Tuple(size), size) + } + + pub fn build(self) -> Ty { + let (Tuple(size), subst) = self.build_internal(); + TyKind::Tuple(size, subst).intern(&Interner) + } +} + impl TyBuilder { pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder { let generics = generics(db.upcast(), trait_id.into()); @@ -970,6 +932,10 @@ impl TyBuilder> { pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder> { TyBuilder::subst_binders(db.impl_self_ty(def)) } + + pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder> { + TyBuilder::subst_binders(db.value_ty(def)) + } } impl Ty { -- cgit v1.2.3 From 715c178f0b52117c4c689c39a0921012bfbb2386 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 4 Apr 2021 12:55:47 +0200 Subject: Move TyBuilder to its own module --- crates/hir_ty/src/builder.rs | 211 ++++++++++++++++++++++++++++++++++++++++++ crates/hir_ty/src/lib.rs | 214 ++----------------------------------------- 2 files changed, 221 insertions(+), 204 deletions(-) create mode 100644 crates/hir_ty/src/builder.rs (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs new file mode 100644 index 000000000..ba158a749 --- /dev/null +++ b/crates/hir_ty/src/builder.rs @@ -0,0 +1,211 @@ +//! `TyBuilder`, a helper for building instances of `Ty` and related types. + +use std::iter; + +use chalk_ir::{ + cast::{Cast, CastTo, Caster}, + interner::HasInterner, + AdtId, BoundVar, DebruijnIndex, Safety, Scalar, +}; +use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId}; +use smallvec::SmallVec; + +use crate::{ + db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, + CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, + TyDefId, TyKind, TypeWalk, ValueTyDefId, +}; + +pub struct TyBuilder { + data: D, + vec: SmallVec<[GenericArg; 2]>, + param_count: usize, +} + +impl TyBuilder { + fn new(data: D, param_count: usize) -> TyBuilder { + TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) } + } + + fn build_internal(self) -> (D, Substitution) { + assert_eq!(self.vec.len(), self.param_count); + // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form + let subst = Substitution(self.vec); + (self.data, subst) + } + + pub fn push(mut self, arg: impl CastTo) -> Self { + self.vec.push(arg.cast(&Interner)); + self + } + + pub fn remaining(&self) -> usize { + self.param_count - self.vec.len() + } + + pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { + self.fill( + (starting_from..) + .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), + ) + } + + pub fn fill_with_unknown(self) -> Self { + self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) + } + + pub fn fill(mut self, filler: impl Iterator>) -> Self { + self.vec.extend(filler.take(self.remaining()).casted(&Interner)); + assert_eq!(self.remaining(), 0); + self + } + + pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { + assert!(self.vec.is_empty()); + assert!(parent_substs.len(&Interner) <= self.param_count); + self.vec.extend(parent_substs.iter(&Interner).cloned()); + self + } +} + +impl TyBuilder<()> { + pub fn unit() -> Ty { + TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) + } + + pub fn fn_ptr(sig: CallableSig) -> Ty { + TyKind::Function(FnPointer { + num_args: sig.params().len(), + sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, + substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), + }) + .intern(&Interner) + } + + pub fn builtin(builtin: BuiltinType) -> Ty { + match builtin { + BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), + BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), + BuiltinType::Str => TyKind::Str.intern(&Interner), + BuiltinType::Int(t) => { + TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) + } + BuiltinType::Uint(t) => { + TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) + } + BuiltinType::Float(t) => { + TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) + } + } + } + + pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into) -> TyBuilder<()> { + let def = def.into(); + let params = generics(db.upcast(), def); + let param_count = params.len(); + TyBuilder::new((), param_count) + } + + pub fn build(self) -> Substitution { + let ((), subst) = self.build_internal(); + subst + } +} + +impl TyBuilder { + pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder { + let generics = generics(db.upcast(), adt.into()); + let param_count = generics.len(); + TyBuilder::new(adt, param_count) + } + + pub fn fill_with_defaults( + mut self, + db: &dyn HirDatabase, + mut fallback: impl FnMut() -> Ty, + ) -> Self { + let defaults = db.generic_defaults(self.data.into()); + for default_ty in defaults.iter().skip(self.vec.len()) { + if default_ty.skip_binders().is_unknown() { + self.vec.push(fallback().cast(&Interner)); + } else { + // each default can depend on the previous parameters + let subst_so_far = Substitution(self.vec.clone()); + self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); + } + } + self + } + + pub fn build(self) -> Ty { + let (adt, subst) = self.build_internal(); + TyKind::Adt(AdtId(adt), subst).intern(&Interner) + } +} + +pub struct Tuple(usize); +impl TyBuilder { + pub fn tuple(size: usize) -> TyBuilder { + TyBuilder::new(Tuple(size), size) + } + + pub fn build(self) -> Ty { + let (Tuple(size), subst) = self.build_internal(); + TyKind::Tuple(size, subst).intern(&Interner) + } +} + +impl TyBuilder { + pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder { + let generics = generics(db.upcast(), trait_id.into()); + let param_count = generics.len(); + TyBuilder::new(trait_id, param_count) + } + + pub fn build(self) -> TraitRef { + let (trait_id, substitution) = self.build_internal(); + TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } + } +} + +impl TyBuilder { + pub fn assoc_type_projection( + db: &dyn HirDatabase, + type_alias: TypeAliasId, + ) -> TyBuilder { + let generics = generics(db.upcast(), type_alias.into()); + let param_count = generics.len(); + TyBuilder::new(type_alias, param_count) + } + + pub fn build(self) -> ProjectionTy { + let (type_alias, substitution) = self.build_internal(); + ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution } + } +} + +impl> TyBuilder> { + fn subst_binders(b: Binders) -> Self { + let param_count = b.num_binders; + TyBuilder::new(b, param_count) + } + + pub fn build(self) -> T { + let (b, subst) = self.build_internal(); + b.subst(&subst) + } +} + +impl TyBuilder> { + pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder> { + TyBuilder::subst_binders(db.ty(def.into())) + } + + pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder> { + TyBuilder::subst_binders(db.impl_self_ty(def)) + } + + pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder> { + TyBuilder::subst_binders(db.value_ty(def)) + } +} diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index f99b70f2b..ebdcc4804 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -14,6 +14,8 @@ mod lower; pub(crate) mod infer; pub(crate) mod utils; mod chalk_cast; +mod chalk_ext; +mod builder; pub mod display; pub mod db; @@ -23,21 +25,18 @@ pub mod diagnostics; mod tests; #[cfg(test)] mod test_db; -mod chalk_ext; -use std::{iter, mem, sync::Arc}; +use std::{mem, sync::Arc}; + +use chalk_ir::cast::{CastTo, Caster}; +use itertools::Itertools; +use smallvec::SmallVec; use base_db::salsa; -use chalk_ir::{ - cast::{CastTo, Caster}, - interner::HasInterner, -}; use hir_def::{ - builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, - GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, + expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, + LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, }; -use itertools::Itertools; -use smallvec::SmallVec; use crate::{ db::HirDatabase, @@ -46,6 +45,7 @@ use crate::{ }; pub use autoderef::autoderef; +pub use builder::TyBuilder; pub use chalk_ext::TyExt; pub use infer::{could_unify, InferenceResult, InferenceVar}; pub use lower::{ @@ -744,200 +744,6 @@ impl TypeWalk for CallableSig { } } -pub struct TyBuilder { - data: D, - vec: SmallVec<[GenericArg; 2]>, - param_count: usize, -} - -impl TyBuilder { - fn new(data: D, param_count: usize) -> TyBuilder { - TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) } - } - - fn build_internal(self) -> (D, Substitution) { - assert_eq!(self.vec.len(), self.param_count); - // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form - let subst = Substitution(self.vec); - (self.data, subst) - } - - pub fn push(mut self, arg: impl CastTo) -> Self { - self.vec.push(arg.cast(&Interner)); - self - } - - fn remaining(&self) -> usize { - self.param_count - self.vec.len() - } - - pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { - self.fill( - (starting_from..) - .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), - ) - } - - pub fn fill_with_unknown(self) -> Self { - self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) - } - - pub fn fill(mut self, filler: impl Iterator>) -> Self { - self.vec.extend(filler.take(self.remaining()).casted(&Interner)); - assert_eq!(self.remaining(), 0); - self - } - - pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { - assert!(self.vec.is_empty()); - assert!(parent_substs.len(&Interner) <= self.param_count); - self.vec.extend(parent_substs.iter(&Interner).cloned()); - self - } -} - -impl TyBuilder<()> { - pub fn unit() -> Ty { - TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) - } - - pub fn fn_ptr(sig: CallableSig) -> Ty { - TyKind::Function(FnPointer { - num_args: sig.params().len(), - sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, - substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), - }) - .intern(&Interner) - } - - pub fn builtin(builtin: BuiltinType) -> Ty { - match builtin { - BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), - BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), - BuiltinType::Str => TyKind::Str.intern(&Interner), - BuiltinType::Int(t) => { - TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) - } - BuiltinType::Uint(t) => { - TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) - } - BuiltinType::Float(t) => { - TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) - } - } - } - - pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into) -> TyBuilder<()> { - let def = def.into(); - let params = generics(db.upcast(), def); - let param_count = params.len(); - TyBuilder::new((), param_count) - } - - pub fn build(self) -> Substitution { - let ((), subst) = self.build_internal(); - subst - } -} - -impl TyBuilder { - pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder { - let generics = generics(db.upcast(), adt.into()); - let param_count = generics.len(); - TyBuilder::new(adt, param_count) - } - - pub fn fill_with_defaults( - mut self, - db: &dyn HirDatabase, - mut fallback: impl FnMut() -> Ty, - ) -> Self { - let defaults = db.generic_defaults(self.data.into()); - for default_ty in defaults.iter().skip(self.vec.len()) { - if default_ty.skip_binders().is_unknown() { - self.vec.push(fallback().cast(&Interner)); - } else { - // each default can depend on the previous parameters - let subst_so_far = Substitution(self.vec.clone()); - self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); - } - } - self - } - - pub fn build(self) -> Ty { - let (adt, subst) = self.build_internal(); - TyKind::Adt(AdtId(adt), subst).intern(&Interner) - } -} - -struct Tuple(usize); -impl TyBuilder { - pub fn tuple(size: usize) -> TyBuilder { - TyBuilder::new(Tuple(size), size) - } - - pub fn build(self) -> Ty { - let (Tuple(size), subst) = self.build_internal(); - TyKind::Tuple(size, subst).intern(&Interner) - } -} - -impl TyBuilder { - pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder { - let generics = generics(db.upcast(), trait_id.into()); - let param_count = generics.len(); - TyBuilder::new(trait_id, param_count) - } - - pub fn build(self) -> TraitRef { - let (trait_id, substitution) = self.build_internal(); - TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } - } -} - -impl TyBuilder { - pub fn assoc_type_projection( - db: &dyn HirDatabase, - type_alias: TypeAliasId, - ) -> TyBuilder { - let generics = generics(db.upcast(), type_alias.into()); - let param_count = generics.len(); - TyBuilder::new(type_alias, param_count) - } - - pub fn build(self) -> ProjectionTy { - let (type_alias, substitution) = self.build_internal(); - ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution } - } -} - -impl> TyBuilder> { - fn subst_binders(b: Binders) -> Self { - let param_count = b.num_binders; - TyBuilder::new(b, param_count) - } - - pub fn build(self) -> T { - let (b, subst) = self.build_internal(); - b.subst(&subst) - } -} - -impl TyBuilder> { - pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder> { - TyBuilder::subst_binders(db.ty(def.into())) - } - - pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder> { - TyBuilder::subst_binders(db.impl_self_ty(def)) - } - - pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder> { - TyBuilder::subst_binders(db.value_ty(def)) - } -} - impl Ty { pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { match self.kind(&Interner) { -- cgit v1.2.3 From a4d7bdf1c884a9f3dd415a882fa56422adae89bf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 4 Apr 2021 13:07:06 +0200 Subject: Replace Substitution::bound_vars and ::type_params_for_generics --- crates/hir_ty/src/display.rs | 4 ++-- crates/hir_ty/src/infer.rs | 4 ++-- crates/hir_ty/src/infer/path.rs | 2 +- crates/hir_ty/src/lib.rs | 28 ++-------------------------- crates/hir_ty/src/lower.rs | 24 ++++++++---------------- crates/hir_ty/src/traits/chalk.rs | 10 +++++----- crates/hir_ty/src/utils.rs | 24 ++++++++++++++++++++++-- 7 files changed, 42 insertions(+), 54 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index eb82e1a11..39e0b328d 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -19,7 +19,7 @@ use crate::{ db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, - ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyExt, TyKind, + ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, }; @@ -592,7 +592,7 @@ impl HirDisplay for Ty { write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? } TypeParamProvenance::ArgumentImplTrait => { - let substs = Substitution::type_params_for_generics(f.db, &generics); + let substs = generics.type_params_subst(f.db); let bounds = f .db .generic_predicates(id.parent) diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index caafeccb8..1b1d4458c 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -38,7 +38,7 @@ use syntax::SmolStr; use super::{ traits::{DomainGoal, Guidance, Solution}, - InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, + InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeWalk, }; use crate::{ db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, @@ -487,7 +487,7 @@ impl<'a> InferenceContext<'a> { } TypeNs::SelfType(impl_id) => { let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); - let substs = Substitution::type_params_for_generics(self.db, &generics); + let substs = generics.type_params_subst(self.db); let ty = self.db.impl_self_ty(impl_id).subst(&substs); match unresolved { None => { diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index d55ae4900..671ea355f 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -80,7 +80,7 @@ impl<'a> InferenceContext<'a> { } ValueNs::ImplSelf(impl_id) => { let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); - let substs = Substitution::type_params_for_generics(self.db, &generics); + let substs = generics.type_params_subst(self.db); let ty = self.db.impl_self_ty(impl_id).subst(&substs); if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { let ty = self.db.value_ty(struct_id.into()).subst(&substs); diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index ebdcc4804..6d6443ca3 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -41,7 +41,7 @@ use hir_def::{ use crate::{ db::HirDatabase, display::HirDisplay, - utils::{generics, make_mut_slice, Generics}, + utils::{generics, make_mut_slice}, }; pub use autoderef::autoderef; @@ -463,34 +463,10 @@ impl Substitution { Substitution(elements.into_iter().casted(interner).collect()) } - /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). - pub(crate) fn type_params_for_generics( - db: &dyn HirDatabase, - generic_params: &Generics, - ) -> Substitution { - Substitution::from_iter( - &Interner, - generic_params - .iter() - .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)), - ) - } - /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). pub fn type_params(db: &dyn HirDatabase, def: impl Into) -> Substitution { let params = generics(db.upcast(), def.into()); - Substitution::type_params_for_generics(db, ¶ms) - } - - /// Return Substs that replace each parameter by a bound variable. - pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { - Substitution::from_iter( - &Interner, - generic_params - .iter() - .enumerate() - .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), - ) + params.type_params_subst(db) } } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 644a2eed5..f9a721fdf 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -234,7 +234,7 @@ impl<'a> TyLoweringContext<'a> { let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx); let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); let generics = generics(self.db.upcast(), func.into()); - let parameters = Substitution::bound_vars(&generics, self.in_binders); + let parameters = generics.bound_vars_subst(self.in_binders); TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters, @@ -411,24 +411,16 @@ impl<'a> TyLoweringContext<'a> { TypeNs::SelfType(impl_id) => { let generics = generics(self.db.upcast(), impl_id.into()); let substs = match self.type_param_mode { - TypeParamLoweringMode::Placeholder => { - Substitution::type_params_for_generics(self.db, &generics) - } - TypeParamLoweringMode::Variable => { - Substitution::bound_vars(&generics, self.in_binders) - } + TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), + TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), }; self.db.impl_self_ty(impl_id).subst(&substs) } TypeNs::AdtSelfType(adt) => { let generics = generics(self.db.upcast(), adt.into()); let substs = match self.type_param_mode { - TypeParamLoweringMode::Placeholder => { - Substitution::type_params_for_generics(self.db, &generics) - } - TypeParamLoweringMode::Variable => { - Substitution::bound_vars(&generics, self.in_binders) - } + TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), + TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), }; self.db.ty(adt.into()).subst(&substs) } @@ -1060,7 +1052,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { /// function body. fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders { let generics = generics(db.upcast(), def.into()); - let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); + let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); Binders::new( substs.len(&Interner), TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), @@ -1105,7 +1097,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders Vec { let resolver = trait_.resolver(db); @@ -249,6 +249,26 @@ impl Generics { self.parent_generics.as_ref().and_then(|g| g.find_param(param)) } } + + /// Returns a Substitution that replaces each parameter by a bound variable. + pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution { + Substitution::from_iter( + &Interner, + self.iter() + .enumerate() + .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), + ) + } + + /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`). + pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution { + Substitution::from_iter( + &Interner, + self.iter().map(|(id, _)| { + TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner) + }), + ) + } } fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option { -- cgit v1.2.3 From ebdfc932e74ff11c8c14c513614212b7c07bf400 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 4 Apr 2021 13:16:16 +0200 Subject: Replace Substitution::type_params --- crates/hir_ty/src/builder.rs | 5 +++++ crates/hir_ty/src/display.rs | 3 +-- crates/hir_ty/src/lib.rs | 8 +------- crates/hir_ty/src/lower.rs | 7 ++++--- 4 files changed, 11 insertions(+), 12 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs index ba158a749..4d3b4eade 100644 --- a/crates/hir_ty/src/builder.rs +++ b/crates/hir_ty/src/builder.rs @@ -99,6 +99,11 @@ impl TyBuilder<()> { } } + pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into) -> Substitution { + let params = generics(db.upcast(), def.into()); + params.type_params_subst(db) + } + pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into) -> TyBuilder<()> { let def = def.into(); let params = generics(db.upcast(), def); diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 39e0b328d..385bd9405 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -19,8 +19,7 @@ use crate::{ db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, - ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, - WhereClause, + ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, }; pub struct HirFormatter<'a> { diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 6d6443ca3..a8c87eadf 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -462,12 +462,6 @@ impl Substitution { ) -> Self { Substitution(elements.into_iter().casted(interner).collect()) } - - /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). - pub fn type_params(db: &dyn HirDatabase, def: impl Into) -> Substitution { - let params = generics(db.upcast(), def.into()); - params.type_params_subst(db) - } } /// Return an index of a parameter in the generic type parameter list by it's id. @@ -944,7 +938,7 @@ impl Ty { let param_data = &generic_params.types[id.local_id]; match param_data.provenance { hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { - let substs = Substitution::type_params(db, id.parent); + let substs = TyBuilder::type_params_subst(db, id.parent); let predicates = db .generic_predicates(id.parent) .into_iter() diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index f9a721fdf..214655807 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -470,12 +470,13 @@ impl<'a> TyLoweringContext<'a> { TypeParamLoweringMode::Placeholder => { // if we're lowering to placeholders, we have to put // them in now - let s = Substitution::type_params( - self.db, + let generics = generics( + self.db.upcast(), self.resolver.generic_def().expect( "there should be generics if there's a generic param", ), ); + let s = generics.type_params_subst(self.db); t.substitution.clone().subst_bound_vars(&s) } TypeParamLoweringMode::Variable => t.substitution.clone(), @@ -963,7 +964,7 @@ pub(crate) fn trait_environment_query( // function default implementations (and hypothetical code // inside consts or type aliases) cov_mark::hit!(trait_self_implements_self); - let substs = Substitution::type_params(db, trait_id); + let substs = TyBuilder::type_params_subst(db, trait_id); let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; let pred = WhereClause::Implemented(trait_ref); let program_clause: chalk_ir::ProgramClause = pred.to_chalk(db).cast(&Interner); -- cgit v1.2.3 From cde3857897955558ed0e60cf8158e18d5c75d188 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 4 Apr 2021 13:23:22 +0200 Subject: Add comment --- crates/hir_ty/src/builder.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs index 4d3b4eade..4a9a8058f 100644 --- a/crates/hir_ty/src/builder.rs +++ b/crates/hir_ty/src/builder.rs @@ -16,7 +16,10 @@ use crate::{ TyDefId, TyKind, TypeWalk, ValueTyDefId, }; +/// This is a builder for `Ty` or anything that needs a `Substitution`. pub struct TyBuilder { + /// The `data` field is used to keep track of what we're building (e.g. an + /// ADT, a `TraitRef`, ...). data: D, vec: SmallVec<[GenericArg; 2]>, param_count: usize, -- cgit v1.2.3