From cf6809645e2327e20edd30eb535d4f06fa116b5c Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 30 Nov 2019 12:35:37 +0100 Subject: Handle cycles in impl types better - impl Trait for S is allowed - impl Trait for S is an invalid cycle, but we can add cycle recovery for it in Salsa now --- crates/ra_hir_ty/src/traits/chalk.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 35de37e6b..104346ada 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -20,8 +20,8 @@ use ra_db::salsa::{InternId, InternKey}; use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ - db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy, - Substs, TraitRef, Ty, TypeCtor, TypeWalk, + db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, + TraitRef, Ty, TypeCtor, TypeWalk, }; /// This represents a trait whose name we could not resolve. @@ -630,10 +630,7 @@ fn impl_block_datum( chalk_id: chalk_ir::ImplId, impl_id: ImplId, ) -> Option>> { - let trait_ref = match db.impl_ty(impl_id) { - ImplTy::TraitRef(it) => it, - ImplTy::Inherent(_) => return None, - }; + let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); let generic_params = db.generic_params(impl_id.into()); @@ -787,11 +784,7 @@ fn type_alias_associated_ty_value( _ => panic!("assoc ty value should be in impl"), }; - let trait_ref = match db.impl_ty(impl_id) { - ImplTy::TraitRef(it) => it, - // we don't return any assoc ty values if the impl'd trait can't be resolved - ImplTy::Inherent(_) => panic!("assoc ty value should not exist"), - }; + let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved let assoc_ty = db .trait_data(trait_ref.trait_) -- cgit v1.2.3 From 176207f1e87bb1f2c70529cdbc66ae8c96584b03 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 3 Dec 2019 12:16:39 +0100 Subject: Extract built-in trait implementations to separate module This untangles the builtin logic from the Chalk translation. --- crates/ra_hir_ty/src/traits/builtin.rs | 161 +++++++++++++++++++++++++++++ crates/ra_hir_ty/src/traits/chalk.rs | 184 ++++++++++----------------------- 2 files changed, 218 insertions(+), 127 deletions(-) create mode 100644 crates/ra_hir_ty/src/traits/builtin.rs (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs new file mode 100644 index 000000000..598fd81e3 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -0,0 +1,161 @@ +//! This module provides the built-in trait implementations, e.g. to make +//! closures implement `Fn`. +use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; +use hir_expand::name; +use ra_db::CrateId; + +use super::{AssocTyValue, Impl}; +use crate::{db::HirDatabase, ApplicationTy, Substs, TraitRef, Ty, TypeCtor}; + +pub(super) struct BuiltinImplData { + pub num_vars: usize, + pub trait_ref: TraitRef, + pub where_clauses: Vec, + pub assoc_ty_values: Vec, +} + +pub(super) struct BuiltinImplAssocTyValueData { + pub impl_: Impl, + pub assoc_ty_id: TypeAliasId, + pub num_vars: usize, + pub value: Ty, +} + +pub(super) fn get_builtin_impls( + db: &impl HirDatabase, + krate: CrateId, + ty: &Ty, + trait_: TraitId, + mut callback: impl FnMut(Impl), +) { + if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { + for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() + { + if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { + if trait_ == actual_trait { + let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; + callback(Impl::ClosureFnTraitImpl(impl_)); + } + } + } + } +} + +pub(super) fn impl_datum( + db: &impl HirDatabase, + krate: CrateId, + impl_: Impl, +) -> Option { + match impl_ { + Impl::ImplBlock(_) => unreachable!(), + Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), + } +} + +pub(super) fn associated_ty_value( + db: &impl HirDatabase, + krate: CrateId, + data: AssocTyValue, +) -> BuiltinImplAssocTyValueData { + match data { + AssocTyValue::TypeAlias(_) => unreachable!(), + AssocTyValue::ClosureFnTraitImplOutput(data) => { + closure_fn_trait_output_assoc_ty_value(db, krate, data) + } + } +} + +fn closure_fn_trait_impl_datum( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> Option { + // for some closure |X, Y| -> Z: + // impl Fn<(T, U)> for closure V> { Output = V } + + let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait + + // validate FnOnce trait, since we need it in the assoc ty value definition + // and don't want to return a valid value only to find out later that FnOnce + // is broken + let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; + + let num_args: u16 = match &db.body(data.def.into())[data.expr] { + Expr::Lambda { args, .. } => args.len() as u16, + _ => { + log::warn!("closure for closure type {:?} not found", data); + 0 + } + }; + + let arg_ty = Ty::apply( + TypeCtor::Tuple { cardinality: num_args }, + Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), + ); + let sig_ty = Ty::apply( + TypeCtor::FnPtr { num_args }, + 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_: trait_.into(), + substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), + }; + + let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); + + Some(BuiltinImplData { + num_vars: num_args as usize + 1, + trait_ref, + where_clauses: Vec::new(), + assoc_ty_values: vec![output_ty_id], + }) +} + +fn closure_fn_trait_output_assoc_ty_value( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> BuiltinImplAssocTyValueData { + let impl_ = Impl::ClosureFnTraitImpl(data.clone()); + + let num_args: u16 = match &db.body(data.def.into())[data.expr] { + Expr::Lambda { args, .. } => args.len() as u16, + _ => { + log::warn!("closure for closure type {:?} not found", data); + 0 + } + }; + + let output_ty = Ty::Bound(num_args.into()); + + let fn_once_trait = + get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); + + let output_ty_id = db + .trait_data(fn_once_trait) + .associated_type_by_name(&name::OUTPUT_TYPE) + .expect("assoc ty value should not exist"); + + BuiltinImplAssocTyValueData { + impl_, + assoc_ty_id: output_ty_id, + num_vars: num_args as usize + 1, + value: output_ty, + } +} + +fn get_fn_trait( + db: &impl HirDatabase, + krate: CrateId, + fn_trait: super::FnTrait, +) -> Option { + let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; + match target { + LangItemTarget::TraitId(t) => Some(t), + _ => None, + } +} diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 104346ada..e3f02fa15 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -8,17 +8,16 @@ use chalk_ir::{ TypeName, UniverseIndex, }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use ra_db::CrateId; use hir_def::{ - expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId, - ImplId, Lookup, TraitId, TypeAliasId, + AssocItemId, AstItemDef, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, +}; +use ra_db::{ + salsa::{InternId, InternKey}, + CrateId, }; -use hir_expand::name; - -use ra_db::salsa::{InternId, InternKey}; -use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; +use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, @@ -395,6 +394,51 @@ where } } +impl ToChalk for builtin::BuiltinImplData { + type Chalk = chalk_rust_ir::ImplDatum; + + fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum { + let impl_type = chalk_rust_ir::ImplType::External; + let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); + + let impl_datum_bound = + chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; + let associated_ty_value_ids = + self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); + chalk_rust_ir::ImplDatum { + binders: make_binders(impl_datum_bound, self.num_vars), + impl_type, + polarity: chalk_rust_ir::Polarity::Positive, + associated_ty_value_ids, + } + } + + fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum) -> Self { + unimplemented!() + } +} + +impl ToChalk for builtin::BuiltinImplAssocTyValueData { + type Chalk = chalk_rust_ir::AssociatedTyValue; + + fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue { + let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; + + chalk_rust_ir::AssociatedTyValue { + associated_ty_id: self.assoc_ty_id.to_chalk(db), + impl_id: self.impl_.to_chalk(db), + value: make_binders(value_bound, self.num_vars), + } + } + + fn from_chalk( + _db: &impl HirDatabase, + _data: chalk_rust_ir::AssociatedTyValue, + ) -> builtin::BuiltinImplAssocTyValueData { + unimplemented!() + } +} + fn make_binders(value: T, num_vars: usize) -> chalk_ir::Binders { chalk_ir::Binders { value, @@ -456,18 +500,10 @@ where .collect(); let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { - for &fn_trait in - [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() - { - if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) { - if trait_ == actual_trait { - let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait }; - result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db)); - } - } - } - } + + builtin::get_builtin_impls(self.db, self.krate, &ty, trait_, |i| { + result.push(i.to_chalk(self.db)) + }); debug!("impls_for_trait returned {} impls", result.len()); result @@ -619,7 +655,7 @@ pub(crate) fn impl_datum_query( let impl_: Impl = from_chalk(db, impl_id); match impl_ { Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), - Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), + _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), } .unwrap_or_else(invalid_impl_datum) } @@ -700,63 +736,6 @@ fn invalid_impl_datum() -> Arc> { Arc::new(impl_datum) } -fn closure_fn_trait_impl_datum( - db: &impl HirDatabase, - krate: CrateId, - data: super::ClosureFnTraitImplData, -) -> Option>> { - // for some closure |X, Y| -> Z: - // impl Fn<(T, U)> for closure V> { Output = V } - - let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait - - // validate FnOnce trait, since we need it in the assoc ty value definition - // and don't want to return a valid value only to find out later that FnOnce - // is broken - let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; - - let num_args: u16 = match &db.body(data.def.into())[data.expr] { - Expr::Lambda { args, .. } => args.len() as u16, - _ => { - log::warn!("closure for closure type {:?} not found", data); - 0 - } - }; - - let arg_ty = Ty::apply( - TypeCtor::Tuple { cardinality: num_args }, - Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), - ); - let sig_ty = Ty::apply( - TypeCtor::FnPtr { num_args }, - 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_: trait_.into(), - substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), - }; - - let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); - - let impl_type = chalk_rust_ir::ImplType::External; - - let impl_datum_bound = chalk_rust_ir::ImplDatumBound { - trait_ref: trait_ref.to_chalk(db), - where_clauses: Vec::new(), - }; - let impl_datum = ImplDatum { - binders: make_binders(impl_datum_bound, num_args as usize + 1), - impl_type, - polarity: chalk_rust_ir::Polarity::Positive, - associated_ty_value_ids: vec![output_ty_id], - }; - Some(Arc::new(impl_datum)) -} - pub(crate) fn associated_ty_value_query( db: &impl HirDatabase, krate: CrateId, @@ -767,9 +746,7 @@ pub(crate) fn associated_ty_value_query( AssocTyValue::TypeAlias(type_alias) => { type_alias_associated_ty_value(db, krate, type_alias) } - AssocTyValue::ClosureFnTraitImplOutput(data) => { - closure_fn_trait_output_assoc_ty_value(db, krate, data) - } + _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)), } } @@ -802,53 +779,6 @@ fn type_alias_associated_ty_value( Arc::new(value) } -fn closure_fn_trait_output_assoc_ty_value( - db: &impl HirDatabase, - krate: CrateId, - data: super::ClosureFnTraitImplData, -) -> Arc> { - let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); - - let num_args: u16 = match &db.body(data.def.into())[data.expr] { - Expr::Lambda { args, .. } => args.len() as u16, - _ => { - log::warn!("closure for closure type {:?} not found", data); - 0 - } - }; - - let output_ty = Ty::Bound(num_args.into()); - - let fn_once_trait = - get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); - - let output_ty_id = db - .trait_data(fn_once_trait) - .associated_type_by_name(&name::OUTPUT_TYPE) - .expect("assoc ty value should not exist"); - - let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; - - let value = chalk_rust_ir::AssociatedTyValue { - associated_ty_id: output_ty_id.to_chalk(db), - impl_id, - value: make_binders(value_bound, num_args as usize + 1), - }; - Arc::new(value) -} - -fn get_fn_trait( - db: &impl HirDatabase, - krate: CrateId, - fn_trait: super::FnTrait, -) -> Option { - let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; - match target { - LangItemTarget::TraitId(t) => Some(t), - _ => None, - } -} - fn id_from_chalk(chalk_id: chalk_ir::RawId) -> T { T::from_intern_id(InternId::from(chalk_id.index)) } -- cgit v1.2.3 From 8e9837df21942ca12a5aece0a868ea46eb405742 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 11:50:36 +0100 Subject: Remove idx and parent generics from generics This makes `hir_def::GenericParams` flatter. The logic for re-numbering the params is moved to hir instead. --- crates/ra_hir_ty/src/traits/chalk.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index e3f02fa15..1d44320b9 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -19,8 +19,8 @@ use ra_db::{ use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ - db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, - TraitRef, Ty, TypeCtor, TypeWalk, + db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, + ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; /// This represents a trait whose name we could not resolve. @@ -547,7 +547,7 @@ pub(crate) fn associated_ty_data_query( ContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), }; - let generic_params = db.generic_params(type_alias.into()); + let generic_params = generics(db, type_alias.into()); let bound_data = chalk_rust_ir::AssociatedTyDatumBound { // FIXME add bounds and where clauses bounds: vec![], @@ -589,7 +589,7 @@ pub(crate) fn trait_datum_query( let trait_: TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); - let generic_params = db.generic_params(trait_.into()); + let generic_params = generics(db, trait_.into()); let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, @@ -626,7 +626,7 @@ pub(crate) fn struct_datum_query( let where_clauses = type_ctor .as_generic_def() .map(|generic_def| { - let generic_params = db.generic_params(generic_def.into()); + let generic_params = generics(db, generic_def.into()); let bound_vars = Substs::bound_vars(&generic_params); convert_where_clauses(db, generic_def, &bound_vars) }) @@ -669,7 +669,7 @@ fn impl_block_datum( let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); - let generic_params = db.generic_params(impl_id.into()); + let generic_params = generics(db, impl_id.into()); let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; @@ -767,7 +767,7 @@ fn type_alias_associated_ty_value( .trait_data(trait_ref.trait_) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well - let generic_params = db.generic_params(impl_id.into()); + let generic_params = generics(db, impl_id.into()); let bound_vars = Substs::bound_vars(&generic_params); let ty = db.ty(type_alias.into()).subst(&bound_vars); let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; -- cgit v1.2.3 From d6c2b92409902d9ceca8cd064026cfcc1f357cf6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 13:05:05 +0100 Subject: Refactor parameter count tracking --- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1d44320b9..1e7ff93d5 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -557,7 +557,7 @@ pub(crate) fn associated_ty_data_query( trait_id: trait_.to_chalk(db), id, name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), - binders: make_binders(bound_data, generic_params.count_params_including_parent()), + binders: make_binders(bound_data, generic_params.len()), }; Arc::new(datum) } -- cgit v1.2.3 From 7b0644d81e52d00a7a6795b187f356213ff68225 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:09:13 +0100 Subject: Switch to the new location for impls --- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1e7ff93d5..ff299f511 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -673,7 +673,7 @@ fn impl_block_datum( let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; - let impl_type = if impl_id.module(db).krate == krate { + let impl_type = if impl_id.lookup(db).container.krate == krate { chalk_rust_ir::ImplType::Local } else { chalk_rust_ir::ImplType::External -- cgit v1.2.3 From 82e9b245587046d2a1ed432225b19023adbe3245 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:34:03 +0100 Subject: Move traits to the new loc --- crates/ra_hir_ty/src/traits/chalk.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index ff299f511..fc21872b2 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,9 +9,7 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{ - AssocItemId, AstItemDef, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, -}; +use hir_def::{AssocItemId, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -593,7 +591,7 @@ pub(crate) fn trait_datum_query( let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, - upstream: trait_.module(db).krate != krate, + upstream: trait_.lookup(db).container.krate != krate, non_enumerable: true, coinductive: false, // only relevant for Chalk testing // FIXME set these flags correctly -- cgit v1.2.3 From 259c42f00e2e85594c7373166bc8467ce375a045 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 21:43:53 +0100 Subject: Add macros for known names and paths --- crates/ra_hir_ty/src/traits/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 598fd81e3..27c475a3c 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -1,7 +1,7 @@ //! This module provides the built-in trait implementations, e.g. to make //! closures implement `Fn`. use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; -use hir_expand::name; +use hir_expand::name::N; use ra_db::CrateId; use super::{AssocTyValue, Impl}; @@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum( // and don't want to return a valid value only to find out later that FnOnce // is broken let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&N![Output])?; let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value( let output_ty_id = db .trait_data(fn_once_trait) - .associated_type_by_name(&name::OUTPUT_TYPE) + .associated_type_by_name(&N![Output]) .expect("assoc ty value should not exist"); BuiltinImplAssocTyValueData { -- cgit v1.2.3 From 6911bc89a784ce72b4dfd8e0ba72bd22ce898395 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 22:01:06 +0100 Subject: Rename N! to name! --- crates/ra_hir_ty/src/traits/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 27c475a3c..cd587a338 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -1,7 +1,7 @@ //! This module provides the built-in trait implementations, e.g. to make //! closures implement `Fn`. use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; -use hir_expand::name::N; +use hir_expand::name::name; use ra_db::CrateId; use super::{AssocTyValue, Impl}; @@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum( // and don't want to return a valid value only to find out later that FnOnce // is broken let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&N![Output])?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value( let output_ty_id = db .trait_data(fn_once_trait) - .associated_type_by_name(&N![Output]) + .associated_type_by_name(&name![Output]) .expect("assoc ty value should not exist"); BuiltinImplAssocTyValueData { -- cgit v1.2.3 From 8fc20b65035d93bcc1b3a89127916bd165a8d938 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:59:50 +0100 Subject: Rename ContainerId -> AssocContainerId --- crates/ra_hir_ty/src/traits/chalk.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index fc21872b2..6a31014d8 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,7 +9,7 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{AssocItemId, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; +use hir_def::{AssocContainerId, AssocItemId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -542,7 +542,7 @@ pub(crate) fn associated_ty_data_query( debug!("associated_ty_data {:?}", id); let type_alias: TypeAliasId = from_chalk(db, id); let trait_ = match type_alias.lookup(db).container { - ContainerId::TraitId(t) => t, + AssocContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), }; let generic_params = generics(db, type_alias.into()); @@ -755,7 +755,7 @@ fn type_alias_associated_ty_value( ) -> Arc> { let type_alias_data = db.type_alias_data(type_alias); let impl_id = match type_alias.lookup(db).container { - ContainerId::ImplId(it) => it, + AssocContainerId::ImplId(it) => it, _ => panic!("assoc ty value should be in impl"), }; -- cgit v1.2.3 From f42697e54b9d0a040011cb04c266d51710e249f1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 12:29:25 +0100 Subject: Support for nested traits --- crates/ra_hir_ty/src/traits/chalk.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 6a31014d8..dd4fa9664 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,7 +9,9 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{AssocContainerId, AssocItemId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; +use hir_def::{ + AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId, +}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -591,7 +593,7 @@ pub(crate) fn trait_datum_query( let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, - upstream: trait_.lookup(db).container.krate != krate, + upstream: trait_.lookup(db).container.module(db).krate != krate, non_enumerable: true, coinductive: false, // only relevant for Chalk testing // FIXME set these flags correctly -- cgit v1.2.3 From 1234dda9ee60a19a83a9664c2e1208247566b49b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 13:47:44 +0100 Subject: Use generic ItemLoc for impls --- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index dd4fa9664..5eb032d86 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -673,7 +673,7 @@ fn impl_block_datum( let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; - let impl_type = if impl_id.lookup(db).container.krate == krate { + let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { chalk_rust_ir::ImplType::Local } else { chalk_rust_ir::ImplType::External -- cgit v1.2.3 From 67a2555f6d4c3914742fd42645ca043cf56f358b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 14:29:33 +0100 Subject: Update Chalk, clean up Chalk integration a bit --- crates/ra_hir_ty/src/traits/chalk.rs | 180 +++++++++++++++++------------------ 1 file changed, 87 insertions(+), 93 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 5eb032d86..3a91a374d 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -3,15 +3,9 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{ - cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId, - TypeName, UniverseIndex, -}; -use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; +use chalk_ir::{cast::Cast, family::ChalkIr, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; -use hir_def::{ - AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId, -}; +use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -23,9 +17,20 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; +pub type TypeFamily = chalk_ir::family::ChalkIr; // TODO use everywhere +pub type AssocTypeId = chalk_ir::AssocTypeId; +pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; +pub type TraitId = chalk_ir::TraitId; +pub type TraitDatum = chalk_rust_ir::TraitDatum; +pub type StructId = chalk_ir::StructId; +pub type StructDatum = chalk_rust_ir::StructDatum; +pub type ImplId = chalk_ir::ImplId; +pub type ImplDatum = chalk_rust_ir::ImplDatum; +pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; +pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue; + /// This represents a trait whose name we could not resolve. -const UNKNOWN_TRAIT: chalk_ir::TraitId = - chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); +const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); pub(super) trait ToChalk { type Chalk; @@ -53,7 +58,7 @@ impl ToChalk for Ty { _ => { // other TypeCtors get interned and turned into a chalk StructId let struct_id = apply_ty.ctor.to_chalk(db); - TypeName::TypeKindId(struct_id.into()) + TypeName::Struct(struct_id.into()) } }; let parameters = apply_ty.parameters.to_chalk(db); @@ -71,11 +76,13 @@ impl ToChalk for Ty { Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), Ty::Dyn(predicates) => { let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); - chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() + let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; + chalk_ir::TyData::Dyn(bounded_ty).intern() } Ty::Opaque(predicates) => { let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); - chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() + let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; + chalk_ir::TyData::Opaque(bounded_ty).intern() } Ty::Unknown => { let parameters = Vec::new(); @@ -87,10 +94,9 @@ impl ToChalk for Ty { fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk.data().clone() { chalk_ir::TyData::Apply(apply_ty) => { - // FIXME this is kind of hacky due to the fact that - // TypeName::Placeholder is a Ty::Param on our side + // TODO clean this up now that Placeholder isn't in TypeName anymore match apply_ty.name { - TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { + TypeName::Struct(struct_id) => { let ctor = from_chalk(db, struct_id); let parameters = from_chalk(db, apply_ty.parameters); Ty::Apply(ApplicationTy { ctor, parameters }) @@ -101,14 +107,12 @@ impl ToChalk for Ty { Ty::Apply(ApplicationTy { ctor, parameters }) } TypeName::Error => Ty::Unknown, - // FIXME handle TypeKindId::Trait/Type here - TypeName::TypeKindId(_) => unimplemented!(), - TypeName::Placeholder(idx) => { - assert_eq!(idx.ui, UniverseIndex::ROOT); - Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } - } } } + chalk_ir::TyData::Placeholder(idx) => { + assert_eq!(idx.ui, UniverseIndex::ROOT); + Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } + } chalk_ir::TyData::Projection(proj) => { let associated_ty = from_chalk(db, proj.associated_ty_id); let parameters = from_chalk(db, proj.parameters); @@ -118,15 +122,15 @@ impl ToChalk for Ty { chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, chalk_ir::TyData::Dyn(where_clauses) => { - assert_eq!(where_clauses.binders.len(), 1); + assert_eq!(where_clauses.bounds.binders.len(), 1); let predicates = - where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); + where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); Ty::Dyn(predicates) } chalk_ir::TyData::Opaque(where_clauses) => { - assert_eq!(where_clauses.binders.len(), 1); + assert_eq!(where_clauses.bounds.binders.len(), 1); let predicates = - where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); + where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); Ty::Opaque(predicates) } } @@ -143,9 +147,9 @@ impl ToChalk for Substs { fn from_chalk(db: &impl HirDatabase, parameters: Vec>) -> Substs { 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!(), + .map(|p| match p.ty() { + Some(ty) => from_chalk(db, ty.clone()), + None => unimplemented!(), }) .collect(); Substs(tys) @@ -168,65 +172,62 @@ impl ToChalk for TraitRef { } } -impl ToChalk for TraitId { - type Chalk = chalk_ir::TraitId; +impl ToChalk for hir_def::TraitId { + type Chalk = TraitId; - fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { + fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { chalk_ir::TraitId(id_to_chalk(self)) } - fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId { + fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { id_from_chalk(trait_id.0) } } impl ToChalk for TypeCtor { - type Chalk = chalk_ir::StructId; + type Chalk = StructId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { + fn to_chalk(self, db: &impl HirDatabase) -> StructId { db.intern_type_ctor(self).into() } - fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { + fn from_chalk(db: &impl HirDatabase, struct_id: StructId) -> TypeCtor { db.lookup_intern_type_ctor(struct_id.into()) } } impl ToChalk for Impl { - type Chalk = chalk_ir::ImplId; + type Chalk = ImplId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { + fn to_chalk(self, db: &impl HirDatabase) -> ImplId { db.intern_chalk_impl(self).into() } - fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { + fn from_chalk(db: &impl HirDatabase, impl_id: ImplId) -> Impl { db.lookup_intern_chalk_impl(impl_id.into()) } } impl ToChalk for TypeAliasId { - type Chalk = chalk_ir::TypeId; + type Chalk = AssocTypeId; - fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { - chalk_ir::TypeId(id_to_chalk(self)) + fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { + chalk_ir::AssocTypeId(id_to_chalk(self)) } - fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId { + fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { id_from_chalk(type_alias_id.0) } } impl ToChalk for AssocTyValue { - type Chalk = chalk_rust_ir::AssociatedTyValueId; + type Chalk = AssociatedTyValueId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { + fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValueId { db.intern_assoc_ty_value(self).into() } - fn from_chalk( - db: &impl HirDatabase, - assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, - ) -> AssocTyValue { + fn from_chalk(db: &impl HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) } } @@ -468,28 +469,28 @@ impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> where DB: HirDatabase, { - fn associated_ty_data(&self, id: TypeId) -> Arc> { + fn associated_ty_data(&self, id: AssocTypeId) -> Arc { self.db.associated_ty_data(id) } - fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc> { + fn trait_datum(&self, trait_id: TraitId) -> Arc { self.db.trait_datum(self.krate, trait_id) } - fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc> { + fn struct_datum(&self, struct_id: StructId) -> Arc { self.db.struct_datum(self.krate, struct_id) } - fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc> { + fn impl_datum(&self, impl_id: ImplId) -> Arc { self.db.impl_datum(self.krate, impl_id) } fn impls_for_trait( &self, - trait_id: chalk_ir::TraitId, - parameters: &[Parameter], - ) -> Vec { + trait_id: TraitId, + parameters: &[Parameter], + ) -> Vec { debug!("impls_for_trait {:?}", trait_id); if trait_id == UNKNOWN_TRAIT { return Vec::new(); } - let trait_: TraitId = from_chalk(self.db, trait_id); + let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); let mut result: Vec<_> = self .db .impls_for_trait(self.krate, trait_.into()) @@ -508,39 +509,32 @@ where debug!("impls_for_trait returned {} impls", result.len()); result } - fn impl_provided_for( - &self, - auto_trait_id: chalk_ir::TraitId, - struct_id: chalk_ir::StructId, - ) -> bool { + fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool { debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); false // FIXME } - fn type_name(&self, _id: TypeKindId) -> Identifier { - unimplemented!() - } - fn associated_ty_value( - &self, - id: chalk_rust_ir::AssociatedTyValueId, - ) -> Arc> { + fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate.into(), id) } fn custom_clauses(&self) -> Vec> { vec![] } - fn local_impls_to_coherence_check( - &self, - _trait_id: chalk_ir::TraitId, - ) -> Vec { + fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { // We don't do coherence checking (yet) unimplemented!() } + fn as_struct_id(&self, id: &TypeName) -> Option { + match id { + TypeName::Struct(struct_id) => Some(*struct_id), + _ => None, + } + } } pub(crate) fn associated_ty_data_query( db: &impl HirDatabase, - id: TypeId, -) -> Arc> { + id: AssocTypeId, +) -> Arc { debug!("associated_ty_data {:?}", id); let type_alias: TypeAliasId = from_chalk(db, id); let trait_ = match type_alias.lookup(db).container { @@ -565,8 +559,8 @@ pub(crate) fn associated_ty_data_query( pub(crate) fn trait_datum_query( db: &impl HirDatabase, krate: CrateId, - trait_id: chalk_ir::TraitId, -) -> Arc> { + trait_id: TraitId, +) -> Arc { debug!("trait_datum {:?}", trait_id); if trait_id == UNKNOWN_TRAIT { let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; @@ -586,7 +580,7 @@ pub(crate) fn trait_datum_query( associated_ty_ids: vec![], }); } - let trait_: TraitId = from_chalk(db, trait_id); + let trait_: hir_def::TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); let generic_params = generics(db, trait_.into()); @@ -616,8 +610,8 @@ pub(crate) fn trait_datum_query( pub(crate) fn struct_datum_query( db: &impl HirDatabase, krate: CrateId, - struct_id: chalk_ir::StructId, -) -> Arc> { + struct_id: StructId, +) -> Arc { debug!("struct_datum {:?}", struct_id); let type_ctor: TypeCtor = from_chalk(db, struct_id); debug!("struct {:?} = {:?}", struct_id, type_ctor); @@ -648,8 +642,8 @@ pub(crate) fn struct_datum_query( pub(crate) fn impl_datum_query( db: &impl HirDatabase, krate: CrateId, - impl_id: chalk_ir::ImplId, -) -> Arc> { + impl_id: ImplId, +) -> Arc { let _p = ra_prof::profile("impl_datum"); debug!("impl_datum {:?}", impl_id); let impl_: Impl = from_chalk(db, impl_id); @@ -663,9 +657,9 @@ pub(crate) fn impl_datum_query( fn impl_block_datum( db: &impl HirDatabase, krate: CrateId, - chalk_id: chalk_ir::ImplId, - impl_id: ImplId, -) -> Option>> { + chalk_id: ImplId, + impl_id: hir_def::ImplId, +) -> Option> { let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); @@ -721,7 +715,7 @@ fn impl_block_datum( Some(Arc::new(impl_datum)) } -fn invalid_impl_datum() -> Arc> { +fn invalid_impl_datum() -> Arc { let trait_ref = chalk_ir::TraitRef { trait_id: UNKNOWN_TRAIT, parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], @@ -754,7 +748,7 @@ fn type_alias_associated_ty_value( db: &impl HirDatabase, _krate: CrateId, type_alias: TypeAliasId, -) -> Arc> { +) -> Arc { let type_alias_data = db.type_alias_data(type_alias); let impl_id = match type_alias.lookup(db).container { AssocContainerId::ImplId(it) => it, @@ -786,25 +780,25 @@ fn id_to_chalk(salsa_id: T) -> chalk_ir::RawId { chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } } -impl From for crate::TypeCtorId { - fn from(struct_id: chalk_ir::StructId) -> Self { +impl From for crate::TypeCtorId { + fn from(struct_id: StructId) -> Self { id_from_chalk(struct_id.0) } } -impl From for chalk_ir::StructId { +impl From for StructId { fn from(type_ctor_id: crate::TypeCtorId) -> Self { chalk_ir::StructId(id_to_chalk(type_ctor_id)) } } -impl From for crate::traits::GlobalImplId { - fn from(impl_id: chalk_ir::ImplId) -> Self { +impl From for crate::traits::GlobalImplId { + fn from(impl_id: ImplId) -> Self { id_from_chalk(impl_id.0) } } -impl From for chalk_ir::ImplId { +impl From for ImplId { fn from(impl_id: crate::traits::GlobalImplId) -> Self { chalk_ir::ImplId(id_to_chalk(impl_id)) } -- cgit v1.2.3 From 6b5efe5bdab160278469417734f4bb619c7bac61 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 14:46:15 +0100 Subject: Refactor Chalk integration some more --- crates/ra_hir_ty/src/traits/chalk.rs | 148 ++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 72 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 3a91a374d..d53d3fdeb 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{cast::Cast, family::ChalkIr, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; +use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; use ra_db::{ @@ -17,7 +17,7 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; -pub type TypeFamily = chalk_ir::family::ChalkIr; // TODO use everywhere +pub type TypeFamily = chalk_ir::family::ChalkIr; pub type AssocTypeId = chalk_ir::AssocTypeId; pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; pub type TraitId = chalk_ir::TraitId; @@ -46,21 +46,11 @@ where } impl ToChalk for Ty { - type Chalk = chalk_ir::Ty; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { + type Chalk = chalk_ir::Ty; + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { match self { Ty::Apply(apply_ty) => { - let name = match apply_ty.ctor { - TypeCtor::AssociatedType(type_alias) => { - let type_id = type_alias.to_chalk(db); - TypeName::AssociatedType(type_id) - } - _ => { - // other TypeCtors get interned and turned into a chalk StructId - let struct_id = apply_ty.ctor.to_chalk(db); - TypeName::Struct(struct_id.into()) - } - }; + let name = apply_ty.ctor.to_chalk(db); let parameters = apply_ty.parameters.to_chalk(db); chalk_ir::ApplicationTy { name, parameters }.cast().intern() } @@ -70,7 +60,8 @@ impl ToChalk for Ty { chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() } Ty::Param { idx, .. } => { - PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::() + PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } + .to_ty::() } Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), @@ -91,24 +82,16 @@ impl ToChalk for Ty { } } } - fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { + fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk.data().clone() { - chalk_ir::TyData::Apply(apply_ty) => { - // TODO clean this up now that Placeholder isn't in TypeName anymore - match apply_ty.name { - TypeName::Struct(struct_id) => { - let ctor = from_chalk(db, struct_id); - let parameters = from_chalk(db, apply_ty.parameters); - Ty::Apply(ApplicationTy { ctor, parameters }) - } - TypeName::AssociatedType(type_id) => { - let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); - let parameters = from_chalk(db, apply_ty.parameters); - Ty::Apply(ApplicationTy { ctor, parameters }) - } - TypeName::Error => Ty::Unknown, + chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { + TypeName::Error => Ty::Unknown, + _ => { + let ctor = from_chalk(db, apply_ty.name); + let parameters = from_chalk(db, apply_ty.parameters); + Ty::Apply(ApplicationTy { ctor, parameters }) } - } + }, chalk_ir::TyData::Placeholder(idx) => { assert_eq!(idx.ui, UniverseIndex::ROOT); Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } @@ -138,13 +121,16 @@ impl ToChalk for Ty { } impl ToChalk for Substs { - type Chalk = Vec>; + type Chalk = Vec>; - fn to_chalk(self, db: &impl HirDatabase) -> Vec> { + fn to_chalk(self, db: &impl HirDatabase) -> Vec> { self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() } - fn from_chalk(db: &impl HirDatabase, parameters: Vec>) -> Substs { + fn from_chalk( + db: &impl HirDatabase, + parameters: Vec>, + ) -> Substs { let tys = parameters .into_iter() .map(|p| match p.ty() { @@ -157,15 +143,15 @@ impl ToChalk for Substs { } impl ToChalk for TraitRef { - type Chalk = chalk_ir::TraitRef; + type Chalk = chalk_ir::TraitRef; - fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { + fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { let trait_id = self.trait_.to_chalk(db); let parameters = self.substs.to_chalk(db); chalk_ir::TraitRef { trait_id, parameters } } - fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { + fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { let trait_ = from_chalk(db, trait_ref.trait_id); let substs = from_chalk(db, trait_ref.parameters); TraitRef { trait_, substs } @@ -185,14 +171,31 @@ impl ToChalk for hir_def::TraitId { } impl ToChalk for TypeCtor { - type Chalk = StructId; + type Chalk = TypeName; - fn to_chalk(self, db: &impl HirDatabase) -> StructId { - db.intern_type_ctor(self).into() + fn to_chalk(self, db: &impl HirDatabase) -> TypeName { + match self { + TypeCtor::AssociatedType(type_alias) => { + let type_id = type_alias.to_chalk(db); + TypeName::AssociatedType(type_id) + } + _ => { + // other TypeCtors get interned and turned into a chalk StructId + let struct_id = db.intern_type_ctor(self).into(); + TypeName::Struct(struct_id) + } + } } - fn from_chalk(db: &impl HirDatabase, struct_id: StructId) -> TypeCtor { - db.lookup_intern_type_ctor(struct_id.into()) + fn from_chalk(db: &impl HirDatabase, type_name: TypeName) -> TypeCtor { + match type_name { + TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), + TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), + TypeName::Error => { + // this should not be reached, since we don't represent TypeName::Error with TypeCtor + unreachable!() + } + } } } @@ -233,9 +236,9 @@ impl ToChalk for AssocTyValue { } impl ToChalk for GenericPredicate { - type Chalk = chalk_ir::QuantifiedWhereClause; + type Chalk = chalk_ir::QuantifiedWhereClause; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { match self { GenericPredicate::Implemented(trait_ref) => { make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) @@ -259,7 +262,7 @@ impl ToChalk for GenericPredicate { fn from_chalk( db: &impl HirDatabase, - where_clause: chalk_ir::QuantifiedWhereClause, + where_clause: chalk_ir::QuantifiedWhereClause, ) -> GenericPredicate { match where_clause.value { chalk_ir::WhereClause::Implemented(tr) => { @@ -279,9 +282,9 @@ impl ToChalk for GenericPredicate { } impl ToChalk for ProjectionTy { - type Chalk = chalk_ir::ProjectionTy; + type Chalk = chalk_ir::ProjectionTy; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { chalk_ir::ProjectionTy { associated_ty_id: self.associated_ty.to_chalk(db), parameters: self.parameters.to_chalk(db), @@ -290,7 +293,7 @@ impl ToChalk for ProjectionTy { fn from_chalk( db: &impl HirDatabase, - projection_ty: chalk_ir::ProjectionTy, + projection_ty: chalk_ir::ProjectionTy, ) -> ProjectionTy { ProjectionTy { associated_ty: from_chalk(db, projection_ty.associated_ty_id), @@ -300,31 +303,31 @@ impl ToChalk for ProjectionTy { } impl ToChalk for super::ProjectionPredicate { - type Chalk = chalk_ir::Normalize; + type Chalk = chalk_ir::Normalize; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { chalk_ir::Normalize { projection: self.projection_ty.to_chalk(db), ty: self.ty.to_chalk(db), } } - fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { + fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { unimplemented!() } } impl ToChalk for Obligation { - type Chalk = chalk_ir::DomainGoal; + type Chalk = chalk_ir::DomainGoal; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { match self { Obligation::Trait(tr) => tr.to_chalk(db).cast(), Obligation::Projection(pr) => pr.to_chalk(db).cast(), } } - fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { + fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { unimplemented!() } } @@ -348,16 +351,17 @@ where } impl ToChalk for Arc { - type Chalk = chalk_ir::Environment; + type Chalk = chalk_ir::Environment; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment { let mut clauses = Vec::new(); for pred in &self.predicates { if pred.is_error() { // for env, we just ignore errors continue; } - let program_clause: chalk_ir::ProgramClause = pred.clone().to_chalk(db).cast(); + let program_clause: chalk_ir::ProgramClause = + pred.clone().to_chalk(db).cast(); clauses.push(program_clause.into_from_env_clause()); } chalk_ir::Environment::new().add_clauses(clauses) @@ -365,7 +369,7 @@ impl ToChalk for Arc { fn from_chalk( _db: &impl HirDatabase, - _env: chalk_ir::Environment, + _env: chalk_ir::Environment, ) -> Arc { unimplemented!() } @@ -373,7 +377,7 @@ impl ToChalk for Arc { impl ToChalk for super::InEnvironment where - T::Chalk: chalk_ir::family::HasTypeFamily, + T::Chalk: chalk_ir::family::HasTypeFamily, { type Chalk = chalk_ir::InEnvironment; @@ -396,9 +400,9 @@ where } impl ToChalk for builtin::BuiltinImplData { - type Chalk = chalk_rust_ir::ImplDatum; + type Chalk = ImplDatum; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum { + fn to_chalk(self, db: &impl HirDatabase) -> ImplDatum { let impl_type = chalk_rust_ir::ImplType::External; let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); @@ -414,15 +418,15 @@ impl ToChalk for builtin::BuiltinImplData { } } - fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum) -> Self { + fn from_chalk(_db: &impl HirDatabase, _data: ImplDatum) -> Self { unimplemented!() } } impl ToChalk for builtin::BuiltinImplAssocTyValueData { - type Chalk = chalk_rust_ir::AssociatedTyValue; + type Chalk = AssociatedTyValue; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue { + fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValue { let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; chalk_rust_ir::AssociatedTyValue { @@ -434,7 +438,7 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData { fn from_chalk( _db: &impl HirDatabase, - _data: chalk_rust_ir::AssociatedTyValue, + _data: AssociatedTyValue, ) -> builtin::BuiltinImplAssocTyValueData { unimplemented!() } @@ -451,7 +455,7 @@ fn convert_where_clauses( db: &impl HirDatabase, def: GenericDefId, substs: &Substs, -) -> Vec> { +) -> Vec> { let generic_predicates = db.generic_predicates(def); let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { @@ -465,7 +469,7 @@ fn convert_where_clauses( result } -impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> +impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> where DB: HirDatabase, { @@ -516,7 +520,7 @@ where fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate.into(), id) } - fn custom_clauses(&self) -> Vec> { + fn custom_clauses(&self) -> Vec> { vec![] } fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { @@ -613,7 +617,7 @@ pub(crate) fn struct_datum_query( struct_id: StructId, ) -> Arc { debug!("struct_datum {:?}", struct_id); - let type_ctor: TypeCtor = from_chalk(db, struct_id); + let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id)); debug!("struct {:?} = {:?}", struct_id, type_ctor); let num_params = type_ctor.num_ty_params(db); let upstream = type_ctor.krate(db) != Some(krate); @@ -733,8 +737,8 @@ fn invalid_impl_datum() -> Arc { pub(crate) fn associated_ty_value_query( db: &impl HirDatabase, krate: CrateId, - id: chalk_rust_ir::AssociatedTyValueId, -) -> Arc> { + id: AssociatedTyValueId, +) -> Arc { let data: AssocTyValue = from_chalk(db, id); match data { AssocTyValue::TypeAlias(type_alias) => { -- cgit v1.2.3 From 4053fcfca0e33f133c53fa755c1b1bcc0b4c11bb Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 15:00:44 +0100 Subject: Introduce our own Chalk TypeFamily, instead of using ChalkIr It's not very different, except we can directly use Salsa IDs instead of casting them. This means we need to refactor the handling of errors to get rid of UNKNOWN_TRAIT though. --- crates/ra_hir_ty/src/traits/builtin.rs | 49 +++++++---- crates/ra_hir_ty/src/traits/chalk.rs | 156 +++++++++++++++++++-------------- 2 files changed, 122 insertions(+), 83 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index cd587a338..dd41176f0 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls( trait_: TraitId, mut callback: impl FnMut(Impl), ) { + // Note: since impl_datum needs to be infallible, we need to make sure here + // that we have all prerequisites to build the respective impls. if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() { if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { if trait_ == actual_trait { let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; - callback(Impl::ClosureFnTraitImpl(impl_)); + if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { + callback(Impl::ClosureFnTraitImpl(impl_)); + } } } } } } -pub(super) fn impl_datum( - db: &impl HirDatabase, - krate: CrateId, - impl_: Impl, -) -> Option { +pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { match impl_ { Impl::ImplBlock(_) => unreachable!(), Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), @@ -65,21 +65,38 @@ pub(super) fn associated_ty_value( } } +fn check_closure_fn_trait_impl_prerequisites( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> bool { + // the respective Fn/FnOnce/FnMut trait needs to exist + if get_fn_trait(db, krate, data.fn_trait).is_none() { + return false; + } + + // FIXME: there are more assumptions that we should probably check here: + // the traits having no type params, FnOnce being a supertrait + + // the FnOnce trait needs to exist and have an assoc type named Output + let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) { + Some(t) => t, + None => return false, + }; + db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some() +} + fn closure_fn_trait_impl_datum( db: &impl HirDatabase, krate: CrateId, data: super::ClosureFnTraitImplData, -) -> Option { +) -> BuiltinImplData { // for some closure |X, Y| -> Z: // impl Fn<(T, U)> for closure V> { Output = V } - let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait - - // validate FnOnce trait, since we need it in the assoc ty value definition - // and don't want to return a valid value only to find out later that FnOnce - // is broken - let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; + let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait + // the existence of the Fn trait has been checked before + .expect("fn trait for closure impl missing"); let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum( let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); - Some(BuiltinImplData { + BuiltinImplData { num_vars: num_args as usize + 1, trait_ref, where_clauses: Vec::new(), assoc_ty_values: vec![output_ty_id], - }) + } } fn closure_fn_trait_output_assoc_ty_value( diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index d53d3fdeb..9e38337e5 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -1,5 +1,5 @@ //! Conversion code from/to Chalk. -use std::sync::Arc; +use std::{fmt, sync::Arc}; use log::debug; @@ -17,7 +17,73 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; -pub type TypeFamily = chalk_ir::family::ChalkIr; +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct TypeFamily {} + +impl chalk_ir::family::TypeFamily for TypeFamily { + type InternedType = Box>; + type InternedLifetime = chalk_ir::LifetimeData; + type InternedParameter = chalk_ir::ParameterData; + type DefId = InternId; + + // FIXME: implement these + fn debug_struct_id( + _type_kind_id: chalk_ir::StructId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_trait_id( + _type_kind_id: chalk_ir::TraitId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_assoc_type_id( + _id: chalk_ir::AssocTypeId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_projection( + _projection: &chalk_ir::ProjectionTy, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn intern_ty(ty: chalk_ir::TyData) -> Box> { + Box::new(ty) + } + + fn ty_data(ty: &Box>) -> &chalk_ir::TyData { + ty + } + + fn intern_lifetime(lifetime: chalk_ir::LifetimeData) -> chalk_ir::LifetimeData { + lifetime + } + + fn lifetime_data(lifetime: &chalk_ir::LifetimeData) -> &chalk_ir::LifetimeData { + lifetime + } + + fn intern_parameter(parameter: chalk_ir::ParameterData) -> chalk_ir::ParameterData { + parameter + } + + fn parameter_data(parameter: &chalk_ir::ParameterData) -> &chalk_ir::ParameterData { + parameter + } +} + +impl chalk_ir::family::HasTypeFamily for TypeFamily { + type TypeFamily = Self; +} + pub type AssocTypeId = chalk_ir::AssocTypeId; pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; pub type TraitId = chalk_ir::TraitId; @@ -29,9 +95,6 @@ pub type ImplDatum = chalk_rust_ir::ImplDatum; pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue; -/// This represents a trait whose name we could not resolve. -const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); - pub(super) trait ToChalk { type Chalk; fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; @@ -162,11 +225,11 @@ impl ToChalk for hir_def::TraitId { type Chalk = TraitId; fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { - chalk_ir::TraitId(id_to_chalk(self)) + chalk_ir::TraitId(self.as_intern_id()) } fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { - id_from_chalk(trait_id.0) + InternKey::from_intern_id(trait_id.0) } } @@ -215,11 +278,11 @@ impl ToChalk for TypeAliasId { type Chalk = AssocTypeId; fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { - chalk_ir::AssocTypeId(id_to_chalk(self)) + chalk_ir::AssocTypeId(self.as_intern_id()) } fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { - id_from_chalk(type_alias_id.0) + InternKey::from_intern_id(type_alias_id.0) } } @@ -250,13 +313,7 @@ impl ToChalk for GenericPredicate { }), 0, ), - GenericPredicate::Error => { - let impossible_trait_ref = chalk_ir::TraitRef { - trait_id: UNKNOWN_TRAIT, - parameters: vec![Ty::Unknown.to_chalk(db).cast()], - }; - make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) - } + GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), } } @@ -266,10 +323,6 @@ impl ToChalk for GenericPredicate { ) -> GenericPredicate { match where_clause.value { chalk_ir::WhereClause::Implemented(tr) => { - if tr.trait_id == UNKNOWN_TRAIT { - // FIXME we need an Error enum on the Chalk side to avoid this - return GenericPredicate::Error; - } GenericPredicate::Implemented(from_chalk(db, tr)) } chalk_ir::WhereClause::ProjectionEq(projection_eq) => { @@ -460,9 +513,8 @@ fn convert_where_clauses( let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { if pred.is_error() { - // HACK: Return just the single predicate (which is always false - // anyway), otherwise Chalk can easily get into slow situations - return vec![pred.clone().subst(substs).to_chalk(db)]; + // skip errored predicates completely + continue; } result.push(pred.clone().subst(substs).to_chalk(db)); } @@ -491,10 +543,11 @@ where parameters: &[Parameter], ) -> Vec { debug!("impls_for_trait {:?}", trait_id); - if trait_id == UNKNOWN_TRAIT { - return Vec::new(); - } let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); + + // Note: Since we're using impls_for_trait, only impls where the trait + // can be resolved should ever reach Chalk. `impl_datum` relies on that + // and will panic if the trait can't be resolved. let mut result: Vec<_> = self .db .impls_for_trait(self.krate, trait_.into()) @@ -566,24 +619,6 @@ pub(crate) fn trait_datum_query( trait_id: TraitId, ) -> Arc { debug!("trait_datum {:?}", trait_id); - if trait_id == UNKNOWN_TRAIT { - let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; - - let flags = chalk_rust_ir::TraitFlags { - auto: false, - marker: false, - upstream: true, - fundamental: false, - non_enumerable: true, - coinductive: false, - }; - return Arc::new(TraitDatum { - id: trait_id, - binders: make_binders(trait_datum_bound, 1), - flags, - associated_ty_ids: vec![], - }); - } let trait_: hir_def::TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); @@ -653,9 +688,8 @@ pub(crate) fn impl_datum_query( let impl_: Impl = from_chalk(db, impl_id); match impl_ { Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), - _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), + _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)), } - .unwrap_or_else(invalid_impl_datum) } fn impl_block_datum( @@ -663,8 +697,11 @@ fn impl_block_datum( krate: CrateId, chalk_id: ImplId, impl_id: hir_def::ImplId, -) -> Option> { - let trait_ref = db.impl_trait(impl_id)?; +) -> Arc { + let trait_ref = db + .impl_trait(impl_id) + // ImplIds for impls where the trait ref can't be resolved should never reach Chalk + .expect("invalid impl passed to Chalk"); let impl_data = db.impl_data(impl_id); let generic_params = generics(db, impl_id.into()); @@ -716,21 +753,6 @@ fn impl_block_datum( polarity, associated_ty_value_ids, }; - Some(Arc::new(impl_datum)) -} - -fn invalid_impl_datum() -> Arc { - let trait_ref = chalk_ir::TraitRef { - trait_id: UNKNOWN_TRAIT, - parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], - }; - let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; - let impl_datum = ImplDatum { - binders: make_binders(impl_datum_bound, 1), - impl_type: chalk_rust_ir::ImplType::External, - polarity: chalk_rust_ir::Polarity::Positive, - associated_ty_value_ids: Vec::new(), - }; Arc::new(impl_datum) } @@ -786,25 +808,25 @@ fn id_to_chalk(salsa_id: T) -> chalk_ir::RawId { impl From for crate::TypeCtorId { fn from(struct_id: StructId) -> Self { - id_from_chalk(struct_id.0) + InternKey::from_intern_id(struct_id.0) } } impl From for StructId { fn from(type_ctor_id: crate::TypeCtorId) -> Self { - chalk_ir::StructId(id_to_chalk(type_ctor_id)) + chalk_ir::StructId(type_ctor_id.as_intern_id()) } } impl From for crate::traits::GlobalImplId { fn from(impl_id: ImplId) -> Self { - id_from_chalk(impl_id.0) + InternKey::from_intern_id(impl_id.0) } } impl From for ImplId { fn from(impl_id: crate::traits::GlobalImplId) -> Self { - chalk_ir::ImplId(id_to_chalk(impl_id)) + chalk_ir::ImplId(impl_id.as_intern_id()) } } -- cgit v1.2.3 From 1f7f4578f72721c1b0e17e8405f986fd2ce89aaf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 19:15:06 +0100 Subject: Filter out error predicates in type bounds as well --- crates/ra_hir_ty/src/traits/chalk.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir_ty/src/traits') diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 9e38337e5..555930c9b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -129,12 +129,22 @@ impl ToChalk for Ty { Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), Ty::Dyn(predicates) => { - let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); + let where_clauses = predicates + .iter() + .filter(|p| !p.is_error()) + .cloned() + .map(|p| p.to_chalk(db)) + .collect(); let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Dyn(bounded_ty).intern() } Ty::Opaque(predicates) => { - let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); + let where_clauses = predicates + .iter() + .filter(|p| !p.is_error()) + .cloned() + .map(|p| p.to_chalk(db)) + .collect(); let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Opaque(bounded_ty).intern() } -- cgit v1.2.3