From d6dc75f9f22b73faf8c526be69ca43e52d6db1bf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 7 May 2019 18:53:16 +0200 Subject: Handle auto traits & negative impls We don't pass field types to Chalk yet though, so the auto trait inference won't be correct. --- crates/ra_hir/src/code_model_api.rs | 4 ++++ crates/ra_hir/src/impl_block.rs | 8 +++++++- crates/ra_hir/src/traits.rs | 8 +++++++- crates/ra_hir/src/ty/traits/chalk.rs | 24 +++++++++++++++++++----- 4 files changed, 37 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 55e1793c5..0c4a80bfa 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -703,6 +703,10 @@ impl Trait { TraitRef::for_trait(db, self) } + pub fn is_auto(self, db: &impl DefDatabase) -> bool { + self.trait_data(db).is_auto() + } + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let r = self.module(db).resolver(db); // add generic params, if present diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index a8a466e43..b7dd775f1 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -93,6 +93,10 @@ impl ImplBlock { db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() } + pub fn is_negative(&self, db: &impl DefDatabase) -> bool { + db.impls_in_module(self.module).impls[self.impl_id].negative + } + pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { let r = self.module().resolver(db); // add generic params, if present @@ -108,6 +112,7 @@ pub struct ImplData { target_trait: Option, target_type: TypeRef, items: Vec, + negative: bool, } impl ImplData { @@ -120,6 +125,7 @@ impl ImplData { let target_trait = node.target_trait().map(TypeRef::from_ast); let target_type = TypeRef::from_ast_opt(node.target_type()); let ctx = LocationCtx::new(db, module, file_id); + let negative = node.is_negative(); let items = if let Some(item_list) = node.item_list() { item_list .impl_items() @@ -132,7 +138,7 @@ impl ImplData { } else { Vec::new() }; - ImplData { target_trait, target_type, items } + ImplData { target_trait, target_type, items, negative } } pub fn target_trait(&self) -> Option<&TypeRef> { diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs index 15f0977b7..dfe883fa4 100644 --- a/crates/ra_hir/src/traits.rs +++ b/crates/ra_hir/src/traits.rs @@ -11,6 +11,7 @@ use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationC pub struct TraitData { name: Option, items: Vec, + auto: bool, } impl TraitData { @@ -19,6 +20,7 @@ impl TraitData { let name = node.name().map(|n| n.as_name()); let module = tr.module(db); let ctx = LocationCtx::new(db, module, file_id); + let auto = node.is_auto(); let items = if let Some(item_list) = node.item_list() { item_list .impl_items() @@ -31,7 +33,7 @@ impl TraitData { } else { Vec::new() }; - Arc::new(TraitData { name, items }) + Arc::new(TraitData { name, items, auto }) } pub(crate) fn name(&self) -> &Option { @@ -41,6 +43,10 @@ impl TraitData { pub(crate) fn items(&self) -> &[TraitItem] { &self.items } + + pub(crate) fn is_auto(&self) -> bool { + self.auto + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 8fa0ba7a5..027c5ec4c 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -12,7 +12,9 @@ use ra_db::salsa::{InternId, InternKey}; use crate::{ Trait, HasGenericParams, ImplBlock, db::HirDatabase, - ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate}, generics::GenericDef, ty::CallableDef, + ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef}, + ty::display::HirDisplay, + generics::GenericDef, }; use super::ChalkContext; @@ -232,10 +234,10 @@ where let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); let flags = chalk_rust_ir::TraitFlags { + auto: trait_.is_auto(self.db), + upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), // FIXME set these flags correctly - auto: false, marker: false, - upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), fundamental: false, }; let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); @@ -329,9 +331,21 @@ where chalk_rust_ir::ImplType::External }; let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars); + let negative = impl_block.is_negative(self.db); + debug!( + "impl {:?}: {}{} where {:?}", + impl_id, + if negative { "!" } else { "" }, + trait_ref.display(self.db), + where_clauses + ); + let trait_ref = trait_ref.to_chalk(self.db); let impl_datum_bound = chalk_rust_ir::ImplDatumBound { - // FIXME handle negative impls (impl !Sync for Foo) - trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), + trait_ref: if negative { + chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref) + } else { + chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref) + }, where_clauses, associated_ty_values: Vec::new(), // FIXME add associated type values impl_type, -- cgit v1.2.3