Handle auto traits & negative impls

We don't pass field types to Chalk yet though, so the auto trait inference won't
be correct.
This commit is contained in:
Florian Diebold 2019-05-07 18:53:16 +02:00
parent 7744cd41e2
commit d6dc75f9f2
5 changed files with 48 additions and 8 deletions

View file

@ -703,6 +703,10 @@ impl Trait {
TraitRef::for_trait(db, self) 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 { pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
let r = self.module(db).resolver(db); let r = self.module(db).resolver(db);
// add generic params, if present // add generic params, if present

View file

@ -93,6 +93,10 @@ impl ImplBlock {
db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() 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 { pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
let r = self.module().resolver(db); let r = self.module().resolver(db);
// add generic params, if present // add generic params, if present
@ -108,6 +112,7 @@ pub struct ImplData {
target_trait: Option<TypeRef>, target_trait: Option<TypeRef>,
target_type: TypeRef, target_type: TypeRef,
items: Vec<ImplItem>, items: Vec<ImplItem>,
negative: bool,
} }
impl ImplData { impl ImplData {
@ -120,6 +125,7 @@ impl ImplData {
let target_trait = node.target_trait().map(TypeRef::from_ast); let target_trait = node.target_trait().map(TypeRef::from_ast);
let target_type = TypeRef::from_ast_opt(node.target_type()); let target_type = TypeRef::from_ast_opt(node.target_type());
let ctx = LocationCtx::new(db, module, file_id); let ctx = LocationCtx::new(db, module, file_id);
let negative = node.is_negative();
let items = if let Some(item_list) = node.item_list() { let items = if let Some(item_list) = node.item_list() {
item_list item_list
.impl_items() .impl_items()
@ -132,7 +138,7 @@ impl ImplData {
} else { } else {
Vec::new() Vec::new()
}; };
ImplData { target_trait, target_type, items } ImplData { target_trait, target_type, items, negative }
} }
pub fn target_trait(&self) -> Option<&TypeRef> { pub fn target_trait(&self) -> Option<&TypeRef> {

View file

@ -11,6 +11,7 @@ use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationC
pub struct TraitData { pub struct TraitData {
name: Option<Name>, name: Option<Name>,
items: Vec<TraitItem>, items: Vec<TraitItem>,
auto: bool,
} }
impl TraitData { impl TraitData {
@ -19,6 +20,7 @@ impl TraitData {
let name = node.name().map(|n| n.as_name()); let name = node.name().map(|n| n.as_name());
let module = tr.module(db); let module = tr.module(db);
let ctx = LocationCtx::new(db, module, file_id); let ctx = LocationCtx::new(db, module, file_id);
let auto = node.is_auto();
let items = if let Some(item_list) = node.item_list() { let items = if let Some(item_list) = node.item_list() {
item_list item_list
.impl_items() .impl_items()
@ -31,7 +33,7 @@ impl TraitData {
} else { } else {
Vec::new() Vec::new()
}; };
Arc::new(TraitData { name, items }) Arc::new(TraitData { name, items, auto })
} }
pub(crate) fn name(&self) -> &Option<Name> { pub(crate) fn name(&self) -> &Option<Name> {
@ -41,6 +43,10 @@ impl TraitData {
pub(crate) fn items(&self) -> &[TraitItem] { pub(crate) fn items(&self) -> &[TraitItem] {
&self.items &self.items
} }
pub(crate) fn is_auto(&self) -> bool {
self.auto
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View file

@ -12,7 +12,9 @@ use ra_db::salsa::{InternId, InternKey};
use crate::{ use crate::{
Trait, HasGenericParams, ImplBlock, Trait, HasGenericParams, ImplBlock,
db::HirDatabase, 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; use super::ChalkContext;
@ -232,10 +234,10 @@ where
let bound_vars = Substs::bound_vars(&generic_params); let bound_vars = Substs::bound_vars(&generic_params);
let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db); let trait_ref = trait_.trait_ref(self.db).subst(&bound_vars).to_chalk(self.db);
let flags = chalk_rust_ir::TraitFlags { let flags = chalk_rust_ir::TraitFlags {
// FIXME set these flags correctly auto: trait_.is_auto(self.db),
auto: false,
marker: false,
upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), upstream: trait_.module(self.db).krate(self.db) != Some(self.krate),
// FIXME set these flags correctly
marker: false,
fundamental: false, fundamental: false,
}; };
let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars);
@ -329,9 +331,21 @@ where
chalk_rust_ir::ImplType::External chalk_rust_ir::ImplType::External
}; };
let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars); 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 { let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
// FIXME handle negative impls (impl !Sync for Foo) trait_ref: if negative {
trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref)
} else {
chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref)
},
where_clauses, where_clauses,
associated_ty_values: Vec::new(), // FIXME add associated type values associated_ty_values: Vec::new(), // FIXME add associated type values
impl_type, impl_type,

View file

@ -170,6 +170,10 @@ impl ast::ImplBlock {
let second = types.next(); let second = types.next();
(first, second) (first, second)
} }
pub fn is_negative(&self) -> bool {
self.syntax().children_with_tokens().any(|t| t.kind() == EXCL)
}
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -348,3 +352,9 @@ impl ast::WherePred {
.find(|it| it.kind() == LIFETIME) .find(|it| it.kind() == LIFETIME)
} }
} }
impl ast::TraitDef {
pub fn is_auto(&self) -> bool {
self.syntax().children_with_tokens().any(|t| t.kind() == AUTO_KW)
}
}