mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
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:
parent
7744cd41e2
commit
d6dc75f9f2
5 changed files with 48 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue