From e480d81988fc0c0e4f80f1c54058b95b9aaf1ebf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 1 Apr 2021 21:04:02 +0200 Subject: Introduce `GenericArg` like in Chalk Plus some more adaptations to Substitution. Lots of `assert_ty_ref` that we should revisit when introducing lifetime/const parameters. --- crates/hir/src/lib.rs | 31 +++-- crates/hir_ty/src/autoderef.rs | 9 +- crates/hir_ty/src/chalk_cast.rs | 22 +++- crates/hir_ty/src/diagnostics/expr.rs | 4 +- crates/hir_ty/src/diagnostics/match_check.rs | 5 +- crates/hir_ty/src/display.rs | 61 ++++++---- crates/hir_ty/src/infer/coerce.rs | 2 +- crates/hir_ty/src/infer/expr.rs | 24 ++-- crates/hir_ty/src/infer/pat.rs | 17 +-- crates/hir_ty/src/infer/path.rs | 6 +- crates/hir_ty/src/infer/unify.rs | 55 +++++---- crates/hir_ty/src/lib.rs | 173 +++++++++++++++++++-------- crates/hir_ty/src/lower.rs | 17 +-- crates/hir_ty/src/method_resolution.rs | 7 +- crates/hir_ty/src/traits.rs | 2 +- crates/hir_ty/src/traits/chalk.rs | 10 +- crates/hir_ty/src/traits/chalk/mapping.rs | 39 ++++-- 17 files changed, 323 insertions(+), 161 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 06fd6542d..fcc577384 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1829,9 +1829,11 @@ impl Type { ); match db.trait_solve(self.krate, goal)? { - Solution::Unique(SolutionVariables(subst)) => { - subst.value.first().map(|ty| self.derived(ty.clone())) - } + Solution::Unique(SolutionVariables(subst)) => subst + .value + .interned(&Interner) + .first() + .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), Solution::Ambig(_) => None, } } @@ -1889,7 +1891,9 @@ impl Type { | TyKind::Tuple(_, substs) | TyKind::OpaqueType(_, substs) | TyKind::FnDef(_, substs) - | TyKind::Closure(_, substs) => substs.iter().any(go), + | TyKind::Closure(_, substs) => { + substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go) + } TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { go(ty) @@ -1928,7 +1932,10 @@ impl Type { pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec { if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { - substs.iter().map(|ty| self.derived(ty.clone())).collect() + substs + .iter(&Interner) + .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())) + .collect() } else { Vec::new() } @@ -1973,8 +1980,9 @@ impl Type { .strip_references() .substs() .into_iter() - .flat_map(|substs| substs.iter()) - .map(move |ty| self.derived(ty.clone())) + .flat_map(|substs| substs.iter(&Interner)) + .filter_map(|arg| arg.ty(&Interner).cloned()) + .map(move |ty| self.derived(ty)) } pub fn iterate_method_candidates( @@ -2080,7 +2088,7 @@ impl Type { substs: &Substitution, cb: &mut impl FnMut(Type), ) { - for ty in substs.iter() { + for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) { walk_type(db, &type_.derived(ty.clone()), cb); } } @@ -2096,7 +2104,12 @@ impl Type { WhereClause::Implemented(trait_ref) => { cb(type_.clone()); // skip the self type. it's likely the type we just got the bounds from - for ty in trait_ref.substitution.iter().skip(1) { + for ty in trait_ref + .substitution + .iter(&Interner) + .skip(1) + .filter_map(|a| a.ty(&Interner)) + { walk_type(db, &type_.derived(ty.clone()), cb); } } diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index dc5fc759a..5e3c018a8 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -131,7 +131,7 @@ fn deref_by_trait( // new variables in that case for i in 1..vars.0.binders.len(&Interner) { - if vars.0.value[i - 1].interned(&Interner) + if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).interned(&Interner) != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) { warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); @@ -139,7 +139,12 @@ fn deref_by_trait( } } Some(Canonical { - value: vars.0.value[vars.0.value.len() - 1].clone(), + value: vars + .0 + .value + .at(&Interner, vars.0.value.len(&Interner) - 1) + .assert_ty_ref(&Interner) + .clone(), binders: vars.0.binders.clone(), }) } diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs index bf884ae15..df6492113 100644 --- a/crates/hir_ty/src/chalk_cast.rs +++ b/crates/hir_ty/src/chalk_cast.rs @@ -5,7 +5,7 @@ use chalk_ir::{ interner::HasInterner, }; -use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; +use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause}; macro_rules! has_interner { ($t:ty) => { @@ -17,6 +17,8 @@ macro_rules! has_interner { has_interner!(WhereClause); has_interner!(DomainGoal); +has_interner!(GenericArg); +has_interner!(Ty); impl CastTo for TraitRef { fn cast_to(self, _interner: &Interner) -> WhereClause { @@ -36,6 +38,12 @@ impl CastTo for WhereClause { } } +impl CastTo for Ty { + fn cast_to(self, interner: &Interner) -> GenericArg { + GenericArg::new(interner, GenericArgData::Ty(self)) + } +} + macro_rules! transitive_impl { ($a:ty, $b:ty, $c:ty) => { impl CastTo<$c> for $a { @@ -51,3 +59,15 @@ macro_rules! transitive_impl { transitive_impl!(TraitRef, WhereClause, DomainGoal); transitive_impl!(AliasEq, WhereClause, DomainGoal); + +macro_rules! reflexive_impl { + ($a:ty) => { + impl CastTo<$a> for $a { + fn cast_to(self, _interner: &Interner) -> $a { + self + } + } + }; +} + +reflexive_impl!(GenericArg); diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 3909ad354..373d1cb74 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs @@ -392,7 +392,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> { _ => return, }; - if params.len() > 0 && params[0] == mismatch.actual { + if params.len(&Interner) > 0 + && params.at(&Interner, 0).ty(&Interner) == Some(&mismatch.actual) + { let (_, source_map) = db.body_with_source_map(self.owner); if let Ok(source_ptr) = source_map.expr_syntax(id) { diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 9cb472b51..85ba58c44 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -792,7 +792,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult { let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); Some(Constructor::Tuple { - arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), + arity: cx.infer.type_of_pat[pat_id] + .as_tuple() + .ok_or(MatchCheckErr::Unknown)? + .len(&Interner), }) } Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 51480304b..59fd18c2a 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -8,7 +8,7 @@ use hir_def::{ find_path, generics::TypeParamProvenance, item_scope::ItemInNs, - path::{GenericArg, Path, PathKind}, + path::{Path, PathKind}, type_ref::{TypeBound, TypeRef}, visibility::Visibility, AssocContainerId, Lookup, ModuleId, TraitId, @@ -18,7 +18,7 @@ use hir_expand::name::Name; 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, ImplTraitId, Interner, Lifetime, OpaqueTy, + CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, }; @@ -251,16 +251,16 @@ impl HirDisplay for ProjectionTy { } let trait_ = f.db.trait_data(self.trait_(f.db)); - let first_parameter = self.substitution[0].into_displayable( + let first_parameter = self.self_type_parameter().into_displayable( f.db, f.max_size, f.omit_verbose_types, f.display_target, ); write!(f, "<{} as {}", first_parameter, trait_.name)?; - if self.substitution.len() > 1 { + if self.substitution.len(&Interner) > 1 { write!(f, "<")?; - f.write_joined(&self.substitution[1..], ", ")?; + f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; write!(f, ">")?; } write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; @@ -274,7 +274,15 @@ impl HirDisplay for OpaqueTy { return write!(f, "{}", TYPE_HINT_TRUNCATION); } - self.substitution[0].hir_fmt(f) + self.substitution.at(&Interner, 0).hir_fmt(f) + } +} + +impl HirDisplay for GenericArg { + fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { + match self.interned() { + crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), + } } } @@ -373,9 +381,9 @@ impl HirDisplay for Ty { } } TyKind::Tuple(_, substs) => { - if substs.len() == 1 { + if substs.len(&Interner) == 1 { write!(f, "(")?; - substs[0].hir_fmt(f)?; + substs.at(&Interner, 0).hir_fmt(f)?; write!(f, ",)")?; } else { write!(f, "(")?; @@ -399,7 +407,7 @@ impl HirDisplay for Ty { write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? } }; - if parameters.len() > 0 { + if parameters.len(&Interner) > 0 { let generics = generics(f.db.upcast(), def.into()); let (parent_params, self_param, type_params, _impl_trait_params) = generics.provenance_split(); @@ -451,7 +459,7 @@ impl HirDisplay for Ty { } } - if parameters.len() > 0 { + if parameters.len(&Interner) > 0 { let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() { @@ -463,9 +471,11 @@ impl HirDisplay for Ty { None => parameters.0.as_ref(), Some(default_parameters) => { let mut default_from = 0; - for (i, parameter) in parameters.iter().enumerate() { - match (parameter.interned(&Interner), default_parameters.get(i)) - { + for (i, parameter) in parameters.iter(&Interner).enumerate() { + match ( + parameter.assert_ty_ref(&Interner).interned(&Interner), + default_parameters.get(i), + ) { (&TyKind::Unknown, _) | (_, None) => { default_from = i + 1; } @@ -473,7 +483,8 @@ impl HirDisplay for Ty { let actual_default = default_parameter .clone() .subst(¶meters.prefix(i)); - if parameter != &actual_default { + if parameter.assert_ty_ref(&Interner) != &actual_default + { default_from = i + 1; } } @@ -504,7 +515,7 @@ impl HirDisplay for Ty { // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) if f.display_target.is_test() { write!(f, "{}::{}", trait_.name, type_alias_data.name)?; - if parameters.len() > 0 { + if parameters.len(&Interner) > 0 { write!(f, "<")?; f.write_joined(&*parameters.0, ", ")?; write!(f, ">")?; @@ -537,7 +548,7 @@ impl HirDisplay for Ty { } ImplTraitId::AsyncBlockTypeImplTrait(..) => { write!(f, "impl Future")?; } } @@ -548,7 +559,7 @@ impl HirDisplay for Ty { DisplaySourceCodeError::Closure, )); } - let sig = substs[0].callable_sig(f.db); + let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db); if let Some(sig) = sig { if sig.params().is_empty() { write!(f, "||")?; @@ -718,7 +729,9 @@ fn write_bounds_like_dyn_trait( write!(f, "{}", f.db.trait_data(trait_).name)?; if let [_, params @ ..] = &*trait_ref.substitution.0 { if is_fn_trait { - if let Some(args) = params.first().and_then(|it| it.as_tuple()) { + if let Some(args) = + params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) + { write!(f, "(")?; f.write_joined(&*args.0, ", ")?; write!(f, ")")?; @@ -767,16 +780,16 @@ impl TraitRef { return write!(f, "{}", TYPE_HINT_TRUNCATION); } - self.substitution[0].hir_fmt(f)?; + self.self_type_parameter().hir_fmt(f)?; if use_as { write!(f, " as ")?; } else { write!(f, ": ")?; } write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; - if self.substitution.len() > 1 { + if self.substitution.len(&Interner) > 1 { write!(f, "<")?; - f.write_joined(&self.substitution[1..], ", ")?; + f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; write!(f, ">")?; } Ok(()) @@ -1016,11 +1029,11 @@ impl HirDisplay for Path { } } -impl HirDisplay for GenericArg { +impl HirDisplay for hir_def::path::GenericArg { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { match self { - GenericArg::Type(ty) => ty.hir_fmt(f), - GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), + hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f), + hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), } } } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 9c62932b1..8f7322b36 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -100,7 +100,7 @@ impl<'a> InferenceContext<'a> { }, (TyKind::Closure(.., substs), TyKind::Function { .. }) => { - from_ty = substs[0].clone(); + from_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); } _ => {} diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 25ab3ea4c..b99b6cd21 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -266,7 +266,7 @@ impl<'a> InferenceContext<'a> { let sig_ty = TyKind::Function(FnPointer { num_args: sig_tys.len() - 1, sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, - substs: Substitution(sig_tys.clone().into()), + substs: Substitution::from_iter(&Interner, sig_tys.clone()), }) .intern(&Interner); let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); @@ -406,7 +406,7 @@ impl<'a> InferenceContext<'a> { self.unify(&ty, &expected.ty); - let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); + let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); for field in fields.iter() { @@ -456,9 +456,13 @@ impl<'a> InferenceContext<'a> { .unwrap_or(true) }; match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { - TyKind::Tuple(_, substs) => { - name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) - } + TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { + substs + .interned(&Interner) + .get(idx) + .map(|a| a.assert_ty_ref(&Interner)) + .cloned() + }), TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { let local_id = self.db.struct_data(*s).variant_data.field(name)?; let field = FieldId { parent: (*s).into(), local_id }; @@ -635,7 +639,7 @@ 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()), + Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), None => self.err_ty(), }, (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { @@ -694,8 +698,8 @@ impl<'a> InferenceContext<'a> { Expr::Tuple { exprs } => { let mut tys = match expected.ty.interned(&Interner) { TyKind::Tuple(_, substs) => substs - .iter() - .cloned() + .iter(&Interner) + .map(|a| a.assert_ty_ref(&Interner).clone()) .chain(repeat_with(|| self.table.new_type_var())) .take(exprs.len()) .collect::>(), @@ -706,7 +710,7 @@ impl<'a> InferenceContext<'a> { self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); } - TyKind::Tuple(tys.len(), Substitution(tys.into())).intern(&Interner) + TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner) } Expr::Array(array) => { let elem_ty = match expected.ty.interned(&Interner) { @@ -953,7 +957,7 @@ impl<'a> InferenceContext<'a> { substs.push(self.err_ty()); } assert_eq!(substs.len(), total_len); - Substitution(substs.into()) + Substitution::from_iter(&Interner, substs) } fn register_obligations_for_call(&mut self, callable_ty: &Ty) { diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 474363709..f1316415f 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -35,7 +35,7 @@ impl<'a> InferenceContext<'a> { } self.unify(&ty, expected); - let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); + let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); let (pre, post) = match ellipsis { @@ -74,7 +74,7 @@ impl<'a> InferenceContext<'a> { self.unify(&ty, expected); - let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); + let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); for subpat in subpats { @@ -134,7 +134,8 @@ impl<'a> InferenceContext<'a> { }; let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); let err_ty = self.err_ty(); - let mut expectations_iter = expectations.iter().chain(repeat(&err_ty)); + let mut expectations_iter = + expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty)); let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); @@ -142,7 +143,8 @@ impl<'a> InferenceContext<'a> { inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); - TyKind::Tuple(inner_tys.len(), Substitution(inner_tys.into())).intern(&Interner) + TyKind::Tuple(inner_tys.len(), Substitution::from_iter(&Interner, inner_tys)) + .intern(&Interner) } Pat::Or(ref pats) => { if let Some((first_pat, rest)) = pats.split_first() { @@ -236,9 +238,10 @@ impl<'a> InferenceContext<'a> { Pat::Box { inner } => match self.resolve_boxed_box() { Some(box_adt) => { let (inner_ty, alloc_ty) = match expected.as_adt() { - Some((adt, subst)) if adt == box_adt => { - (subst[0].clone(), subst.get(1).cloned()) - } + Some((adt, subst)) if adt == box_adt => ( + subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), + subst.interned(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), + ), _ => (self.result.standard_types.unknown.clone(), None), }; diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 717738789..b96391776 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs @@ -97,12 +97,12 @@ impl<'a> InferenceContext<'a> { let ty = self.db.value_ty(typable); // self_subst is just for the parent - let parent_substs = self_subst.unwrap_or_else(Substitution::empty); + 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()) + let full_substs = Substitution::builder(substs.len(&Interner)) .use_parent_substs(&parent_substs) - .fill(substs.0[parent_substs.len()..].iter().cloned()) + .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 5ea4b7481..0efc62e53 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -129,29 +129,28 @@ impl Canonicalized { solution: Canonical, ) { // the solution may contain new variables, which we need to convert to new inference vars - let new_vars = Substitution( - solution - .binders - .iter(&Interner) - .map(|k| match k.kind { - VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), - VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), - VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), - // HACK: Chalk can sometimes return new lifetime variables. We - // want to just skip them, but to not mess up the indices of - // other variables, we'll just create a new type variable in - // their place instead. This should not matter (we never see the - // actual *uses* of the lifetime variable). - VariableKind::Lifetime => ctx.table.new_type_var(), - _ => panic!("const variable in solution"), - }) - .collect(), + let new_vars = Substitution::from_iter( + &Interner, + solution.binders.iter(&Interner).map(|k| match k.kind { + VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), + VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), + VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), + // HACK: Chalk can sometimes return new lifetime variables. We + // want to just skip them, but to not mess up the indices of + // other variables, we'll just create a new type variable in + // their place instead. This should not matter (we never see the + // actual *uses* of the lifetime variable). + VariableKind::Lifetime => ctx.table.new_type_var(), + _ => panic!("const variable in solution"), + }), ); - for (i, ty) in solution.value.into_iter().enumerate() { + for (i, ty) in solution.value.iter(&Interner).enumerate() { let (v, k) = self.free_vars[i]; // eagerly replace projections in the type; we may be getting types // e.g. from where clauses where this hasn't happened yet - let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); + let ty = ctx.normalize_associated_types_in( + ty.assert_ty_ref(&Interner).clone().subst_bound_vars(&new_vars), + ); ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); } } @@ -163,13 +162,13 @@ pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { let mut table = InferenceTable::new(); - let vars = Substitution( + let vars = Substitution::from_iter( + &Interner, tys.binders .iter(&Interner) // we always use type vars here because we want everything to // fallback to Unknown in the end (kind of hacky, as below) - .map(|_| table.new_type_var()) - .collect(), + .map(|_| table.new_type_var()), ); let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); @@ -178,7 +177,8 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { } // default any type vars that weren't unified back to their original bound vars // (kind of hacky) - for (i, var) in vars.iter().enumerate() { + for (i, var) in vars.iter(&Interner).enumerate() { + let var = var.assert_ty_ref(&Interner); if &*table.resolve_ty_shallow(var) == var { table.unify( var, @@ -188,7 +188,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option { } Some( Substitution::builder(tys.binders.len(&Interner)) - .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) + .fill( + vars.iter(&Interner) + .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), + ) .build(), ) } @@ -284,7 +287,9 @@ impl InferenceTable { substs2: &Substitution, depth: usize, ) -> bool { - substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) + substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { + self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) + }) } fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 6f9c698e6..c927ed973 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -24,9 +24,10 @@ mod tests; #[cfg(test)] mod test_db; -use std::{iter, mem, ops::Deref, sync::Arc}; +use std::{iter, mem, sync::Arc}; use base_db::salsa; +use chalk_ir::cast::{CastTo, Caster}; use hir_def::{ builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, @@ -109,7 +110,7 @@ impl ProjectionTy { } pub fn self_type_parameter(&self) -> &Ty { - &self.substitution[0] + &self.substitution.interned(&Interner)[0].assert_ty_ref(&Interner) } fn trait_(&self, db: &dyn HirDatabase) -> TraitId { @@ -324,9 +325,72 @@ impl Ty { } } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub struct GenericArg { + interned: GenericArgData, +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum GenericArgData { + Ty(Ty), +} + +impl GenericArg { + /// Constructs a generic argument using `GenericArgData`. + pub fn new(_interner: &Interner, data: GenericArgData) -> Self { + GenericArg { interned: data } + } + + /// Gets the interned value. + pub fn interned(&self) -> &GenericArgData { + &self.interned + } + + /// Asserts that this is a type argument. + pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { + self.ty(interner).unwrap() + } + + /// Checks whether the generic argument is a type. + pub fn is_ty(&self, _interner: &Interner) -> bool { + match self.interned() { + GenericArgData::Ty(_) => true, + } + } + + /// Returns the type if it is one, `None` otherwise. + pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { + match self.interned() { + GenericArgData::Ty(t) => Some(t), + } + } +} + +impl TypeWalk for GenericArg { + fn walk(&self, f: &mut impl FnMut(&Ty)) { + match &self.interned { + GenericArgData::Ty(ty) => { + ty.walk(f); + } + } + } + + fn walk_mut_binders( + &mut self, + f: &mut impl FnMut(&mut Ty, DebruijnIndex), + binders: DebruijnIndex, + ) { + match &mut self.interned { + GenericArgData::Ty(ty) => { + ty.walk_mut_binders(f, binders); + } + } + } +} + /// A list of substitutions for generic parameters. #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub struct Substitution(SmallVec<[Ty; 2]>); +pub struct Substitution(SmallVec<[GenericArg; 2]>); impl TypeWalk for Substitution { fn walk(&self, f: &mut impl FnMut(&Ty)) { @@ -347,18 +411,34 @@ impl TypeWalk for Substitution { } impl Substitution { - pub fn interned(&self, _: &Interner) -> &[Ty] { + pub fn interned(&self, _: &Interner) -> &[GenericArg] { &self.0 } - pub fn empty() -> Substitution { + pub fn len(&self, _: &Interner) -> usize { + self.0.len() + } + + pub fn is_empty(&self, _: &Interner) -> bool { + self.0.is_empty() + } + + pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { + &self.0[i] + } + + pub fn empty(_: &Interner) -> Substitution { Substitution(SmallVec::new()) } + pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { + self.0.iter() + } + pub fn single(ty: Ty) -> Substitution { Substitution({ let mut v = SmallVec::new(); - v.push(ty); + v.push(ty.cast(&Interner)); v }) } @@ -371,15 +451,11 @@ impl Substitution { Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) } - pub fn as_single(&self) -> &Ty { - if self.0.len() != 1 { - panic!("expected substs of len 1, got {:?}", self); - } - &self.0[0] - } - - pub fn from_iter(_interner: &Interner, elements: impl IntoIterator) -> Self { - Substitution(elements.into_iter().collect()) + pub fn from_iter( + interner: &Interner, + elements: impl IntoIterator>, + ) -> Self { + Substitution(elements.into_iter().casted(interner).collect()) } /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). @@ -387,11 +463,11 @@ impl Substitution { db: &dyn HirDatabase, generic_params: &Generics, ) -> Substitution { - Substitution( + Substitution::from_iter( + &Interner, generic_params .iter() - .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)) - .collect(), + .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)), ) } @@ -403,12 +479,12 @@ impl Substitution { /// Return Substs that replace each parameter by a bound variable. pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { - Substitution( + Substitution::from_iter( + &Interner, generic_params .iter() .enumerate() - .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)) - .collect(), + .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), ) } @@ -435,18 +511,18 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option { #[derive(Debug, Clone)] pub struct SubstsBuilder { - vec: Vec, + vec: Vec, param_count: usize, } impl SubstsBuilder { pub fn build(self) -> Substitution { assert_eq!(self.vec.len(), self.param_count); - Substitution(self.vec.into()) + Substitution::from_iter(&Interner, self.vec) } - pub fn push(mut self, ty: Ty) -> Self { - self.vec.push(ty); + pub fn push(mut self, ty: impl CastTo) -> Self { + self.vec.push(ty.cast(&Interner)); self } @@ -465,28 +541,20 @@ impl SubstsBuilder { self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) } - pub fn fill(mut self, filler: impl Iterator) -> Self { - self.vec.extend(filler.take(self.remaining())); + 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() <= self.param_count); - self.vec.extend(parent_substs.iter().cloned()); + assert!(parent_substs.len(&Interner) <= self.param_count); + self.vec.extend(parent_substs.iter(&Interner).cloned()); self } } -impl Deref for Substitution { - type Target = [Ty]; - - fn deref(&self) -> &[Ty] { - &self.0 - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub struct Binders { pub num_binders: usize, @@ -535,7 +603,7 @@ impl Binders<&T> { impl Binders { /// Substitutes all variables. pub fn subst(self, subst: &Substitution) -> T { - assert_eq!(subst.len(), self.num_binders); + assert_eq!(subst.len(&Interner), self.num_binders); self.value.subst_bound_vars(subst) } } @@ -563,7 +631,7 @@ pub struct TraitRef { impl TraitRef { pub fn self_type_parameter(&self) -> &Ty { - &self.substitution[0] + &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) } pub fn hir_trait_id(&self) -> TraitId { @@ -699,14 +767,20 @@ impl CallableSig { .shift_bound_vars_out(DebruijnIndex::ONE) .interned(&Interner) .iter() - .cloned() + .map(|arg| arg.assert_ty_ref(&Interner).clone()) .collect(), is_varargs: fn_ptr.sig.variadic, } } pub fn from_substs(substs: &Substitution) -> CallableSig { - CallableSig { params_and_return: substs.iter().cloned().collect(), is_varargs: false } + CallableSig { + params_and_return: substs + .iter(&Interner) + .map(|arg| arg.assert_ty_ref(&Interner).clone()) + .collect(), + is_varargs: false, + } } pub fn params(&self) -> &[Ty] { @@ -738,7 +812,7 @@ impl TypeWalk for CallableSig { impl Ty { pub fn unit() -> Self { - TyKind::Tuple(0, Substitution::empty()).intern(&Interner) + TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) } pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { @@ -908,7 +982,7 @@ impl Ty { Some(sig.subst(¶meters)) } TyKind::Closure(.., substs) => { - let sig_param = &substs[0]; + let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner); sig_param.callable_sig(db) } _ => None, @@ -960,7 +1034,7 @@ impl Ty { 0, WhereClause::Implemented(TraitRef { trait_id: to_chalk_trait_id(future_trait), - substitution: Substitution::empty(), + substitution: Substitution::empty(&Interner), }), ); Some(vec![impl_bound]) @@ -1109,7 +1183,10 @@ pub trait TypeWalk { &mut |ty, binders| { if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { if bound.debruijn >= binders { - *ty = substs.0[bound.index].clone().shift_bound_vars(binders); + *ty = substs.0[bound.index] + .assert_ty_ref(&Interner) + .clone() + .shift_bound_vars(binders); } } }, @@ -1156,12 +1233,12 @@ impl TypeWalk for Ty { fn walk(&self, f: &mut impl FnMut(&Ty)) { match self.interned(&Interner) { TyKind::Alias(AliasTy::Projection(p_ty)) => { - for t in p_ty.substitution.iter() { + for t in p_ty.substitution.iter(&Interner) { t.walk(f); } } TyKind::Alias(AliasTy::Opaque(o_ty)) => { - for t in o_ty.substitution.iter() { + for t in o_ty.substitution.iter(&Interner) { t.walk(f); } } @@ -1175,7 +1252,7 @@ impl TypeWalk for Ty { } _ => { if let Some(substs) = self.substs() { - for t in substs.iter() { + for t in substs.iter(&Interner) { t.walk(f); } } diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 72ee060e0..f595683e5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -178,9 +178,10 @@ impl<'a> TyLoweringContext<'a> { } TypeRef::Placeholder => TyKind::Unknown.intern(&Interner), TypeRef::Fn(params, is_varargs) => { - let substs = Substitution(params.iter().map(|tr| self.lower_ty(tr)).collect()); + let substs = + Substitution::from_iter(&Interner, params.iter().map(|tr| self.lower_ty(tr))); TyKind::Function(FnPointer { - num_args: substs.len() - 1, + num_args: substs.len(&Interner) - 1, sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs }, substs, }) @@ -625,7 +626,7 @@ impl<'a> TyLoweringContext<'a> { for default_ty in defaults.iter().skip(substs.len()) { // each default can depend on the previous parameters - let substs_so_far = Substitution(substs.clone().into()); + let substs_so_far = Substitution::from_iter(&Interner, substs.clone()); substs.push(default_ty.clone().subst(&substs_so_far)); } } @@ -638,7 +639,7 @@ impl<'a> TyLoweringContext<'a> { } assert_eq!(substs.len(), total_len); - Substitution(substs.into()) + Substitution::from_iter(&Interner, substs) } fn lower_trait_ref_from_path( @@ -1062,7 +1063,7 @@ 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); Binders::new( - substs.len(), + substs.len(&Interner), TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), ) } @@ -1107,7 +1108,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders Binders { let generics = generics(db.upcast(), adt.into()); let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); - Binders::new(substs.len(), Ty::adt_ty(adt, substs)) + Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) } fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index bf7d5eded..054896475 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -720,7 +720,7 @@ pub(crate) fn inherent_impl_substs( chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), UniverseIndex::ROOT, )) - .take(vars.len()), + .take(vars.len(&Interner)), ); let tys = Canonical { binders: CanonicalVarKinds::from_iter(&Interner, kinds), @@ -732,7 +732,8 @@ pub(crate) fn inherent_impl_substs( // Unknown. I think this can only really happen if self_ty contained // Unknown, and in that case we want the result to contain Unknown in those // places again. - substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner))) + substs + .map(|s| fallback_bound_vars(s.suffix(vars.len(&Interner)), self_ty.binders.len(&Interner))) } /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past @@ -821,7 +822,7 @@ fn generic_implements_goal( chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), UniverseIndex::ROOT, )) - .take(substs.len() - 1), + .take(substs.len(&Interner) - 1), ); let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; let obligation = trait_ref.cast(&Interner); diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index ccee0e5ad..a15b6486e 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -138,7 +138,7 @@ pub(crate) fn trait_solve_query( .. })) = &goal.value.goal { - if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { + if let TyKind::BoundVar(_) = projection_ty.self_type_parameter().interned(&Interner) { // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible return Some(Solution::Ambig(Guidance::Unknown)); } diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 011bef6f6..cf7ed1e11 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{fold::shift::Shift, CanonicalVarKinds, GenericArg}; +use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; use base_db::{salsa::InternKey, CrateId}; @@ -80,7 +80,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { fn impls_for_trait( &self, trait_id: TraitId, - parameters: &[GenericArg], + parameters: &[chalk_ir::GenericArg], binders: &CanonicalVarKinds, ) -> Vec { debug!("impls_for_trait {:?}", trait_id); @@ -308,7 +308,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { _closure_id: chalk_ir::ClosureId, _substs: &chalk_ir::Substitution, ) -> chalk_ir::Substitution { - Substitution::empty().to_chalk(self.db) + Substitution::empty(&Interner).to_chalk(self.db) } fn trait_name(&self, trait_id: chalk_ir::TraitId) -> String { @@ -439,7 +439,7 @@ pub(crate) fn trait_datum_query( lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); let trait_datum = TraitDatum { id: trait_id, - binders: make_binders(trait_datum_bound, bound_vars.len()), + binders: make_binders(trait_datum_bound, bound_vars.len(&Interner)), flags, associated_ty_ids, well_known, @@ -577,7 +577,7 @@ fn impl_def_datum( .collect(); debug!("impl_datum: {:?}", impl_datum_bound); let impl_datum = ImplDatum { - binders: make_binders(impl_datum_bound, bound_vars.len()), + binders: make_binders(impl_datum_bound, bound_vars.len(&Interner)), impl_type, polarity, associated_ty_value_ids, diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index aef6b8a15..452b357e8 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -13,7 +13,7 @@ use crate::{ db::HirDatabase, primitive::UintTy, traits::{Canonical, DomainGoal}, - AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, + AliasTy, CallableDefId, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, }; @@ -137,7 +137,7 @@ impl ToChalk for Ty { db, substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), ); - TyKind::Function(FnPointer { num_args: (substs.len() - 1), sig, substs }) + TyKind::Function(FnPointer { num_args: (substs.len(&Interner) - 1), sig, substs }) } chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx), chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, @@ -216,24 +216,39 @@ fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty { chalk_ir::TyKind::Array(arg, const_).intern(&Interner) } +impl ToChalk for GenericArg { + type Chalk = chalk_ir::GenericArg; + + fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { + match self.interned { + crate::GenericArgData::Ty(ty) => ty.to_chalk(db).cast(&Interner), + } + } + + fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { + match chalk.interned() { + chalk_ir::GenericArgData::Ty(ty) => Ty::from_chalk(db, ty.clone()).cast(&Interner), + chalk_ir::GenericArgData::Lifetime(_) => unimplemented!(), + chalk_ir::GenericArgData::Const(_) => unimplemented!(), + } + } +} + impl ToChalk for Substitution { type Chalk = chalk_ir::Substitution; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution { - chalk_ir::Substitution::from_iter(&Interner, self.iter().map(|ty| ty.clone().to_chalk(db))) + chalk_ir::Substitution::from_iter( + &Interner, + self.iter(&Interner).map(|ty| ty.clone().to_chalk(db)), + ) } fn from_chalk( db: &dyn HirDatabase, parameters: chalk_ir::Substitution, ) -> Substitution { - let tys = parameters - .iter(&Interner) - .map(|p| match p.ty(&Interner) { - Some(ty) => from_chalk(db, ty.clone()), - None => unimplemented!(), - }) - .collect(); + let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); Substitution(tys) } } @@ -531,7 +546,7 @@ pub(super) fn generic_predicate_to_inline_bound( // have the expected self type return None; } - let args_no_self = trait_ref.substitution[1..] + let args_no_self = trait_ref.substitution.interned(&Interner)[1..] .iter() .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) .collect(); @@ -543,7 +558,7 @@ pub(super) fn generic_predicate_to_inline_bound( return None; } let trait_ = projection_ty.trait_(db); - let args_no_self = projection_ty.substitution[1..] + let args_no_self = projection_ty.substitution.interned(&Interner)[1..] .iter() .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) .collect(); -- cgit v1.2.3