From daaf46177e5dc63e20e5a1ec5692e53cc8f7bc34 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 26 Sep 2019 21:37:03 +0200 Subject: Add SubstsBuilder + further refactoring. --- crates/ra_hir/src/ty/autoderef.rs | 14 +++--- crates/ra_hir/src/ty/infer.rs | 15 +++--- crates/ra_hir/src/ty/infer/path.rs | 10 ++-- crates/ra_hir/src/ty/infer/unify.rs | 24 ++++------ crates/ra_hir/src/ty/lower.rs | 20 +++++--- crates/ra_hir/src/ty/method_resolution.rs | 18 ++----- crates/ra_hir/src/ty/tests.rs | 1 - crates/ra_hir/src/ty/traits/chalk.rs | 80 ++++++++----------------------- 8 files changed, 66 insertions(+), 116 deletions(-) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 94f8ecdc9..02492ca14 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs @@ -7,7 +7,7 @@ use std::iter::successors; use log::{info, warn}; -use super::{traits::Solution, Canonical, Ty, TypeWalk}; +use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; const AUTODEREF_RECURSION_LIMIT: usize = 10; @@ -44,7 +44,8 @@ fn deref_by_trait( }; let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; - if target.generic_params(db).count_params_including_parent() != 1 { + let generic_params = target.generic_params(db); + if generic_params.count_params_including_parent() != 1 { // the Target type + Deref trait should only have one generic parameter, // namely Deref's Self type return None; @@ -54,12 +55,13 @@ fn deref_by_trait( let env = super::lower::trait_env(db, resolver); + let parameters = Substs::build_for_generics(&generic_params) + .push(ty.value.clone().shift_bound_vars(1)) + .build(); + let projection = super::traits::ProjectionPredicate { ty: Ty::Bound(0), - projection_ty: super::ProjectionTy { - associated_ty: target, - parameters: vec![ty.value.clone().shift_bound_vars(1)].into(), - }, + projection_ty: super::ProjectionTy { associated_ty: target, parameters }, }; let obligation = super::Obligation::Projection(projection); diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index db3377357..8e07fc186 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); - let inner_tys: Substs = args + let inner_tys = args .iter() .zip(expectations_iter) .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) - .collect::>() - .into(); + .collect(); - Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys) + Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys)) } Pat::Ref { pat, mutability } => { let expectation = match expected.as_reference() { @@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty: pat_ty.clone(), projection_ty: ProjectionTy { associated_ty: into_iter_item_alias, - parameters: vec![iterable_ty].into(), + parameters: Substs::single(iterable_ty), }, }; self.obligations.push(Obligation::Projection(projection)); @@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { sig_tys.push(ret_ty.clone()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, - sig_tys.into(), + Substs(sig_tys.into()), ); let closure_ty = Ty::apply_one( TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, @@ -1400,7 +1399,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty: ty.clone(), projection_ty: ProjectionTy { associated_ty: future_future_output_alias, - parameters: vec![inner_ty].into(), + parameters: Substs::single(inner_ty), }, }; self.obligations.push(Obligation::Projection(projection)); @@ -1419,7 +1418,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty: ty.clone(), projection_ty: ProjectionTy { associated_ty: ops_try_ok_alias, - parameters: vec![inner_ty].into(), + parameters: Substs::single(inner_ty), }, }; self.obligations.push(Obligation::Projection(projection)); diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index feb7481b2..db979353a 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs @@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { AssocItem::Const(c) => ValueNs::Const(c), AssocItem::TypeAlias(_) => unreachable!(), }; - let generics = item.generic_params(self.db); - let mut substs = Vec::with_capacity(generics.count_params_including_parent()); - substs.extend(trait_ref.substs.iter().cloned()); - substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len())); + let substs = Substs::build_for_def(self.db, item) + .use_parent_substs(&trait_ref.substs) + .fill_with_unknown() + .build(); self.write_assoc_resolution(id, item); - Some((def, Some(substs.into()))) + Some((def, Some(substs))) } fn resolve_ty_assoc_item( diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index b6ebee3b1..d161aa6b3 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs @@ -3,7 +3,8 @@ use super::{InferenceContext, Obligation}; use crate::db::HirDatabase; use crate::ty::{ - Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, + Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, + TypeWalk, }; impl<'a, D: HirDatabase> InferenceContext<'a, D> { @@ -74,12 +75,9 @@ where } fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { - let substs = trait_ref - .substs - .iter() - .map(|ty| self.do_canonicalize_ty(ty.clone())) - .collect::>(); - TraitRef { trait_: trait_ref.trait_, substs: substs.into() } + let substs = + trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); + TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) } } fn into_canonicalized(self, result: T) -> Canonicalized { @@ -90,12 +88,9 @@ where } fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { - let params = projection_ty - .parameters - .iter() - .map(|ty| self.do_canonicalize_ty(ty.clone())) - .collect::>(); - ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() } + let params = + projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); + ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) } } fn do_canonicalize_projection_predicate( @@ -153,8 +148,7 @@ impl Canonicalized { solution: Canonical>, ) { // the solution may contain new variables, which we need to convert to new inference vars - let new_vars = - (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::>().into(); + let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect()); for (i, ty) in solution.value.into_iter().enumerate() { let var = self.free_vars[i]; ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index dd503d771..4b67c82e7 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -239,14 +239,10 @@ impl Ty { let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); for t in traits { if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { - let generics = t.generic_params(db); - let mut substs = Vec::new(); - substs.push(self_ty.clone()); - substs.extend( - iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1), - ); + let substs = + Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); // FIXME handle type parameters on the segment - return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() }); + return Ty::Projection(ProjectionTy { associated_ty, parameters: substs }); } } Ty::Unknown @@ -766,6 +762,16 @@ pub enum CallableDef { } impl_froms!(CallableDef: Function, Struct, EnumVariant); +impl CallableDef { + pub fn krate(self, db: &impl HirDatabase) -> Option { + match self { + CallableDef::Function(f) => f.krate(db), + CallableDef::Struct(s) => s.krate(db), + CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db), + } + } +} + impl From for GenericDef { fn from(def: CallableDef) -> GenericDef { match def { diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 4b71b376f..ad2ab560d 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -10,7 +10,6 @@ use rustc_hash::FxHashMap; use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; use crate::{ db::HirDatabase, - generics::HasGenericParams, impl_block::{ImplBlock, ImplId}, nameres::CrateModuleId, resolve::Resolver, @@ -331,20 +330,13 @@ fn generic_implements_goal( trait_: Trait, self_ty: Canonical, ) -> Canonical> { - let mut substs = Vec::new(); - let generics = trait_.generic_params(db); let num_vars = self_ty.num_vars; - substs.push(self_ty.value); - substs.extend( - generics - .params_including_parent() - .into_iter() - .skip(1) - .enumerate() - .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)), - ); + let substs = super::Substs::build_for_def(db, trait_) + .push(self_ty.value) + .fill_with_bound_vars(num_vars as u32) + .build(); let num_vars = substs.len() - 1 + self_ty.num_vars; - let trait_ref = TraitRef { trait_, substs: substs.into() }; + let trait_ref = TraitRef { trait_, substs }; let obligation = super::Obligation::Trait(trait_ref); Canonical { num_vars, value: InEnvironment::new(env, obligation) } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 4362bb27a..7de434180 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -3321,7 +3321,6 @@ fn test() { S2.into()<|>; } #[test] fn method_resolution_encountering_fn_type() { - covers!(trait_resolution_on_fn_type); type_at( r#" //- /main.rs diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 538b4d3ec..2642a54bf 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -10,17 +10,13 @@ use chalk_ir::{ use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; use ra_db::salsa::{InternId, InternKey}; -use test_utils::tested_by; use super::{Canonical, ChalkContext, Impl, Obligation}; use crate::{ db::HirDatabase, generics::GenericDef, ty::display::HirDisplay, - ty::{ - ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, - TypeWalk, - }, + ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, }; @@ -124,14 +120,15 @@ impl ToChalk for Substs { } fn from_chalk(db: &impl HirDatabase, parameters: Vec) -> Substs { - parameters + let tys = parameters .into_iter() .map(|p| match p { chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), }) .collect::>() - .into() + .into(); + Substs(tys) } } @@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query( struct_id: chalk_ir::StructId, ) -> Arc { debug!("struct_datum {:?}", struct_id); - let type_ctor = from_chalk(db, struct_id); + let type_ctor: TypeCtor = from_chalk(db, struct_id); debug!("struct {:?} = {:?}", struct_id, type_ctor); - // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor - // FIXME extract this to a method on Ty - let (num_params, where_clauses, upstream) = match type_ctor { - TypeCtor::Bool - | TypeCtor::Char - | TypeCtor::Int(_) - | TypeCtor::Float(_) - | TypeCtor::Never - | TypeCtor::Str => (0, vec![], true), - TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => { - (1, vec![], true) - } - TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true), - TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true), - TypeCtor::FnDef(callable) => { - tested_by!(trait_resolution_on_fn_type); - let upstream = match callable { - CallableDef::Function(f) => f.module(db).krate(db), - CallableDef::Struct(s) => s.module(db).krate(db), - CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db), - } != Some(krate); - let generic_def: GenericDef = callable.into(); + let num_params = type_ctor.num_ty_params(db); + let upstream = type_ctor.krate(db) != Some(krate); + let where_clauses = type_ctor + .as_generic_def() + .map(|generic_def| { let generic_params = generic_def.generic_params(db); let bound_vars = Substs::bound_vars(&generic_params); - let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); - (generic_params.count_params_including_parent(), where_clauses, upstream) - } - TypeCtor::Adt(adt) => { - let generic_params = adt.generic_params(db); - let bound_vars = Substs::bound_vars(&generic_params); - let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars); - ( - generic_params.count_params_including_parent(), - where_clauses, - adt.krate(db) != Some(krate), - ) - } - TypeCtor::AssociatedType(type_alias) => { - let generic_params = type_alias.generic_params(db); - let bound_vars = Substs::bound_vars(&generic_params); - let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); - ( - generic_params.count_params_including_parent(), - where_clauses, - type_alias.krate(db) != Some(krate), - ) - } - TypeCtor::Closure { def, .. } => { - let upstream = def.krate(db) != Some(krate); - (1, vec![], upstream) - } - }; + convert_where_clauses(db, generic_def, &bound_vars) + }) + .unwrap_or_else(Vec::new); let flags = chalk_rust_ir::StructFlags { upstream, // FIXME set fundamental flag correctly @@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum( let arg_ty = Ty::apply( TypeCtor::Tuple { cardinality: num_args }, - (0..num_args).map(|i| Ty::Bound(i.into())).collect::>().into(), + Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), ); let output_ty = Ty::Bound(num_args.into()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args }, - (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::>().into(), + Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), ); let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); - let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() }; + let trait_ref = TraitRef { + trait_, + substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), + }; let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; -- cgit v1.2.3