Move synstructure hack out of ItemTree lowering

This commit is contained in:
Jonas Schievink 2021-12-08 15:44:52 +01:00
parent 77f2d34930
commit c0a30ff21d
5 changed files with 58 additions and 12 deletions

View file

@ -255,7 +255,7 @@ impl ImplData {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstData {
/// const _: () = ();
/// `None` for `const _: () = ();`
pub name: Option<Name>,
pub type_ref: Interned<TypeRef>,
pub visibility: RawVisibility,

View file

@ -648,7 +648,7 @@ pub struct Enum {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Const {
/// const _: () = ();
/// `None` for `const _: () = ();`
pub name: Option<Name>,
pub visibility: RawVisibilityId,
pub type_ref: Interned<TypeRef>,

View file

@ -375,12 +375,7 @@ impl<'a> Ctx<'a> {
}
fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
let mut name = konst.name().map(|it| it.as_name());
if name.as_ref().map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) {
// FIXME: this is a hack to treat consts generated by synstructure as unnamed
// remove this some time in the future
name = None;
}
let name = konst.name().map(|it| it.as_name());
let type_ref = self.lower_type_ref_opt(konst.ty());
let visibility = self.lower_visibility(konst);
let ast_id = self.source_ast_id_map.ast_id(konst);

View file

@ -8,8 +8,9 @@ use arrayvec::ArrayVec;
use base_db::{CrateId, Edition};
use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
use hir_def::{
lang_item::LangItemTarget, nameres::DefMap, AssocItemId, BlockId, FunctionId, GenericDefId,
HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId,
item_scope::ItemScope, lang_item::LangItemTarget, nameres::DefMap, AssocItemId, BlockId,
ConstId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId,
ModuleId, TraitId,
};
use hir_expand::name::Name;
use rustc_hash::{FxHashMap, FxHashSet};
@ -177,7 +178,7 @@ impl TraitImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
for konst in module_data.scope.unnamed_consts() {
for konst in collect_unnamed_consts(db, &module_data.scope) {
let body = db.body(konst.into());
for (_, block_def_map) in body.blocks(db.upcast()) {
self.collect_def_map(db, &block_def_map);
@ -297,7 +298,7 @@ impl InherentImpls {
// To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
for konst in module_data.scope.unnamed_consts() {
for konst in collect_unnamed_consts(db, &module_data.scope) {
let body = db.body(konst.into());
for (_, block_def_map) in body.blocks(db.upcast()) {
self.collect_def_map(db, &block_def_map);
@ -318,6 +319,34 @@ impl InherentImpls {
}
}
fn collect_unnamed_consts<'a>(
db: &'a dyn HirDatabase,
scope: &'a ItemScope,
) -> impl Iterator<Item = ConstId> + 'a {
let unnamed_consts = scope.unnamed_consts();
// FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those.
// Should be removed once synstructure stops doing that.
let synstructure_hack_consts = scope.values().filter_map(|(item, _)| match item {
ModuleDefId::ConstId(id) => {
let loc = id.lookup(db.upcast());
let item_tree = loc.id.item_tree(db.upcast());
if item_tree[loc.id.value]
.name
.as_ref()
.map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_"))
{
Some(id)
} else {
None
}
}
_ => None,
});
unnamed_consts.chain(synstructure_hack_consts)
}
pub fn def_crates(
db: &dyn HirDatabase,
ty: &Ty,

View file

@ -1248,6 +1248,28 @@ fn f() {
);
}
#[test]
fn trait_impl_in_synstructure_const() {
check_types(
r#"
struct S;
trait Tr {
fn method(&self) -> u16;
}
const _DERIVE_Tr_: () = {
impl Tr for S {}
};
fn f() {
S.method();
//^^^^^^^^^^ u16
}
"#,
);
}
#[test]
fn inherent_impl_in_unnamed_const() {
check_types(