Merge commit 'a9116523604c998e7781f60d3b5a6f586e0414a9' into sync-from-ra

This commit is contained in:
Laurențiu Nicola 2024-01-21 16:53:06 +02:00
commit 595b4c3c32
315 changed files with 7088 additions and 4415 deletions

View File

@ -8,6 +8,7 @@ end_of_line = lf
insert_final_newline = true insert_final_newline = true
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
max_line_length = 100
[*.md] [*.md]
indent_size = 2 indent_size = 2

View File

@ -160,9 +160,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chalk-derive" name = "chalk-derive"
version = "0.95.0" version = "0.96.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3" checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -172,9 +172,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-ir" name = "chalk-ir"
version = "0.95.0" version = "0.96.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484" checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"chalk-derive", "chalk-derive",
@ -183,9 +183,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-recursive" name = "chalk-recursive"
version = "0.95.0" version = "0.96.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847" checksum = "4c4559e5c9b200240453b07d893f9c3c74413b53b0d33cbe272c68b0b77aa1c3"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
@ -196,9 +196,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-solve" name = "chalk-solve"
version = "0.95.0" version = "0.96.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6" checksum = "0882e68ce9eb5a0a2413806538494d19df6ee520ab17d1faf489e952f32e98b8"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
@ -1001,9 +1001,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.6.4" version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]] [[package]]
name = "memmap2" name = "memmap2"
@ -1532,6 +1532,7 @@ dependencies = [
"lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lsp-types", "lsp-types",
"mbe", "mbe",
"memchr",
"mimalloc", "mimalloc",
"nohash-hasher", "nohash-hasher",
"num_cpus", "num_cpus",
@ -1712,9 +1713,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]] [[package]]
name = "smol_str" name = "smol_str"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49"
dependencies = [ dependencies = [
"serde", "serde",
] ]

View File

@ -105,7 +105,7 @@ dissimilar = "1.0.7"
either = "1.9.0" either = "1.9.0"
expect-test = "1.4.0" expect-test = "1.4.0"
hashbrown = { version = "0.14", features = [ hashbrown = { version = "0.14", features = [
"inline-more", "inline-more",
], default-features = false } ], default-features = false }
indexmap = "2.1.0" indexmap = "2.1.0"
itertools = "0.12.0" itertools = "0.12.0"
@ -118,11 +118,11 @@ semver = "1.0.14"
serde = { version = "1.0.192", features = ["derive"] } serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108" serde_json = "1.0.108"
smallvec = { version = "1.10.0", features = [ smallvec = { version = "1.10.0", features = [
"const_new", "const_new",
"union", "union",
"const_generics", "const_generics",
] } ] }
smol_str = "0.2.0" smol_str = "0.2.1"
text-size = "1.1.1" text-size = "1.1.1"
tracing = "0.1.40" tracing = "0.1.40"
tracing-tree = "0.3.0" tracing-tree = "0.3.0"
@ -138,8 +138,63 @@ xshell = "0.2.5"
# We need to freeze the version of the crate, as the raw-api feature is considered unstable # We need to freeze the version of the crate, as the raw-api feature is considered unstable
dashmap = { version = "=5.5.3", features = ["raw-api"] } dashmap = { version = "=5.5.3", features = ["raw-api"] }
[workspace.lints.rust]
rust_2018_idioms = "warn"
unused_lifetimes = "warn"
semicolon_in_expressions_from_macros = "warn"
[workspace.lints.clippy] [workspace.lints.clippy]
collapsible_if = "allow" # FIXME Remove the tidy test once the lint table is stable
needless_pass_by_value = "allow"
nonminimal_bool = "allow" ## lint groups
redundant_pattern_matching = "allow" complexity = { level = "warn", priority = -1 }
correctness = { level = "deny", priority = -1 }
perf = { level = "deny", priority = -1 }
restriction = { level = "allow", priority = -1 }
style = { level = "warn", priority = -1 }
suspicious = { level = "warn", priority = -1 }
## allow following lints
# () makes a fine error in most cases
result_unit_err = "allow"
# We don't expose public APIs that matter like this
len_without_is_empty = "allow"
# We have macros that rely on this currently
enum_variant_names = "allow"
# Builder pattern disagrees
new_ret_no_self = "allow"
## Following lints should be tackled at some point
borrowed_box = "allow"
borrow_deref_ref = "allow"
derivable_impls = "allow"
derived_hash_with_manual_eq = "allow"
field_reassign_with_default = "allow"
forget_non_drop = "allow"
format_collect = "allow"
large_enum_variant = "allow"
needless_doctest_main = "allow"
new_without_default = "allow"
non_canonical_clone_impl = "allow"
non_canonical_partial_ord_impl = "allow"
self_named_constructors = "allow"
skip_while_next = "allow"
too_many_arguments = "allow"
toplevel_ref_arg = "allow"
type_complexity = "allow"
unnecessary_cast = "allow"
unnecessary_filter_map = "allow"
unnecessary_lazy_evaluations = "allow"
unnecessary_mut_passed = "allow"
useless_conversion = "allow"
useless_format = "allow"
wildcard_in_or_patterns = "allow"
wrong_self_convention = "allow"
## warn at following lints
dbg_macro = "warn"
todo = "warn"
unimplemented = "allow"
rc_buffer = "warn"
# FIXME enable this, we use this pattern a lot so its annoying work ...
# str_to_string = "warn"

View File

@ -9,7 +9,7 @@
use std::{fmt, mem, ops, str::FromStr}; use std::{fmt, mem, ops, str::FromStr};
use cfg::CfgOptions; use cfg::CfgOptions;
use la_arena::{Arena, Idx}; use la_arena::{Arena, Idx, RawIdx};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use semver::Version; use semver::Version;
use syntax::SmolStr; use syntax::SmolStr;
@ -157,6 +157,10 @@ impl CrateOrigin {
pub fn is_lib(&self) -> bool { pub fn is_lib(&self) -> bool {
matches!(self, CrateOrigin::Library { .. }) matches!(self, CrateOrigin::Library { .. })
} }
pub fn is_lang(&self) -> bool {
matches!(self, CrateOrigin::Lang { .. })
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -174,7 +178,7 @@ impl From<&str> for LangCrateOrigin {
match s { match s {
"alloc" => LangCrateOrigin::Alloc, "alloc" => LangCrateOrigin::Alloc,
"core" => LangCrateOrigin::Core, "core" => LangCrateOrigin::Core,
"proc-macro" => LangCrateOrigin::ProcMacro, "proc-macro" | "proc_macro" => LangCrateOrigin::ProcMacro,
"std" => LangCrateOrigin::Std, "std" => LangCrateOrigin::Std,
"test" => LangCrateOrigin::Test, "test" => LangCrateOrigin::Test,
_ => LangCrateOrigin::Other, _ => LangCrateOrigin::Other,
@ -257,6 +261,7 @@ impl ReleaseChannel {
} }
} }
#[allow(clippy::should_implement_trait)]
pub fn from_str(str: &str) -> Option<Self> { pub fn from_str(str: &str) -> Option<Self> {
Some(match str { Some(match str {
"" | "stable" => ReleaseChannel::Stable, "" | "stable" => ReleaseChannel::Stable,
@ -326,7 +331,7 @@ impl CrateData {
return false; return false;
} }
if let Some(_) = opts.next() { if opts.next().is_some() {
return false; return false;
} }
} }
@ -522,7 +527,7 @@ impl CrateGraph {
self.arena.iter().map(|(idx, _)| idx) self.arena.iter().map(|(idx, _)| idx)
} }
// FIXME: used for `handle_hack_cargo_workspace`, should be removed later // FIXME: used for fixing up the toolchain sysroot, should be removed and done differently
#[doc(hidden)] #[doc(hidden)]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateId, &mut CrateData)> + '_ { pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateId, &mut CrateData)> + '_ {
self.arena.iter_mut() self.arena.iter_mut()
@ -619,7 +624,12 @@ impl CrateGraph {
/// This will deduplicate the crates of the graph where possible. /// This will deduplicate the crates of the graph where possible.
/// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id. /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
/// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted. /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) { pub fn extend(
&mut self,
mut other: CrateGraph,
proc_macros: &mut ProcMacroPaths,
on_finished: impl FnOnce(&FxHashMap<CrateId, CrateId>),
) {
let topo = other.crates_in_topological_order(); let topo = other.crates_in_topological_order();
let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default(); let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
for topo in topo { for topo in topo {
@ -630,7 +640,7 @@ impl CrateGraph {
let res = self.arena.iter().find_map(|(id, data)| { let res = self.arena.iter().find_map(|(id, data)| {
match (&data.origin, &crate_data.origin) { match (&data.origin, &crate_data.origin) {
(a, b) if a == b => { (a, b) if a == b => {
if data.eq_ignoring_origin_and_deps(&crate_data, false) { if data.eq_ignoring_origin_and_deps(crate_data, false) {
return Some((id, false)); return Some((id, false));
} }
} }
@ -642,8 +652,8 @@ impl CrateGraph {
// version and discard the library one as the local version may have // version and discard the library one as the local version may have
// dev-dependencies that we want to keep resolving. See #15656 for more // dev-dependencies that we want to keep resolving. See #15656 for more
// information. // information.
if data.eq_ignoring_origin_and_deps(&crate_data, true) { if data.eq_ignoring_origin_and_deps(crate_data, true) {
return Some((id, if a.is_local() { false } else { true })); return Some((id, !a.is_local()));
} }
} }
(_, _) => return None, (_, _) => return None,
@ -670,6 +680,8 @@ impl CrateGraph {
*proc_macros = *proc_macros =
mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect(); mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect();
on_finished(&id_map);
} }
fn find_path( fn find_path(
@ -721,6 +733,29 @@ impl CrateGraph {
fn hacky_find_crate<'a>(&'a self, display_name: &'a str) -> impl Iterator<Item = CrateId> + 'a { fn hacky_find_crate<'a>(&'a self, display_name: &'a str) -> impl Iterator<Item = CrateId> + 'a {
self.iter().filter(move |it| self[*it].display_name.as_deref() == Some(display_name)) self.iter().filter(move |it| self[*it].display_name.as_deref() == Some(display_name))
} }
/// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies.
/// Returns a mapping from old crate ids to new crate ids.
pub fn remove_crates_except(&mut self, to_keep: &[CrateId]) -> Vec<Option<CrateId>> {
let mut id_map = vec![None; self.arena.len()];
self.arena = std::mem::take(&mut self.arena)
.into_iter()
.filter_map(|(id, data)| if to_keep.contains(&id) { Some((id, data)) } else { None })
.enumerate()
.map(|(new_id, (id, data))| {
id_map[id.into_raw().into_u32() as usize] =
Some(CrateId::from_raw(RawIdx::from_u32(new_id as u32)));
data
})
.collect();
for (_, data) in self.arena.iter_mut() {
data.dependencies.iter_mut().for_each(|dep| {
dep.crate_id =
id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered")
});
}
id_map
}
} }
impl ops::Index<CrateId> for CrateGraph { impl ops::Index<CrateId> for CrateGraph {

View File

@ -24,12 +24,12 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode}, item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode},
lang_item::LangItem, lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource}, nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId, AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId,
LocalFieldId, Lookup, MacroId, VariantId, VariantId,
}; };
#[derive(Default, Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner {
impl Attrs { impl Attrs {
pub const EMPTY: Self = Self(RawAttrs::EMPTY); pub const EMPTY: Self = Self(RawAttrs::EMPTY);
pub(crate) fn variants_attrs_query(
db: &dyn DefDatabase,
e: EnumId,
) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
let _p = profile::span("variants_attrs_query");
// FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
let mut res = ArenaMap::default();
let loc = e.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
let enum_ = &item_tree[loc.id.value];
let crate_graph = db.crate_graph();
let cfg_options = &crate_graph[krate].cfg_options;
let mut idx = 0;
for variant in enum_.variants.clone() {
let attrs = item_tree.attrs(db, krate, variant.into());
if attrs.is_cfg_enabled(cfg_options) {
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
idx += 1;
}
}
Arc::new(res)
}
pub(crate) fn fields_attrs_query( pub(crate) fn fields_attrs_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
v: VariantId, v: VariantId,
@ -108,29 +81,11 @@ impl Attrs {
let crate_graph = db.crate_graph(); let crate_graph = db.crate_graph();
let (fields, item_tree, krate) = match v { let (fields, item_tree, krate) = match v {
VariantId::EnumVariantId(it) => { VariantId::EnumVariantId(it) => {
let e = it.parent; let loc = it.lookup(db);
let loc = e.lookup(db); let krate = loc.parent.lookup(db).container.krate;
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let enum_ = &item_tree[loc.id.value]; let variant = &item_tree[loc.id.value];
(variant.fields.clone(), item_tree, krate)
let cfg_options = &crate_graph[krate].cfg_options;
let Some(variant) = enum_
.variants
.clone()
.filter(|variant| {
let attrs = item_tree.attrs(db, krate, (*variant).into());
attrs.is_cfg_enabled(cfg_options)
})
.zip(0u32..)
.find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx)))
.map(|(variant, _idx)| variant)
else {
return Arc::new(res);
};
(item_tree[variant].fields.clone(), item_tree, krate)
} }
VariantId::StructId(it) => { VariantId::StructId(it) => {
let loc = it.lookup(db); let loc = it.lookup(db);
@ -401,10 +356,12 @@ impl AttrsWithOwner {
AttrDefId::FieldId(it) => { AttrDefId::FieldId(it) => {
return db.fields_attrs(it.parent)[it.local_id].clone(); return db.fields_attrs(it.parent)[it.local_id].clone();
} }
AttrDefId::EnumVariantId(it) => {
return db.variants_attrs(it.parent)[it.local_id].clone();
}
// FIXME: DRY this up // FIXME: DRY this up
AttrDefId::EnumVariantId(it) => {
let id = it.lookup(db).id;
let tree = id.item_tree(db);
tree.raw_attrs(id.value.into()).clone()
}
AttrDefId::AdtId(it) => match it { AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), AdtId::StructId(it) => attrs_from_item_tree_loc(db, it),
AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it),
@ -503,12 +460,7 @@ impl AttrsWithOwner {
AdtId::EnumId(id) => any_has_attrs(db, id), AdtId::EnumId(id) => any_has_attrs(db, id),
}, },
AttrDefId::FunctionId(id) => any_has_attrs(db, id), AttrDefId::FunctionId(id) => any_has_attrs(db, id),
AttrDefId::EnumVariantId(id) => { AttrDefId::EnumVariantId(id) => any_has_attrs(db, id),
let map = db.variants_attrs_source_map(id.parent);
let file_id = id.parent.lookup(db).id.file_id();
let root = db.parse_or_expand(file_id);
InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root)))
}
AttrDefId::StaticId(id) => any_has_attrs(db, id), AttrDefId::StaticId(id) => any_has_attrs(db, id),
AttrDefId::ConstId(id) => any_has_attrs(db, id), AttrDefId::ConstId(id) => any_has_attrs(db, id),
AttrDefId::TraitId(id) => any_has_attrs(db, id), AttrDefId::TraitId(id) => any_has_attrs(db, id),
@ -654,13 +606,16 @@ fn any_has_attrs<'db>(
id.lookup(db).source(db).map(ast::AnyHasAttrs::new) id.lookup(db).source(db).map(ast::AnyHasAttrs::new)
} }
fn attrs_from_item_tree<N: ItemTreeNode>(db: &dyn DefDatabase, id: ItemTreeId<N>) -> RawAttrs { fn attrs_from_item_tree<N: ItemTreeModItemNode>(
db: &dyn DefDatabase,
id: ItemTreeId<N>,
) -> RawAttrs {
let tree = id.item_tree(db); let tree = id.item_tree(db);
let mod_item = N::id_to_mod_item(id.value); let mod_item = N::id_to_mod_item(id.value);
tree.raw_attrs(mod_item.into()).clone() tree.raw_attrs(mod_item.into()).clone()
} }
fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>(
db: &(dyn DefDatabase + 'db), db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>, lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>,
) -> RawAttrs { ) -> RawAttrs {
@ -668,7 +623,7 @@ fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
attrs_from_item_tree(db, id) attrs_from_item_tree(db, id)
} }
fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>(
db: &(dyn DefDatabase + 'db), db: &(dyn DefDatabase + 'db),
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>, lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>,
) -> RawAttrs { ) -> RawAttrs {
@ -676,20 +631,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>(
attrs_from_item_tree(db, id) attrs_from_item_tree(db, id)
} }
pub(crate) fn variants_attrs_source_map(
db: &dyn DefDatabase,
def: EnumId,
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
let mut res = ArenaMap::default();
let child_source = def.child_source(db);
for (idx, variant) in child_source.value.iter() {
res.insert(idx, AstPtr::new(variant));
}
Arc::new(res)
}
pub(crate) fn fields_attrs_source_map( pub(crate) fn fields_attrs_source_map(
db: &dyn DefDatabase, db: &dyn DefDatabase,
def: VariantId, def: VariantId,

View File

@ -26,7 +26,7 @@ use crate::{
}, },
nameres::DefMap, nameres::DefMap,
path::{ModPath, Path}, path::{ModPath, Path},
src::{HasChildSource, HasSource}, src::HasSource,
BlockId, DefWithBodyId, HasModule, Lookup, BlockId, DefWithBodyId, HasModule, Lookup,
}; };
@ -37,7 +37,7 @@ pub struct Body {
pub pats: Arena<Pat>, pub pats: Arena<Pat>,
pub bindings: Arena<Binding>, pub bindings: Arena<Binding>,
pub labels: Arena<Label>, pub labels: Arena<Label>,
/// Id of the closure/generator that owns the corresponding binding. If a binding is owned by the /// Id of the closure/coroutine that owns the corresponding binding. If a binding is owned by the
/// top level expression, it will not be listed in here. /// top level expression, it will not be listed in here.
pub binding_owners: FxHashMap<BindingId, ExprId>, pub binding_owners: FxHashMap<BindingId, ExprId>,
/// The patterns for the function's parameters. While the parameter types are /// The patterns for the function's parameters. While the parameter types are
@ -160,8 +160,9 @@ impl Body {
src.map(|it| it.body()) src.map(|it| it.body())
} }
DefWithBodyId::VariantId(v) => { DefWithBodyId::VariantId(v) => {
let src = v.parent.child_source(db); let s = v.lookup(db);
src.map(|it| it[v.local_id].expr()) let src = s.source(db);
src.map(|it| it.expr())
} }
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()), DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
} }
@ -257,12 +258,12 @@ impl Body {
} }
} }
Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => { Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => {
args.iter().copied().for_each(|p| f(p)); args.iter().copied().for_each(f);
} }
Pat::Ref { pat, .. } => f(*pat), Pat::Ref { pat, .. } => f(*pat),
Pat::Slice { prefix, slice, suffix } => { Pat::Slice { prefix, slice, suffix } => {
let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter()); let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
total_iter.copied().for_each(|p| f(p)); total_iter.copied().for_each(f);
} }
Pat::Record { args, .. } => { Pat::Record { args, .. } => {
args.iter().for_each(|RecordFieldPat { pat, .. }| f(*pat)); args.iter().for_each(|RecordFieldPat { pat, .. }| f(*pat));
@ -368,7 +369,7 @@ impl BodySourceMap {
} }
pub fn label_syntax(&self, label: LabelId) -> LabelSource { pub fn label_syntax(&self, label: LabelId) -> LabelSource {
self.label_map_back[label].clone() self.label_map_back[label]
} }
pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> { pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
@ -377,11 +378,11 @@ impl BodySourceMap {
} }
pub fn field_syntax(&self, expr: ExprId) -> FieldSource { pub fn field_syntax(&self, expr: ExprId) -> FieldSource {
self.field_map_back[&expr].clone() self.field_map_back[&expr]
} }
pub fn pat_field_syntax(&self, pat: PatId) -> PatFieldSource { pub fn pat_field_syntax(&self, pat: PatId) -> PatFieldSource {
self.pat_field_map_back[&pat].clone() self.pat_field_map_back[&pat]
} }
pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroExpr>) -> Option<ExprId> { pub fn macro_expansion_expr(&self, node: InFile<&ast::MacroExpr>) -> Option<ExprId> {

View File

@ -81,7 +81,7 @@ pub(super) fn lower(
expander, expander,
current_try_block_label: None, current_try_block_label: None,
is_lowering_assignee_expr: false, is_lowering_assignee_expr: false,
is_lowering_generator: false, is_lowering_coroutine: false,
label_ribs: Vec::new(), label_ribs: Vec::new(),
current_binding_owner: None, current_binding_owner: None,
} }
@ -99,7 +99,7 @@ struct ExprCollector<'a> {
source_map: BodySourceMap, source_map: BodySourceMap,
is_lowering_assignee_expr: bool, is_lowering_assignee_expr: bool,
is_lowering_generator: bool, is_lowering_coroutine: bool,
current_try_block_label: Option<LabelId>, current_try_block_label: Option<LabelId>,
// points to the expression that a try expression will target (replaces current_try_block_label) // points to the expression that a try expression will target (replaces current_try_block_label)
@ -417,7 +417,7 @@ impl ExprCollector<'_> {
self.alloc_expr(Expr::Return { expr }, syntax_ptr) self.alloc_expr(Expr::Return { expr }, syntax_ptr)
} }
ast::Expr::YieldExpr(e) => { ast::Expr::YieldExpr(e) => {
self.is_lowering_generator = true; self.is_lowering_coroutine = true;
let expr = e.expr().map(|e| self.collect_expr(e)); let expr = e.expr().map(|e| self.collect_expr(e));
self.alloc_expr(Expr::Yield { expr }, syntax_ptr) self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
} }
@ -525,18 +525,18 @@ impl ExprCollector<'_> {
.and_then(|r| r.ty()) .and_then(|r| r.ty())
.map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it))); .map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
let prev_is_lowering_generator = mem::take(&mut this.is_lowering_generator); let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
let prev_try_block_label = this.current_try_block_label.take(); let prev_try_block_label = this.current_try_block_label.take();
let body = this.collect_expr_opt(e.body()); let body = this.collect_expr_opt(e.body());
let closure_kind = if this.is_lowering_generator { let closure_kind = if this.is_lowering_coroutine {
let movability = if e.static_token().is_some() { let movability = if e.static_token().is_some() {
Movability::Static Movability::Static
} else { } else {
Movability::Movable Movability::Movable
}; };
ClosureKind::Generator(movability) ClosureKind::Coroutine(movability)
} else if e.async_token().is_some() { } else if e.async_token().is_some() {
ClosureKind::Async ClosureKind::Async
} else { } else {
@ -544,7 +544,7 @@ impl ExprCollector<'_> {
}; };
let capture_by = let capture_by =
if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref }; if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
this.is_lowering_generator = prev_is_lowering_generator; this.is_lowering_coroutine = prev_is_lowering_coroutine;
this.current_binding_owner = prev_binding_owner; this.current_binding_owner = prev_binding_owner;
this.current_try_block_label = prev_try_block_label; this.current_try_block_label = prev_try_block_label;
this.body.exprs[result_expr_id] = Expr::Closure { this.body.exprs[result_expr_id] = Expr::Closure {
@ -776,11 +776,10 @@ impl ExprCollector<'_> {
None => self.collect_expr_opt(e.condition()), None => self.collect_expr_opt(e.condition()),
}; };
let break_expr = let break_expr = self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr);
self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone());
let if_expr = self.alloc_expr( let if_expr = self.alloc_expr(
Expr::If { condition, then_branch: body, else_branch: Some(break_expr) }, Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
syntax_ptr.clone(), syntax_ptr,
); );
self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr) self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr)
} }
@ -811,19 +810,19 @@ impl ExprCollector<'_> {
return self.alloc_expr(Expr::Missing, syntax_ptr); return self.alloc_expr(Expr::Missing, syntax_ptr);
}; };
let head = self.collect_expr_opt(e.iterable()); let head = self.collect_expr_opt(e.iterable());
let into_iter_fn_expr = self.alloc_expr(Expr::Path(into_iter_fn), syntax_ptr.clone()); let into_iter_fn_expr = self.alloc_expr(Expr::Path(into_iter_fn), syntax_ptr);
let iterator = self.alloc_expr( let iterator = self.alloc_expr(
Expr::Call { Expr::Call {
callee: into_iter_fn_expr, callee: into_iter_fn_expr,
args: Box::new([head]), args: Box::new([head]),
is_assignee_expr: false, is_assignee_expr: false,
}, },
syntax_ptr.clone(), syntax_ptr,
); );
let none_arm = MatchArm { let none_arm = MatchArm {
pat: self.alloc_pat_desugared(Pat::Path(Box::new(option_none))), pat: self.alloc_pat_desugared(Pat::Path(Box::new(option_none))),
guard: None, guard: None,
expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone()), expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr),
}; };
let some_pat = Pat::TupleStruct { let some_pat = Pat::TupleStruct {
path: Some(Box::new(option_some)), path: Some(Box::new(option_some)),
@ -839,27 +838,25 @@ impl ExprCollector<'_> {
}), }),
}; };
let iter_name = Name::generate_new_name(); let iter_name = Name::generate_new_name();
let iter_expr = let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr.clone());
let iter_expr_mut = self.alloc_expr( let iter_expr_mut = self.alloc_expr(
Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut }, Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
syntax_ptr.clone(), syntax_ptr,
); );
let iter_next_fn_expr = self.alloc_expr(Expr::Path(iter_next_fn), syntax_ptr.clone()); let iter_next_fn_expr = self.alloc_expr(Expr::Path(iter_next_fn), syntax_ptr);
let iter_next_expr = self.alloc_expr( let iter_next_expr = self.alloc_expr(
Expr::Call { Expr::Call {
callee: iter_next_fn_expr, callee: iter_next_fn_expr,
args: Box::new([iter_expr_mut]), args: Box::new([iter_expr_mut]),
is_assignee_expr: false, is_assignee_expr: false,
}, },
syntax_ptr.clone(), syntax_ptr,
); );
let loop_inner = self.alloc_expr( let loop_inner = self.alloc_expr(
Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) }, Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
syntax_ptr.clone(), syntax_ptr,
); );
let loop_outer = let loop_outer = self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr);
self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr.clone());
let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable); let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable);
let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None }); let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
self.add_definition_to_binding(iter_binding, iter_pat); self.add_definition_to_binding(iter_binding, iter_pat);
@ -868,7 +865,7 @@ impl ExprCollector<'_> {
expr: iterator, expr: iterator,
arms: Box::new([MatchArm { pat: iter_pat, guard: None, expr: loop_outer }]), arms: Box::new([MatchArm { pat: iter_pat, guard: None, expr: loop_outer }]),
}, },
syntax_ptr.clone(), syntax_ptr,
) )
} }
@ -896,10 +893,10 @@ impl ExprCollector<'_> {
return self.alloc_expr(Expr::Missing, syntax_ptr); return self.alloc_expr(Expr::Missing, syntax_ptr);
}; };
let operand = self.collect_expr_opt(e.expr()); let operand = self.collect_expr_opt(e.expr());
let try_branch = self.alloc_expr(Expr::Path(try_branch), syntax_ptr.clone()); let try_branch = self.alloc_expr(Expr::Path(try_branch), syntax_ptr);
let expr = self.alloc_expr( let expr = self.alloc_expr(
Expr::Call { callee: try_branch, args: Box::new([operand]), is_assignee_expr: false }, Expr::Call { callee: try_branch, args: Box::new([operand]), is_assignee_expr: false },
syntax_ptr.clone(), syntax_ptr,
); );
let continue_name = Name::generate_new_name(); let continue_name = Name::generate_new_name();
let continue_binding = let continue_binding =
@ -914,7 +911,7 @@ impl ExprCollector<'_> {
ellipsis: None, ellipsis: None,
}), }),
guard: None, guard: None,
expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr.clone()), expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
}; };
let break_name = Name::generate_new_name(); let break_name = Name::generate_new_name();
let break_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated); let break_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated);
@ -928,18 +925,18 @@ impl ExprCollector<'_> {
}), }),
guard: None, guard: None,
expr: { expr: {
let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr.clone()); let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr);
let callee = self.alloc_expr(Expr::Path(try_from_residual), syntax_ptr.clone()); let callee = self.alloc_expr(Expr::Path(try_from_residual), syntax_ptr);
let result = self.alloc_expr( let result = self.alloc_expr(
Expr::Call { callee, args: Box::new([it]), is_assignee_expr: false }, Expr::Call { callee, args: Box::new([it]), is_assignee_expr: false },
syntax_ptr.clone(), syntax_ptr,
); );
self.alloc_expr( self.alloc_expr(
match self.current_try_block_label { match self.current_try_block_label {
Some(label) => Expr::Break { expr: Some(result), label: Some(label) }, Some(label) => Expr::Break { expr: Some(result), label: Some(label) },
None => Expr::Return { expr: Some(result) }, None => Expr::Return { expr: Some(result) },
}, },
syntax_ptr.clone(), syntax_ptr,
) )
}, },
}; };
@ -1847,8 +1844,8 @@ impl ExprCollector<'_> {
flags as u128, flags as u128,
Some(BuiltinUint::U32), Some(BuiltinUint::U32),
))); )));
let precision = self.make_count(&precision, argmap); let precision = self.make_count(precision, argmap);
let width = self.make_count(&width, argmap); let width = self.make_count(width, argmap);
let format_placeholder_new = { let format_placeholder_new = {
let format_placeholder_new = let format_placeholder_new =
@ -1994,7 +1991,7 @@ impl ExprCollector<'_> {
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
let src = self.expander.in_file(ptr); let src = self.expander.in_file(ptr);
let id = self.body.exprs.alloc(expr); let id = self.body.exprs.alloc(expr);
self.source_map.expr_map_back.insert(id, src.clone()); self.source_map.expr_map_back.insert(id, src);
self.source_map.expr_map.insert(src, id); self.source_map.expr_map.insert(src, id);
id id
} }
@ -2022,7 +2019,7 @@ impl ExprCollector<'_> {
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
let src = self.expander.in_file(ptr); let src = self.expander.in_file(ptr);
let id = self.body.pats.alloc(pat); let id = self.body.pats.alloc(pat);
self.source_map.pat_map_back.insert(id, src.clone()); self.source_map.pat_map_back.insert(id, src);
self.source_map.pat_map.insert(src, id); self.source_map.pat_map.insert(src, id);
id id
} }
@ -2037,7 +2034,7 @@ impl ExprCollector<'_> {
fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId { fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
let src = self.expander.in_file(ptr); let src = self.expander.in_file(ptr);
let id = self.body.labels.alloc(label); let id = self.body.labels.alloc(label);
self.source_map.label_map_back.insert(id, src.clone()); self.source_map.label_map_back.insert(id, src);
self.source_map.label_map.insert(src, id); self.source_map.label_map.insert(src, id);
id id
} }

View File

@ -3,7 +3,6 @@
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use itertools::Itertools; use itertools::Itertools;
use syntax::ast::HasName;
use crate::{ use crate::{
hir::{ hir::{
@ -19,35 +18,30 @@ use super::*;
pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String { pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String {
let header = match owner { let header = match owner {
DefWithBodyId::FunctionId(it) => { DefWithBodyId::FunctionId(it) => {
let item_tree_id = it.lookup(db).id; it.lookup(db).id.resolved(db, |it| format!("fn {}", it.name.display(db.upcast())))
}
DefWithBodyId::StaticId(it) => it
.lookup(db)
.id
.resolved(db, |it| format!("static {} = ", it.name.display(db.upcast()))),
DefWithBodyId::ConstId(it) => it.lookup(db).id.resolved(db, |it| {
format!( format!(
"fn {}", "const {} = ",
item_tree_id.item_tree(db)[item_tree_id.value].name.display(db.upcast()) match &it.name {
Some(name) => name.display(db.upcast()).to_string(),
None => "_".to_string(),
}
) )
} }),
DefWithBodyId::StaticId(it) => {
let item_tree_id = it.lookup(db).id;
format!(
"static {} = ",
item_tree_id.item_tree(db)[item_tree_id.value].name.display(db.upcast())
)
}
DefWithBodyId::ConstId(it) => {
let item_tree_id = it.lookup(db).id;
let name = match &item_tree_id.item_tree(db)[item_tree_id.value].name {
Some(name) => name.display(db.upcast()).to_string(),
None => "_".to_string(),
};
format!("const {name} = ")
}
DefWithBodyId::InTypeConstId(_) => format!("In type const = "), DefWithBodyId::InTypeConstId(_) => format!("In type const = "),
DefWithBodyId::VariantId(it) => { DefWithBodyId::VariantId(it) => {
let src = it.parent.child_source(db); let loc = it.lookup(db);
let variant = &src.value[it.local_id]; let enum_loc = loc.parent.lookup(db);
match &variant.name() { format!(
Some(name) => name.to_string(), "enum {}::{}",
None => "_".to_string(), enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
} loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
)
} }
}; };
@ -384,7 +378,7 @@ impl Printer<'_> {
} }
Expr::Closure { args, arg_types, ret_type, body, closure_kind, capture_by } => { Expr::Closure { args, arg_types, ret_type, body, closure_kind, capture_by } => {
match closure_kind { match closure_kind {
ClosureKind::Generator(Movability::Static) => { ClosureKind::Coroutine(Movability::Static) => {
w!(self, "static "); w!(self, "static ");
} }
ClosureKind::Async => { ClosureKind::Async => {

View File

@ -13,8 +13,8 @@ use crate::{
item_scope::ItemScope, item_scope::ItemScope,
nameres::DefMap, nameres::DefMap,
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId, AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId,
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId, ModuleDefId, ModuleId, TraitId, UseId, VariantId,
}; };
pub trait ChildBySource { pub trait ChildBySource {
@ -204,13 +204,22 @@ impl ChildBySource for VariantId {
} }
impl ChildBySource for EnumId { impl ChildBySource for EnumId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) { fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
let arena_map = self.child_source(db); let loc = &self.lookup(db);
let arena_map = arena_map.as_ref(); if file_id != loc.id.file_id() {
for (local_id, source) in arena_map.value.iter() { return;
let id = EnumVariantId { parent: *self, local_id };
res[keys::VARIANT].insert(source.clone(), id)
} }
let tree = loc.id.item_tree(db);
let ast_id_map = db.ast_id_map(loc.id.file_id());
let root = db.parse_or_expand(loc.id.file_id());
db.enum_data(*self).variants.iter().for_each(|&(variant, _)| {
res[keys::ENUM_VARIANT].insert(
ast_id_map.get(tree[variant.lookup(db).id.value].ast_id).to_node(&root),
variant,
);
});
} }
} }

View File

@ -19,7 +19,7 @@ use crate::{
macro_call_as_call_id, macro_call_as_call_id,
nameres::{ nameres::{
attr_resolution::ResolvedAttr, attr_resolution::ResolvedAttr,
diagnostics::DefDiagnostic, diagnostics::{DefDiagnostic, DefDiagnostics},
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
DefMap, MacroSubNs, DefMap, MacroSubNs,
}, },
@ -233,6 +233,7 @@ pub struct TraitData {
} }
impl TraitData { impl TraitData {
#[inline]
pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
db.trait_data_with_diagnostics(tr).0 db.trait_data_with_diagnostics(tr).0
} }
@ -240,13 +241,10 @@ impl TraitData {
pub(crate) fn trait_data_with_diagnostics_query( pub(crate) fn trait_data_with_diagnostics_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
tr: TraitId, tr: TraitId,
) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) { ) -> (Arc<TraitData>, DefDiagnostics) {
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
let item_tree = tree_id.item_tree(db); let item_tree = tree_id.item_tree(db);
let tr_def = &item_tree[tree_id.value]; let tr_def = &item_tree[tree_id.value];
let _cx = stdx::panic_context::enter(format!(
"trait_data_query({tr:?} -> {tr_loc:?} -> {tr_def:?})"
));
let name = tr_def.name.clone(); let name = tr_def.name.clone();
let is_auto = tr_def.is_auto; let is_auto = tr_def.is_auto;
let is_unsafe = tr_def.is_unsafe; let is_unsafe = tr_def.is_unsafe;
@ -274,7 +272,7 @@ impl TraitData {
rustc_has_incoherent_inherent_impls, rustc_has_incoherent_inherent_impls,
fundamental, fundamental,
}), }),
diagnostics.into(), DefDiagnostics::new(diagnostics),
) )
} }
@ -333,6 +331,7 @@ pub struct ImplData {
} }
impl ImplData { impl ImplData {
#[inline]
pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> { pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
db.impl_data_with_diagnostics(id).0 db.impl_data_with_diagnostics(id).0
} }
@ -340,7 +339,7 @@ impl ImplData {
pub(crate) fn impl_data_with_diagnostics_query( pub(crate) fn impl_data_with_diagnostics_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
id: ImplId, id: ImplId,
) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) { ) -> (Arc<ImplData>, DefDiagnostics) {
let _p = profile::span("impl_data_with_diagnostics_query"); let _p = profile::span("impl_data_with_diagnostics_query");
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
@ -367,7 +366,7 @@ impl ImplData {
is_unsafe, is_unsafe,
attribute_calls, attribute_calls,
}), }),
diagnostics.into(), DefDiagnostics::new(diagnostics),
) )
} }

View File

@ -21,15 +21,14 @@ use crate::{
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId}, item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
lang_item::LangItem, lang_item::LangItem,
lower::LowerCtx, lower::LowerCtx,
nameres::diagnostics::DefDiagnostic, nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
src::HasChildSource, src::HasChildSource,
src::HasSource, src::HasSource,
trace::Trace, trace::Trace,
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}, tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
type_ref::TypeRef, type_ref::TypeRef,
visibility::RawVisibility, visibility::RawVisibility,
EnumId, EnumLoc, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
UnionId, VariantId,
}; };
/// Note that we use `StructData` for unions as well! /// Note that we use `StructData` for unions as well!
@ -43,7 +42,7 @@ pub struct StructData {
} }
bitflags! { bitflags! {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructFlags: u8 { pub struct StructFlags: u8 {
const NO_FLAGS = 0; const NO_FLAGS = 0;
/// Indicates whether the struct is `PhantomData`. /// Indicates whether the struct is `PhantomData`.
@ -65,7 +64,7 @@ bitflags! {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumData { pub struct EnumData {
pub name: Name, pub name: Name,
pub variants: Arena<EnumVariantData>, pub variants: Box<[(EnumVariantId, Name)]>,
pub repr: Option<ReprOptions>, pub repr: Option<ReprOptions>,
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub rustc_has_incoherent_inherent_impls: bool, pub rustc_has_incoherent_inherent_impls: bool,
@ -75,7 +74,6 @@ pub struct EnumData {
pub struct EnumVariantData { pub struct EnumVariantData {
pub name: Name, pub name: Name,
pub variant_data: Arc<VariantData>, pub variant_data: Arc<VariantData>,
pub tree_id: la_arena::Idx<crate::item_tree::Variant>,
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -182,6 +180,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
} }
impl StructData { impl StructData {
#[inline]
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
db.struct_data_with_diagnostics(id).0 db.struct_data_with_diagnostics(id).0
} }
@ -189,7 +188,7 @@ impl StructData {
pub(crate) fn struct_data_with_diagnostics_query( pub(crate) fn struct_data_with_diagnostics_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
id: StructId, id: StructId,
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) { ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db); let loc = id.lookup(db);
let krate = loc.container.krate; let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
@ -234,10 +233,11 @@ impl StructData {
visibility: item_tree[strukt.visibility].clone(), visibility: item_tree[strukt.visibility].clone(),
flags, flags,
}), }),
diagnostics.into(), DefDiagnostics::new(diagnostics),
) )
} }
#[inline]
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
db.union_data_with_diagnostics(id).0 db.union_data_with_diagnostics(id).0
} }
@ -245,7 +245,7 @@ impl StructData {
pub(crate) fn union_data_with_diagnostics_query( pub(crate) fn union_data_with_diagnostics_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
id: UnionId, id: UnionId,
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) { ) -> (Arc<StructData>, DefDiagnostics) {
let loc = id.lookup(db); let loc = id.lookup(db);
let krate = loc.container.krate; let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
@ -280,24 +280,16 @@ impl StructData {
visibility: item_tree[union.visibility].clone(), visibility: item_tree[union.visibility].clone(),
flags, flags,
}), }),
diagnostics.into(), DefDiagnostics::new(diagnostics),
) )
} }
} }
impl EnumData { impl EnumData {
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
db.enum_data_with_diagnostics(e).0
}
pub(crate) fn enum_data_with_diagnostics_query(
db: &dyn DefDatabase,
e: EnumId,
) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
let loc = e.lookup(db); let loc = e.lookup(db);
let krate = loc.container.krate; let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let rustc_has_incoherent_inherent_impls = item_tree let rustc_has_incoherent_inherent_impls = item_tree
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
@ -305,53 +297,21 @@ impl EnumData {
.exists(); .exists();
let enum_ = &item_tree[loc.id.value]; let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
let mut diagnostics = Vec::new();
for tree_id in enum_.variants.clone() {
let attrs = item_tree.attrs(db, krate, tree_id.into());
let var = &item_tree[tree_id];
if attrs.is_cfg_enabled(&cfg_options) {
let (var_data, field_diagnostics) = lower_fields(
db,
krate,
loc.id.file_id(),
loc.container.local_id,
&item_tree,
&cfg_options,
&var.fields,
Some(enum_.visibility),
);
diagnostics.extend(field_diagnostics);
variants.alloc(EnumVariantData { Arc::new(EnumData {
name: var.name.clone(), name: enum_.name.clone(),
variant_data: Arc::new(var_data), variants: loc.container.def_map(db).enum_definitions[&e]
tree_id, .iter()
}); .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
} else { .collect(),
diagnostics.push(DefDiagnostic::unconfigured_code( repr,
loc.container.local_id, visibility: item_tree[enum_.visibility].clone(),
InFile::new(loc.id.file_id(), var.ast_id.erase()), rustc_has_incoherent_inherent_impls,
attrs.cfg().unwrap(), })
cfg_options.clone(),
))
}
}
(
Arc::new(EnumData {
name: enum_.name.clone(),
variants,
repr,
visibility: item_tree[enum_.visibility].clone(),
rustc_has_incoherent_inherent_impls,
}),
diagnostics.into(),
)
} }
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?; let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
Some(id) Some(id)
} }
@ -363,82 +323,48 @@ impl EnumData {
} }
} }
impl HasChildSource<LocalEnumVariantId> for EnumId { impl EnumVariantData {
type Value = ast::Variant; #[inline]
fn child_source( pub(crate) fn enum_variant_data_query(
&self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> { e: EnumVariantId,
let loc = &self.lookup(db); ) -> Arc<EnumVariantData> {
let src = loc.source(db); db.enum_variant_data_with_diagnostics(e).0
let mut trace = Trace::new_for_map();
lower_enum(db, &mut trace, &src, loc);
src.with_value(trace.into_map())
} }
}
fn lower_enum( pub(crate) fn enum_variant_data_with_diagnostics_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
trace: &mut Trace<EnumVariantData, ast::Variant>, e: EnumVariantId,
ast: &InFile<ast::Enum>, ) -> (Arc<EnumVariantData>, DefDiagnostics) {
loc: &EnumLoc, let loc = e.lookup(db);
) { let container = loc.parent.lookup(db).container;
let item_tree = loc.id.item_tree(db); let krate = container.krate;
let krate = loc.container.krate; let item_tree = loc.id.item_tree(db);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
let variant = &item_tree[loc.id.value];
let item_tree_variants = item_tree[loc.id.value].variants.clone(); let (var_data, diagnostics) = lower_fields(
db,
let cfg_options = &db.crate_graph()[krate].cfg_options; krate,
let variants = ast loc.id.file_id(),
.value container.local_id,
.variant_list() &item_tree,
.into_iter() &cfg_options,
.flat_map(|it| it.variants()) &variant.fields,
.zip(item_tree_variants) Some(item_tree[loc.parent.lookup(db).id.value].visibility),
.filter(|&(_, item_tree_id)| {
item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options)
});
for (var, item_tree_id) in variants {
trace.alloc(
|| var.clone(),
|| EnumVariantData {
name: var.name().map_or_else(Name::missing, |it| it.as_name()),
variant_data: Arc::new(VariantData::new(
db,
ast.with_value(var.kind()),
loc.container,
&item_tree,
item_tree_id,
)),
tree_id: item_tree_id,
},
); );
(
Arc::new(EnumVariantData {
name: variant.name.clone(),
variant_data: Arc::new(var_data),
}),
DefDiagnostics::new(diagnostics),
)
} }
} }
impl VariantData { impl VariantData {
fn new(
db: &dyn DefDatabase,
flavor: InFile<ast::StructKind>,
module_id: ModuleId,
item_tree: &ItemTree,
variant: la_arena::Idx<crate::item_tree::Variant>,
) -> Self {
let mut trace = Trace::new_for_arena();
match lower_struct(
db,
&mut trace,
&flavor,
module_id.krate,
item_tree,
&item_tree[variant].fields,
) {
StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
StructKind::Record => VariantData::Record(trace.into_arena()),
StructKind::Unit => VariantData::Unit,
}
}
pub fn fields(&self) -> &Arena<FieldData> { pub fn fields(&self) -> &Arena<FieldData> {
const EMPTY: &Arena<FieldData> = &Arena::new(); const EMPTY: &Arena<FieldData> = &Arena::new();
match &self { match &self {
@ -468,14 +394,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
let item_tree; let item_tree;
let (src, fields, container) = match *self { let (src, fields, container) = match *self {
VariantId::EnumVariantId(it) => { VariantId::EnumVariantId(it) => {
// I don't really like the fact that we call into parent source let lookup = it.lookup(db);
// here, this might add to more queries then necessary.
let lookup = it.parent.lookup(db);
item_tree = lookup.id.item_tree(db); item_tree = lookup.id.item_tree(db);
let src = it.parent.child_source(db); (
let tree_id = db.enum_data(it.parent).variants[it.local_id].tree_id; lookup.source(db).map(|it| it.kind()),
let fields = &item_tree[tree_id].fields; &item_tree[lookup.id.value].fields,
(src.map(|map| map[it.local_id].kind()), fields, lookup.container) lookup.parent.lookup(db).container,
)
} }
VariantId::StructId(it) => { VariantId::StructId(it) => {
let lookup = it.lookup(db); let lookup = it.lookup(db);
@ -490,11 +415,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
let lookup = it.lookup(db); let lookup = it.lookup(db);
item_tree = lookup.id.item_tree(db); item_tree = lookup.id.item_tree(db);
( (
lookup.source(db).map(|it| { lookup.source(db).map(|it| it.kind()),
it.record_field_list()
.map(ast::StructKind::Record)
.unwrap_or(ast::StructKind::Unit)
}),
&item_tree[lookup.id.value].fields, &item_tree[lookup.id.value].fields,
lookup.container, lookup.container,
) )

View File

@ -11,7 +11,7 @@ use crate::{
attr::{Attrs, AttrsWithOwner}, attr::{Attrs, AttrsWithOwner},
body::{scope::ExprScopes, Body, BodySourceMap}, body::{scope::ExprScopes, Body, BodySourceMap},
data::{ data::{
adt::{EnumData, StructData}, adt::{EnumData, EnumVariantData, StructData},
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData, ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData, ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
}, },
@ -19,15 +19,15 @@ use crate::{
import_map::ImportMap, import_map::ImportMap,
item_tree::{AttrOwner, ItemTree}, item_tree::{AttrOwner, ItemTree},
lang_item::{self, LangItem, LangItemTarget, LangItems}, lang_item::{self, LangItem, LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostic, DefMap}, nameres::{diagnostics::DefDiagnostics, DefMap},
visibility::{self, Visibility}, visibility::{self, Visibility},
AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId, AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId,
FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId, ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId,
LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc,
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
VariantId, UseId, UseLoc, VariantId,
}; };
#[salsa::query_group(InternDatabaseStorage)] #[salsa::query_group(InternDatabaseStorage)]
@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase {
#[salsa::interned] #[salsa::interned]
fn intern_enum(&self, loc: EnumLoc) -> EnumId; fn intern_enum(&self, loc: EnumLoc) -> EnumId;
#[salsa::interned] #[salsa::interned]
fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId;
#[salsa::interned]
fn intern_const(&self, loc: ConstLoc) -> ConstId; fn intern_const(&self, loc: ConstLoc) -> ConstId;
#[salsa::interned] #[salsa::interned]
fn intern_static(&self, loc: StaticLoc) -> StaticId; fn intern_static(&self, loc: StaticLoc) -> StaticId;
@ -93,21 +95,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(DefMap::crate_def_map_query)] #[salsa::invoke(DefMap::crate_def_map_query)]
fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
/// Computes the block-level `DefMap`, returning `None` when `block` doesn't contain any inner /// Computes the block-level `DefMap`.
/// items directly.
///
/// For example:
///
/// ```
/// fn f() { // (0)
/// { // (1)
/// fn inner() {}
/// }
/// }
/// ```
///
/// The `block_def_map` for block 0 would return `None`, while `block_def_map` of block 1 would
/// return a `DefMap` containing `inner`.
#[salsa::invoke(DefMap::block_def_map_query)] #[salsa::invoke(DefMap::block_def_map_query)]
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>; fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
@ -115,36 +103,46 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
// region:data // region:data
#[salsa::transparent]
#[salsa::invoke(StructData::struct_data_query)] #[salsa::invoke(StructData::struct_data_query)]
fn struct_data(&self, id: StructId) -> Arc<StructData>; fn struct_data(&self, id: StructId) -> Arc<StructData>;
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)] #[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
fn struct_data_with_diagnostics(&self, id: StructId) fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc<StructData>, DefDiagnostics);
-> (Arc<StructData>, Arc<[DefDiagnostic]>);
#[salsa::transparent]
#[salsa::invoke(StructData::union_data_query)] #[salsa::invoke(StructData::union_data_query)]
fn union_data(&self, id: UnionId) -> Arc<StructData>; fn union_data(&self, id: UnionId) -> Arc<StructData>;
#[salsa::invoke(StructData::union_data_with_diagnostics_query)] #[salsa::invoke(StructData::union_data_with_diagnostics_query)]
fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>); fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, DefDiagnostics);
#[salsa::invoke(EnumData::enum_data_query)] #[salsa::invoke(EnumData::enum_data_query)]
fn enum_data(&self, e: EnumId) -> Arc<EnumData>; fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)] #[salsa::transparent]
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>); #[salsa::invoke(EnumVariantData::enum_variant_data_query)]
fn enum_variant_data(&self, id: EnumVariantId) -> Arc<EnumVariantData>;
#[salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)]
fn enum_variant_data_with_diagnostics(
&self,
id: EnumVariantId,
) -> (Arc<EnumVariantData>, DefDiagnostics);
#[salsa::transparent]
#[salsa::invoke(ImplData::impl_data_query)] #[salsa::invoke(ImplData::impl_data_query)]
fn impl_data(&self, e: ImplId) -> Arc<ImplData>; fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)] #[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>); fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, DefDiagnostics);
#[salsa::transparent]
#[salsa::invoke(TraitData::trait_data_query)] #[salsa::invoke(TraitData::trait_data_query)]
fn trait_data(&self, e: TraitId) -> Arc<TraitData>; fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)] #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>); fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, DefDiagnostics);
#[salsa::invoke(TraitAliasData::trait_alias_query)] #[salsa::invoke(TraitAliasData::trait_alias_query)]
fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>; fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>;
@ -189,18 +187,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
// region:attrs // region:attrs
#[salsa::invoke(Attrs::variants_attrs_query)]
fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
#[salsa::invoke(Attrs::fields_attrs_query)] #[salsa::invoke(Attrs::fields_attrs_query)]
fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
#[salsa::invoke(crate::attr::variants_attrs_source_map)]
fn variants_attrs_source_map(
&self,
def: EnumId,
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
#[salsa::invoke(crate::attr::fields_attrs_source_map)] #[salsa::invoke(crate::attr::fields_attrs_source_map)]
fn fields_attrs_source_map( fn fields_attrs_source_map(
&self, &self,
@ -211,7 +200,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
fn attrs(&self, def: AttrDefId) -> Attrs; fn attrs(&self, def: AttrDefId) -> Attrs;
#[salsa::transparent] #[salsa::transparent]
#[salsa::invoke(lang_item::lang_attr_query)] #[salsa::invoke(lang_item::lang_attr)]
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>; fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
// endregion:attrs // endregion:attrs
@ -239,6 +228,11 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(LangItems::crate_lang_items_query)] #[salsa::invoke(LangItems::crate_lang_items_query)]
fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>; fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>;
#[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>;
#[salsa::invoke(crate::lang_item::crate_notable_traits)]
fn crate_notable_traits(&self, krate: CrateId) -> Option<Arc<[TraitId]>>;
fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
} }
@ -265,10 +259,8 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
None => continue, None => continue,
}; };
let segments = tt.split(|tt| match tt { let segments =
tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => true, tt.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','));
_ => false,
});
for output in segments.skip(1) { for output in segments.skip(1) {
match output { match output {
[tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "no_std" => { [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "no_std" => {

View File

@ -28,7 +28,7 @@ pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new(); pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
pub const USE: Key<ast::Use, UseId> = Key::new(); pub const USE: Key<ast::Use, UseId> = Key::new();
pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new(); pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new(); pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new(); pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new(); pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();

View File

@ -2,7 +2,10 @@
use std::{cmp::Ordering, iter}; use std::{cmp::Ordering, iter};
use hir_expand::name::{known, AsName, Name}; use hir_expand::{
name::{known, AsName, Name},
Lookup,
};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::{ use crate::{
@ -139,9 +142,10 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() { if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
// - if the item is an enum variant, refer to it via the enum // - if the item is an enum variant, refer to it via the enum
if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) { if let Some(mut path) =
let data = ctx.db.enum_data(variant.parent); find_path_inner(ctx, ItemInNs::Types(variant.lookup(ctx.db).parent.into()), from)
path.push_segment(data.variants[variant.local_id].name.clone()); {
path.push_segment(ctx.db.enum_variant_data(variant).name.clone());
return Some(path); return Some(path);
} }
// If this doesn't work, it seems we have no way of referring to the // If this doesn't work, it seems we have no way of referring to the
@ -226,7 +230,7 @@ fn find_path_for_module(
} }
if let value @ Some(_) = if let value @ Some(_) =
find_in_prelude(ctx.db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from) find_in_prelude(ctx.db, &root_def_map, def_map, ItemInNs::Types(module_id.into()), from)
{ {
return value.zip(Some(Stable)); return value.zip(Some(Stable));
} }

View File

@ -400,9 +400,8 @@ impl GenericParams {
params params
.type_or_consts .type_or_consts
.iter() .iter()
.filter_map(|(idx, param)| { .filter(|(idx, _)| enabled((*idx).into()))
enabled(idx.into()).then(|| param.clone()) .map(|(_, param)| param.clone())
})
.collect() .collect()
}), }),
lifetimes: all_lifetimes_enabled lifetimes: all_lifetimes_enabled
@ -411,9 +410,8 @@ impl GenericParams {
params params
.lifetimes .lifetimes
.iter() .iter()
.filter_map(|(idx, param)| { .filter(|(idx, _)| enabled((*idx).into()))
enabled(idx.into()).then(|| param.clone()) .map(|(_, param)| param.clone())
})
.collect() .collect()
}), }),
where_predicates: params.where_predicates.clone(), where_predicates: params.where_predicates.clone(),

View File

@ -300,7 +300,7 @@ pub struct InlineAsm {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ClosureKind { pub enum ClosureKind {
Closure, Closure,
Generator(Movability), Coroutine(Movability),
Async, Async,
} }

View File

@ -10,7 +10,7 @@ use hir_expand::{
AstId, AstId,
}; };
use intern::Interned; use intern::Interned;
use syntax::ast::{self, HasName}; use syntax::ast::{self, HasName, IsString};
use crate::{ use crate::{
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint}, builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
@ -120,7 +120,12 @@ pub enum TypeRef {
Array(Box<TypeRef>, ConstRef), Array(Box<TypeRef>, ConstRef),
Slice(Box<TypeRef>), Slice(Box<TypeRef>),
/// A fn pointer. Last element of the vector is the return type. /// A fn pointer. Last element of the vector is the return type.
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/), Fn(
Vec<(Option<Name>, TypeRef)>,
bool, /*varargs*/
bool, /*is_unsafe*/
Option<Interned<str>>, /* abi */
),
ImplTrait(Vec<Interned<TypeBound>>), ImplTrait(Vec<Interned<TypeBound>>),
DynTrait(Vec<Interned<TypeBound>>), DynTrait(Vec<Interned<TypeBound>>),
Macro(AstId<ast::MacroCall>), Macro(AstId<ast::MacroCall>),
@ -225,8 +230,17 @@ impl TypeRef {
} else { } else {
Vec::new() Vec::new()
}; };
fn lower_abi(abi: ast::Abi) -> Interned<str> {
match abi.abi_string() {
Some(tok) => Interned::new_str(tok.text_without_quotes()),
// `extern` default to be `extern "C"`.
_ => Interned::new_str("C"),
}
}
let abi = inner.abi().map(lower_abi);
params.push((None, ret_ty)); params.push((None, ret_ty));
TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some()) TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some(), abi)
} }
// for types are close enough for our purposes to the inner type for now... // for types are close enough for our purposes to the inner type for now...
ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()), ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@ -260,7 +274,7 @@ impl TypeRef {
fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) { fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
f(type_ref); f(type_ref);
match type_ref { match type_ref {
TypeRef::Fn(params, _, _) => { TypeRef::Fn(params, _, _, _) => {
params.iter().for_each(|(_, param_type)| go(param_type, f)) params.iter().for_each(|(_, param_type)| go(param_type, f))
} }
TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)), TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),
@ -396,11 +410,7 @@ impl ConstRef {
lower_ctx: &LowerCtx<'_>, lower_ctx: &LowerCtx<'_>,
param: &ast::ConstParam, param: &ast::ConstParam,
) -> Option<Self> { ) -> Option<Self> {
let default = param.default_val(); param.default_val().map(|default| Self::from_const_arg(lower_ctx, Some(default)))
match default {
Some(_) => Some(Self::from_const_arg(lower_ctx, default)),
None => None,
}
} }
pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a { pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {

View File

@ -294,14 +294,14 @@ impl SearchMode {
pub fn check(self, query: &str, case_sensitive: bool, candidate: &str) -> bool { pub fn check(self, query: &str, case_sensitive: bool, candidate: &str) -> bool {
match self { match self {
SearchMode::Exact if case_sensitive => candidate == query, SearchMode::Exact if case_sensitive => candidate == query,
SearchMode::Exact => candidate.eq_ignore_ascii_case(&query), SearchMode::Exact => candidate.eq_ignore_ascii_case(query),
SearchMode::Prefix => { SearchMode::Prefix => {
query.len() <= candidate.len() && { query.len() <= candidate.len() && {
let prefix = &candidate[..query.len() as usize]; let prefix = &candidate[..query.len() as usize];
if case_sensitive { if case_sensitive {
prefix == query prefix == query
} else { } else {
prefix.eq_ignore_ascii_case(&query) prefix.eq_ignore_ascii_case(query)
} }
} }
} }
@ -382,11 +382,11 @@ impl Query {
} }
fn matches_assoc_mode(&self, is_trait_assoc_item: IsTraitAssocItem) -> bool { fn matches_assoc_mode(&self, is_trait_assoc_item: IsTraitAssocItem) -> bool {
match (is_trait_assoc_item, self.assoc_mode) { !matches!(
(is_trait_assoc_item, self.assoc_mode),
(IsTraitAssocItem::Yes, AssocSearchMode::Exclude) (IsTraitAssocItem::Yes, AssocSearchMode::Exclude)
| (IsTraitAssocItem::No, AssocSearchMode::AssocItemsOnly) => false, | (IsTraitAssocItem::No, AssocSearchMode::AssocItemsOnly)
_ => true, )
}
} }
} }

View File

@ -41,7 +41,7 @@ mod tests;
use std::{ use std::{
fmt::{self, Debug}, fmt::{self, Debug},
hash::{Hash, Hasher}, hash::{Hash, Hasher},
ops::Index, ops::{Index, Range},
}; };
use ast::{AstNode, HasName, StructKind}; use ast::{AstNode, HasName, StructKind};
@ -308,7 +308,7 @@ pub enum AttrOwner {
/// Inner attributes of the source file. /// Inner attributes of the source file.
TopLevel, TopLevel,
Variant(Idx<Variant>), Variant(FileItemTreeId<Variant>),
Field(Idx<Field>), Field(Idx<Field>),
Param(Idx<Param>), Param(Idx<Param>),
TypeOrConstParamData(Idx<TypeOrConstParamData>), TypeOrConstParamData(Idx<TypeOrConstParamData>),
@ -329,7 +329,7 @@ macro_rules! from_attrs {
from_attrs!( from_attrs!(
ModItem(ModItem), ModItem(ModItem),
Variant(Idx<Variant>), Variant(FileItemTreeId<Variant>),
Field(Idx<Field>), Field(Idx<Field>),
Param(Idx<Param>), Param(Idx<Param>),
TypeOrConstParamData(Idx<TypeOrConstParamData>), TypeOrConstParamData(Idx<TypeOrConstParamData>),
@ -337,7 +337,7 @@ from_attrs!(
); );
/// Trait implemented by all item nodes in the item tree. /// Trait implemented by all item nodes in the item tree.
pub trait ItemTreeNode: Clone { pub trait ItemTreeModItemNode: Clone {
type Source: AstIdNode + Into<ast::Item>; type Source: AstIdNode + Into<ast::Item>;
fn ast_id(&self) -> FileAstId<Self::Source>; fn ast_id(&self) -> FileAstId<Self::Source>;
@ -352,35 +352,44 @@ pub trait ItemTreeNode: Clone {
fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem; fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
} }
pub struct FileItemTreeId<N: ItemTreeNode>(Idx<N>); pub struct FileItemTreeId<N>(Idx<N>);
impl<N: ItemTreeNode> FileItemTreeId<N> { impl<N> FileItemTreeId<N> {
pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> {
(range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
.map(RawIdx::from_u32)
.map(Idx::from_raw)
.map(Self)
}
}
impl<N> FileItemTreeId<N> {
pub fn index(&self) -> Idx<N> { pub fn index(&self) -> Idx<N> {
self.0 self.0
} }
} }
impl<N: ItemTreeNode> Clone for FileItemTreeId<N> { impl<N> Clone for FileItemTreeId<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0) Self(self.0)
} }
} }
impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {} impl<N> Copy for FileItemTreeId<N> {}
impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> { impl<N> PartialEq for FileItemTreeId<N> {
fn eq(&self, other: &FileItemTreeId<N>) -> bool { fn eq(&self, other: &FileItemTreeId<N>) -> bool {
self.0 == other.0 self.0 == other.0
} }
} }
impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {} impl<N> Eq for FileItemTreeId<N> {}
impl<N: ItemTreeNode> Hash for FileItemTreeId<N> { impl<N> Hash for FileItemTreeId<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state) self.0.hash(state)
} }
} }
impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> { impl<N> fmt::Debug for FileItemTreeId<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
@ -415,12 +424,12 @@ impl TreeId {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ItemTreeId<N: ItemTreeNode> { pub struct ItemTreeId<N> {
tree: TreeId, tree: TreeId,
pub value: FileItemTreeId<N>, pub value: FileItemTreeId<N>,
} }
impl<N: ItemTreeNode> ItemTreeId<N> { impl<N> ItemTreeId<N> {
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self { pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
Self { tree, value: idx } Self { tree, value: idx }
} }
@ -436,24 +445,31 @@ impl<N: ItemTreeNode> ItemTreeId<N> {
pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> { pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
self.tree.item_tree(db) self.tree.item_tree(db)
} }
pub fn resolved<R>(self, db: &dyn DefDatabase, cb: impl FnOnce(&N) -> R) -> R
where
ItemTree: Index<FileItemTreeId<N>, Output = N>,
{
cb(&self.tree.item_tree(db)[self.value])
}
} }
impl<N: ItemTreeNode> Copy for ItemTreeId<N> {} impl<N> Copy for ItemTreeId<N> {}
impl<N: ItemTreeNode> Clone for ItemTreeId<N> { impl<N> Clone for ItemTreeId<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> { impl<N> PartialEq for ItemTreeId<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.tree == other.tree && self.value == other.value self.tree == other.tree && self.value == other.value
} }
} }
impl<N: ItemTreeNode> Eq for ItemTreeId<N> {} impl<N> Eq for ItemTreeId<N> {}
impl<N: ItemTreeNode> Hash for ItemTreeId<N> { impl<N> Hash for ItemTreeId<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.tree.hash(state); self.tree.hash(state);
self.value.hash(state); self.value.hash(state);
@ -478,7 +494,7 @@ macro_rules! mod_items {
)+ )+
$( $(
impl ItemTreeNode for $typ { impl ItemTreeModItemNode for $typ {
type Source = $ast; type Source = $ast;
fn ast_id(&self) -> FileAstId<Self::Source> { fn ast_id(&self) -> FileAstId<Self::Source> {
@ -561,13 +577,20 @@ impl Index<RawVisibilityId> for ItemTree {
} }
} }
impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { impl<N: ItemTreeModItemNode> Index<FileItemTreeId<N>> for ItemTree {
type Output = N; type Output = N;
fn index(&self, id: FileItemTreeId<N>) -> &N { fn index(&self, id: FileItemTreeId<N>) -> &N {
N::lookup(self, id.index()) N::lookup(self, id.index())
} }
} }
impl Index<FileItemTreeId<Variant>> for ItemTree {
type Output = Variant;
fn index(&self, id: FileItemTreeId<Variant>) -> &Variant {
&self[id.index()]
}
}
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct Use { pub struct Use {
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
@ -678,7 +701,7 @@ pub struct Enum {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>, pub generic_params: Interned<GenericParams>,
pub variants: IdxRange<Variant>, pub variants: Range<FileItemTreeId<Variant>>,
pub ast_id: FileAstId<ast::Enum>, pub ast_id: FileAstId<ast::Enum>,
} }

View File

@ -3,7 +3,7 @@
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId}; use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId};
use syntax::ast::{self, HasModuleItem, HasTypeBounds}; use syntax::ast::{self, HasModuleItem, HasTypeBounds, IsString};
use crate::{ use crate::{
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
@ -13,7 +13,7 @@ use crate::{
use super::*; use super::*;
fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { fn id<N: ItemTreeModItemNode>(index: Idx<N>) -> FileItemTreeId<N> {
FileItemTreeId(index) FileItemTreeId(index)
} }
@ -253,25 +253,27 @@ impl<'a> Ctx<'a> {
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_); let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
let variants = match &enum_.variant_list() { let variants = match &enum_.variant_list() {
Some(variant_list) => self.lower_variants(variant_list), Some(variant_list) => self.lower_variants(variant_list),
None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()), None => {
FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx())
}
}; };
let res = Enum { name, visibility, generic_params, variants, ast_id }; let res = Enum { name, visibility, generic_params, variants, ast_id };
Some(id(self.data().enums.alloc(res))) Some(id(self.data().enums.alloc(res)))
} }
fn lower_variants(&mut self, variants: &ast::VariantList) -> IdxRange<Variant> { fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
let start = self.next_variant_idx(); let start = self.next_variant_idx();
for variant in variants.variants() { for variant in variants.variants() {
if let Some(data) = self.lower_variant(&variant) { if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data); let idx = self.data().variants.alloc(data);
self.add_attrs( self.add_attrs(
idx.into(), FileItemTreeId(idx).into(),
RawAttrs::new(self.db.upcast(), &variant, self.span_map()), RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
); );
} }
} }
let end = self.next_variant_idx(); let end = self.next_variant_idx();
IdxRange::new(start..end) FileItemTreeId(start)..FileItemTreeId(end)
} }
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> { fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
@ -719,16 +721,10 @@ enum HasImplicitSelf {
} }
fn lower_abi(abi: ast::Abi) -> Interned<str> { fn lower_abi(abi: ast::Abi) -> Interned<str> {
// FIXME: Abi::abi() -> Option<SyntaxToken>? match abi.abi_string() {
match abi.syntax().last_token() { Some(tok) => Interned::new_str(tok.text_without_quotes()),
Some(tok) if tok.kind() == SyntaxKind::STRING => { // `extern` default to be `extern "C"`.
// FIXME: Better way to unescape? _ => Interned::new_str("C"),
Interned::new_str(tok.text().trim_matches('"'))
}
_ => {
// `extern` default to be `extern "C"`.
Interned::new_str("C")
}
} }
} }

View File

@ -2,6 +2,8 @@
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use span::ErasedFileAstId;
use crate::{ use crate::{
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
pretty::{print_path, print_type_bounds, print_type_ref}, pretty::{print_path, print_type_bounds, print_type_ref},
@ -118,7 +120,11 @@ impl Printer<'_> {
w!(self, "{{"); w!(self, "{{");
self.indented(|this| { self.indented(|this| {
for field in fields.clone() { for field in fields.clone() {
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field]; let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
this.print_ast_id(match ast_id {
FieldAstId::Record(it) => it.erase(),
FieldAstId::Tuple(it) => it.erase(),
});
this.print_attrs_of(field, "\n"); this.print_attrs_of(field, "\n");
this.print_visibility(*visibility); this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast())); w!(this, "{}: ", name.display(self.db.upcast()));
@ -132,7 +138,11 @@ impl Printer<'_> {
w!(self, "("); w!(self, "(");
self.indented(|this| { self.indented(|this| {
for field in fields.clone() { for field in fields.clone() {
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field]; let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
this.print_ast_id(match ast_id {
FieldAstId::Record(it) => it.erase(),
FieldAstId::Tuple(it) => it.erase(),
});
this.print_attrs_of(field, "\n"); this.print_attrs_of(field, "\n");
this.print_visibility(*visibility); this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast())); w!(this, "{}: ", name.display(self.db.upcast()));
@ -200,14 +210,16 @@ impl Printer<'_> {
match item { match item {
ModItem::Use(it) => { ModItem::Use(it) => {
let Use { visibility, use_tree, ast_id: _ } = &self.tree[it]; let Use { visibility, use_tree, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "use "); w!(self, "use ");
self.print_use_tree(use_tree); self.print_use_tree(use_tree);
wln!(self, ";"); wln!(self, ";");
} }
ModItem::ExternCrate(it) => { ModItem::ExternCrate(it) => {
let ExternCrate { name, alias, visibility, ast_id: _ } = &self.tree[it]; let ExternCrate { name, alias, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "extern crate {}", name.display(self.db.upcast())); w!(self, "extern crate {}", name.display(self.db.upcast()));
if let Some(alias) = alias { if let Some(alias) = alias {
@ -216,7 +228,8 @@ impl Printer<'_> {
wln!(self, ";"); wln!(self, ";");
} }
ModItem::ExternBlock(it) => { ModItem::ExternBlock(it) => {
let ExternBlock { abi, ast_id: _, children } = &self.tree[it]; let ExternBlock { abi, ast_id, children } = &self.tree[it];
self.print_ast_id(ast_id.erase());
w!(self, "extern "); w!(self, "extern ");
if let Some(abi) = abi { if let Some(abi) = abi {
w!(self, "\"{}\" ", abi); w!(self, "\"{}\" ", abi);
@ -237,9 +250,10 @@ impl Printer<'_> {
abi, abi,
params, params,
ret_type, ret_type,
ast_id: _, ast_id,
flags, flags,
} = &self.tree[it]; } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
if flags.contains(FnFlags::HAS_DEFAULT_KW) { if flags.contains(FnFlags::HAS_DEFAULT_KW) {
w!(self, "default "); w!(self, "default ");
@ -263,7 +277,12 @@ impl Printer<'_> {
self.indented(|this| { self.indented(|this| {
for param in params.clone() { for param in params.clone() {
this.print_attrs_of(param, "\n"); this.print_attrs_of(param, "\n");
match &this.tree[param].type_ref { let Param { type_ref, ast_id } = &this.tree[param];
this.print_ast_id(match ast_id {
ParamAstId::Param(it) => it.erase(),
ParamAstId::SelfParam(it) => it.erase(),
});
match type_ref {
Some(ty) => { Some(ty) => {
if flags.contains(FnFlags::HAS_SELF_PARAM) { if flags.contains(FnFlags::HAS_SELF_PARAM) {
w!(this, "self: "); w!(this, "self: ");
@ -288,7 +307,8 @@ impl Printer<'_> {
} }
} }
ModItem::Struct(it) => { ModItem::Struct(it) => {
let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it]; let Struct { visibility, name, fields, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "struct {}", name.display(self.db.upcast())); w!(self, "struct {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params);
@ -300,7 +320,8 @@ impl Printer<'_> {
} }
} }
ModItem::Union(it) => { ModItem::Union(it) => {
let Union { name, visibility, fields, generic_params, ast_id: _ } = &self.tree[it]; let Union { name, visibility, fields, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "union {}", name.display(self.db.upcast())); w!(self, "union {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params);
@ -312,14 +333,16 @@ impl Printer<'_> {
} }
} }
ModItem::Enum(it) => { ModItem::Enum(it) => {
let Enum { name, visibility, variants, generic_params, ast_id: _ } = &self.tree[it]; let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "enum {}", name.display(self.db.upcast())); w!(self, "enum {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params);
self.print_where_clause_and_opening_brace(generic_params); self.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| { self.indented(|this| {
for variant in variants.clone() { for variant in FileItemTreeId::range_iter(variants.clone()) {
let Variant { name, fields, ast_id: _ } = &this.tree[variant]; let Variant { name, fields, ast_id } = &this.tree[variant];
this.print_ast_id(ast_id.erase());
this.print_attrs_of(variant, "\n"); this.print_attrs_of(variant, "\n");
w!(this, "{}", name.display(self.db.upcast())); w!(this, "{}", name.display(self.db.upcast()));
this.print_fields(fields); this.print_fields(fields);
@ -329,7 +352,8 @@ impl Printer<'_> {
wln!(self, "}}"); wln!(self, "}}");
} }
ModItem::Const(it) => { ModItem::Const(it) => {
let Const { name, visibility, type_ref, ast_id: _ } = &self.tree[it]; let Const { name, visibility, type_ref, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "const "); w!(self, "const ");
match name { match name {
@ -341,7 +365,8 @@ impl Printer<'_> {
wln!(self, " = _;"); wln!(self, " = _;");
} }
ModItem::Static(it) => { ModItem::Static(it) => {
let Static { name, visibility, mutable, type_ref, ast_id: _ } = &self.tree[it]; let Static { name, visibility, mutable, type_ref, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "static "); w!(self, "static ");
if *mutable { if *mutable {
@ -353,15 +378,9 @@ impl Printer<'_> {
wln!(self); wln!(self);
} }
ModItem::Trait(it) => { ModItem::Trait(it) => {
let Trait { let Trait { name, visibility, is_auto, is_unsafe, items, generic_params, ast_id } =
name, &self.tree[it];
visibility, self.print_ast_id(ast_id.erase());
is_auto,
is_unsafe,
items,
generic_params,
ast_id: _,
} = &self.tree[it];
self.print_visibility(*visibility); self.print_visibility(*visibility);
if *is_unsafe { if *is_unsafe {
w!(self, "unsafe "); w!(self, "unsafe ");
@ -380,7 +399,8 @@ impl Printer<'_> {
wln!(self, "}}"); wln!(self, "}}");
} }
ModItem::TraitAlias(it) => { ModItem::TraitAlias(it) => {
let TraitAlias { name, visibility, generic_params, ast_id: _ } = &self.tree[it]; let TraitAlias { name, visibility, generic_params, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "trait {}", name.display(self.db.upcast())); w!(self, "trait {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params);
@ -397,8 +417,9 @@ impl Printer<'_> {
is_unsafe, is_unsafe,
items, items,
generic_params, generic_params,
ast_id: _, ast_id,
} = &self.tree[it]; } = &self.tree[it];
self.print_ast_id(ast_id.erase());
if *is_unsafe { if *is_unsafe {
w!(self, "unsafe"); w!(self, "unsafe");
} }
@ -422,8 +443,9 @@ impl Printer<'_> {
wln!(self, "}}"); wln!(self, "}}");
} }
ModItem::TypeAlias(it) => { ModItem::TypeAlias(it) => {
let TypeAlias { name, visibility, bounds, type_ref, generic_params, ast_id: _ } = let TypeAlias { name, visibility, bounds, type_ref, generic_params, ast_id } =
&self.tree[it]; &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "type {}", name.display(self.db.upcast())); w!(self, "type {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params); self.print_generic_params(generic_params);
@ -440,7 +462,8 @@ impl Printer<'_> {
wln!(self); wln!(self);
} }
ModItem::Mod(it) => { ModItem::Mod(it) => {
let Mod { name, visibility, kind, ast_id: _ } = &self.tree[it]; let Mod { name, visibility, kind, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "mod {}", name.display(self.db.upcast())); w!(self, "mod {}", name.display(self.db.upcast()));
match kind { match kind {
@ -459,15 +482,24 @@ impl Printer<'_> {
} }
} }
ModItem::MacroCall(it) => { ModItem::MacroCall(it) => {
let MacroCall { path, ast_id: _, expand_to: _, call_site: _ } = &self.tree[it]; let MacroCall { path, ast_id, expand_to, call_site } = &self.tree[it];
let _ = writeln!(
self,
"// AstId: {:?}, Span: {}, ExpandTo: {:?}",
ast_id.erase().into_raw(),
call_site,
expand_to
);
wln!(self, "{}!(...);", path.display(self.db.upcast())); wln!(self, "{}!(...);", path.display(self.db.upcast()));
} }
ModItem::MacroRules(it) => { ModItem::MacroRules(it) => {
let MacroRules { name, ast_id: _ } = &self.tree[it]; let MacroRules { name, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db.upcast())); wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db.upcast()));
} }
ModItem::Macro2(it) => { ModItem::Macro2(it) => {
let Macro2 { name, visibility, ast_id: _ } = &self.tree[it]; let Macro2 { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast())); wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast()));
} }
@ -583,6 +615,10 @@ impl Printer<'_> {
}); });
true true
} }
fn print_ast_id(&mut self, ast_id: ErasedFileAstId) {
wln!(self, "// AstId: {:?}", ast_id.into_raw());
}
} }
impl Write for Printer<'_> { impl Write for Printer<'_> {

View File

@ -34,17 +34,23 @@ use a::{c, d::{e}};
#![no_std] #![no_std]
#![doc = " another file comment"] #![doc = " another file comment"]
// AstId: 1
pub(self) extern crate self as renamed; pub(self) extern crate self as renamed;
// AstId: 2
pub(super) extern crate bli; pub(super) extern crate bli;
// AstId: 3
pub use crate::path::{nested, items as renamed, Trait as _}; pub use crate::path::{nested, items as renamed, Trait as _};
// AstId: 4
pub(self) use globs::*; pub(self) use globs::*;
#[doc = " docs on import"] #[doc = " docs on import"]
// AstId: 5
pub(self) use crate::{A, B}; pub(self) use crate::{A, B};
// AstId: 6
pub(self) use a::{c, d::{e}}; pub(self) use a::{c, d::{e}};
"##]], "##]],
); );
@ -68,14 +74,18 @@ extern "C" {
"#, "#,
expect![[r##" expect![[r##"
#[on_extern_block] #[on_extern_block]
// AstId: 1
extern "C" { extern "C" {
#[on_extern_type] #[on_extern_type]
// AstId: 2
pub(self) type ExType; pub(self) type ExType;
#[on_extern_static] #[on_extern_static]
// AstId: 3
pub(self) static EX_STATIC: u8 = _; pub(self) static EX_STATIC: u8 = _;
#[on_extern_fn] #[on_extern_fn]
// AstId: 4
pub(self) fn ex_fn() -> (); pub(self) fn ex_fn() -> ();
} }
"##]], "##]],
@ -112,38 +122,52 @@ enum E {
} }
} }
"#, "#,
expect![[r##" expect![[r#"
// AstId: 1
pub(self) struct Unit; pub(self) struct Unit;
#[derive(Debug)] #[derive(Debug)]
// AstId: 2
pub(self) struct Struct { pub(self) struct Struct {
// AstId: 6
#[doc = " fld docs"] #[doc = " fld docs"]
pub(self) fld: (), pub(self) fld: (),
} }
// AstId: 3
pub(self) struct Tuple( pub(self) struct Tuple(
// AstId: 7
#[attr] #[attr]
pub(self) 0: u8, pub(self) 0: u8,
); );
// AstId: 4
pub(self) union Ize { pub(self) union Ize {
// AstId: 8
pub(self) a: (), pub(self) a: (),
// AstId: 9
pub(self) b: (), pub(self) b: (),
} }
// AstId: 5
pub(self) enum E { pub(self) enum E {
// AstId: 10
#[doc = " comment on Unit"] #[doc = " comment on Unit"]
Unit, Unit,
// AstId: 11
#[doc = " comment on Tuple"] #[doc = " comment on Tuple"]
Tuple( Tuple(
// AstId: 13
pub(self) 0: u8, pub(self) 0: u8,
), ),
// AstId: 12
Struct { Struct {
// AstId: 14
#[doc = " comment on a: u8"] #[doc = " comment on a: u8"]
pub(self) a: u8, pub(self) a: u8,
}, },
} }
"##]], "#]],
); );
} }
@ -166,26 +190,35 @@ trait Tr: SuperTrait + 'lifetime {
} }
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub static mut ST: () = _; pub static mut ST: () = _;
// AstId: 2
pub(self) const _: Anon = _; pub(self) const _: Anon = _;
#[attr] #[attr]
#[inner_attr_in_fn] #[inner_attr_in_fn]
// AstId: 3
pub(self) fn f( pub(self) fn f(
#[attr] #[attr]
// AstId: 5
u8, u8,
// AstId: 6
(), (),
) -> () { ... } ) -> () { ... }
// AstId: 4
pub(self) trait Tr<Self> pub(self) trait Tr<Self>
where where
Self: SuperTrait, Self: SuperTrait,
Self: 'lifetime Self: 'lifetime
{ {
// AstId: 8
pub(self) type Assoc: AssocBound = Default; pub(self) type Assoc: AssocBound = Default;
// AstId: 9
pub(self) fn method( pub(self) fn method(
// AstId: 10
self: &Self, self: &Self,
) -> (); ) -> ();
} }
@ -211,12 +244,16 @@ mod outline;
expect![[r##" expect![[r##"
#[doc = " outer"] #[doc = " outer"]
#[doc = " inner"] #[doc = " inner"]
// AstId: 1
pub(self) mod inline { pub(self) mod inline {
// AstId: 3
pub(self) use super::*; pub(self) use super::*;
// AstId: 4
pub(self) fn fn_in_module() -> () { ... } pub(self) fn fn_in_module() -> () { ... }
} }
// AstId: 2
pub(self) mod outline; pub(self) mod outline;
"##]], "##]],
); );
@ -235,10 +272,13 @@ pub macro m2() {}
m!(); m!();
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
macro_rules! m { ... } macro_rules! m { ... }
// AstId: 2
pub macro m2 { ... } pub macro m2 { ... }
// AstId: 3, Span: 0:3@0..5#0, ExpandTo: Items
m!(...); m!(...);
"#]], "#]],
); );
@ -258,12 +298,19 @@ struct S {
} }
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub(self) struct S { pub(self) struct S {
// AstId: 2
pub(self) a: self::Ty, pub(self) a: self::Ty,
// AstId: 3
pub(self) b: super::SuperTy, pub(self) b: super::SuperTy,
// AstId: 4
pub(self) c: super::super::SuperSuperTy, pub(self) c: super::super::SuperSuperTy,
// AstId: 5
pub(self) d: ::abs::Path, pub(self) d: ::abs::Path,
// AstId: 6
pub(self) e: crate::Crate, pub(self) e: crate::Crate,
// AstId: 7
pub(self) f: plain::path::Ty, pub(self) f: plain::path::Ty,
} }
"#]], "#]],
@ -282,10 +329,15 @@ struct S {
} }
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub(self) struct S { pub(self) struct S {
// AstId: 2
pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>, pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>,
// AstId: 3
pub(self) b: Qualified::<Self=Fully>::Syntax, pub(self) b: Qualified::<Self=Fully>::Syntax,
// AstId: 4
pub(self) c: <TypeAnchored>::Path::<'a>, pub(self) c: <TypeAnchored>::Path::<'a>,
// AstId: 5
pub(self) d: dyn for<'a> Trait::<'a>, pub(self) d: dyn for<'a> Trait::<'a>,
} }
"#]], "#]],
@ -312,42 +364,53 @@ union Union<'a, T, const U: u8> {}
trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {} trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub(self) struct S<'a, 'b, T, const K: u8> pub(self) struct S<'a, 'b, T, const K: u8>
where where
T: Copy, T: Copy,
T: 'a, T: 'a,
T: 'b T: 'b
{ {
// AstId: 8
pub(self) field: &'a &'b T, pub(self) field: &'a &'b T,
} }
// AstId: 2
pub(self) struct Tuple<T, U>( pub(self) struct Tuple<T, U>(
// AstId: 9
pub(self) 0: T, pub(self) 0: T,
// AstId: 10
pub(self) 1: U, pub(self) 1: U,
) )
where where
T: Copy, T: Copy,
U: ?Sized; U: ?Sized;
// AstId: 3
impl<'a, 'b, T, const K: u8> S::<'a, 'b, T, K> impl<'a, 'b, T, const K: u8> S::<'a, 'b, T, K>
where where
T: Copy, T: Copy,
T: 'a, T: 'a,
T: 'b T: 'b
{ {
// AstId: 12
pub(self) fn f<G>( pub(self) fn f<G>(
// AstId: 13
impl Copy, impl Copy,
) -> impl Copy ) -> impl Copy
where where
G: 'a { ... } G: 'a { ... }
} }
// AstId: 4
pub(self) enum Enum<'a, T, const U: u8> { pub(self) enum Enum<'a, T, const U: u8> {
} }
// AstId: 5
pub(self) union Union<'a, T, const U: u8> { pub(self) union Union<'a, T, const U: u8> {
} }
// AstId: 6
pub(self) trait Tr<'a, Self, T> pub(self) trait Tr<'a, Self, T>
where where
Self: Super, Self: Super,
@ -366,6 +429,7 @@ fn generics_with_attributes() {
struct S<#[cfg(never)] T>; struct S<#[cfg(never)] T>;
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub(self) struct S<#[cfg(never)] T>; pub(self) struct S<#[cfg(never)] T>;
"#]], "#]],
) )
@ -378,6 +442,7 @@ fn pub_self() {
pub(self) struct S; pub(self) struct S;
"#, "#,
expect![[r#" expect![[r#"
// AstId: 1
pub(self) struct S; pub(self) struct S;
"#]], "#]],
) )

View File

@ -125,12 +125,8 @@ impl LangItems {
} }
ModuleDefId::AdtId(AdtId::EnumId(e)) => { ModuleDefId::AdtId(AdtId::EnumId(e)) => {
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
db.enum_data(e).variants.iter().for_each(|(local_id, _)| { crate_def_map.enum_definitions[&e].iter().for_each(|&id| {
lang_items.collect_lang_item( lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
db,
EnumVariantId { parent: e, local_id },
LangItemTarget::EnumVariant,
);
}); });
} }
ModuleDefId::AdtId(AdtId::StructId(s)) => { ModuleDefId::AdtId(AdtId::StructId(s)) => {
@ -188,15 +184,51 @@ impl LangItems {
T: Into<AttrDefId> + Copy, T: Into<AttrDefId> + Copy,
{ {
let _p = profile::span("collect_lang_item"); let _p = profile::span("collect_lang_item");
if let Some(lang_item) = db.lang_attr(item.into()) { if let Some(lang_item) = lang_attr(db, item.into()) {
self.items.entry(lang_item).or_insert_with(|| constructor(item)); self.items.entry(lang_item).or_insert_with(|| constructor(item));
} }
} }
} }
pub(crate) fn lang_attr_query(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> { pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
let attrs = db.attrs(item); let attrs = db.attrs(item);
attrs.by_key("lang").string_value().and_then(|it| LangItem::from_str(&it)) attrs.by_key("lang").string_value().and_then(|it| LangItem::from_str(it))
}
pub(crate) fn notable_traits_in_deps(
db: &dyn DefDatabase,
krate: CrateId,
) -> Arc<[Arc<[TraitId]>]> {
let _p = profile::span("notable_traits_in_deps").detail(|| format!("{krate:?}"));
let crate_graph = db.crate_graph();
Arc::from_iter(
crate_graph.transitive_deps(krate).filter_map(|krate| db.crate_notable_traits(krate)),
)
}
pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: CrateId) -> Option<Arc<[TraitId]>> {
let _p = profile::span("crate_notable_traits").detail(|| format!("{krate:?}"));
let mut traits = Vec::new();
let crate_def_map = db.crate_def_map(krate);
for (_, module_data) in crate_def_map.modules() {
for def in module_data.scope.declarations() {
if let ModuleDefId::TraitId(trait_) = def {
if db.attrs(trait_.into()).has_doc_notable_trait() {
traits.push(trait_);
}
}
}
}
if traits.is_empty() {
None
} else {
Some(traits.into_iter().collect())
}
} }
pub enum GenericRequirement { pub enum GenericRequirement {
@ -228,6 +260,7 @@ macro_rules! language_item_table {
} }
/// Opposite of [`LangItem::name`] /// Opposite of [`LangItem::name`]
#[allow(clippy::should_implement_trait)]
pub fn from_str(name: &str) -> Option<Self> { pub fn from_str(name: &str) -> Option<Self> {
match name { match name {
$( stringify!($name) => Some(LangItem::$variant), )* $( stringify!($name) => Some(LangItem::$variant), )*
@ -334,8 +367,8 @@ language_item_table! {
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0); Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None; CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1); Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None; Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;

View File

@ -99,8 +99,8 @@ use crate::{
data::adt::VariantData, data::adt::VariantData,
db::DefDatabase, db::DefDatabase,
item_tree::{ item_tree::{
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2,
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
}, },
}; };
@ -213,28 +213,28 @@ impl ModuleId {
pub type LocalModuleId = Idx<nameres::ModuleData>; pub type LocalModuleId = Idx<nameres::ModuleData>;
#[derive(Debug)] #[derive(Debug)]
pub struct ItemLoc<N: ItemTreeNode> { pub struct ItemLoc<N: ItemTreeModItemNode> {
pub container: ModuleId, pub container: ModuleId,
pub id: ItemTreeId<N>, pub id: ItemTreeId<N>,
} }
impl<N: ItemTreeNode> Clone for ItemLoc<N> { impl<N: ItemTreeModItemNode> Clone for ItemLoc<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { container: self.container, id: self.id } Self { container: self.container, id: self.id }
} }
} }
impl<N: ItemTreeNode> Copy for ItemLoc<N> {} impl<N: ItemTreeModItemNode> Copy for ItemLoc<N> {}
impl<N: ItemTreeNode> PartialEq for ItemLoc<N> { impl<N: ItemTreeModItemNode> PartialEq for ItemLoc<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id self.container == other.container && self.id == other.id
} }
} }
impl<N: ItemTreeNode> Eq for ItemLoc<N> {} impl<N: ItemTreeModItemNode> Eq for ItemLoc<N> {}
impl<N: ItemTreeNode> Hash for ItemLoc<N> { impl<N: ItemTreeModItemNode> Hash for ItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state); self.container.hash(state);
self.id.hash(state); self.id.hash(state);
@ -242,28 +242,28 @@ impl<N: ItemTreeNode> Hash for ItemLoc<N> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct AssocItemLoc<N: ItemTreeNode> { pub struct AssocItemLoc<N: ItemTreeModItemNode> {
pub container: ItemContainerId, pub container: ItemContainerId,
pub id: ItemTreeId<N>, pub id: ItemTreeId<N>,
} }
impl<N: ItemTreeNode> Clone for AssocItemLoc<N> { impl<N: ItemTreeModItemNode> Clone for AssocItemLoc<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { container: self.container, id: self.id } Self { container: self.container, id: self.id }
} }
} }
impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {} impl<N: ItemTreeModItemNode> Copy for AssocItemLoc<N> {}
impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> { impl<N: ItemTreeModItemNode> PartialEq for AssocItemLoc<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id self.container == other.container && self.id == other.id
} }
} }
impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {} impl<N: ItemTreeModItemNode> Eq for AssocItemLoc<N> {}
impl<N: ItemTreeNode> Hash for AssocItemLoc<N> { impl<N: ItemTreeModItemNode> Hash for AssocItemLoc<N> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.container.hash(state); self.container.hash(state);
self.id.hash(state); self.id.hash(state);
@ -297,14 +297,16 @@ pub struct EnumId(salsa::InternId);
pub type EnumLoc = ItemLoc<Enum>; pub type EnumLoc = ItemLoc<Enum>;
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
// FIXME: rename to `VariantId`, only enums can ave variants
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumVariantId { pub struct EnumVariantId(salsa::InternId);
pub parent: EnumId,
pub local_id: LocalEnumVariantId,
}
pub type LocalEnumVariantId = Idx<data::adt::EnumVariantData>; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumVariantLoc {
pub id: ItemTreeId<Variant>,
pub parent: EnumId,
pub index: u32,
}
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FieldId { pub struct FieldId {
@ -731,9 +733,7 @@ pub struct InTypeConstLoc {
impl PartialEq for InTypeConstLoc { impl PartialEq for InTypeConstLoc {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.id == other.id self.id == other.id && self.owner == other.owner && *self.expected_ty == *other.expected_ty
&& self.owner == other.owner
&& &*self.expected_ty == &*other.expected_ty
} }
} }
@ -953,23 +953,21 @@ impl VariantId {
match self { match self {
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
VariantId::EnumVariantId(it) => { VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(),
db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
}
} }
} }
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
match self { match self {
VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(), VariantId::EnumVariantId(it) => it.lookup(db).id.file_id(),
VariantId::StructId(it) => it.lookup(db).id.file_id(), VariantId::StructId(it) => it.lookup(db).id.file_id(),
VariantId::UnionId(it) => it.lookup(db).id.file_id(), VariantId::UnionId(it) => it.lookup(db).id.file_id(),
} }
} }
pub fn adt_id(self) -> AdtId { pub fn adt_id(self, db: &dyn DefDatabase) -> AdtId {
match self { match self {
VariantId::EnumVariantId(it) => it.parent.into(), VariantId::EnumVariantId(it) => it.lookup(db).parent.into(),
VariantId::StructId(it) => it.into(), VariantId::StructId(it) => it.into(),
VariantId::UnionId(it) => it.into(), VariantId::UnionId(it) => it.into(),
} }
@ -991,7 +989,8 @@ impl HasModule for ItemContainerId {
} }
} }
impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> { impl<N: ItemTreeModItemNode> HasModule for AssocItemLoc<N> {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.container.module(db) self.container.module(db)
} }
@ -1007,7 +1006,22 @@ impl HasModule for AdtId {
} }
} }
impl HasModule for EnumId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container
}
}
impl HasModule for EnumVariantId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).parent.module(db)
}
}
impl HasModule for ExternCrateId { impl HasModule for ExternCrateId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container self.lookup(db).container
} }
@ -1016,7 +1030,7 @@ impl HasModule for ExternCrateId {
impl HasModule for VariantId { impl HasModule for VariantId {
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
match self { match self {
VariantId::EnumVariantId(it) => it.parent.lookup(db).container, VariantId::EnumVariantId(it) => it.lookup(db).parent.module(db),
VariantId::StructId(it) => it.lookup(db).container, VariantId::StructId(it) => it.lookup(db).container,
VariantId::UnionId(it) => it.lookup(db).container, VariantId::UnionId(it) => it.lookup(db).container,
} }
@ -1045,7 +1059,7 @@ impl HasModule for TypeOwnerId {
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container, TypeOwnerId::TraitAliasId(it) => it.lookup(db).container,
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db), TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db),
TypeOwnerId::ImplId(it) => it.lookup(db).container, TypeOwnerId::ImplId(it) => it.lookup(db).container,
TypeOwnerId::EnumVariantId(it) => it.parent.lookup(db).container, TypeOwnerId::EnumVariantId(it) => it.lookup(db).parent.module(db),
} }
} }
} }
@ -1056,7 +1070,7 @@ impl HasModule for DefWithBodyId {
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
DefWithBodyId::StaticId(it) => it.lookup(db).module(db), DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
DefWithBodyId::ConstId(it) => it.lookup(db).module(db), DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
DefWithBodyId::VariantId(it) => it.parent.lookup(db).container, DefWithBodyId::VariantId(it) => it.lookup(db).parent.module(db),
DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
} }
} }
@ -1071,19 +1085,21 @@ impl HasModule for GenericDefId {
GenericDefId::TraitAliasId(it) => it.lookup(db).container, GenericDefId::TraitAliasId(it) => it.lookup(db).container,
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::ImplId(it) => it.lookup(db).container,
GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, GenericDefId::EnumVariantId(it) => it.lookup(db).parent.lookup(db).container,
GenericDefId::ConstId(it) => it.lookup(db).module(db), GenericDefId::ConstId(it) => it.lookup(db).module(db),
} }
} }
} }
impl HasModule for TypeAliasId { impl HasModule for TypeAliasId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).module(db) self.lookup(db).module(db)
} }
} }
impl HasModule for TraitId { impl HasModule for TraitId {
#[inline]
fn module(&self, db: &dyn DefDatabase) -> ModuleId { fn module(&self, db: &dyn DefDatabase) -> ModuleId {
self.lookup(db).container self.lookup(db).container
} }
@ -1098,7 +1114,7 @@ impl ModuleDefId {
ModuleDefId::ModuleId(id) => *id, ModuleDefId::ModuleId(id) => *id,
ModuleDefId::FunctionId(id) => id.lookup(db).module(db), ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
ModuleDefId::AdtId(id) => id.module(db), ModuleDefId::AdtId(id) => id.module(db),
ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container, ModuleDefId::EnumVariantId(id) => id.lookup(db).parent.module(db),
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
ModuleDefId::StaticId(id) => id.lookup(db).module(db), ModuleDefId::StaticId(id) => id.lookup(db).module(db),
ModuleDefId::TraitId(id) => id.lookup(db).container, ModuleDefId::TraitId(id) => id.lookup(db).container,
@ -1117,7 +1133,7 @@ impl AttrDefId {
AttrDefId::FieldId(it) => it.parent.module(db).krate, AttrDefId::FieldId(it) => it.parent.module(db).krate,
AttrDefId::AdtId(it) => it.module(db).krate, AttrDefId::AdtId(it) => it.module(db).krate,
AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate, AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate, AttrDefId::EnumVariantId(it) => it.lookup(db).parent.module(db).krate,
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate, AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate, AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
AttrDefId::TraitId(it) => it.lookup(db).container.krate, AttrDefId::TraitId(it) => it.lookup(db).container.krate,

View File

@ -35,9 +35,9 @@ macro_rules! f {
}; };
} }
struct#FileId(0):1@58..64\2# MyTraitMap2#FileId(0):2@31..42\0# {#FileId(0):1@72..73\2# struct#0:1@58..64#2# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#2#
map#FileId(0):1@86..89\2#:#FileId(0):1@89..90\2# #FileId(0):1@89..90\2#::#FileId(0):1@91..92\2#std#FileId(0):1@93..96\2#::#FileId(0):1@96..97\2#collections#FileId(0):1@98..109\2#::#FileId(0):1@109..110\2#HashSet#FileId(0):1@111..118\2#<#FileId(0):1@118..119\2#(#FileId(0):1@119..120\2#)#FileId(0):1@120..121\2#>#FileId(0):1@121..122\2#,#FileId(0):1@122..123\2# map#0:1@86..89#2#:#0:1@89..90#2# #0:1@89..90#2#::#0:1@91..92#2#std#0:1@93..96#2#::#0:1@96..97#2#collections#0:1@98..109#2#::#0:1@109..110#2#HashSet#0:1@111..118#2#<#0:1@118..119#2#(#0:1@119..120#2#)#0:1@120..121#2#>#0:1@121..122#2#,#0:1@122..123#2#
}#FileId(0):1@132..133\2# }#0:1@132..133#2#
"#]], "#]],
); );
} }
@ -75,12 +75,12 @@ macro_rules! f {
}; };
} }
fn#FileId(0):2@30..32\0# main#FileId(0):2@33..37\0#(#FileId(0):2@37..38\0#)#FileId(0):2@38..39\0# {#FileId(0):2@40..41\0# fn#0:2@30..32#0# main#0:2@33..37#0#(#0:2@37..38#0#)#0:2@38..39#0# {#0:2@40..41#0#
1#FileId(0):2@50..51\0#;#FileId(0):2@51..52\0# 1#0:2@50..51#0#;#0:2@51..52#0#
1.0#FileId(0):2@61..64\0#;#FileId(0):2@64..65\0# 1.0#0:2@61..64#0#;#0:2@64..65#0#
(#FileId(0):2@74..75\0#(#FileId(0):2@75..76\0#1#FileId(0):2@76..77\0#,#FileId(0):2@77..78\0# )#FileId(0):2@78..79\0#,#FileId(0):2@79..80\0# )#FileId(0):2@80..81\0#.#FileId(0):2@81..82\0#0#FileId(0):2@82..85\0#.#FileId(0):2@82..85\0#0#FileId(0):2@82..85\0#;#FileId(0):2@85..86\0# (#0:2@74..75#0#(#0:2@75..76#0#1#0:2@76..77#0#,#0:2@77..78#0# )#0:2@78..79#0#,#0:2@79..80#0# )#0:2@80..81#0#.#0:2@81..82#0#0#0:2@82..85#0#.#0:2@82..85#0#0#0:2@82..85#0#;#0:2@85..86#0#
let#FileId(0):2@95..98\0# x#FileId(0):2@99..100\0# =#FileId(0):2@101..102\0# 1#FileId(0):2@103..104\0#;#FileId(0):2@104..105\0# let#0:2@95..98#0# x#0:2@99..100#0# =#0:2@101..102#0# 1#0:2@103..104#0#;#0:2@104..105#0#
}#FileId(0):2@110..111\0# }#0:2@110..111#0#
"#]], "#]],
@ -171,7 +171,7 @@ fn main(foo: ()) {
} }
fn main(foo: ()) { fn main(foo: ()) {
/* error: unresolved macro unresolved */"helloworld!"#FileId(0):3@207..323\6#; /* error: unresolved macro unresolved */"helloworld!"#0:3@207..323#6#;
} }
} }
@ -197,7 +197,7 @@ macro_rules! mk_struct {
#[macro_use] #[macro_use]
mod foo; mod foo;
struct#FileId(1):1@59..65\2# Foo#FileId(0):2@32..35\0#(#FileId(1):1@70..71\2#u32#FileId(0):2@41..44\0#)#FileId(1):1@74..75\2#;#FileId(1):1@75..76\2# struct#1:1@59..65#2# Foo#0:2@32..35#0#(#1:1@70..71#2#u32#0:2@41..44#0#)#1:1@74..75#2#;#1:1@75..76#2#
"#]], "#]],
); );
} }

View File

@ -291,15 +291,8 @@ fn pretty_print_macro_expansion(
let span = map.span_for_range(token.text_range()); let span = map.span_for_range(token.text_range());
format_to!(res, "#"); format_to!(res, "#");
if show_spans { if show_spans {
format_to!( format_to!(res, "{span}",);
res, } else if show_ctxt {
"{:?}:{:?}@{:?}",
span.anchor.file_id,
span.anchor.ast_id.into_raw(),
span.range,
);
}
if show_ctxt {
format_to!(res, "\\{}", span.ctx); format_to!(res, "\\{}", span.ctx);
} }
format_to!(res, "#"); format_to!(res, "#");

View File

@ -181,8 +181,8 @@ fn foo(&self) {
self.0. 1; self.0. 1;
} }
fn#FileId(0):1@45..47\0# foo#FileId(0):1@48..51\0#(#FileId(0):1@51..52\0#&#FileId(0):1@52..53\0#self#FileId(0):1@53..57\0# )#FileId(0):1@57..58\0# {#FileId(0):1@59..60\0# fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#&#0:1@52..53#0#self#0:1@53..57#0# )#0:1@57..58#0# {#0:1@59..60#0#
self#FileId(0):1@65..69\0# .#FileId(0):1@69..70\0#0#FileId(0):1@70..71\0#.#FileId(0):1@71..72\0#1#FileId(0):1@73..74\0#;#FileId(0):1@74..75\0# self#0:1@65..69#0# .#0:1@69..70#0#0#0:1@70..71#0#.#0:1@71..72#0#1#0:1@73..74#0#;#0:1@74..75#0#
}#FileId(0):1@76..77\0#"#]], }#0:1@76..77#0#"#]],
); );
} }

View File

@ -80,8 +80,8 @@ use crate::{
path::ModPath, path::ModPath,
per_ns::PerNs, per_ns::PerNs,
visibility::{Visibility, VisibilityExplicity}, visibility::{Visibility, VisibilityExplicity},
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup, AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
}; };
/// Contains the results of (early) name resolution. /// Contains the results of (early) name resolution.
@ -113,6 +113,7 @@ pub struct DefMap {
/// this contains all kinds of macro, not just `macro_rules!` macro. /// this contains all kinds of macro, not just `macro_rules!` macro.
/// ExternCrateId being None implies it being imported from the general prelude import. /// ExternCrateId being None implies it being imported from the general prelude import.
macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>, macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
pub(crate) enum_definitions: FxHashMap<EnumId, Box<[EnumVariantId]>>,
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
/// attributes. /// attributes.
@ -370,6 +371,7 @@ impl DefMap {
macro_use_prelude: FxHashMap::default(), macro_use_prelude: FxHashMap::default(),
derive_helpers_in_scope: FxHashMap::default(), derive_helpers_in_scope: FxHashMap::default(),
diagnostics: Vec::new(), diagnostics: Vec::new(),
enum_definitions: FxHashMap::default(),
data: Arc::new(DefMapCrateData { data: Arc::new(DefMapCrateData {
extern_prelude: FxHashMap::default(), extern_prelude: FxHashMap::default(),
exported_derives: FxHashMap::default(), exported_derives: FxHashMap::default(),
@ -612,12 +614,14 @@ impl DefMap {
krate: _, krate: _,
prelude: _, prelude: _,
data: _, data: _,
enum_definitions,
} = self; } = self;
macro_use_prelude.shrink_to_fit(); macro_use_prelude.shrink_to_fit();
diagnostics.shrink_to_fit(); diagnostics.shrink_to_fit();
modules.shrink_to_fit(); modules.shrink_to_fit();
derive_helpers_in_scope.shrink_to_fit(); derive_helpers_in_scope.shrink_to_fit();
enum_definitions.shrink_to_fit();
for (_, module) in modules.iter_mut() { for (_, module) in modules.iter_mut() {
module.children.shrink_to_fit(); module.children.shrink_to_fit();
module.scope.shrink_to_fit(); module.scope.shrink_to_fit();

View File

@ -3,7 +3,7 @@
//! `DefCollector::collect` contains the fixed-point iteration loop which //! `DefCollector::collect` contains the fixed-point iteration loop which
//! resolves imports and expands macros. //! resolves imports and expands macros.
use std::{cmp::Ordering, iter, mem}; use std::{cmp::Ordering, iter, mem, ops::Not};
use base_db::{CrateId, Dependency, Edition, FileId}; use base_db::{CrateId, Dependency, Edition, FileId};
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
use la_arena::Idx; use la_arena::Idx;
use limit::Limit; use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::{Span, SyntaxContextId}; use span::{ErasedFileAstId, Span, SyntaxContextId};
use stdx::always; use stdx::always;
use syntax::{ast, SmolStr}; use syntax::{ast, SmolStr};
use triomphe::Arc; use triomphe::Arc;
@ -35,8 +35,8 @@ use crate::{
derive_macro_as_call_id, derive_macro_as_call_id,
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{ item_tree::{
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
}, },
macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{ nameres::{
@ -51,7 +51,7 @@ use crate::{
per_ns::PerNs, per_ns::PerNs,
tt, tt,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId, AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
@ -980,24 +980,26 @@ impl DefCollector<'_> {
cov_mark::hit!(glob_enum); cov_mark::hit!(glob_enum);
// glob import from enum => just import all the variants // glob import from enum => just import all the variants
// XXX: urgh, so this works by accident! Here, we look at // We need to check if the def map the enum is from is us, if it is we can't
// the enum data, and, in theory, this might require us to // call the def-map query since we are currently constructing it!
// look back at the crate_def_map, creating a cycle. For let loc = e.lookup(self.db);
// example, `enum E { crate::some_macro!(); }`. Luckily, the let tree = loc.id.item_tree(self.db);
// only kind of macro that is allowed inside enum is a let current_def_map = self.def_map.krate == loc.container.krate
// `cfg_macro`, and we don't need to run name resolution for && self.def_map.block_id() == loc.container.block;
// it, but this is sheer luck! let def_map;
let enum_data = self.db.enum_data(e); let resolutions = if current_def_map {
let resolutions = enum_data &self.def_map.enum_definitions[&e]
.variants } else {
.iter() def_map = loc.container.def_map(self.db);
.map(|(local_id, variant_data)| { &def_map.enum_definitions[&e]
let name = variant_data.name.clone(); }
let variant = EnumVariantId { parent: e, local_id }; .iter()
let res = PerNs::both(variant.into(), variant.into(), vis, None); .map(|&variant| {
(Some(name), res) let name = tree[variant.lookup(self.db).id.value].name.clone();
}) let res = PerNs::both(variant.into(), variant.into(), vis, None);
.collect::<Vec<_>>(); (Some(name), res)
})
.collect::<Vec<_>>();
self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id))); self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
} }
Some(d) => { Some(d) => {
@ -1404,7 +1406,7 @@ impl DefCollector<'_> {
} }
if let errors @ [_, ..] = &*value { if let errors @ [_, ..] = &*value {
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id); let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, &errors); let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors);
self.def_map.diagnostics.push(diag); self.def_map.diagnostics.push(diag);
} }
@ -1577,7 +1579,10 @@ impl ModCollector<'_, '_> {
let attrs = self.item_tree.attrs(db, krate, item.into()); let attrs = self.item_tree.attrs(db, krate, item.into());
if let Some(cfg) = attrs.cfg() { if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) { if !self.is_cfg_enabled(&cfg) {
self.emit_unconfigured_diagnostic(item, &cfg); self.emit_unconfigured_diagnostic(
InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()),
&cfg,
);
return; return;
} }
} }
@ -1708,17 +1713,47 @@ impl ModCollector<'_, '_> {
} }
ModItem::Enum(id) => { ModItem::Enum(id) => {
let it = &self.item_tree[id]; let it = &self.item_tree[id];
let enum_ =
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
.intern(db);
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
update_def( update_def(self.def_collector, enum_.into(), &it.name, vis, false);
self.def_collector,
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } let mut index = 0;
.intern(db) let variants = FileItemTreeId::range_iter(it.variants.clone())
.into(), .filter_map(|variant| {
&it.name, let is_enabled = self
vis, .item_tree
false, .attrs(db, krate, variant.into())
); .cfg()
.and_then(|cfg| self.is_cfg_enabled(&cfg).not().then_some(cfg))
.map_or(Ok(()), Err);
match is_enabled {
Err(cfg) => {
self.emit_unconfigured_diagnostic(
InFile::new(
self.file_id(),
self.item_tree[variant.index()].ast_id.erase(),
),
&cfg,
);
None
}
Ok(()) => Some({
let loc = EnumVariantLoc {
id: ItemTreeId::new(self.tree_id, variant),
parent: enum_,
index,
}
.intern(db);
index += 1;
loc
}),
}
})
.collect();
self.def_collector.def_map.enum_definitions.insert(enum_, variants);
} }
ModItem::Const(id) => { ModItem::Const(id) => {
let it = &self.item_tree[id]; let it = &self.item_tree[id];
@ -1905,31 +1940,40 @@ impl ModCollector<'_, '_> {
let is_enabled = item_tree let is_enabled = item_tree
.top_level_attrs(db, krate) .top_level_attrs(db, krate)
.cfg() .cfg()
.map_or(true, |cfg| self.is_cfg_enabled(&cfg)); .and_then(|cfg| self.is_cfg_enabled(&cfg).not().then_some(cfg))
if is_enabled { .map_or(Ok(()), Err);
let module_id = self.push_child_module( match is_enabled {
module.name.clone(), Err(cfg) => {
ast_id.value, self.emit_unconfigured_diagnostic(
Some((file_id, is_mod_rs)), ast_id.map(|it| it.erase()),
&self.item_tree[module.visibility], &cfg,
module_id, );
);
ModCollector {
def_collector: self.def_collector,
macro_depth: self.macro_depth,
module_id,
tree_id: TreeId::new(file_id.into(), None),
item_tree: &item_tree,
mod_dir,
} }
.collect_in_top_module(item_tree.top_level_items()); Ok(()) => {
let is_macro_use = is_macro_use let module_id = self.push_child_module(
|| item_tree module.name.clone(),
.top_level_attrs(db, krate) ast_id.value,
.by_key("macro_use") Some((file_id, is_mod_rs)),
.exists(); &self.item_tree[module.visibility],
if is_macro_use { module_id,
self.import_all_legacy_macros(module_id); );
ModCollector {
def_collector: self.def_collector,
macro_depth: self.macro_depth,
module_id,
tree_id: TreeId::new(file_id.into(), None),
item_tree: &item_tree,
mod_dir,
}
.collect_in_top_module(item_tree.top_level_items());
let is_macro_use = is_macro_use
|| item_tree
.top_level_attrs(db, krate)
.by_key("macro_use")
.exists();
if is_macro_use {
self.import_all_legacy_macros(module_id);
}
} }
} }
} }
@ -2243,7 +2287,7 @@ impl ModCollector<'_, '_> {
&MacroCall { ref path, ast_id, expand_to, call_site }: &MacroCall, &MacroCall { ref path, ast_id, expand_to, call_site }: &MacroCall,
container: ItemContainerId, container: ItemContainerId,
) { ) {
let ast_id = AstIdWithPath::new(self.file_id(), ast_id, ModPath::clone(&path)); let ast_id = AstIdWithPath::new(self.file_id(), ast_id, ModPath::clone(path));
let db = self.def_collector.db; let db = self.def_collector.db;
// FIXME: Immediately expanding in "Case 1" is insufficient since "Case 2" may also define // FIXME: Immediately expanding in "Case 1" is insufficient since "Case 2" may also define
@ -2327,9 +2371,9 @@ impl ModCollector<'_, '_> {
}; };
for (name, macs) in source.scope.legacy_macros() { for (name, macs) in source.scope.legacy_macros() {
macs.last().map(|&mac| { if let Some(&mac) = macs.last() {
target.scope.define_legacy_macro(name.clone(), mac); target.scope.define_legacy_macro(name.clone(), mac);
}); }
} }
} }
@ -2360,10 +2404,7 @@ impl ModCollector<'_, '_> {
self.def_collector.cfg_options.check(cfg) != Some(false) self.def_collector.cfg_options.check(cfg) != Some(false)
} }
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) { fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile<ErasedFileAstId>, cfg: &CfgExpr) {
let ast_id = item.ast_id(self.item_tree);
let ast_id = InFile::new(self.file_id(), ast_id.erase());
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id, self.module_id,
ast_id, ast_id,

View File

@ -40,6 +40,23 @@ pub enum DefDiagnosticKind {
MacroDefError { ast: AstId<ast::Macro>, message: String }, MacroDefError { ast: AstId<ast::Macro>, message: String },
} }
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DefDiagnostics(Option<triomphe::Arc<Box<[DefDiagnostic]>>>);
impl DefDiagnostics {
pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self {
Self(if diagnostics.is_empty() {
None
} else {
Some(triomphe::Arc::new(diagnostics.into_boxed_slice()))
})
}
pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> {
self.0.as_ref().into_iter().flat_map(|it| &***it)
}
}
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct DefDiagnostic { pub struct DefDiagnostic {
pub in_module: LocalModuleId, pub in_module: LocalModuleId,

View File

@ -11,18 +11,18 @@
//! `ReachedFixedPoint` signals about this. //! `ReachedFixedPoint` signals about this.
use base_db::Edition; use base_db::Edition;
use hir_expand::name::Name; use hir_expand::{name::Name, Lookup};
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
data::adt::VariantData,
db::DefDatabase, db::DefDatabase,
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
item_tree::Fields,
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, AdtId, CrateId, LocalModuleId, ModuleDefId,
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -355,29 +355,42 @@ impl DefMap {
ModuleDefId::AdtId(AdtId::EnumId(e)) => { ModuleDefId::AdtId(AdtId::EnumId(e)) => {
// enum variant // enum variant
cov_mark::hit!(can_import_enum_variant); cov_mark::hit!(can_import_enum_variant);
let enum_data = db.enum_data(e); let def_map;
match enum_data.variant(segment) {
Some(local_id) => { let loc = e.lookup(db);
let variant = EnumVariantId { parent: e, local_id }; let tree = loc.id.item_tree(db);
match &*enum_data.variants[local_id].variant_data { let current_def_map =
VariantData::Record(_) => { self.krate == loc.container.krate && self.block_id() == loc.container.block;
PerNs::types(variant.into(), Visibility::Public, None) let res = if current_def_map {
} &self.enum_definitions[&e]
VariantData::Tuple(_) | VariantData::Unit => PerNs::both( } else {
variant.into(), def_map = loc.container.def_map(db);
variant.into(), &def_map.enum_definitions[&e]
Visibility::Public, }
None, .iter()
), .find_map(|&variant| {
let variant_data = &tree[variant.lookup(db).id.value];
(variant_data.name == *segment).then(|| match variant_data.fields {
Fields::Record(_) => {
PerNs::types(variant.into(), Visibility::Public, None)
} }
} Fields::Tuple(_) | Fields::Unit => PerNs::both(
variant.into(),
variant.into(),
Visibility::Public,
None,
),
})
});
match res {
Some(res) => res,
None => { None => {
return ResolvePathResult::with( return ResolvePathResult::with(
PerNs::types(e.into(), vis, imp), PerNs::types(e.into(), vis, imp),
ReachedFixedPoint::Yes, ReachedFixedPoint::Yes,
Some(i), Some(i),
Some(self.krate), Some(self.krate),
); )
} }
} }
} }

View File

@ -1348,8 +1348,8 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
let actual = def_map let actual = def_map
.macro_use_prelude .macro_use_prelude
.iter() .keys()
.map(|(name, _)| name.display(&db).to_string()) .map(|name| name.display(&db).to_string())
.sorted() .sorted()
.join("\n"); .join("\n");

View File

@ -154,7 +154,7 @@ impl Path {
pub fn mod_path(&self) -> Option<&ModPath> { pub fn mod_path(&self) -> Option<&ModPath> {
match self { match self {
Path::Normal { mod_path, .. } => Some(&mod_path), Path::Normal { mod_path, .. } => Some(mod_path),
Path::LangItem(..) => None, Path::LangItem(..) => None,
} }
} }
@ -219,13 +219,13 @@ impl<'a> PathSegments<'a> {
} }
pub fn skip(&self, len: usize) -> PathSegments<'a> { pub fn skip(&self, len: usize) -> PathSegments<'a> {
PathSegments { PathSegments {
segments: &self.segments.get(len..).unwrap_or(&[]), segments: self.segments.get(len..).unwrap_or(&[]),
generic_args: self.generic_args.and_then(|it| it.get(len..)), generic_args: self.generic_args.and_then(|it| it.get(len..)),
} }
} }
pub fn take(&self, len: usize) -> PathSegments<'a> { pub fn take(&self, len: usize) -> PathSegments<'a> {
PathSegments { PathSegments {
segments: &self.segments.get(..len).unwrap_or(&self.segments), segments: self.segments.get(..len).unwrap_or(self.segments),
generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)), generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
} }
} }

View File

@ -53,7 +53,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
) )
}) })
.map(Interned::new); .map(Interned::new);
if let Some(_) = args { if args.is_some() {
generic_args.resize(segments.len(), None); generic_args.resize(segments.len(), None);
generic_args.push(args); generic_args.push(args);
} }

View File

@ -39,11 +39,9 @@ pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write)
LangItemTarget::Trait(it) => { LangItemTarget::Trait(it) => {
write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))? write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))?
} }
LangItemTarget::EnumVariant(it) => write!( LangItemTarget::EnumVariant(it) => {
buf, write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast()))?
"{}", }
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast())
)?,
} }
if let Some(s) = s { if let Some(s) = s {
@ -194,12 +192,17 @@ pub(crate) fn print_type_ref(
print_type_ref(db, elem, buf)?; print_type_ref(db, elem, buf)?;
write!(buf, "]")?; write!(buf, "]")?;
} }
TypeRef::Fn(args_and_ret, varargs, is_unsafe) => { TypeRef::Fn(args_and_ret, varargs, is_unsafe, abi) => {
let ((_, return_type), args) = let ((_, return_type), args) =
args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
if *is_unsafe { if *is_unsafe {
write!(buf, "unsafe ")?; write!(buf, "unsafe ")?;
} }
if let Some(abi) = abi {
buf.write_str("extern ")?;
buf.write_str(abi)?;
buf.write_char(' ')?;
}
write!(buf, "fn(")?; write!(buf, "fn(")?;
for (i, (_, typeref)) in args.iter().enumerate() { for (i, (_, typeref)) in args.iter().enumerate() {
if i != 0 { if i != 0 {

View File

@ -239,8 +239,7 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
visibility: &RawVisibility, visibility: &RawVisibility,
) -> Option<Visibility> { ) -> Option<Visibility> {
let within_impl = let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_)));
self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
match visibility { match visibility {
RawVisibility::Module(_, _) => { RawVisibility::Module(_, _) => {
let (item_map, module) = self.item_scope(); let (item_map, module) = self.item_scope();
@ -509,7 +508,7 @@ impl Resolver {
.map(|id| ExternCrateDeclData::extern_crate_decl_data_query(db, id).name.clone()) .map(|id| ExternCrateDeclData::extern_crate_decl_data_query(db, id).name.clone())
} }
pub fn extern_crates_in_scope<'a>(&'a self) -> impl Iterator<Item = (Name, ModuleId)> + 'a { pub fn extern_crates_in_scope(&self) -> impl Iterator<Item = (Name, ModuleId)> + '_ {
self.module_scope self.module_scope
.def_map .def_map
.extern_prelude() .extern_prelude()
@ -1111,7 +1110,7 @@ impl HasResolver for DefWithBodyId {
DefWithBodyId::ConstId(c) => c.resolver(db), DefWithBodyId::ConstId(c) => c.resolver(db),
DefWithBodyId::FunctionId(f) => f.resolver(db), DefWithBodyId::FunctionId(f) => f.resolver(db),
DefWithBodyId::StaticId(s) => s.resolver(db), DefWithBodyId::StaticId(s) => s.resolver(db),
DefWithBodyId::VariantId(v) => v.parent.resolver(db), DefWithBodyId::VariantId(v) => v.resolver(db),
DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db), DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db),
} }
} }
@ -1137,7 +1136,7 @@ impl HasResolver for GenericDefId {
GenericDefId::TraitAliasId(inner) => inner.resolver(db), GenericDefId::TraitAliasId(inner) => inner.resolver(db),
GenericDefId::TypeAliasId(inner) => inner.resolver(db), GenericDefId::TypeAliasId(inner) => inner.resolver(db),
GenericDefId::ImplId(inner) => inner.resolver(db), GenericDefId::ImplId(inner) => inner.resolver(db),
GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), GenericDefId::EnumVariantId(inner) => inner.resolver(db),
GenericDefId::ConstId(inner) => inner.resolver(db), GenericDefId::ConstId(inner) => inner.resolver(db),
} }
} }
@ -1145,14 +1144,14 @@ impl HasResolver for GenericDefId {
impl HasResolver for EnumVariantId { impl HasResolver for EnumVariantId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver { fn resolver(self, db: &dyn DefDatabase) -> Resolver {
self.parent.resolver(db) self.lookup(db).parent.resolver(db)
} }
} }
impl HasResolver for VariantId { impl HasResolver for VariantId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver { fn resolver(self, db: &dyn DefDatabase) -> Resolver {
match self { match self {
VariantId::EnumVariantId(it) => it.parent.resolver(db), VariantId::EnumVariantId(it) => it.resolver(db),
VariantId::StructId(it) => it.resolver(db), VariantId::StructId(it) => it.resolver(db),
VariantId::UnionId(it) => it.resolver(db), VariantId::UnionId(it) => it.resolver(db),
} }

View File

@ -5,8 +5,8 @@ use la_arena::ArenaMap;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc, db::DefDatabase, item_tree::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup,
MacroRulesLoc, ProcMacroLoc, UseId, Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId,
}; };
pub trait HasSource { pub trait HasSource {
@ -14,7 +14,7 @@ pub trait HasSource {
fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value>; fn source(&self, db: &dyn DefDatabase) -> InFile<Self::Value>;
} }
impl<N: ItemTreeNode> HasSource for AssocItemLoc<N> { impl<N: ItemTreeModItemNode> HasSource for AssocItemLoc<N> {
type Value = N::Source; type Value = N::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> { fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
@ -27,7 +27,7 @@ impl<N: ItemTreeNode> HasSource for AssocItemLoc<N> {
} }
} }
impl<N: ItemTreeNode> HasSource for ItemLoc<N> { impl<N: ItemTreeModItemNode> HasSource for ItemLoc<N> {
type Value = N::Source; type Value = N::Source;
fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> { fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
@ -40,6 +40,19 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
} }
} }
impl HasSource for EnumVariantLoc {
type Value = ast::Variant;
fn source(&self, db: &dyn DefDatabase) -> InFile<ast::Variant> {
let tree = self.id.item_tree(db);
let ast_id_map = db.ast_id_map(self.id.file_id());
let root = db.parse_or_expand(self.id.file_id());
let node = &tree[self.id.value];
InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id).to_node(&root))
}
}
impl HasSource for Macro2Loc { impl HasSource for Macro2Loc {
type Value = ast::MacroDef; type Value = ast::MacroDef;

View File

@ -18,6 +18,7 @@ pub(crate) struct Trace<T, V> {
} }
impl<T, V> Trace<T, V> { impl<T, V> Trace<T, V> {
#[allow(dead_code)]
pub(crate) fn new_for_arena() -> Trace<T, V> { pub(crate) fn new_for_arena() -> Trace<T, V> {
Trace { arena: Some(Arena::default()), map: None, len: 0 } Trace { arena: Some(Arena::default()), map: None, len: 0 }
} }
@ -41,6 +42,7 @@ impl<T, V> Trace<T, V> {
id id
} }
#[allow(dead_code)]
pub(crate) fn into_arena(mut self) -> Arena<T> { pub(crate) fn into_arena(mut self) -> Arena<T> {
self.arena.take().unwrap() self.arena.take().unwrap()
} }

View File

@ -222,13 +222,7 @@ pub(crate) fn field_visibilities_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
variant_id: VariantId, variant_id: VariantId,
) -> Arc<ArenaMap<LocalFieldId, Visibility>> { ) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
let var_data = match variant_id { let var_data = variant_id.variant_data(db);
VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
VariantId::EnumVariantId(it) => {
db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
}
};
let resolver = variant_id.module(db).resolver(db); let resolver = variant_id.module(db).resolver(db);
let mut res = ArenaMap::default(); let mut res = ArenaMap::default();
for (field_id, field_data) in var_data.fields().iter() { for (field_id, field_data) in var_data.fields().iter() {

View File

@ -191,7 +191,7 @@ impl AstIdMap {
/// The [`AstId`] of the root node /// The [`AstId`] of the root node
pub fn root(&self) -> SyntaxNodePtr { pub fn root(&self) -> SyntaxNodePtr {
self.arena[Idx::from_raw(RawIdx::from_u32(0))].clone() self.arena[Idx::from_raw(RawIdx::from_u32(0))]
} }
pub fn ast_id<N: AstIdNode>(&self, item: &N) -> FileAstId<N> { pub fn ast_id<N: AstIdNode>(&self, item: &N) -> FileAstId<N> {
@ -213,11 +213,11 @@ impl AstIdMap {
} }
pub fn get<N: AstIdNode>(&self, id: FileAstId<N>) -> AstPtr<N> { pub fn get<N: AstIdNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
AstPtr::try_from_raw(self.arena[id.raw].clone()).unwrap() AstPtr::try_from_raw(self.arena[id.raw]).unwrap()
} }
pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr { pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr {
self.arena[id].clone() self.arena[id]
} }
fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId { fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId {
@ -239,9 +239,7 @@ impl AstIdMap {
} }
fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 { fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 {
let mut hasher = BuildHasherDefault::<FxHasher>::default().build_hasher(); BuildHasherDefault::<FxHasher>::default().hash_one(ptr)
ptr.hash(&mut hasher);
hasher.finish()
} }
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]

View File

@ -31,7 +31,7 @@ impl ops::Deref for RawAttrs {
fn deref(&self) -> &[Attr] { fn deref(&self) -> &[Attr] {
match &self.entries { match &self.entries {
Some(it) => &*it, Some(it) => it,
None => &[], None => &[],
} }
} }
@ -79,7 +79,7 @@ impl RawAttrs {
Self { Self {
entries: Some(Arc::from_iter(a.iter().cloned().chain(b.iter().map(|it| { entries: Some(Arc::from_iter(a.iter().cloned().chain(b.iter().map(|it| {
let mut it = it.clone(); let mut it = it.clone();
it.id.id = it.id.ast_index() as u32 + last_ast_index it.id.id = (it.id.ast_index() as u32 + last_ast_index)
| (it.id.cfg_attr_index().unwrap_or(0) as u32) | (it.id.cfg_attr_index().unwrap_or(0) as u32)
<< AttrId::AST_INDEX_BITS; << AttrId::AST_INDEX_BITS;
it it

View File

@ -425,7 +425,7 @@ fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<t
let name = &adt.name; let name = &adt.name;
let patterns = adt.shape.as_pattern(span, name); let patterns = adt.shape.as_pattern(span, name);
let exprs = adt.shape.as_pattern_map(name, |it| quote! {span => #it .clone() }, span); let exprs = adt.shape.as_pattern_map(name, |it| quote! {span => #it .clone() }, span);
let arms = patterns.into_iter().zip(exprs.into_iter()).map(|(pat, expr)| { let arms = patterns.into_iter().zip(exprs).map(|(pat, expr)| {
let fat_arrow = fat_arrow(span); let fat_arrow = fat_arrow(span);
quote! {span => quote! {span =>
#pat #fat_arrow #expr, #pat #fat_arrow #expr,

View File

@ -125,7 +125,7 @@ fn mk_pound(span: Span) -> tt::Subtree {
vec![crate::tt::Leaf::Punct(crate::tt::Punct { vec![crate::tt::Leaf::Punct(crate::tt::Punct {
char: '#', char: '#',
spacing: crate::tt::Spacing::Alone, spacing: crate::tt::Spacing::Alone,
span: span, span,
}) })
.into()], .into()],
span, span,
@ -279,9 +279,9 @@ fn format_args_expand_general(
let pound = mk_pound(span); let pound = mk_pound(span);
let mut tt = tt.clone(); let mut tt = tt.clone();
tt.delimiter.kind = tt::DelimiterKind::Parenthesis; tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
return ExpandResult::ok(quote! {span => ExpandResult::ok(quote! {span =>
builtin #pound format_args #tt builtin #pound format_args #tt
}); })
} }
fn asm_expand( fn asm_expand(
@ -392,6 +392,7 @@ fn unreachable_expand(
ExpandResult::ok(call) ExpandResult::ok(call)
} }
#[allow(clippy::never_loop)]
fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool { fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
// To determine the edition, we check the first span up the expansion // To determine the edition, we check the first span up the expansion
// stack that does not have #[allow_internal_unstable(edition_panic)]. // stack that does not have #[allow_internal_unstable(edition_panic)].
@ -624,7 +625,7 @@ fn relative_file(
fn parse_string(tt: &tt::Subtree) -> Result<String, ExpandError> { fn parse_string(tt: &tt::Subtree) -> Result<String, ExpandError> {
tt.token_trees tt.token_trees
.get(0) .first()
.and_then(|tt| match tt { .and_then(|tt| match tt {
tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it), tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it),
_ => None, _ => None,

View File

@ -218,6 +218,9 @@ pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc<RealSpanMa
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)]; let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
let ast_id_map = db.ast_id_map(file_id.into()); let ast_id_map = db.ast_id_map(file_id.into());
let tree = db.parse(file_id).tree(); let tree = db.parse(file_id).tree();
// FIXME: Descend into modules and other item containing items that are not annotated with attributes
// and allocate pairs for those as well. This gives us finer grained span anchors resulting in
// better incrementality
pairs.extend( pairs.extend(
tree.items() tree.items()
.map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())),
@ -630,8 +633,8 @@ fn decl_macro_expander(
map.as_ref(), map.as_ref(),
map.span_for_range(macro_rules.macro_rules_token().unwrap().text_range()), map.span_for_range(macro_rules.macro_rules_token().unwrap().text_range()),
); );
let mac = mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars);
mac mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars)
} }
None => mbe::DeclarativeMacro::from_err( None => mbe::DeclarativeMacro::from_err(
mbe::ParseError::Expected("expected a token tree".into()), mbe::ParseError::Expected("expected a token tree".into()),
@ -648,8 +651,8 @@ fn decl_macro_expander(
map.as_ref(), map.as_ref(),
map.span_for_range(macro_def.macro_token().unwrap().text_range()), map.span_for_range(macro_def.macro_token().unwrap().text_range()),
); );
let mac = mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars);
mac mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars)
} }
None => mbe::DeclarativeMacro::from_err( None => mbe::DeclarativeMacro::from_err(
mbe::ParseError::Expected("expected a token tree".into()), mbe::ParseError::Expected("expected a token tree".into()),
@ -719,7 +722,7 @@ fn macro_expand(
db.decl_macro_expander(loc.def.krate, id).expand(db, arg.clone(), macro_call_id) db.decl_macro_expander(loc.def.krate, id).expand(db, arg.clone(), macro_call_id)
} }
MacroDefKind::BuiltIn(it, _) => { MacroDefKind::BuiltIn(it, _) => {
it.expand(db, macro_call_id, &arg).map_err(Into::into) it.expand(db, macro_call_id, arg).map_err(Into::into)
} }
// This might look a bit odd, but we do not expand the inputs to eager macros here. // This might look a bit odd, but we do not expand the inputs to eager macros here.
// Eager macros inputs are expanded, well, eagerly when we collect the macro calls. // Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
@ -743,10 +746,10 @@ fn macro_expand(
}; };
} }
MacroDefKind::BuiltInEager(it, _) => { MacroDefKind::BuiltInEager(it, _) => {
it.expand(db, macro_call_id, &arg).map_err(Into::into) it.expand(db, macro_call_id, arg).map_err(Into::into)
} }
MacroDefKind::BuiltInAttr(it, _) => { MacroDefKind::BuiltInAttr(it, _) => {
let mut res = it.expand(db, macro_call_id, &arg); let mut res = it.expand(db, macro_call_id, arg);
fixup::reverse_fixups(&mut res.value, &undo_info); fixup::reverse_fixups(&mut res.value, &undo_info);
res res
} }

View File

@ -68,7 +68,7 @@ pub(crate) fn fixup_syntax(
let node_range = node.text_range(); let node_range = node.text_range();
if can_handle_error(&node) && has_error_to_handle(&node) { if can_handle_error(&node) && has_error_to_handle(&node) {
remove.insert(node.clone().into()); remove.insert(node.clone());
// the node contains an error node, we have to completely replace it by something valid // the node contains an error node, we have to completely replace it by something valid
let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site); let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site);
let idx = original.len() as u32; let idx = original.len() as u32;

View File

@ -77,7 +77,7 @@ macro_rules! impl_intern_lookup {
impl $crate::Intern for $loc { impl $crate::Intern for $loc {
type Database<'db> = dyn $db + 'db; type Database<'db> = dyn $db + 'db;
type ID = $id; type ID = $id;
fn intern<'db>(self, db: &Self::Database<'db>) -> $id { fn intern(self, db: &Self::Database<'_>) -> $id {
db.$intern(self) db.$intern(self)
} }
} }
@ -85,7 +85,7 @@ macro_rules! impl_intern_lookup {
impl $crate::Lookup for $id { impl $crate::Lookup for $id {
type Database<'db> = dyn $db + 'db; type Database<'db> = dyn $db + 'db;
type Data = $loc; type Data = $loc;
fn lookup<'db>(&self, db: &Self::Database<'db>) -> $loc { fn lookup(&self, db: &Self::Database<'_>) -> $loc {
db.$lookup(*self) db.$lookup(*self)
} }
} }
@ -96,13 +96,13 @@ macro_rules! impl_intern_lookup {
pub trait Intern { pub trait Intern {
type Database<'db>: ?Sized; type Database<'db>: ?Sized;
type ID; type ID;
fn intern<'db>(self, db: &Self::Database<'db>) -> Self::ID; fn intern(self, db: &Self::Database<'_>) -> Self::ID;
} }
pub trait Lookup { pub trait Lookup {
type Database<'db>: ?Sized; type Database<'db>: ?Sized;
type Data; type Data;
fn lookup<'db>(&self, db: &Self::Database<'db>) -> Self::Data; fn lookup(&self, db: &Self::Database<'_>) -> Self::Data;
} }
impl_intern_lookup!( impl_intern_lookup!(
@ -425,7 +425,7 @@ impl MacroDefId {
pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> { pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
match self.kind { match self.kind {
MacroDefKind::ProcMacro(.., id) => return Either::Right(id), MacroDefKind::ProcMacro(.., id) => Either::Right(id),
MacroDefKind::Declarative(id) MacroDefKind::Declarative(id)
| MacroDefKind::BuiltIn(_, id) | MacroDefKind::BuiltIn(_, id)
| MacroDefKind::BuiltInAttr(_, id) | MacroDefKind::BuiltInAttr(_, id)
@ -657,10 +657,10 @@ impl ExpansionInfo {
} }
/// Maps the passed in file range down into a macro expansion if it is the input to a macro call. /// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
pub fn map_range_down<'a>( pub fn map_range_down(
&'a self, &self,
span: Span, span: Span,
) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + 'a>> { ) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + '_>> {
let tokens = self let tokens = self
.exp_map .exp_map
.ranges_with_span(span) .ranges_with_span(span)

View File

@ -301,7 +301,7 @@ pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) ->
result_mark = Some(mark); result_mark = Some(mark);
} }
result_mark.flatten().map(|call| db.lookup_intern_macro_call(call.into()).def.krate) result_mark.flatten().map(|call| db.lookup_intern_macro_call(call).def.krate)
} }
pub use crate::name as __name; pub use crate::name as __name;

View File

@ -2,7 +2,7 @@
use std::fmt; use std::fmt;
use syntax::{ast, utils::is_raw_identifier, SmolStr}; use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr};
/// `Name` is a wrapper around string, which is used in hir for both references /// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are /// and declarations. In theory, names should also carry hygiene info, but we are
@ -69,8 +69,8 @@ impl Name {
} }
/// Shortcut to create inline plain text name. Panics if `text.len() > 22` /// Shortcut to create inline plain text name. Panics if `text.len() > 22`
const fn new_inline(text: &str) -> Name { const fn new_static(text: &'static str) -> Name {
Name::new_text(SmolStr::new_inline(text)) Name::new_text(SmolStr::new_static(text))
} }
/// Resolve a name from the text of token. /// Resolve a name from the text of token.
@ -83,7 +83,7 @@ impl Name {
// Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their // Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their
// escaped form. // escaped form.
None if is_raw_identifier(raw_text) => { None if is_raw_identifier(raw_text) => {
Name::new_text(SmolStr::from_iter(["r#", raw_text])) Name::new_text(format_smolstr!("r#{}", raw_text))
} }
_ => Name::new_text(raw_text.into()), _ => Name::new_text(raw_text.into()),
} }
@ -99,7 +99,7 @@ impl Name {
/// name is equal only to itself. It's not clear how to implement this in /// name is equal only to itself. It's not clear how to implement this in
/// salsa though, so we punt on that bit for a moment. /// salsa though, so we punt on that bit for a moment.
pub const fn missing() -> Name { pub const fn missing() -> Name {
Name::new_inline("[missing name]") Name::new_static("[missing name]")
} }
/// Returns true if this is a fake name for things missing in the source code. See /// Returns true if this is a fake name for things missing in the source code. See
@ -119,7 +119,7 @@ impl Name {
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
static CNT: AtomicUsize = AtomicUsize::new(0); static CNT: AtomicUsize = AtomicUsize::new(0);
let c = CNT.fetch_add(1, Ordering::Relaxed); let c = CNT.fetch_add(1, Ordering::Relaxed);
Name::new_text(format!("<ra@gennew>{c}").into()) Name::new_text(format_smolstr!("<ra@gennew>{c}"))
} }
/// Returns the tuple index this name represents if it is a tuple field. /// Returns the tuple index this name represents if it is a tuple field.
@ -260,7 +260,7 @@ pub mod known {
$( $(
#[allow(bad_style)] #[allow(bad_style)]
pub const $ident: super::Name = pub const $ident: super::Name =
super::Name::new_inline(stringify!($ident)); super::Name::new_static(stringify!($ident));
)* )*
}; };
} }
@ -471,11 +471,11 @@ pub mod known {
); );
// self/Self cannot be used as an identifier // self/Self cannot be used as an identifier
pub const SELF_PARAM: super::Name = super::Name::new_inline("self"); pub const SELF_PARAM: super::Name = super::Name::new_static("self");
pub const SELF_TYPE: super::Name = super::Name::new_inline("Self"); pub const SELF_TYPE: super::Name = super::Name::new_static("Self");
pub const STATIC_LIFETIME: super::Name = super::Name::new_inline("'static"); pub const STATIC_LIFETIME: super::Name = super::Name::new_static("'static");
pub const DOLLAR_CRATE: super::Name = super::Name::new_inline("$crate"); pub const DOLLAR_CRATE: super::Name = super::Name::new_static("$crate");
#[macro_export] #[macro_export]
macro_rules! name { macro_rules! name {

View File

@ -1,11 +1,13 @@
//! A simplified version of quote-crate like quasi quote macro //! A simplified version of quote-crate like quasi quote macro
#![allow(clippy::crate_in_macro_def)]
use span::Span; use span::Span;
use syntax::format_smolstr;
use crate::name::Name; use crate::name::Name;
pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> { pub(crate) const fn dollar_crate(span: Span) -> tt::Ident<Span> {
tt::Ident { text: syntax::SmolStr::new_inline("$crate"), span } tt::Ident { text: syntax::SmolStr::new_static("$crate"), span }
} }
// A helper macro quote macro // A helper macro quote macro
@ -17,13 +19,13 @@ pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
#[macro_export] #[macro_export]
macro_rules! __quote { macro_rules! __quote {
($span:ident) => { ($span:ident) => {
Vec::<crate::tt::TokenTree>::new() Vec::<$crate::tt::TokenTree>::new()
}; };
( @SUBTREE($span:ident) $delim:ident $($tt:tt)* ) => { ( @SUBTREE($span:ident) $delim:ident $($tt:tt)* ) => {
{ {
let children = $crate::__quote!($span $($tt)*); let children = $crate::__quote!($span $($tt)*);
crate::tt::Subtree { $crate::tt::Subtree {
delimiter: crate::tt::Delimiter { delimiter: crate::tt::Delimiter {
kind: crate::tt::DelimiterKind::$delim, kind: crate::tt::DelimiterKind::$delim,
open: $span, open: $span,
@ -214,8 +216,8 @@ impl_to_to_tokentrees! {
_span: crate::tt::Literal => self { self }; _span: crate::tt::Literal => self { self };
_span: crate::tt::Ident => self { self }; _span: crate::tt::Ident => self { self };
_span: crate::tt::Punct => self { self }; _span: crate::tt::Punct => self { self };
span: &str => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}}; span: &str => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}};
span: String => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}}; span: String => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}};
span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}}; span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}};
} }

View File

@ -23,10 +23,10 @@ oorandom = "11.1.3"
tracing.workspace = true tracing.workspace = true
rustc-hash.workspace = true rustc-hash.workspace = true
scoped-tls = "1.0.0" scoped-tls = "1.0.0"
chalk-solve = { version = "0.95.0", default-features = false } chalk-solve = { version = "0.96.0", default-features = false }
chalk-ir = "0.95.0" chalk-ir = "0.96.0"
chalk-recursive = { version = "0.95.0", default-features = false } chalk-recursive = { version = "0.96.0", default-features = false }
chalk-derive = "0.95.0" chalk-derive = "0.96.0"
la-arena.workspace = true la-arena.workspace = true
once_cell = "1.17.0" once_cell = "1.17.0"
triomphe.workspace = true triomphe.workspace = true

View File

@ -227,21 +227,21 @@ impl TyBuilder<()> {
TyBuilder::new((), params, parent_subst) TyBuilder::new((), params, parent_subst)
} }
/// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`. /// Creates a `TyBuilder` to build `Substitution` for a coroutine defined in `parent`.
/// ///
/// A generator's substitution consists of: /// A coroutine's substitution consists of:
/// - resume type of generator /// - resume type of coroutine
/// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield)) /// - yield type of coroutine ([`Coroutine::Yield`](std::ops::Coroutine::Yield))
/// - return type of generator ([`Generator::Return`](std::ops::Generator::Return)) /// - return type of coroutine ([`Coroutine::Return`](std::ops::Coroutine::Return))
/// - generic parameters in scope on `parent` /// - generic parameters in scope on `parent`
/// in this order. /// in this order.
/// ///
/// This method prepopulates the builder with placeholder substitution of `parent`, so you /// This method prepopulates the builder with placeholder substitution of `parent`, so you
/// should only push exactly 3 `GenericArg`s before building. /// should only push exactly 3 `GenericArg`s before building.
pub fn subst_for_generator(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> { pub fn subst_for_coroutine(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
let parent_subst = let parent_subst =
parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db)); parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db));
// These represent resume type, yield type, and return type of generator. // These represent resume type, yield type, and return type of coroutine.
let params = std::iter::repeat(ParamKind::Type).take(3).collect(); let params = std::iter::repeat(ParamKind::Type).take(3).collect();
TyBuilder::new((), params, parent_subst) TyBuilder::new((), params, parent_subst)
} }

View File

@ -230,7 +230,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
well_known_trait: rust_ir::WellKnownTrait, well_known_trait: rust_ir::WellKnownTrait,
) -> Option<chalk_ir::TraitId<Interner>> { ) -> Option<chalk_ir::TraitId<Interner>> {
let lang_attr = lang_item_from_well_known_trait(well_known_trait); let lang_attr = lang_item_from_well_known_trait(well_known_trait);
let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) { let trait_ = match self.db.lang_item(self.krate, lang_attr) {
Some(LangItemTarget::Trait(trait_)) => trait_, Some(LangItemTarget::Trait(trait_)) => trait_,
_ => return None, _ => return None,
}; };
@ -424,18 +424,18 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId<Interner>) -> String { fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId<Interner>) -> String {
format!("fn_{}", fn_def_id.0) format!("fn_{}", fn_def_id.0)
} }
fn generator_datum( fn coroutine_datum(
&self, &self,
id: chalk_ir::GeneratorId<Interner>, id: chalk_ir::CoroutineId<Interner>,
) -> Arc<chalk_solve::rust_ir::GeneratorDatum<Interner>> { ) -> Arc<chalk_solve::rust_ir::CoroutineDatum<Interner>> {
let (parent, expr) = self.db.lookup_intern_generator(id.into()); let (parent, expr) = self.db.lookup_intern_coroutine(id.into());
// We fill substitution with unknown type, because we only need to know whether the generic // We fill substitution with unknown type, because we only need to know whether the generic
// params are types or consts to build `Binders` and those being filled up are for // params are types or consts to build `Binders` and those being filled up are for
// `resume_type`, `yield_type`, and `return_type` of the generator in question. // `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build(); let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
let input_output = rust_ir::GeneratorInputOutputDatum { let input_output = rust_ir::CoroutineInputOutputDatum {
resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(Interner), .intern(Interner),
yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1)) yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1))
@ -453,35 +453,35 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
let movability = match self.db.body(parent)[expr] { let movability = match self.db.body(parent)[expr] {
hir_def::hir::Expr::Closure { hir_def::hir::Expr::Closure {
closure_kind: hir_def::hir::ClosureKind::Generator(movability), closure_kind: hir_def::hir::ClosureKind::Coroutine(movability),
.. ..
} => movability, } => movability,
_ => unreachable!("non generator expression interned as generator"), _ => unreachable!("non coroutine expression interned as coroutine"),
}; };
let movability = match movability { let movability = match movability {
Movability::Static => rust_ir::Movability::Static, Movability::Static => rust_ir::Movability::Static,
Movability::Movable => rust_ir::Movability::Movable, Movability::Movable => rust_ir::Movability::Movable,
}; };
Arc::new(rust_ir::GeneratorDatum { movability, input_output }) Arc::new(rust_ir::CoroutineDatum { movability, input_output })
} }
fn generator_witness_datum( fn coroutine_witness_datum(
&self, &self,
id: chalk_ir::GeneratorId<Interner>, id: chalk_ir::CoroutineId<Interner>,
) -> Arc<chalk_solve::rust_ir::GeneratorWitnessDatum<Interner>> { ) -> Arc<chalk_solve::rust_ir::CoroutineWitnessDatum<Interner>> {
// FIXME: calculate inner types // FIXME: calculate inner types
let inner_types = let inner_types =
rust_ir::GeneratorWitnessExistential { types: wrap_empty_binders(vec![]) }; rust_ir::CoroutineWitnessExistential { types: wrap_empty_binders(vec![]) };
let (parent, _) = self.db.lookup_intern_generator(id.into()); let (parent, _) = self.db.lookup_intern_coroutine(id.into());
// See the comment in `generator_datum()` for unknown types. // See the comment in `coroutine_datum()` for unknown types.
let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build(); let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
let it = subst let it = subst
.iter(Interner) .iter(Interner)
.map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone())); .map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
let inner_types = crate::make_type_and_const_binders(it, inner_types); let inner_types = crate::make_type_and_const_binders(it, inner_types);
Arc::new(rust_ir::GeneratorWitnessDatum { inner_types }) Arc::new(rust_ir::CoroutineWitnessDatum { inner_types })
} }
fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> { fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
@ -617,7 +617,7 @@ fn well_known_trait_from_lang_item(item: LangItem) -> Option<WellKnownTrait> {
LangItem::Fn => WellKnownTrait::Fn, LangItem::Fn => WellKnownTrait::Fn,
LangItem::FnMut => WellKnownTrait::FnMut, LangItem::FnMut => WellKnownTrait::FnMut,
LangItem::FnOnce => WellKnownTrait::FnOnce, LangItem::FnOnce => WellKnownTrait::FnOnce,
LangItem::Generator => WellKnownTrait::Generator, LangItem::Coroutine => WellKnownTrait::Coroutine,
LangItem::Sized => WellKnownTrait::Sized, LangItem::Sized => WellKnownTrait::Sized,
LangItem::Unpin => WellKnownTrait::Unpin, LangItem::Unpin => WellKnownTrait::Unpin,
LangItem::Unsize => WellKnownTrait::Unsize, LangItem::Unsize => WellKnownTrait::Unsize,
@ -639,7 +639,7 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem {
WellKnownTrait::Fn => LangItem::Fn, WellKnownTrait::Fn => LangItem::Fn,
WellKnownTrait::FnMut => LangItem::FnMut, WellKnownTrait::FnMut => LangItem::FnMut,
WellKnownTrait::FnOnce => LangItem::FnOnce, WellKnownTrait::FnOnce => LangItem::FnOnce,
WellKnownTrait::Generator => LangItem::Generator, WellKnownTrait::Coroutine => LangItem::Coroutine,
WellKnownTrait::Sized => LangItem::Sized, WellKnownTrait::Sized => LangItem::Sized,
WellKnownTrait::Tuple => LangItem::Tuple, WellKnownTrait::Tuple => LangItem::Tuple,
WellKnownTrait::Unpin => LangItem::Unpin, WellKnownTrait::Unpin => LangItem::Unpin,
@ -819,7 +819,11 @@ pub(crate) fn fn_def_datum_query(
}; };
let datum = FnDefDatum { let datum = FnDefDatum {
id: fn_def_id, id: fn_def_id,
sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs }, sig: chalk_ir::FnSig {
abi: sig.abi,
safety: chalk_ir::Safety::Safe,
variadic: sig.is_varargs,
},
binders: chalk_ir::Binders::new(binders, bound), binders: chalk_ir::Binders::new(binders, bound),
}; };
Arc::new(datum) Arc::new(datum)

View File

@ -202,11 +202,7 @@ impl TyExt for Ty {
fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> { fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
match self.kind(Interner) { match self.kind(Interner) {
TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)), TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
TyKind::FnDef(def, parameters) => { TyKind::FnDef(def, parameters) => Some(CallableSig::from_def(db, *def, parameters)),
let callable_def = db.lookup_intern_callable_def((*def).into());
let sig = db.callable_item_signature(callable_def);
Some(sig.substitute(Interner, parameters))
}
TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db), TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db),
_ => None, _ => None,
} }
@ -218,7 +214,7 @@ impl TyExt for Ty {
// invariant ensured by `TyLoweringContext::lower_dyn_trait()`. // invariant ensured by `TyLoweringContext::lower_dyn_trait()`.
// FIXME: dyn types may not have principal trait and we don't want to return auto trait // FIXME: dyn types may not have principal trait and we don't want to return auto trait
// here. // here.
TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| { TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().first().and_then(|b| {
match b.skip_binders() { match b.skip_binders() {
WhereClause::Implemented(trait_ref) => Some(trait_ref), WhereClause::Implemented(trait_ref) => Some(trait_ref),
_ => None, _ => None,
@ -427,7 +423,7 @@ pub trait DynTyExt {
impl DynTyExt for DynTy { impl DynTyExt for DynTy {
fn principal(&self) -> Option<&TraitRef> { fn principal(&self) -> Option<&TraitRef> {
self.bounds.skip_binders().interned().get(0).and_then(|b| match b.skip_binders() { self.bounds.skip_binders().interned().first().and_then(|b| match b.skip_binders() {
crate::WhereClause::Implemented(trait_ref) => Some(trait_ref), crate::WhereClause::Implemented(trait_ref) => Some(trait_ref),
_ => None, _ => None,
}) })

View File

@ -10,7 +10,7 @@ use hir_def::{
type_ref::LiteralConstRef, type_ref::LiteralConstRef,
ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId, ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
}; };
use la_arena::{Idx, RawIdx}; use hir_expand::Lookup;
use stdx::never; use stdx::never;
use triomphe::Arc; use triomphe::Arc;
@ -173,7 +173,7 @@ pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
chalk_ir::ConstValue::InferenceVar(_) => None, chalk_ir::ConstValue::InferenceVar(_) => None,
chalk_ir::ConstValue::Placeholder(_) => None, chalk_ir::ConstValue::Placeholder(_) => None,
chalk_ir::ConstValue::Concrete(c) => match &c.interned { chalk_ir::ConstValue::Concrete(c) => match &c.interned {
ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))), ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, false))),
ConstScalar::UnevaluatedConst(c, subst) => { ConstScalar::UnevaluatedConst(c, subst) => {
let ec = db.const_eval(*c, subst.clone(), None).ok()?; let ec = db.const_eval(*c, subst.clone(), None).ok()?;
try_const_usize(db, &ec) try_const_usize(db, &ec)
@ -256,12 +256,13 @@ pub(crate) fn const_eval_discriminant_variant(
let def = variant_id.into(); let def = variant_id.into();
let body = db.body(def); let body = db.body(def);
if body.exprs[body.body_expr] == Expr::Missing { if body.exprs[body.body_expr] == Expr::Missing {
let prev_idx: u32 = variant_id.local_id.into_raw().into(); let loc = variant_id.lookup(db.upcast());
let prev_idx = prev_idx.checked_sub(1).map(RawIdx::from).map(Idx::from_raw); let prev_idx = loc.index.checked_sub(1);
let value = match prev_idx { let value = match prev_idx {
Some(local_id) => { Some(prev_idx) => {
let prev_variant = EnumVariantId { local_id, parent: variant_id.parent }; 1 + db.const_eval_discriminant(
1 + db.const_eval_discriminant(prev_variant)? db.enum_data(loc.parent).variants[prev_idx as usize].0,
)?
} }
_ => 0, _ => 0,
}; };
@ -297,7 +298,7 @@ pub(crate) fn eval_to_const(
body[expr].walk_child_exprs(|idx| r |= has_closure(body, idx)); body[expr].walk_child_exprs(|idx| r |= has_closure(body, idx));
r r
} }
if has_closure(&ctx.body, expr) { if has_closure(ctx.body, expr) {
// Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic. // Type checking clousres need an isolated body (See the above FIXME). Bail out early to prevent panic.
return unknown_const(infer[expr].clone()); return unknown_const(infer[expr].clone());
} }
@ -307,7 +308,7 @@ pub(crate) fn eval_to_const(
return c; return c;
} }
} }
if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) { if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) {
if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 { if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
return result; return result;
} }

View File

@ -86,8 +86,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::cycle(crate::lower::ty_recover)] #[salsa::cycle(crate::lower::ty_recover)]
fn ty(&self, def: TyDefId) -> Binders<Ty>; fn ty(&self, def: TyDefId) -> Binders<Ty>;
/// Returns the type of the value of the given constant, or `None` if the the `ValueTyDefId` is
/// a `StructId` or `EnumVariantId` with a record constructor.
#[salsa::invoke(crate::lower::value_ty_query)] #[salsa::invoke(crate::lower::value_ty_query)]
fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>; fn value_ty(&self, def: ValueTyDefId) -> Option<Binders<Ty>>;
#[salsa::invoke(crate::lower::impl_self_ty_query)] #[salsa::invoke(crate::lower::impl_self_ty_query)]
#[salsa::cycle(crate::lower::impl_self_ty_recover)] #[salsa::cycle(crate::lower::impl_self_ty_recover)]
@ -199,7 +201,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::interned] #[salsa::interned]
fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
#[salsa::interned] #[salsa::interned]
fn intern_generator(&self, id: (DefWithBodyId, ExprId)) -> InternedGeneratorId; fn intern_coroutine(&self, id: (DefWithBodyId, ExprId)) -> InternedCoroutineId;
#[salsa::invoke(chalk_db::associated_ty_data_query)] #[salsa::invoke(chalk_db::associated_ty_data_query)]
fn associated_ty_data( fn associated_ty_data(
@ -292,7 +294,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
.display(db.upcast()) .display(db.upcast())
.to_string(), .to_string(),
DefWithBodyId::VariantId(it) => { DefWithBodyId::VariantId(it) => {
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string() db.enum_variant_data(it).name.display(db.upcast()).to_string()
} }
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"), DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
}); });
@ -335,8 +337,8 @@ pub struct InternedClosureId(salsa::InternId);
impl_intern_key!(InternedClosureId); impl_intern_key!(InternedClosureId);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InternedGeneratorId(salsa::InternId); pub struct InternedCoroutineId(salsa::InternId);
impl_intern_key!(InternedGeneratorId); impl_intern_key!(InternedCoroutineId);
/// This exists just for Chalk, because Chalk just has a single `FnDefId` where /// This exists just for Chalk, because Chalk just has a single `FnDefId` where
/// we have different IDs for struct and enum variant constructors. /// we have different IDs for struct and enum variant constructors.

View File

@ -387,7 +387,7 @@ impl<'a> DeclValidator<'a> {
for (id, replacement) in pats_replacements { for (id, replacement) in pats_replacements {
if let Ok(source_ptr) = source_map.pat_syntax(id) { if let Ok(source_ptr) = source_map.pat_syntax(id) {
if let Some(ptr) = source_ptr.value.clone().cast::<ast::IdentPat>() { if let Some(ptr) = source_ptr.value.cast::<ast::IdentPat>() {
let root = source_ptr.file_syntax(self.db.upcast()); let root = source_ptr.file_syntax(self.db.upcast());
let ident_pat = ptr.to_node(&root); let ident_pat = ptr.to_node(&root);
let parent = match ident_pat.syntax().parent() { let parent = match ident_pat.syntax().parent() {
@ -582,11 +582,11 @@ impl<'a> DeclValidator<'a> {
// Check the field names. // Check the field names.
let enum_fields_replacements = data let enum_fields_replacements = data
.variants .variants
.values() .iter()
.filter_map(|variant| { .filter_map(|(_, name)| {
Some(Replacement { Some(Replacement {
current_name: variant.name.clone(), current_name: name.clone(),
suggested_text: to_camel_case(&variant.name.to_smol_str())?, suggested_text: to_camel_case(&name.to_smol_str())?,
expected_case: CaseType::UpperCamelCase, expected_case: CaseType::UpperCamelCase,
}) })
}) })

View File

@ -114,35 +114,27 @@ impl ExprValidator {
) { ) {
// Check that the number of arguments matches the number of parameters. // Check that the number of arguments matches the number of parameters.
// FIXME: Due to shortcomings in the current type system implementation, only emit this
// diagnostic if there are no type mismatches in the containing function.
if self.infer.expr_type_mismatches().next().is_some() { if self.infer.expr_type_mismatches().next().is_some() {
return; // FIXME: Due to shortcomings in the current type system implementation, only emit
} // this diagnostic if there are no type mismatches in the containing function.
} else if let Expr::MethodCall { receiver, .. } = expr {
let (callee, _) = match self.infer.method_resolution(call_id) {
Some(it) => it,
None => return,
};
match expr { if filter_map_next_checker
Expr::MethodCall { receiver, .. } => { .get_or_insert_with(|| {
let (callee, _) = match self.infer.method_resolution(call_id) { FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db)
Some(it) => it, })
None => return, .check(call_id, receiver, &callee)
}; .is_some()
{
if filter_map_next_checker self.diagnostics.push(BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap {
.get_or_insert_with(|| { method_call_expr: call_id,
FilterMapNextChecker::new(&self.owner.resolver(db.upcast()), db) });
})
.check(call_id, receiver, &callee)
.is_some()
{
self.diagnostics.push(
BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap {
method_call_expr: call_id,
},
);
}
} }
_ => return, }
};
} }
fn validate_match( fn validate_match(

View File

@ -318,8 +318,7 @@ impl HirDisplay for Pat {
if let Some(variant) = variant { if let Some(variant) = variant {
match variant { match variant {
VariantId::EnumVariantId(v) => { VariantId::EnumVariantId(v) => {
let data = f.db.enum_data(v.parent); write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?;
write!(f, "{}", data.variants[v.local_id].name.display(f.db.upcast()))?;
} }
VariantId::StructId(s) => { VariantId::StructId(s) => {
write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))? write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?

View File

@ -594,7 +594,7 @@ impl SplitWildcard {
let mut ctors: SmallVec<[_; 1]> = enum_data let mut ctors: SmallVec<[_; 1]> = enum_data
.variants .variants
.iter() .iter()
.map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id }) .map(|&(variant, _)| variant)
.filter(|&variant| { .filter(|&variant| {
// If `exhaustive_patterns` is enabled, we exclude variants known to be // If `exhaustive_patterns` is enabled, we exclude variants known to be
// uninhabited. // uninhabited.

View File

@ -409,7 +409,7 @@ impl<'p> Matrix<'p> {
/// Number of columns of this matrix. `None` is the matrix is empty. /// Number of columns of this matrix. `None` is the matrix is empty.
pub(super) fn _column_count(&self) -> Option<usize> { pub(super) fn _column_count(&self) -> Option<usize> {
self.patterns.get(0).map(|r| r.len()) self.patterns.first().map(|r| r.len())
} }
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively

View File

@ -8,7 +8,7 @@ use std::{
}; };
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::{BoundVar, TyKind}; use chalk_ir::{BoundVar, Safety, TyKind};
use hir_def::{ use hir_def::{
data::adt::VariantData, data::adt::VariantData,
db::DefDatabase, db::DefDatabase,
@ -20,8 +20,7 @@ use hir_def::{
path::{Path, PathKind}, path::{Path, PathKind},
type_ref::{TraitBoundModifier, TypeBound, TypeRef}, type_ref::{TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility, visibility::Visibility,
EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::{Internable, Interned}; use intern::{Internable, Interned};
@ -42,7 +41,7 @@ use crate::{
primitive, to_assoc_type_id, primitive, to_assoc_type_id,
utils::{self, detect_variant_from_bytes, generics, ClosureSubst}, utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue, AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
}; };
@ -276,7 +275,7 @@ impl DisplayTarget {
pub enum DisplaySourceCodeError { pub enum DisplaySourceCodeError {
PathNotFound, PathNotFound,
UnknownType, UnknownType,
Generator, Coroutine,
OpaqueType, OpaqueType,
} }
@ -428,7 +427,7 @@ impl HirDisplay for Const {
Ok(()) Ok(())
} }
ConstValue::Concrete(c) => match &c.interned { ConstValue::Concrete(c) => match &c.interned {
ConstScalar::Bytes(b, m) => render_const_scalar(f, &b, m, &data.ty), ConstScalar::Bytes(b, m) => render_const_scalar(f, b, m, &data.ty),
ConstScalar::UnevaluatedConst(c, parameters) => { ConstScalar::UnevaluatedConst(c, parameters) => {
write!(f, "{}", c.name(f.db.upcast()))?; write!(f, "{}", c.name(f.db.upcast()))?;
hir_fmt_generics(f, parameters, c.generic_def(f.db.upcast()))?; hir_fmt_generics(f, parameters, c.generic_def(f.db.upcast()))?;
@ -452,7 +451,7 @@ fn render_const_scalar(
TraitEnvironment::empty(*f.db.crate_graph().crates_in_topological_order().last().unwrap()); TraitEnvironment::empty(*f.db.crate_graph().crates_in_topological_order().last().unwrap());
match ty.kind(Interner) { match ty.kind(Interner) {
TyKind::Scalar(s) => match s { TyKind::Scalar(s) => match s {
Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }), Scalar::Bool => write!(f, "{}", b[0] != 0),
Scalar::Char => { Scalar::Char => {
let it = u128::from_le_bytes(pad16(b, false)) as u32; let it = u128::from_le_bytes(pad16(b, false)) as u32;
let Ok(c) = char::try_from(it) else { let Ok(c) = char::try_from(it) else {
@ -486,7 +485,7 @@ fn render_const_scalar(
let Some(bytes) = memory_map.get(addr, size) else { let Some(bytes) = memory_map.get(addr, size) else {
return f.write_str("<ref-data-not-available>"); return f.write_str("<ref-data-not-available>");
}; };
let s = std::str::from_utf8(&bytes).unwrap_or("<utf8-error>"); let s = std::str::from_utf8(bytes).unwrap_or("<utf8-error>");
write!(f, "{s:?}") write!(f, "{s:?}")
} }
TyKind::Slice(ty) => { TyKind::Slice(ty) => {
@ -508,7 +507,7 @@ fn render_const_scalar(
f.write_str(", ")?; f.write_str(", ")?;
} }
let offset = size_one * i; let offset = size_one * i;
render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, &ty)?; render_const_scalar(f, &bytes[offset..offset + size_one], memory_map, ty)?;
} }
f.write_str("]") f.write_str("]")
} }
@ -534,9 +533,7 @@ fn render_const_scalar(
write!(f, "&{}", data.name.display(f.db.upcast()))?; write!(f, "&{}", data.name.display(f.db.upcast()))?;
Ok(()) Ok(())
} }
_ => { _ => f.write_str("<unsized-enum-or-union>"),
return f.write_str("<unsized-enum-or-union>");
}
}, },
_ => { _ => {
let addr = usize::from_le_bytes(match b.try_into() { let addr = usize::from_le_bytes(match b.try_into() {
@ -580,7 +577,7 @@ fn render_const_scalar(
continue; continue;
}; };
let size = layout.size.bytes_usize(); let size = layout.size.bytes_usize();
render_const_scalar(f, &b[offset..offset + size], memory_map, &ty)?; render_const_scalar(f, &b[offset..offset + size], memory_map, ty)?;
} }
f.write_str(")") f.write_str(")")
} }
@ -613,16 +610,15 @@ fn render_const_scalar(
else { else {
return f.write_str("<failed-to-detect-variant>"); return f.write_str("<failed-to-detect-variant>");
}; };
let data = &f.db.enum_data(e).variants[var_id]; let data = f.db.enum_variant_data(var_id);
write!(f, "{}", data.name.display(f.db.upcast()))?; write!(f, "{}", data.name.display(f.db.upcast()))?;
let field_types = let field_types = f.db.field_types(var_id.into());
f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into());
render_variant_after_name( render_variant_after_name(
&data.variant_data, &data.variant_data,
f, f,
&field_types, &field_types,
f.db.trait_environment(adt.0.into()), f.db.trait_environment(adt.0.into()),
&var_layout, var_layout,
subst, subst,
b, b,
memory_map, memory_map,
@ -653,14 +649,14 @@ fn render_const_scalar(
f.write_str(", ")?; f.write_str(", ")?;
} }
let offset = size_one * i; let offset = size_one * i;
render_const_scalar(f, &b[offset..offset + size_one], memory_map, &ty)?; render_const_scalar(f, &b[offset..offset + size_one], memory_map, ty)?;
} }
f.write_str("]") f.write_str("]")
} }
TyKind::Never => f.write_str("!"), TyKind::Never => f.write_str("!"),
TyKind::Closure(_, _) => f.write_str("<closure>"), TyKind::Closure(_, _) => f.write_str("<closure>"),
TyKind::Generator(_, _) => f.write_str("<generator>"), TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),
TyKind::GeneratorWitness(_, _) => f.write_str("<generator-witness>"), TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),
// The below arms are unreachable, since const eval will bail out before here. // The below arms are unreachable, since const eval will bail out before here.
TyKind::Foreign(_) => f.write_str("<extern-type>"), TyKind::Foreign(_) => f.write_str("<extern-type>"),
TyKind::Error TyKind::Error
@ -720,7 +716,7 @@ fn render_variant_after_name(
} }
write!(f, ")")?; write!(f, ")")?;
} }
return Ok(()); Ok(())
} }
VariantData::Unit => Ok(()), VariantData::Unit => Ok(()),
} }
@ -866,7 +862,7 @@ impl HirDisplay for Ty {
write!(f, ",)")?; write!(f, ",)")?;
} else { } else {
write!(f, "(")?; write!(f, "(")?;
f.write_joined(&*substs.as_slice(Interner), ", ")?; f.write_joined(substs.as_slice(Interner), ", ")?;
write!(f, ")")?; write!(f, ")")?;
} }
} }
@ -883,20 +879,29 @@ impl HirDisplay for Ty {
// function pointer type. // function pointer type.
return sig.hir_fmt(f); return sig.hir_fmt(f);
} }
if let Safety::Unsafe = sig.safety {
write!(f, "unsafe ")?;
}
if !matches!(sig.abi, FnAbi::Rust) {
f.write_str("extern \"")?;
f.write_str(sig.abi.as_str())?;
f.write_str("\" ")?;
}
f.start_location_link(def.into());
match def { match def {
CallableDefId::FunctionId(ff) => { CallableDefId::FunctionId(ff) => {
write!(f, "fn {}", db.function_data(ff).name.display(f.db.upcast()))? write!(f, "fn ")?;
f.start_location_link(def.into());
write!(f, "{}", db.function_data(ff).name.display(f.db.upcast()))?
} }
CallableDefId::StructId(s) => { CallableDefId::StructId(s) => {
f.start_location_link(def.into());
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))? write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
} }
CallableDefId::EnumVariantId(e) => write!( CallableDefId::EnumVariantId(e) => {
f, f.start_location_link(def.into());
"{}", write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast()) }
)?,
}; };
f.end_location_link(); f.end_location_link();
if parameters.len(Interner) > 0 { if parameters.len(Interner) > 0 {
@ -1038,7 +1043,7 @@ impl HirDisplay for Ty {
f.start_location_link(t.into()); f.start_location_link(t.into());
} }
write!(f, "Future")?; write!(f, "Future")?;
if let Some(_) = future_trait { if future_trait.is_some() {
f.end_location_link(); f.end_location_link();
} }
write!(f, "<")?; write!(f, "<")?;
@ -1046,7 +1051,7 @@ impl HirDisplay for Ty {
f.start_location_link(t.into()); f.start_location_link(t.into());
} }
write!(f, "Output")?; write!(f, "Output")?;
if let Some(_) = output { if output.is_some() {
f.end_location_link(); f.end_location_link();
} }
write!(f, " = ")?; write!(f, " = ")?;
@ -1205,17 +1210,16 @@ impl HirDisplay for Ty {
write!(f, "{{unknown}}")?; write!(f, "{{unknown}}")?;
} }
TyKind::InferenceVar(..) => write!(f, "_")?, TyKind::InferenceVar(..) => write!(f, "_")?,
TyKind::Generator(_, subst) => { TyKind::Coroutine(_, subst) => {
if f.display_target.is_source_code() { if f.display_target.is_source_code() {
return Err(HirDisplayError::DisplaySourceCodeError( return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::Generator, DisplaySourceCodeError::Coroutine,
)); ));
} }
let subst = subst.as_slice(Interner); let subst = subst.as_slice(Interner);
let a: Option<SmallVec<[&Ty; 3]>> = subst let a: Option<SmallVec<[&Ty; 3]>> = subst
.get(subst.len() - 3..) .get(subst.len() - 3..)
.map(|args| args.iter().map(|arg| arg.ty(Interner)).collect()) .and_then(|args| args.iter().map(|arg| arg.ty(Interner)).collect());
.flatten();
if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() { if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
write!(f, "|")?; write!(f, "|")?;
@ -1229,10 +1233,10 @@ impl HirDisplay for Ty {
ret_ty.hir_fmt(f)?; ret_ty.hir_fmt(f)?;
} else { } else {
// This *should* be unreachable, but fallback just in case. // This *should* be unreachable, but fallback just in case.
write!(f, "{{generator}}")?; write!(f, "{{coroutine}}")?;
} }
} }
TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?, TyKind::CoroutineWitness(..) => write!(f, "{{coroutine witness}}")?,
} }
Ok(()) Ok(())
} }
@ -1323,9 +1327,19 @@ fn hir_fmt_generics(
impl HirDisplay for CallableSig { impl HirDisplay for CallableSig {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
let CallableSig { params_and_return: _, is_varargs, safety, abi: _ } = *self;
if let Safety::Unsafe = safety {
write!(f, "unsafe ")?;
}
// FIXME: Enable this when the FIXME on FnAbi regarding PartialEq is fixed.
// if !matches!(abi, FnAbi::Rust) {
// f.write_str("extern \"")?;
// f.write_str(abi.as_str())?;
// f.write_str("\" ")?;
// }
write!(f, "fn(")?; write!(f, "fn(")?;
f.write_joined(self.params(), ", ")?; f.write_joined(self.params(), ", ")?;
if self.is_varargs { if is_varargs {
if self.params().is_empty() { if self.params().is_empty() {
write!(f, "...")?; write!(f, "...")?;
} else { } else {
@ -1426,7 +1440,7 @@ fn write_bounds_like_dyn_trait(
f.start_location_link(trait_.into()); f.start_location_link(trait_.into());
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?; write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
f.end_location_link(); f.end_location_link();
if let [_, params @ ..] = &*trait_ref.substitution.as_slice(Interner) { if let [_, params @ ..] = trait_ref.substitution.as_slice(Interner) {
if is_fn_trait { if is_fn_trait {
if let Some(args) = if let Some(args) =
params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple()) params.first().and_then(|it| it.assert_ty_ref(Interner).as_tuple())
@ -1506,7 +1520,7 @@ fn write_bounds_like_dyn_trait(
} }
write!(f, "Sized")?; write!(f, "Sized")?;
} }
if let Some(_) = sized_trait { if sized_trait.is_some() {
f.end_location_link(); f.end_location_link();
} }
} }
@ -1690,11 +1704,15 @@ impl HirDisplay for TypeRef {
inner.hir_fmt(f)?; inner.hir_fmt(f)?;
write!(f, "]")?; write!(f, "]")?;
} }
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => { &TypeRef::Fn(ref parameters, is_varargs, is_unsafe, ref abi) => {
// FIXME: Function pointer qualifiers.
if is_unsafe { if is_unsafe {
write!(f, "unsafe ")?; write!(f, "unsafe ")?;
} }
if let Some(abi) = abi {
f.write_str("extern \"")?;
f.write_str(abi)?;
f.write_str("\" ")?;
}
write!(f, "fn(")?; write!(f, "fn(")?;
if let Some(((_, return_type), function_parameters)) = parameters.split_last() { if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
for index in 0..function_parameters.len() { for index in 0..function_parameters.len() {

View File

@ -40,8 +40,8 @@ use hir_def::{
path::{ModPath, Path}, path::{ModPath, Path},
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs}, resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
type_ref::TypeRef, type_ref::TypeRef,
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup, AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, TupleFieldId, TupleId, TypeAliasId, VariantId,
}; };
use hir_expand::name::{name, Name}; use hir_expand::name::{name, Name};
use indexmap::IndexSet; use indexmap::IndexSet;
@ -87,28 +87,30 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)), DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)), DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
DefWithBodyId::VariantId(v) => { DefWithBodyId::VariantId(v) => {
ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() { ctx.return_ty = TyBuilder::builtin(
hir_def::layout::IntegerType::Pointer(signed) => match signed { match db.enum_data(v.lookup(db.upcast()).parent).variant_body_type() {
true => BuiltinType::Int(BuiltinInt::Isize), hir_def::layout::IntegerType::Pointer(signed) => match signed {
false => BuiltinType::Uint(BuiltinUint::Usize), true => BuiltinType::Int(BuiltinInt::Isize),
false => BuiltinType::Uint(BuiltinUint::Usize),
},
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
true => BuiltinType::Int(match size {
Integer::I8 => BuiltinInt::I8,
Integer::I16 => BuiltinInt::I16,
Integer::I32 => BuiltinInt::I32,
Integer::I64 => BuiltinInt::I64,
Integer::I128 => BuiltinInt::I128,
}),
false => BuiltinType::Uint(match size {
Integer::I8 => BuiltinUint::U8,
Integer::I16 => BuiltinUint::U16,
Integer::I32 => BuiltinUint::U32,
Integer::I64 => BuiltinUint::U64,
Integer::I128 => BuiltinUint::U128,
}),
},
}, },
hir_def::layout::IntegerType::Fixed(size, signed) => match signed { );
true => BuiltinType::Int(match size {
Integer::I8 => BuiltinInt::I8,
Integer::I16 => BuiltinInt::I16,
Integer::I32 => BuiltinInt::I32,
Integer::I64 => BuiltinInt::I64,
Integer::I128 => BuiltinInt::I128,
}),
false => BuiltinType::Uint(match size {
Integer::I8 => BuiltinUint::U8,
Integer::I16 => BuiltinUint::U16,
Integer::I32 => BuiltinUint::U32,
Integer::I64 => BuiltinUint::U64,
Integer::I128 => BuiltinUint::U128,
}),
},
});
} }
DefWithBodyId::InTypeConstId(c) => { DefWithBodyId::InTypeConstId(c) => {
// FIXME(const-generic-body): We should not get the return type in this way. // FIXME(const-generic-body): We should not get the return type in this way.
@ -154,8 +156,9 @@ pub(crate) fn normalize(db: &dyn HirDatabase, trait_env: Arc<TraitEnvironment>,
/// Binding modes inferred for patterns. /// Binding modes inferred for patterns.
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes> /// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
pub enum BindingMode { pub enum BindingMode {
#[default]
Move, Move,
Ref(Mutability), Ref(Mutability),
} }
@ -170,12 +173,6 @@ impl BindingMode {
} }
} }
impl Default for BindingMode {
fn default() -> Self {
BindingMode::Move
}
}
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InferOk<T> { pub(crate) struct InferOk<T> {
value: T, value: T,
@ -534,7 +531,7 @@ pub(crate) struct InferenceContext<'a> {
/// expressions. If `None`, this is in a context where return is /// expressions. If `None`, this is in a context where return is
/// inappropriate, such as a const expression. /// inappropriate, such as a const expression.
return_coercion: Option<CoerceMany>, return_coercion: Option<CoerceMany>,
/// The resume type and the yield type, respectively, of the generator being inferred. /// The resume type and the yield type, respectively, of the coroutine being inferred.
resume_yield_tys: Option<(Ty, Ty)>, resume_yield_tys: Option<(Ty, Ty)>,
diverges: Diverges, diverges: Diverges,
breakables: Vec<BreakableContext>, breakables: Vec<BreakableContext>,
@ -570,10 +567,10 @@ enum BreakableKind {
Border, Border,
} }
fn find_breakable<'c>( fn find_breakable(
ctxs: &'c mut [BreakableContext], ctxs: &mut [BreakableContext],
label: Option<LabelId>, label: Option<LabelId>,
) -> Option<&'c mut BreakableContext> { ) -> Option<&mut BreakableContext> {
let mut ctxs = ctxs let mut ctxs = ctxs
.iter_mut() .iter_mut()
.rev() .rev()
@ -584,10 +581,10 @@ fn find_breakable<'c>(
} }
} }
fn find_continuable<'c>( fn find_continuable(
ctxs: &'c mut [BreakableContext], ctxs: &mut [BreakableContext],
label: Option<LabelId>, label: Option<LabelId>,
) -> Option<&'c mut BreakableContext> { ) -> Option<&mut BreakableContext> {
match label { match label {
Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)), Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
None => find_breakable(ctxs, label), None => find_breakable(ctxs, label),
@ -823,8 +820,8 @@ impl<'a> InferenceContext<'a> {
ImplTraitId::ReturnTypeImplTrait(_, idx) => idx, ImplTraitId::ReturnTypeImplTrait(_, idx) => idx,
_ => unreachable!(), _ => unreachable!(),
}; };
let bounds = (*rpits) let bounds =
.map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.into_iter())); (*rpits).map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.iter()));
let var = self.table.new_type_var(); let var = self.table.new_type_var();
let var_subst = Substitution::from1(Interner, var.clone()); let var_subst = Substitution::from1(Interner, var.clone());
for bound in bounds { for bound in bounds {
@ -1062,7 +1059,7 @@ impl<'a> InferenceContext<'a> {
Some(ResolveValueResult::ValueNs(value, _)) => match value { Some(ResolveValueResult::ValueNs(value, _)) => match value {
ValueNs::EnumVariantId(var) => { ValueNs::EnumVariantId(var) => {
let substs = ctx.substs_from_path(path, var.into(), true); let substs = ctx.substs_from_path(path, var.into(), true);
let ty = self.db.ty(var.parent.into()); let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
return (ty, Some(var.into())); return (ty, Some(var.into()));
} }
@ -1105,7 +1102,7 @@ impl<'a> InferenceContext<'a> {
} }
TypeNs::EnumVariantId(var) => { TypeNs::EnumVariantId(var) => {
let substs = ctx.substs_from_path(path, var.into(), true); let substs = ctx.substs_from_path(path, var.into(), true);
let ty = self.db.ty(var.parent.into()); let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
forbid_unresolved_segments((ty, Some(var.into())), unresolved) forbid_unresolved_segments((ty, Some(var.into())), unresolved)
} }
@ -1131,8 +1128,7 @@ impl<'a> InferenceContext<'a> {
if let Some((AdtId::EnumId(id), _)) = ty.as_adt() { if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
let enum_data = self.db.enum_data(id); let enum_data = self.db.enum_data(id);
let name = current_segment.first().unwrap().name; let name = current_segment.first().unwrap().name;
if let Some(local_id) = enum_data.variant(name) { if let Some(variant) = enum_data.variant(name) {
let variant = EnumVariantId { parent: id, local_id };
return if remaining_segments.len() == 1 { return if remaining_segments.len() == 1 {
(ty, Some(variant.into())) (ty, Some(variant.into()))
} else { } else {
@ -1247,8 +1243,7 @@ impl<'a> InferenceContext<'a> {
// this could be an enum variant or associated type // this could be an enum variant or associated type
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
let enum_data = self.db.enum_data(enum_id); let enum_data = self.db.enum_data(enum_id);
if let Some(local_id) = enum_data.variant(segment) { if let Some(variant) = enum_data.variant(segment) {
let variant = EnumVariantId { parent: enum_id, local_id };
return (ty, Some(variant.into())); return (ty, Some(variant.into()));
} }
} }
@ -1458,10 +1453,10 @@ impl Expectation {
match self { match self {
Expectation::HasType(ety) => { Expectation::HasType(ety) => {
let ety = table.resolve_ty_shallow(ety); let ety = table.resolve_ty_shallow(ety);
if !ety.is_ty_var() { if ety.is_ty_var() {
Expectation::HasType(ety)
} else {
Expectation::None Expectation::None
} else {
Expectation::HasType(ety)
} }
} }
Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),

View File

@ -31,7 +31,6 @@ impl CastCheck {
// Note that this type of cast is actually split into a coercion to a // Note that this type of cast is actually split into a coercion to a
// pointer type and a cast: // pointer type and a cast:
// &[T; N] -> *[T; N] -> *T // &[T; N] -> *[T; N] -> *T
return;
} }
// FIXME: Check other kinds of non-coercion casts and report error if any? // FIXME: Check other kinds of non-coercion casts and report error if any?

View File

@ -27,14 +27,14 @@ use crate::{
static_lifetime, to_chalk_trait_id, static_lifetime, to_chalk_trait_id,
traits::FnTrait, traits::FnTrait,
utils::{self, generics, Generics}, utils::{self, generics, Generics},
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig, Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnAbi, FnPointer,
Interner, Substitution, Ty, TyExt, FnSig, Interner, Substitution, Ty, TyExt,
}; };
use super::{Expectation, InferenceContext}; use super::{Expectation, InferenceContext};
impl InferenceContext<'_> { impl InferenceContext<'_> {
// This function handles both closures and generators. // This function handles both closures and coroutines.
pub(super) fn deduce_closure_type_from_expectations( pub(super) fn deduce_closure_type_from_expectations(
&mut self, &mut self,
closure_expr: ExprId, closure_expr: ExprId,
@ -50,8 +50,8 @@ impl InferenceContext<'_> {
// Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here. // Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
let _ = self.coerce(Some(closure_expr), closure_ty, &expected_ty); let _ = self.coerce(Some(closure_expr), closure_ty, &expected_ty);
// Generators are not Fn* so return early. // Coroutines are not Fn* so return early.
if matches!(closure_ty.kind(Interner), TyKind::Generator(..)) { if matches!(closure_ty.kind(Interner), TyKind::Coroutine(..)) {
return; return;
} }
@ -98,7 +98,11 @@ impl InferenceContext<'_> {
cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature); cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature);
return Some(FnPointer { return Some(FnPointer {
num_binders: bound.len(Interner), num_binders: bound.len(Interner),
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, sig: FnSig {
abi: FnAbi::RustCall,
safety: chalk_ir::Safety::Safe,
variadic: false,
},
substitution: FnSubst(Substitution::from_iter(Interner, sig_tys)), substitution: FnSubst(Substitution::from_iter(Interner, sig_tys)),
}); });
} }
@ -138,13 +142,10 @@ impl HirPlace {
mut current_capture: CaptureKind, mut current_capture: CaptureKind,
len: usize, len: usize,
) -> CaptureKind { ) -> CaptureKind {
match current_capture { if let CaptureKind::ByRef(BorrowKind::Mut { .. }) = current_capture {
CaptureKind::ByRef(BorrowKind::Mut { .. }) => { if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) {
if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) { current_capture = CaptureKind::ByRef(BorrowKind::Unique);
current_capture = CaptureKind::ByRef(BorrowKind::Unique);
}
} }
_ => (),
} }
current_capture current_capture
} }
@ -330,12 +331,10 @@ impl InferenceContext<'_> {
match &self.body[tgt_expr] { match &self.body[tgt_expr] {
Expr::Path(p) => { Expr::Path(p) => {
let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) { if let Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(b), _)) =
if let ResolveValueResult::ValueNs(v, _) = r { resolver.resolve_path_in_value_ns(self.db.upcast(), p)
if let ValueNs::LocalBinding(b) = v { {
return Some(HirPlace { local: b, projections: vec![] }); return Some(HirPlace { local: b, projections: vec![] });
}
}
} }
} }
Expr::Field { expr, name: _ } => { Expr::Field { expr, name: _ } => {
@ -666,7 +665,7 @@ impl InferenceContext<'_> {
| Pat::Or(_) => (), | Pat::Or(_) => (),
Pat::TupleStruct { .. } | Pat::Record { .. } => { Pat::TupleStruct { .. } | Pat::Record { .. } => {
if let Some(variant) = self.result.variant_resolution_for_pat(p) { if let Some(variant) = self.result.variant_resolution_for_pat(p) {
let adt = variant.adt_id(); let adt = variant.adt_id(self.db.upcast());
let is_multivariant = match adt { let is_multivariant = match adt {
hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1, hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1,
_ => false, _ => false,
@ -815,8 +814,7 @@ impl InferenceContext<'_> {
.iter() .iter()
.cloned() .cloned()
.chain((0..cnt).map(|_| ProjectionElem::Deref)) .chain((0..cnt).map(|_| ProjectionElem::Deref))
.collect::<Vec<_>>() .collect::<Vec<_>>();
.into();
match &self.body[pat] { match &self.body[pat] {
Pat::Missing | Pat::Wild => (), Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => { Pat::Tuple { args, ellipsis } => {
@ -858,7 +856,7 @@ impl InferenceContext<'_> {
}; };
let mut p = place.clone(); let mut p = place.clone();
p.projections.push(ProjectionElem::Field(Either::Left(FieldId { p.projections.push(ProjectionElem::Field(Either::Left(FieldId {
parent: variant.into(), parent: variant,
local_id, local_id,
}))); })));
self.consume_with_pat(p, arg); self.consume_with_pat(p, arg);
@ -902,7 +900,7 @@ impl InferenceContext<'_> {
for (arg, (i, _)) in it { for (arg, (i, _)) in it {
let mut p = place.clone(); let mut p = place.clone();
p.projections.push(ProjectionElem::Field(Either::Left(FieldId { p.projections.push(ProjectionElem::Field(Either::Left(FieldId {
parent: variant.into(), parent: variant,
local_id: i, local_id: i,
}))); })));
self.consume_with_pat(p, *arg); self.consume_with_pat(p, *arg);
@ -1007,7 +1005,7 @@ impl InferenceContext<'_> {
let mut deferred_closures = mem::take(&mut self.deferred_closures); let mut deferred_closures = mem::take(&mut self.deferred_closures);
let mut dependents_count: FxHashMap<ClosureId, usize> = let mut dependents_count: FxHashMap<ClosureId, usize> =
deferred_closures.keys().map(|it| (*it, 0)).collect(); deferred_closures.keys().map(|it| (*it, 0)).collect();
for (_, deps) in &self.closure_dependencies { for deps in self.closure_dependencies.values() {
for dep in deps { for dep in deps {
*dependents_count.entry(*dep).or_default() += 1; *dependents_count.entry(*dep).or_default() += 1;
} }

View File

@ -24,7 +24,7 @@ use crate::{
}, },
static_lifetime, static_lifetime,
utils::ClosureSubst, utils::ClosureSubst,
Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution,
Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
}; };
@ -691,7 +691,7 @@ fn coerce_closure_fn_ty(closure_substs: &Substitution, safety: chalk_ir::Safety)
match closure_sig.kind(Interner) { match closure_sig.kind(Interner) {
TyKind::Function(fn_ty) => TyKind::Function(FnPointer { TyKind::Function(fn_ty) => TyKind::Function(FnPointer {
num_binders: fn_ty.num_binders, num_binders: fn_ty.num_binders,
sig: FnSig { safety, ..fn_ty.sig }, sig: FnSig { safety, abi: FnAbi::Rust, variadic: fn_ty.sig.variadic },
substitution: fn_ty.substitution.clone(), substitution: fn_ty.substitution.clone(),
}) })
.intern(Interner), .intern(Interner),

View File

@ -39,9 +39,9 @@ use crate::{
static_lifetime, to_chalk_trait_id, static_lifetime, to_chalk_trait_id,
traits::FnTrait, traits::FnTrait,
utils::{generics, Generics}, utils::{generics, Generics},
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnPointer, FnSig, FnSubst, Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
TyKind, TyExt, TyKind,
}; };
use super::{ use super::{
@ -224,7 +224,11 @@ impl InferenceContext<'_> {
let sig_ty = TyKind::Function(FnPointer { let sig_ty = TyKind::Function(FnPointer {
num_binders: 0, num_binders: 0,
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, sig: FnSig {
abi: FnAbi::RustCall,
safety: chalk_ir::Safety::Safe,
variadic: false,
},
substitution: FnSubst( substitution: FnSubst(
Substitution::from_iter(Interner, sig_tys.iter().cloned()) Substitution::from_iter(Interner, sig_tys.iter().cloned())
.shifted_in(Interner), .shifted_in(Interner),
@ -233,7 +237,7 @@ impl InferenceContext<'_> {
.intern(Interner); .intern(Interner);
let (id, ty, resume_yield_tys) = match closure_kind { let (id, ty, resume_yield_tys) = match closure_kind {
ClosureKind::Generator(_) => { ClosureKind::Coroutine(_) => {
// FIXME: report error when there are more than 1 parameter. // FIXME: report error when there are more than 1 parameter.
let resume_ty = match sig_tys.first() { let resume_ty = match sig_tys.first() {
// When `sig_tys.len() == 1` the first type is the return type, not the // When `sig_tys.len() == 1` the first type is the return type, not the
@ -243,16 +247,16 @@ impl InferenceContext<'_> {
}; };
let yield_ty = self.table.new_type_var(); let yield_ty = self.table.new_type_var();
let subst = TyBuilder::subst_for_generator(self.db, self.owner) let subst = TyBuilder::subst_for_coroutine(self.db, self.owner)
.push(resume_ty.clone()) .push(resume_ty.clone())
.push(yield_ty.clone()) .push(yield_ty.clone())
.push(ret_ty.clone()) .push(ret_ty.clone())
.build(); .build();
let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into(); let coroutine_id = self.db.intern_coroutine((self.owner, tgt_expr)).into();
let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner); let coroutine_ty = TyKind::Coroutine(coroutine_id, subst).intern(Interner);
(None, generator_ty, Some((resume_ty, yield_ty))) (None, coroutine_ty, Some((resume_ty, yield_ty)))
} }
ClosureKind::Closure | ClosureKind::Async => { ClosureKind::Closure | ClosureKind::Async => {
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
@ -276,7 +280,7 @@ impl InferenceContext<'_> {
// Now go through the argument patterns // Now go through the argument patterns
for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) { for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) {
self.infer_top_pat(*arg_pat, &arg_ty); self.infer_top_pat(*arg_pat, arg_ty);
} }
// FIXME: lift these out into a struct // FIXME: lift these out into a struct
@ -435,7 +439,7 @@ impl InferenceContext<'_> {
ty ty
} }
&Expr::Continue { label } => { &Expr::Continue { label } => {
if let None = find_continuable(&mut self.breakables, label) { if find_continuable(&mut self.breakables, label).is_none() {
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
expr: tgt_expr, expr: tgt_expr,
is_break: false, is_break: false,
@ -503,7 +507,7 @@ impl InferenceContext<'_> {
} }
resume_ty resume_ty
} else { } else {
// FIXME: report error (yield expr in non-generator) // FIXME: report error (yield expr in non-coroutine)
self.result.standard_types.unknown.clone() self.result.standard_types.unknown.clone()
} }
} }
@ -942,7 +946,7 @@ impl InferenceContext<'_> {
derefed_callee: &Ty, derefed_callee: &Ty,
adjustments: &mut Vec<Adjustment>, adjustments: &mut Vec<Adjustment>,
callee_ty: &Ty, callee_ty: &Ty,
params: &Vec<Ty>, params: &[Ty],
tgt_expr: ExprId, tgt_expr: ExprId,
) { ) {
match fn_x { match fn_x {
@ -1081,8 +1085,7 @@ impl InferenceContext<'_> {
let inner_exp = expected let inner_exp = expected
.to_option(table) .to_option(table)
.as_ref() .as_ref()
.map(|e| e.as_adt()) .and_then(|e| e.as_adt())
.flatten()
.filter(|(e_adt, _)| e_adt == &box_id) .filter(|(e_adt, _)| e_adt == &box_id)
.map(|(_, subts)| { .map(|(_, subts)| {
let g = subts.at(Interner, 0); let g = subts.at(Interner, 0);
@ -1245,7 +1248,7 @@ impl InferenceContext<'_> {
.build(); .build();
self.write_method_resolution(tgt_expr, func, subst.clone()); self.write_method_resolution(tgt_expr, func, subst.clone());
let method_ty = self.db.value_ty(func.into()).substitute(Interner, &subst); let method_ty = self.db.value_ty(func.into()).unwrap().substitute(Interner, &subst);
self.register_obligations_for_call(&method_ty); self.register_obligations_for_call(&method_ty);
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone())); self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()));
@ -1320,7 +1323,7 @@ impl InferenceContext<'_> {
.unwrap_or_else(|| this.table.new_type_var()); .unwrap_or_else(|| this.table.new_type_var());
let ty = if let Some(expr) = initializer { let ty = if let Some(expr) = initializer {
let ty = if contains_explicit_ref_binding(&this.body, *pat) { let ty = if contains_explicit_ref_binding(this.body, *pat) {
this.infer_expr(*expr, &Expectation::has_type(decl_ty.clone())) this.infer_expr(*expr, &Expectation::has_type(decl_ty.clone()))
} else { } else {
this.infer_expr_coerce( this.infer_expr_coerce(
@ -1541,7 +1544,7 @@ impl InferenceContext<'_> {
self.check_method_call( self.check_method_call(
tgt_expr, tgt_expr,
&[], &[],
self.db.value_ty(func.into()), self.db.value_ty(func.into()).unwrap(),
substs, substs,
ty, ty,
expected, expected,
@ -1586,7 +1589,7 @@ impl InferenceContext<'_> {
item: func.into(), item: func.into(),
}) })
} }
(ty, self.db.value_ty(func.into()), substs) (ty, self.db.value_ty(func.into()).unwrap(), substs)
} }
None => { None => {
let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name) let field_with_same_name_exists = match self.lookup_field(&receiver_ty, method_name)
@ -1716,7 +1719,7 @@ impl InferenceContext<'_> {
// that we have more information about the types of arguments when we // that we have more information about the types of arguments when we
// type-check the functions. This isn't really the right way to do this. // type-check the functions. This isn't really the right way to do this.
for check_closures in [false, true] { for check_closures in [false, true] {
let mut skip_indices = skip_indices.into_iter().copied().fuse().peekable(); let mut skip_indices = skip_indices.iter().copied().fuse().peekable();
let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty())); let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
let expected_iter = expected_inputs let expected_iter = expected_inputs
.iter() .iter()

View File

@ -93,7 +93,7 @@ impl InferenceContext<'_> {
ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner)); ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner));
match def { match def {
_ if subs.len() == 0 => {} _ if subs.is_empty() => {}
Some(def) => { Some(def) => {
let field_types = self.db.field_types(def); let field_types = self.db.field_types(def);
let variant_data = def.variant_data(self.db.upcast()); let variant_data = def.variant_data(self.db.upcast());
@ -223,13 +223,13 @@ impl InferenceContext<'_> {
) -> Ty { ) -> Ty {
let expected = self.resolve_ty_shallow(expected); let expected = self.resolve_ty_shallow(expected);
let expectations = match expected.as_tuple() { let expectations = match expected.as_tuple() {
Some(parameters) => &*parameters.as_slice(Interner), Some(parameters) => parameters.as_slice(Interner),
_ => &[], _ => &[],
}; };
let ((pre, post), n_uncovered_patterns) = match ellipsis { let ((pre, post), n_uncovered_patterns) = match ellipsis {
Some(idx) => (subs.split_at(idx), expectations.len().saturating_sub(subs.len())), Some(idx) => (subs.split_at(idx), expectations.len().saturating_sub(subs.len())),
None => ((&subs[..], &[][..]), 0), None => ((subs, &[][..]), 0),
}; };
let mut expectations_iter = expectations let mut expectations_iter = expectations
.iter() .iter()
@ -423,7 +423,7 @@ impl InferenceContext<'_> {
self.result.binding_modes.insert(pat, mode); self.result.binding_modes.insert(pat, mode);
let inner_ty = match subpat { let inner_ty = match subpat {
Some(subpat) => self.infer_pat(subpat, &expected, default_bm), Some(subpat) => self.infer_pat(subpat, expected, default_bm),
None => expected.clone(), None => expected.clone(),
}; };
let inner_ty = self.insert_type_vars_shallow(inner_ty); let inner_ty = self.insert_type_vars_shallow(inner_ty);
@ -436,7 +436,7 @@ impl InferenceContext<'_> {
}; };
self.write_pat_ty(pat, inner_ty.clone()); self.write_pat_ty(pat, inner_ty.clone());
self.write_binding_ty(binding, bound_ty); self.write_binding_ty(binding, bound_ty);
return inner_ty; inner_ty
} }
fn infer_slice_pat( fn infer_slice_pat(

View File

@ -4,7 +4,7 @@ use chalk_ir::cast::Cast;
use hir_def::{ use hir_def::{
path::{Path, PathSegment}, path::{Path, PathSegment},
resolver::{ResolveValueResult, TypeNs, ValueNs}, resolver::{ResolveValueResult, TypeNs, ValueNs},
AdtId, AssocItemId, EnumVariantId, GenericDefId, ItemContainerId, Lookup, AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use stdx::never; use stdx::never;
@ -34,7 +34,7 @@ impl InferenceContext<'_> {
self.add_required_obligations_for_value_path(generic_def, &substs); self.add_required_obligations_for_value_path(generic_def, &substs);
let ty = self.db.value_ty(value_def).substitute(Interner, &substs); let ty = self.db.value_ty(value_def)?.substitute(Interner, &substs);
let ty = self.normalize_associated_types_in(ty); let ty = self.normalize_associated_types_in(ty);
Some(ty) Some(ty)
} }
@ -98,7 +98,7 @@ impl InferenceContext<'_> {
let Some(generic_def) = value_def.to_generic_def_id() else { let Some(generic_def) = value_def.to_generic_def_id() else {
// `value_def` is the kind of item that can never be generic (i.e. statics, at least // `value_def` is the kind of item that can never be generic (i.e. statics, at least
// currently). We can just skip the binders to get its type. // currently). We can just skip the binders to get its type.
let (ty, binders) = self.db.value_ty(value_def).into_value_and_skipped_binders(); let (ty, binders) = self.db.value_ty(value_def)?.into_value_and_skipped_binders();
stdx::always!( stdx::always!(
parent_substs.is_none() && binders.is_empty(Interner), parent_substs.is_none() && binders.is_empty(Interner),
"non-empty binders for non-generic def", "non-empty binders for non-generic def",
@ -389,14 +389,13 @@ impl InferenceContext<'_> {
name: &Name, name: &Name,
id: ExprOrPatId, id: ExprOrPatId,
) -> Option<(ValueNs, Substitution)> { ) -> Option<(ValueNs, Substitution)> {
let ty = self.resolve_ty_shallow(&ty); let ty = self.resolve_ty_shallow(ty);
let (enum_id, subst) = match ty.as_adt() { let (enum_id, subst) = match ty.as_adt() {
Some((AdtId::EnumId(e), subst)) => (e, subst), Some((AdtId::EnumId(e), subst)) => (e, subst),
_ => return None, _ => return None,
}; };
let enum_data = self.db.enum_data(enum_id); let enum_data = self.db.enum_data(enum_id);
let local_id = enum_data.variant(name)?; let variant = enum_data.variant(name)?;
let variant = EnumVariantId { parent: enum_id, local_id };
self.write_variant_resolution(id, variant.into()); self.write_variant_resolution(id, variant.into());
Some((ValueNs::EnumVariantId(variant), subst.clone())) Some((ValueNs::EnumVariantId(variant), subst.clone()))
} }

View File

@ -250,9 +250,7 @@ impl<'a> InferenceTable<'a> {
// and registering an obligation. But it needs chalk support, so we handle the most basic // and registering an obligation. But it needs chalk support, so we handle the most basic
// case (a non associated const without generic parameters) manually. // case (a non associated const without generic parameters) manually.
if subst.len(Interner) == 0 { if subst.len(Interner) == 0 {
if let Ok(eval) = if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) {
self.db.const_eval((*c_id).into(), subst.clone(), None)
{
eval eval
} else { } else {
unknown_const(c.data(Interner).ty.clone()) unknown_const(c.data(Interner).ty.clone())
@ -490,9 +488,8 @@ impl<'a> InferenceTable<'a> {
pub(crate) fn try_obligation(&mut self, goal: Goal) -> Option<Solution> { pub(crate) fn try_obligation(&mut self, goal: Goal) -> Option<Solution> {
let in_env = InEnvironment::new(&self.trait_env.env, goal); let in_env = InEnvironment::new(&self.trait_env.env, goal);
let canonicalized = self.canonicalize(in_env); let canonicalized = self.canonicalize(in_env);
let solution =
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value); self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value)
solution
} }
pub(crate) fn register_obligation(&mut self, goal: Goal) { pub(crate) fn register_obligation(&mut self, goal: Goal) {

View File

@ -7,7 +7,7 @@ use chalk_ir::{
}; };
use hir_def::{ use hir_def::{
attr::Attrs, data::adt::VariantData, visibility::Visibility, AdtId, EnumVariantId, HasModule, attr::Attrs, data::adt::VariantData, visibility::Visibility, AdtId, EnumVariantId, HasModule,
Lookup, ModuleId, VariantId, ModuleId, VariantId,
}; };
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
@ -30,17 +30,15 @@ pub(crate) fn is_enum_variant_uninhabited_from(
target_mod: ModuleId, target_mod: ModuleId,
db: &dyn HirDatabase, db: &dyn HirDatabase,
) -> bool { ) -> bool {
let enum_data = db.enum_data(variant.parent); let is_local = variant.module(db.upcast()).krate() == target_mod.krate();
let vars_attrs = db.variants_attrs(variant.parent);
let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate();
let mut uninhabited_from = let mut uninhabited_from =
UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() }; UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
let inhabitedness = uninhabited_from.visit_variant( let inhabitedness = uninhabited_from.visit_variant(
variant.into(), variant.into(),
&enum_data.variants[variant.local_id].variant_data, &db.enum_variant_data(variant).variant_data,
subst, subst,
&vars_attrs[variant.local_id], &db.attrs(variant.into()),
is_local, is_local,
); );
inhabitedness == BREAK_VISIBLY_UNINHABITED inhabitedness == BREAK_VISIBLY_UNINHABITED
@ -117,15 +115,14 @@ impl UninhabitedFrom<'_> {
self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local) self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local)
} }
AdtId::EnumId(e) => { AdtId::EnumId(e) => {
let vars_attrs = self.db.variants_attrs(e);
let enum_data = self.db.enum_data(e); let enum_data = self.db.enum_data(e);
for (local_id, enum_var) in enum_data.variants.iter() { for &(variant, _) in enum_data.variants.iter() {
let variant_inhabitedness = self.visit_variant( let variant_inhabitedness = self.visit_variant(
EnumVariantId { parent: e, local_id }.into(), variant.into(),
&enum_var.variant_data, &self.db.enum_variant_data(variant).variant_data,
subst, subst,
&vars_attrs[local_id], &self.db.attrs(variant.into()),
is_local, is_local,
); );
match variant_inhabitedness { match variant_inhabitedness {

View File

@ -3,8 +3,8 @@
use crate::{ use crate::{
chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData,
ConstScalar, Constraint, Constraints, FnDefId, GenericArg, GenericArgData, Goal, GoalData, ConstScalar, Constraint, Constraints, FnAbi, FnDefId, GenericArg, GenericArgData, Goal,
Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause, GoalData, Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause,
ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds, Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds,
}; };
@ -71,7 +71,7 @@ impl chalk_ir::interner::Interner for Interner {
type DefId = InternId; type DefId = InternId;
type InternedAdtId = hir_def::AdtId; type InternedAdtId = hir_def::AdtId;
type Identifier = TypeAliasId; type Identifier = TypeAliasId;
type FnAbi = (); type FnAbi = FnAbi;
fn debug_adt_id( fn debug_adt_id(
type_kind_id: chalk_db::AdtId, type_kind_id: chalk_db::AdtId,
@ -387,7 +387,7 @@ impl chalk_ir::interner::HasInterner for Interner {
macro_rules! has_interner { macro_rules! has_interner {
($t:ty) => { ($t:ty) => {
impl HasInterner for $t { impl HasInterner for $t {
type Interner = crate::Interner; type Interner = $crate::Interner;
} }
}; };
} }

View File

@ -9,7 +9,7 @@ use hir_def::{
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size, Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
StructKind, TargetDataLayout, WrappingRange, StructKind, TargetDataLayout, WrappingRange,
}, },
LocalEnumVariantId, LocalFieldId, StructId, LocalFieldId, StructId,
}; };
use la_arena::{Idx, RawIdx}; use la_arena::{Idx, RawIdx};
use rustc_abi::AddressSpace; use rustc_abi::AddressSpace;
@ -32,15 +32,15 @@ mod adt;
mod target; mod target;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId); pub struct RustcEnumVariantIdx(pub usize);
impl rustc_index::Idx for RustcEnumVariantIdx { impl rustc_index::Idx for RustcEnumVariantIdx {
fn new(idx: usize) -> Self { fn new(idx: usize) -> Self {
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32))) RustcEnumVariantIdx(idx)
} }
fn index(self) -> usize { fn index(self) -> usize {
u32::from(self.0.into_raw()) as usize self.0
} }
} }
@ -202,7 +202,7 @@ pub fn layout_of_ty_query(
return Err(LayoutError::TargetLayoutNotAvailable); return Err(LayoutError::TargetLayoutNotAvailable);
}; };
let cx = LayoutCx { target: &target }; let cx = LayoutCx { target: &target };
let dl = &*cx.current_data_layout(); let dl = cx.current_data_layout();
let ty = normalize(db, trait_env.clone(), ty); let ty = normalize(db, trait_env.clone(), ty);
let result = match ty.kind(Interner) { let result = match ty.kind(Interner) {
TyKind::Adt(AdtId(def), subst) => { TyKind::Adt(AdtId(def), subst) => {
@ -278,7 +278,7 @@ pub fn layout_of_ty_query(
cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)?
} }
TyKind::Array(element, count) => { TyKind::Array(element, count) => {
let count = try_const_usize(db, &count).ok_or(LayoutError::HasErrorConst)? as u64; let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
let element = db.layout_of_ty(element.clone(), trait_env)?; let element = db.layout_of_ty(element.clone(), trait_env)?;
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
@ -408,7 +408,7 @@ pub fn layout_of_ty_query(
cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized) cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized)
.ok_or(LayoutError::Unknown)? .ok_or(LayoutError::Unknown)?
} }
TyKind::Generator(_, _) | TyKind::GeneratorWitness(_, _) => { TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
return Err(LayoutError::NotImplemented) return Err(LayoutError::NotImplemented)
} }
TyKind::Error => return Err(LayoutError::HasErrorType), TyKind::Error => return Err(LayoutError::HasErrorType),

View File

@ -6,9 +6,8 @@ use base_db::salsa::Cycle;
use hir_def::{ use hir_def::{
data::adt::VariantData, data::adt::VariantData,
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout}, layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
AdtId, EnumVariantId, LocalEnumVariantId, VariantId, AdtId, VariantId,
}; };
use la_arena::RawIdx;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use smallvec::SmallVec; use smallvec::SmallVec;
use triomphe::Arc; use triomphe::Arc;
@ -22,8 +21,8 @@ use crate::{
use super::LayoutCx; use super::LayoutCx;
pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx { pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx {
RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0))) RustcEnumVariantIdx(0)
} }
pub fn layout_of_adt_query( pub fn layout_of_adt_query(
@ -62,12 +61,7 @@ pub fn layout_of_adt_query(
let r = data let r = data
.variants .variants
.iter() .iter()
.map(|(idx, v)| { .map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data))
handle_variant(
EnumVariantId { parent: e, local_id: idx }.into(),
&v.variant_data,
)
})
.collect::<Result<SmallVec<_>, _>>()?; .collect::<Result<SmallVec<_>, _>>()?;
(r, data.repr.unwrap_or_default()) (r, data.repr.unwrap_or_default())
} }
@ -86,11 +80,10 @@ pub fn layout_of_adt_query(
matches!(def, AdtId::EnumId(..)), matches!(def, AdtId::EnumId(..)),
is_unsafe_cell(db, def), is_unsafe_cell(db, def),
layout_scalar_valid_range(db, def), layout_scalar_valid_range(db, def),
|min, max| repr_discr(&dl, &repr, min, max).unwrap_or((Integer::I8, false)), |min, max| repr_discr(dl, &repr, min, max).unwrap_or((Integer::I8, false)),
variants.iter_enumerated().filter_map(|(id, _)| { variants.iter_enumerated().filter_map(|(id, _)| {
let AdtId::EnumId(e) = def else { return None }; let AdtId::EnumId(e) = def else { return None };
let d = let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?;
db.const_eval_discriminant(EnumVariantId { parent: e, local_id: id.0 }).ok()?;
Some((id, d)) Some((id, d))
}), }),
// FIXME: The current code for niche-filling relies on variant indices // FIXME: The current code for niche-filling relies on variant indices

View File

@ -12,7 +12,7 @@ pub fn target_data_layout_query(
) -> Option<Arc<TargetDataLayout>> { ) -> Option<Arc<TargetDataLayout>> {
let crate_graph = db.crate_graph(); let crate_graph = db.crate_graph();
let target_layout = crate_graph[krate].target_layout.as_ref().ok()?; let target_layout = crate_graph[krate].target_layout.as_ref().ok()?;
let res = TargetDataLayout::parse_from_llvm_datalayout_string(&target_layout); let res = TargetDataLayout::parse_from_llvm_datalayout_string(target_layout);
if let Err(_e) = &res { if let Err(_e) = &res {
// FIXME: Print the error here once it implements debug/display // FIXME: Print the error here once it implements debug/display
// also logging here is somewhat wrong, but unfortunately this is the earliest place we can // also logging here is somewhat wrong, but unfortunately this is the earliest place we can

View File

@ -366,11 +366,11 @@ fn return_position_impl_trait() {
} }
let waker = Arc::new(EmptyWaker).into(); let waker = Arc::new(EmptyWaker).into();
let mut context = Context::from_waker(&waker); let mut context = Context::from_waker(&waker);
let x = pinned.poll(&mut context);
x pinned.poll(&mut context)
} }
let x = unwrap_fut(f());
x unwrap_fut(f())
} }
size_and_align_expr! { size_and_align_expr! {
struct Foo<T>(T, T, (T, T)); struct Foo<T>(T, T, (T, T));

View File

@ -1,3 +1,6 @@
#![allow(clippy::match_single_binding)]
#![allow(clippy::no_effect)]
use crate::size_and_align_expr; use crate::size_and_align_expr;
#[test] #[test]
@ -36,7 +39,7 @@ fn ref_simple() {
let mut y: i32 = 5; let mut y: i32 = 5;
] ]
|x: i32| { |x: i32| {
y = y + x; y += x;
y y
} }
} }
@ -66,7 +69,7 @@ fn ref_simple() {
let x: &mut X = &mut X(2, 6); let x: &mut X = &mut X(2, 6);
] ]
|| { || {
(*x).0 as i64 + x.1 x.0 as i64 + x.1
} }
} }
} }
@ -188,9 +191,7 @@ fn match_pattern() {
struct X(i64, i32, (u8, i128)); struct X(i64, i32, (u8, i128));
let _y: X = X(2, 5, (7, 3)); let _y: X = X(2, 5, (7, 3));
move |x: i64| { move |x: i64| {
match _y { x
_ => x,
}
} }
} }
size_and_align_expr! { size_and_align_expr! {
@ -264,8 +265,8 @@ fn regression_15623() {
let c = 5; let c = 5;
move || { move || {
let 0 = a else { return b; }; let 0 = a else { return b; };
let y = c;
y c
} }
} }
} }

View File

@ -228,7 +228,7 @@ impl MemoryMap {
let mut transform = |(addr, val): (&usize, &Box<[u8]>)| { let mut transform = |(addr, val): (&usize, &Box<[u8]>)| {
let addr = *addr; let addr = *addr;
let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) }; let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
f(val, align).and_then(|it| Ok((addr, it))) f(val, align).map(|it| (addr, it))
}; };
match self { match self {
MemoryMap::Empty => Ok(Default::default()), MemoryMap::Empty => Ok(Default::default()),
@ -351,10 +351,157 @@ pub struct CallableSig {
params_and_return: Arc<[Ty]>, params_and_return: Arc<[Ty]>,
is_varargs: bool, is_varargs: bool,
safety: Safety, safety: Safety,
abi: FnAbi,
} }
has_interner!(CallableSig); has_interner!(CallableSig);
#[derive(Debug, Copy, Clone, Eq)]
pub enum FnAbi {
Aapcs,
AapcsUnwind,
AmdgpuKernel,
AvrInterrupt,
AvrNonBlockingInterrupt,
C,
CCmseNonsecureCall,
CDecl,
CDeclUnwind,
CUnwind,
Efiapi,
Fastcall,
FastcallUnwind,
Msp430Interrupt,
PlatformIntrinsic,
PtxKernel,
RiscvInterruptM,
RiscvInterruptS,
Rust,
RustCall,
RustCold,
RustIntrinsic,
Stdcall,
StdcallUnwind,
System,
SystemUnwind,
Sysv64,
Sysv64Unwind,
Thiscall,
ThiscallUnwind,
Unadjusted,
Vectorcall,
VectorcallUnwind,
Wasm,
Win64,
Win64Unwind,
X86Interrupt,
Unknown,
}
impl PartialEq for FnAbi {
fn eq(&self, _other: &Self) -> bool {
// FIXME: Proper equality breaks `coercion::two_closures_lub` test
true
}
}
impl Hash for FnAbi {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// Required because of the FIXME above and due to us implementing `Eq`, without this
// we would break the `Hash` + `Eq` contract
core::mem::discriminant(&Self::Unknown).hash(state);
}
}
impl FnAbi {
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> FnAbi {
match s {
"aapcs-unwind" => FnAbi::AapcsUnwind,
"aapcs" => FnAbi::Aapcs,
"amdgpu-kernel" => FnAbi::AmdgpuKernel,
"avr-interrupt" => FnAbi::AvrInterrupt,
"avr-non-blocking-interrupt" => FnAbi::AvrNonBlockingInterrupt,
"C-cmse-nonsecure-call" => FnAbi::CCmseNonsecureCall,
"C-unwind" => FnAbi::CUnwind,
"C" => FnAbi::C,
"cdecl-unwind" => FnAbi::CDeclUnwind,
"cdecl" => FnAbi::CDecl,
"efiapi" => FnAbi::Efiapi,
"fastcall-unwind" => FnAbi::FastcallUnwind,
"fastcall" => FnAbi::Fastcall,
"msp430-interrupt" => FnAbi::Msp430Interrupt,
"platform-intrinsic" => FnAbi::PlatformIntrinsic,
"ptx-kernel" => FnAbi::PtxKernel,
"riscv-interrupt-m" => FnAbi::RiscvInterruptM,
"riscv-interrupt-s" => FnAbi::RiscvInterruptS,
"rust-call" => FnAbi::RustCall,
"rust-cold" => FnAbi::RustCold,
"rust-intrinsic" => FnAbi::RustIntrinsic,
"Rust" => FnAbi::Rust,
"stdcall-unwind" => FnAbi::StdcallUnwind,
"stdcall" => FnAbi::Stdcall,
"system-unwind" => FnAbi::SystemUnwind,
"system" => FnAbi::System,
"sysv64-unwind" => FnAbi::Sysv64Unwind,
"sysv64" => FnAbi::Sysv64,
"thiscall-unwind" => FnAbi::ThiscallUnwind,
"thiscall" => FnAbi::Thiscall,
"unadjusted" => FnAbi::Unadjusted,
"vectorcall-unwind" => FnAbi::VectorcallUnwind,
"vectorcall" => FnAbi::Vectorcall,
"wasm" => FnAbi::Wasm,
"win64-unwind" => FnAbi::Win64Unwind,
"win64" => FnAbi::Win64,
"x86-interrupt" => FnAbi::X86Interrupt,
_ => FnAbi::Unknown,
}
}
pub fn as_str(self) -> &'static str {
match self {
FnAbi::Aapcs => "aapcs",
FnAbi::AapcsUnwind => "aapcs-unwind",
FnAbi::AmdgpuKernel => "amdgpu-kernel",
FnAbi::AvrInterrupt => "avr-interrupt",
FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
FnAbi::C => "C",
FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
FnAbi::CDecl => "C-decl",
FnAbi::CDeclUnwind => "cdecl-unwind",
FnAbi::CUnwind => "C-unwind",
FnAbi::Efiapi => "efiapi",
FnAbi::Fastcall => "fastcall",
FnAbi::FastcallUnwind => "fastcall-unwind",
FnAbi::Msp430Interrupt => "msp430-interrupt",
FnAbi::PlatformIntrinsic => "platform-intrinsic",
FnAbi::PtxKernel => "ptx-kernel",
FnAbi::RiscvInterruptM => "riscv-interrupt-m",
FnAbi::RiscvInterruptS => "riscv-interrupt-s",
FnAbi::Rust => "Rust",
FnAbi::RustCall => "rust-call",
FnAbi::RustCold => "rust-cold",
FnAbi::RustIntrinsic => "rust-intrinsic",
FnAbi::Stdcall => "stdcall",
FnAbi::StdcallUnwind => "stdcall-unwind",
FnAbi::System => "system",
FnAbi::SystemUnwind => "system-unwind",
FnAbi::Sysv64 => "sysv64",
FnAbi::Sysv64Unwind => "sysv64-unwind",
FnAbi::Thiscall => "thiscall",
FnAbi::ThiscallUnwind => "thiscall-unwind",
FnAbi::Unadjusted => "unadjusted",
FnAbi::Vectorcall => "vectorcall",
FnAbi::VectorcallUnwind => "vectorcall-unwind",
FnAbi::Wasm => "wasm",
FnAbi::Win64 => "win64",
FnAbi::Win64Unwind => "win64-unwind",
FnAbi::X86Interrupt => "x86-interrupt",
FnAbi::Unknown => "unknown-abi",
}
}
}
/// A polymorphic function signature. /// A polymorphic function signature.
pub type PolyFnSig = Binders<CallableSig>; pub type PolyFnSig = Binders<CallableSig>;
@ -364,11 +511,17 @@ impl CallableSig {
ret: Ty, ret: Ty,
is_varargs: bool, is_varargs: bool,
safety: Safety, safety: Safety,
abi: FnAbi,
) -> CallableSig { ) -> CallableSig {
params.push(ret); params.push(ret);
CallableSig { params_and_return: params.into(), is_varargs, safety } CallableSig { params_and_return: params.into(), is_varargs, safety, abi }
} }
pub fn from_def(db: &dyn HirDatabase, def: FnDefId, substs: &Substitution) -> CallableSig {
let callable_def = db.lookup_intern_callable_def(def.into());
let sig = db.callable_item_signature(callable_def);
sig.substitute(Interner, substs)
}
pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
CallableSig { CallableSig {
// FIXME: what to do about lifetime params? -> return PolyFnSig // FIXME: what to do about lifetime params? -> return PolyFnSig
@ -385,13 +538,14 @@ impl CallableSig {
), ),
is_varargs: fn_ptr.sig.variadic, is_varargs: fn_ptr.sig.variadic,
safety: fn_ptr.sig.safety, safety: fn_ptr.sig.safety,
abi: fn_ptr.sig.abi,
} }
} }
pub fn to_fn_ptr(&self) -> FnPointer { pub fn to_fn_ptr(&self) -> FnPointer {
FnPointer { FnPointer {
num_binders: 0, num_binders: 0,
sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs }, sig: FnSig { abi: self.abi, safety: self.safety, variadic: self.is_varargs },
substitution: FnSubst(Substitution::from_iter( substitution: FnSubst(Substitution::from_iter(
Interner, Interner,
self.params_and_return.iter().cloned(), self.params_and_return.iter().cloned(),
@ -420,6 +574,7 @@ impl TypeFoldable<Interner> for CallableSig {
params_and_return: folded.into(), params_and_return: folded.into(),
is_varargs: self.is_varargs, is_varargs: self.is_varargs,
safety: self.safety, safety: self.safety,
abi: self.abi,
}) })
} }
} }
@ -704,7 +859,7 @@ pub fn callable_sig_from_fnonce(
let params = let params =
args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect(); args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect();
Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe)) Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe, FnAbi::RustCall))
} }
struct PlaceholderCollector<'db> { struct PlaceholderCollector<'db> {

View File

@ -58,7 +58,7 @@ use crate::{
InTypeConstIdMetadata, InTypeConstIdMetadata,
}, },
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy, AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy, FnAbi, FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy,
QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
}; };
@ -279,14 +279,14 @@ impl<'a> TyLoweringContext<'a> {
.intern(Interner) .intern(Interner)
} }
TypeRef::Placeholder => TyKind::Error.intern(Interner), TypeRef::Placeholder => TyKind::Error.intern(Interner),
&TypeRef::Fn(ref params, variadic, is_unsafe) => { &TypeRef::Fn(ref params, variadic, is_unsafe, ref abi) => {
let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr))) Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
}); });
TyKind::Function(FnPointer { TyKind::Function(FnPointer {
num_binders: 0, // FIXME lower `for<'a> fn()` correctly num_binders: 0, // FIXME lower `for<'a> fn()` correctly
sig: FnSig { sig: FnSig {
abi: (), abi: abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe }, safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
variadic, variadic,
}, },
@ -762,7 +762,7 @@ impl<'a> TyLoweringContext<'a> {
Some(segment) if segment.args_and_bindings.is_some() => Some(segment), Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
_ => last, _ => last,
}; };
(segment, Some(var.parent.into())) (segment, Some(var.lookup(self.db.upcast()).parent.into()))
} }
}; };
if let Some(segment) = segment { if let Some(segment) = segment {
@ -1192,11 +1192,7 @@ impl<'a> TyLoweringContext<'a> {
return None; return None;
} }
if bounds.first().and_then(|b| b.trait_id()).is_none() { bounds.first().and_then(|b| b.trait_id())?;
// When there's no trait bound, that's an error. This happens when the trait refs
// are unresolved.
return None;
}
// As multiple occurrences of the same auto traits *are* permitted, we deduplicate the // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
// bounds. We shouldn't have repeated elements besides auto traits at this point. // bounds. We shouldn't have repeated elements besides auto traits at this point.
@ -1241,7 +1237,7 @@ impl<'a> TyLoweringContext<'a> {
}); });
crate::wrap_empty_binders(clause) crate::wrap_empty_binders(clause)
}); });
predicates.extend(sized_clause.into_iter()); predicates.extend(sized_clause);
predicates.shrink_to_fit(); predicates.shrink_to_fit();
} }
predicates predicates
@ -1339,7 +1335,7 @@ fn named_associated_type_shorthand_candidates<R>(
), ),
_ => None, _ => None,
}); });
if let Some(_) = res { if res.is_some() {
return res; return res;
} }
// Handle `Self::Type` referring to own associated type in trait definitions // Handle `Self::Type` referring to own associated type in trait definitions
@ -1375,11 +1371,13 @@ pub(crate) fn field_types_query(
let (resolver, def): (_, GenericDefId) = match variant_id { let (resolver, def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()), VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()), VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
VariantId::EnumVariantId(it) => (it.parent.resolver(db.upcast()), it.parent.into()), VariantId::EnumVariantId(it) => {
(it.resolver(db.upcast()), it.lookup(db.upcast()).parent.into())
}
}; };
let generics = generics(db.upcast(), def); let generics = generics(db.upcast(), def);
let mut res = ArenaMap::default(); let mut res = ArenaMap::default();
let ctx = TyLoweringContext::new(db, &resolver, GenericDefId::from(variant_id.adt_id()).into()) let ctx = TyLoweringContext::new(db, &resolver, def.into())
.with_type_param_mode(ParamLoweringMode::Variable); .with_type_param_mode(ParamLoweringMode::Variable);
for (field_id, field_data) in var_data.fields().iter() { for (field_id, field_data) in var_data.fields().iter() {
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref))); res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(&field_data.type_ref)));
@ -1677,6 +1675,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
ret, ret,
data.is_varargs(), data.is_varargs(),
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe }, if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
data.abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
); );
make_binders(db, &generics, sig) make_binders(db, &generics, sig)
} }
@ -1721,50 +1720,65 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
.with_type_param_mode(ParamLoweringMode::Variable); .with_type_param_mode(ParamLoweringMode::Variable);
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders(); let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) Binders::new(
binders,
CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
)
} }
/// Build the type of a tuple struct constructor. /// Build the type of a tuple struct constructor.
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<Ty> { fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
let struct_data = db.struct_data(def); let struct_data = db.struct_data(def);
if let StructKind::Unit = struct_data.variant_data.kind() { match struct_data.variant_data.kind() {
return type_for_adt(db, def.into()); StructKind::Record => None,
StructKind::Unit => Some(type_for_adt(db, def.into())),
StructKind::Tuple => {
let generics = generics(db.upcast(), AdtId::from(def).into());
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
Some(make_binders(
db,
&generics,
TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
))
}
} }
let generics = generics(db.upcast(), AdtId::from(def).into());
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
make_binders(
db,
&generics,
TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
)
} }
fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig { fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
let enum_data = db.enum_data(def.parent); let var_data = db.enum_variant_data(def);
let var_data = &enum_data.variants[def.local_id];
let fields = var_data.variant_data.fields(); let fields = var_data.variant_data.fields();
let resolver = def.parent.resolver(db.upcast()); let resolver = def.resolver(db.upcast());
let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into()) let ctx = TyLoweringContext::new(db, &resolver, DefWithBodyId::VariantId(def).into())
.with_type_param_mode(ParamLoweringMode::Variable); .with_type_param_mode(ParamLoweringMode::Variable);
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders(); let (ret, binders) =
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe)) type_for_adt(db, def.lookup(db.upcast()).parent.into()).into_value_and_skipped_binders();
Binders::new(
binders,
CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
)
} }
/// Build the type of a tuple enum variant constructor. /// Build the type of a tuple enum variant constructor.
fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders<Ty> { fn type_for_enum_variant_constructor(
let enum_data = db.enum_data(def.parent); db: &dyn HirDatabase,
let var_data = &enum_data.variants[def.local_id].variant_data; def: EnumVariantId,
if let StructKind::Unit = var_data.kind() { ) -> Option<Binders<Ty>> {
return type_for_adt(db, def.parent.into()); let e = def.lookup(db.upcast()).parent;
match db.enum_variant_data(def).variant_data.kind() {
StructKind::Record => None,
StructKind::Unit => Some(type_for_adt(db, e.into())),
StructKind::Tuple => {
let generics = generics(db.upcast(), e.into());
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
Some(make_binders(
db,
&generics,
TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs)
.intern(Interner),
))
}
} }
let generics = generics(db.upcast(), def.parent.into());
let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
make_binders(
db,
&generics,
TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(Interner),
)
} }
fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
@ -1812,7 +1826,7 @@ impl CallableDefId {
match self { match self {
CallableDefId::FunctionId(f) => f.lookup(db).module(db), CallableDefId::FunctionId(f) => f.lookup(db).module(db),
CallableDefId::StructId(s) => s.lookup(db).container, CallableDefId::StructId(s) => s.lookup(db).container,
CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container, CallableDefId::EnumVariantId(e) => e.module(db),
} }
.krate() .krate()
} }
@ -1881,24 +1895,20 @@ pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &Cycle, def: &TyDefId) ->
make_binders(db, &generics, TyKind::Error.intern(Interner)) make_binders(db, &generics, TyKind::Error.intern(Interner))
} }
pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> { pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option<Binders<Ty>> {
match def { match def {
ValueTyDefId::FunctionId(it) => type_for_fn(db, it), ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
ValueTyDefId::UnionId(it) => type_for_adt(db, it.into()), ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
ValueTyDefId::ConstId(it) => type_for_const(db, it), ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
ValueTyDefId::StaticId(it) => type_for_static(db, it), ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
} }
} }
pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> { pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
let impl_loc = impl_id.lookup(db.upcast());
let impl_data = db.impl_data(impl_id); let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast()); let resolver = impl_id.resolver(db.upcast());
let _cx = stdx::panic_context::enter(format!(
"impl_self_ty_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
));
let generics = generics(db.upcast(), impl_id.into()); let generics = generics(db.upcast(), impl_id.into());
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into()) let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
.with_type_param_mode(ParamLoweringMode::Variable); .with_type_param_mode(ParamLoweringMode::Variable);
@ -1930,12 +1940,8 @@ pub(crate) fn impl_self_ty_recover(
} }
pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
let impl_loc = impl_id.lookup(db.upcast());
let impl_data = db.impl_data(impl_id); let impl_data = db.impl_data(impl_id);
let resolver = impl_id.resolver(db.upcast()); let resolver = impl_id.resolver(db.upcast());
let _cx = stdx::panic_context::enter(format!(
"impl_trait_query({impl_id:?} -> {impl_loc:?} -> {impl_data:?})"
));
let ctx = TyLoweringContext::new(db, &resolver, impl_id.into()) let ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
.with_type_param_mode(ParamLoweringMode::Variable); .with_type_param_mode(ParamLoweringMode::Variable);
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();

View File

@ -103,15 +103,15 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
} }
} }
impl From<chalk_ir::GeneratorId<Interner>> for crate::db::InternedGeneratorId { impl From<chalk_ir::CoroutineId<Interner>> for crate::db::InternedCoroutineId {
fn from(id: chalk_ir::GeneratorId<Interner>) -> Self { fn from(id: chalk_ir::CoroutineId<Interner>) -> Self {
Self::from_intern_id(id.0) Self::from_intern_id(id.0)
} }
} }
impl From<crate::db::InternedGeneratorId> for chalk_ir::GeneratorId<Interner> { impl From<crate::db::InternedCoroutineId> for chalk_ir::CoroutineId<Interner> {
fn from(id: crate::db::InternedGeneratorId) -> Self { fn from(id: crate::db::InternedCoroutineId) -> Self {
chalk_ir::GeneratorId(id.as_intern_id()) chalk_ir::CoroutineId(id.as_intern_id())
} }
} }

View File

@ -86,7 +86,7 @@ impl TyFingerprint {
TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?, TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty), TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
TyKind::Tuple(_, subst) => { TyKind::Tuple(_, subst) => {
let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(Interner)); let first_ty = subst.interned().first().map(|arg| arg.assert_ty_ref(Interner));
match first_ty { match first_ty {
Some(ty) => return TyFingerprint::for_trait_impl(ty), Some(ty) => return TyFingerprint::for_trait_impl(ty),
None => TyFingerprint::Unit, None => TyFingerprint::Unit,
@ -96,8 +96,8 @@ impl TyFingerprint {
| TyKind::OpaqueType(_, _) | TyKind::OpaqueType(_, _)
| TyKind::FnDef(_, _) | TyKind::FnDef(_, _)
| TyKind::Closure(_, _) | TyKind::Closure(_, _)
| TyKind::Generator(..) | TyKind::Coroutine(..)
| TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable, | TyKind::CoroutineWitness(..) => TyFingerprint::Unnameable,
TyKind::Function(fn_ptr) => { TyKind::Function(fn_ptr) => {
TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32) TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32)
} }
@ -541,7 +541,7 @@ impl ReceiverAdjustments {
if let TyKind::Ref(m, l, inner) = ty.kind(Interner) { if let TyKind::Ref(m, l, inner) = ty.kind(Interner) {
if let TyKind::Array(inner, _) = inner.kind(Interner) { if let TyKind::Array(inner, _) = inner.kind(Interner) {
break 'it TyKind::Ref( break 'it TyKind::Ref(
m.clone(), *m,
l.clone(), l.clone(),
TyKind::Slice(inner.clone()).intern(Interner), TyKind::Slice(inner.clone()).intern(Interner),
) )
@ -953,7 +953,7 @@ pub fn iterate_method_candidates_dyn(
let ty = table.instantiate_canonical(ty.clone()); let ty = table.instantiate_canonical(ty.clone());
let deref_chain = autoderef_method_receiver(&mut table, ty); let deref_chain = autoderef_method_receiver(&mut table, ty);
let result = deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| { deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
iterate_method_candidates_with_autoref( iterate_method_candidates_with_autoref(
&receiver_ty, &receiver_ty,
adj, adj,
@ -964,8 +964,7 @@ pub fn iterate_method_candidates_dyn(
name, name,
callback, callback,
) )
}); })
result
} }
LookupMode::Path => { LookupMode::Path => {
// No autoderef for path lookups // No autoderef for path lookups

View File

@ -159,7 +159,7 @@ impl<V, T> ProjectionElem<V, T> {
} }
_ => { _ => {
never!("Overloaded deref on type {} is not a projection", base.display(db)); never!("Overloaded deref on type {} is not a projection", base.display(db));
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
}, },
ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) { ProjectionElem::Field(Either::Left(f)) => match &base.kind(Interner) {
@ -168,7 +168,7 @@ impl<V, T> ProjectionElem<V, T> {
} }
ty => { ty => {
never!("Only adt has field, found {:?}", ty); never!("Only adt has field, found {:?}", ty);
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
}, },
ProjectionElem::Field(Either::Right(f)) => match &base.kind(Interner) { ProjectionElem::Field(Either::Right(f)) => match &base.kind(Interner) {
@ -183,14 +183,14 @@ impl<V, T> ProjectionElem<V, T> {
}), }),
_ => { _ => {
never!("Only tuple has tuple field"); never!("Only tuple has tuple field");
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
}, },
ProjectionElem::ClosureField(f) => match &base.kind(Interner) { ProjectionElem::ClosureField(f) => match &base.kind(Interner) {
TyKind::Closure(id, subst) => closure_field(*id, subst, *f), TyKind::Closure(id, subst) => closure_field(*id, subst, *f),
_ => { _ => {
never!("Only closure has closure field"); never!("Only closure has closure field");
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
}, },
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => { ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => {
@ -198,7 +198,7 @@ impl<V, T> ProjectionElem<V, T> {
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
_ => { _ => {
never!("Overloaded index is not a projection"); never!("Overloaded index is not a projection");
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
} }
} }
@ -217,12 +217,12 @@ impl<V, T> ProjectionElem<V, T> {
TyKind::Slice(_) => base.clone(), TyKind::Slice(_) => base.clone(),
_ => { _ => {
never!("Subslice projection should only happen on slice and array"); never!("Subslice projection should only happen on slice and array");
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
}, },
ProjectionElem::OpaqueCast(_) => { ProjectionElem::OpaqueCast(_) => {
never!("We don't emit these yet"); never!("We don't emit these yet");
return TyKind::Error.intern(Interner); TyKind::Error.intern(Interner)
} }
} }
} }
@ -299,7 +299,7 @@ pub struct Place {
impl Place { impl Place {
fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool { fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool {
self.local == child.local self.local == child.local
&& child.projection.lookup(store).starts_with(&self.projection.lookup(store)) && child.projection.lookup(store).starts_with(self.projection.lookup(store))
} }
/// The place itself is not included /// The place itself is not included
@ -333,7 +333,7 @@ pub enum AggregateKind {
Adt(VariantId, Substitution), Adt(VariantId, Substitution),
Union(UnionId, FieldId), Union(UnionId, FieldId),
Closure(Ty), Closure(Ty),
//Generator(LocalDefId, SubstsRef, Movability), //Coroutine(LocalDefId, SubstsRef, Movability),
} }
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@ -453,8 +453,8 @@ pub enum TerminatorKind {
/// `dest = move _0`. It might additionally do other things, like have side-effects in the /// `dest = move _0`. It might additionally do other things, like have side-effects in the
/// aliasing model. /// aliasing model.
/// ///
/// If the body is a generator body, this has slightly different semantics; it instead causes a /// If the body is a coroutine body, this has slightly different semantics; it instead causes a
/// `GeneratorState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned /// `CoroutineState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
/// to the return place. /// to the return place.
Return, Return,
@ -566,14 +566,14 @@ pub enum TerminatorKind {
/// Marks a suspend point. /// Marks a suspend point.
/// ///
/// Like `Return` terminators in generator bodies, this computes `value` and then a /// Like `Return` terminators in coroutine bodies, this computes `value` and then a
/// `GeneratorState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to /// `CoroutineState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
/// the return place of the function calling this one, and execution continues in the calling /// the return place of the function calling this one, and execution continues in the calling
/// function. When next invoked with the same first argument, execution of this function /// function. When next invoked with the same first argument, execution of this function
/// continues at the `resume` basic block, with the second argument written to the `resume_arg` /// continues at the `resume` basic block, with the second argument written to the `resume_arg`
/// place. If the generator is dropped before then, the `drop` basic block is invoked. /// place. If the coroutine is dropped before then, the `drop` basic block is invoked.
/// ///
/// Not permitted in bodies that are not generator bodies, or after generator lowering. /// Not permitted in bodies that are not coroutine bodies, or after coroutine lowering.
/// ///
/// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`? /// **Needs clarification**: What about the evaluation order of the `resume_arg` and `value`?
Yield { Yield {
@ -583,21 +583,21 @@ pub enum TerminatorKind {
resume: BasicBlockId, resume: BasicBlockId,
/// The place to store the resume argument in. /// The place to store the resume argument in.
resume_arg: Place, resume_arg: Place,
/// Cleanup to be done if the generator is dropped at this suspend point. /// Cleanup to be done if the coroutine is dropped at this suspend point.
drop: Option<BasicBlockId>, drop: Option<BasicBlockId>,
}, },
/// Indicates the end of dropping a generator. /// Indicates the end of dropping a coroutine.
/// ///
/// Semantically just a `return` (from the generators drop glue). Only permitted in the same situations /// Semantically just a `return` (from the coroutines drop glue). Only permitted in the same situations
/// as `yield`. /// as `yield`.
/// ///
/// **Needs clarification**: Is that even correct? The generator drop code is always confusing /// **Needs clarification**: Is that even correct? The coroutine drop code is always confusing
/// to me, because it's not even really in the current body. /// to me, because it's not even really in the current body.
/// ///
/// **Needs clarification**: Are there type system constraints on these terminators? Should /// **Needs clarification**: Are there type system constraints on these terminators? Should
/// there be a "block type" like `cleanup` blocks for them? /// there be a "block type" like `cleanup` blocks for them?
GeneratorDrop, CoroutineDrop,
/// A block where control flow only ever takes one real path, but borrowck needs to be more /// A block where control flow only ever takes one real path, but borrowck needs to be more
/// conservative. /// conservative.
@ -989,8 +989,8 @@ pub enum Rvalue {
/// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo` /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
/// has a destructor. /// has a destructor.
/// ///
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
/// generator lowering, `Generator` aggregate kinds are disallowed too. /// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
Aggregate(AggregateKind, Box<[Operand]>), Aggregate(AggregateKind, Box<[Operand]>),
/// Transmutes a `*mut u8` into shallow-initialized `Box<T>`. /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
@ -1140,7 +1140,7 @@ impl MirBody {
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::GeneratorDrop | TerminatorKind::CoroutineDrop
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable => (), | TerminatorKind::Unreachable => (),

View File

@ -53,7 +53,7 @@ fn all_mir_bodies(
match db.mir_body_for_closure(c) { match db.mir_body_for_closure(c) {
Ok(body) => { Ok(body) => {
cb(body.clone()); cb(body.clone());
body.closures.iter().map(|&it| for_closure(db, it, cb)).collect() body.closures.iter().try_for_each(|&it| for_closure(db, it, cb))
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -61,7 +61,7 @@ fn all_mir_bodies(
match db.mir_body(def) { match db.mir_body(def) {
Ok(body) => { Ok(body) => {
cb(body.clone()); cb(body.clone());
body.closures.iter().map(|&it| for_closure(db, it, &mut cb)).collect() body.closures.iter().try_for_each(|&it| for_closure(db, it, &mut cb))
} }
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -159,7 +159,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::Goto { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume | TerminatorKind::UnwindResume
| TerminatorKind::GeneratorDrop | TerminatorKind::CoroutineDrop
| TerminatorKind::Abort | TerminatorKind::Abort
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
@ -257,7 +257,7 @@ fn ever_initialized_map(
for statement in &block.statements { for statement in &block.statements {
match &statement.kind { match &statement.kind {
StatementKind::Assign(p, _) => { StatementKind::Assign(p, _) => {
if p.projection.lookup(&body.projection_store).len() == 0 && p.local == l { if p.projection.lookup(&body.projection_store).is_empty() && p.local == l {
is_ever_initialized = true; is_ever_initialized = true;
} }
} }
@ -295,30 +295,23 @@ fn ever_initialized_map(
| TerminatorKind::Return | TerminatorKind::Return
| TerminatorKind::Unreachable => (), | TerminatorKind::Unreachable => (),
TerminatorKind::Call { target, cleanup, destination, .. } => { TerminatorKind::Call { target, cleanup, destination, .. } => {
if destination.projection.lookup(&body.projection_store).len() == 0 if destination.projection.lookup(&body.projection_store).is_empty()
&& destination.local == l && destination.local == l
{ {
is_ever_initialized = true; is_ever_initialized = true;
} }
target target.iter().chain(cleanup).for_each(|&it| process(it, is_ever_initialized));
.into_iter()
.chain(cleanup.into_iter())
.for_each(|&it| process(it, is_ever_initialized));
} }
TerminatorKind::Drop { target, unwind, place: _ } => { TerminatorKind::Drop { target, unwind, place: _ } => {
iter::once(target) iter::once(target).chain(unwind).for_each(|&it| process(it, is_ever_initialized));
.into_iter()
.chain(unwind.into_iter())
.for_each(|&it| process(it, is_ever_initialized));
} }
TerminatorKind::DropAndReplace { .. } TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::CoroutineDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => { | TerminatorKind::FalseUnwind { .. } => {
never!("We don't emit these MIR terminators yet"); never!("We don't emit these MIR terminators yet");
()
} }
} }
} }
@ -346,11 +339,8 @@ fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap<LocalId, M
} }
fn record_usage(local: LocalId, result: &mut ArenaMap<LocalId, MutabilityReason>) { fn record_usage(local: LocalId, result: &mut ArenaMap<LocalId, MutabilityReason>) {
match &mut result[local] { if let it @ MutabilityReason::Unused = &mut result[local] {
it @ MutabilityReason::Unused => { *it = MutabilityReason::Not;
*it = MutabilityReason::Not;
}
_ => (),
}; };
} }
@ -439,7 +429,7 @@ fn mutability_of_locals(
| TerminatorKind::Unreachable | TerminatorKind::Unreachable
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } | TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::CoroutineDrop
| TerminatorKind::Drop { .. } | TerminatorKind::Drop { .. }
| TerminatorKind::DropAndReplace { .. } | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
@ -452,7 +442,7 @@ fn mutability_of_locals(
for arg in args.iter() { for arg in args.iter() {
record_usage_for_operand(arg, &mut result); record_usage_for_operand(arg, &mut result);
} }
if destination.projection.lookup(&body.projection_store).len() == 0 { if destination.projection.lookup(&body.projection_store).is_empty() {
if ever_init_map.get(destination.local).copied().unwrap_or_default() { if ever_init_map.get(destination.local).copied().unwrap_or_default() {
push_mut_span(destination.local, MirSpan::Unknown, &mut result); push_mut_span(destination.local, MirSpan::Unknown, &mut result);
} else { } else {

View File

@ -272,6 +272,7 @@ const STACK_OFFSET: usize = 1 << 30;
const HEAP_OFFSET: usize = 1 << 29; const HEAP_OFFSET: usize = 1 << 29;
impl Address { impl Address {
#[allow(clippy::double_parens)]
fn from_bytes(it: &[u8]) -> Result<Self> { fn from_bytes(it: &[u8]) -> Result<Self> {
Ok(Address::from_usize(from_bytes!(usize, it))) Ok(Address::from_usize(from_bytes!(usize, it)))
} }
@ -291,12 +292,11 @@ impl Address {
} }
fn to_usize(&self) -> usize { fn to_usize(&self) -> usize {
let as_num = match self { match self {
Stack(it) => *it + STACK_OFFSET, Stack(it) => *it + STACK_OFFSET,
Heap(it) => *it + HEAP_OFFSET, Heap(it) => *it + HEAP_OFFSET,
Invalid(it) => *it, Invalid(it) => *it,
}; }
as_num
} }
fn map(&self, f: impl FnOnce(usize) -> usize) -> Address { fn map(&self, f: impl FnOnce(usize) -> usize) -> Address {
@ -485,8 +485,7 @@ impl DropFlags {
fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool { fn remove_place(&mut self, p: &Place, store: &ProjectionStore) -> bool {
// FIXME: replace parents with parts // FIXME: replace parents with parts
if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(&it)) if let Some(parent) = p.iterate_over_parents(store).find(|it| self.need_drop.contains(it)) {
{
self.need_drop.remove(&parent); self.need_drop.remove(&parent);
return true; return true;
} }
@ -551,7 +550,7 @@ pub fn interpret_mir(
memory_map.vtable.shrink_to_fit(); memory_map.vtable.shrink_to_fit();
MemoryMap::Complex(Box::new(memory_map)) MemoryMap::Complex(Box::new(memory_map))
}; };
return Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty)); Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty))
})(); })();
(it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr }) (it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })
} }
@ -562,12 +561,12 @@ const EXECUTION_LIMIT: usize = 100_000;
const EXECUTION_LIMIT: usize = 10_000_000; const EXECUTION_LIMIT: usize = 10_000_000;
impl Evaluator<'_> { impl Evaluator<'_> {
pub fn new<'a>( pub fn new(
db: &'a dyn HirDatabase, db: &dyn HirDatabase,
owner: DefWithBodyId, owner: DefWithBodyId,
assert_placeholder_ty_is_unused: bool, assert_placeholder_ty_is_unused: bool,
trait_env: Option<Arc<TraitEnvironment>>, trait_env: Option<Arc<TraitEnvironment>>,
) -> Evaluator<'a> { ) -> Evaluator<'_> {
let crate_id = owner.module(db.upcast()).krate(); let crate_id = owner.module(db.upcast()).krate();
Evaluator { Evaluator {
stack: vec![0], stack: vec![0],
@ -585,7 +584,7 @@ impl Evaluator<'_> {
assert_placeholder_ty_is_unused, assert_placeholder_ty_is_unused,
stack_depth_limit: 100, stack_depth_limit: 100,
execution_limit: EXECUTION_LIMIT, execution_limit: EXECUTION_LIMIT,
memory_limit: 1000_000_000, // 2GB, 1GB for stack and 1GB for heap memory_limit: 1_000_000_000, // 2GB, 1GB for stack and 1GB for heap
layout_cache: RefCell::new(Default::default()), layout_cache: RefCell::new(Default::default()),
projected_ty_cache: RefCell::new(Default::default()), projected_ty_cache: RefCell::new(Default::default()),
not_special_fn_cache: RefCell::new(Default::default()), not_special_fn_cache: RefCell::new(Default::default()),
@ -752,7 +751,7 @@ impl Evaluator<'_> {
Variants::Multiple { variants, .. } => { Variants::Multiple { variants, .. } => {
&variants[match f.parent { &variants[match f.parent {
hir_def::VariantId::EnumVariantId(it) => { hir_def::VariantId::EnumVariantId(it) => {
RustcEnumVariantIdx(it.local_id) RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize)
} }
_ => { _ => {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
@ -816,8 +815,8 @@ impl Evaluator<'_> {
}) })
} }
fn interpret_mir<'slf>( fn interpret_mir(
&'slf mut self, &mut self,
body: Arc<MirBody>, body: Arc<MirBody>,
args: impl Iterator<Item = IntervalOrOwned>, args: impl Iterator<Item = IntervalOrOwned>,
) -> Result<Interval> { ) -> Result<Interval> {
@ -837,7 +836,7 @@ impl Evaluator<'_> {
not_supported!("missing stack frame"); not_supported!("missing stack frame");
}; };
let e = (|| { let e = (|| {
let mut locals = &mut my_stack_frame.locals; let locals = &mut my_stack_frame.locals;
let body = locals.body.clone(); let body = locals.body.clone();
loop { loop {
let current_block = &body.basic_blocks[current_block_idx]; let current_block = &body.basic_blocks[current_block_idx];
@ -849,12 +848,10 @@ impl Evaluator<'_> {
for statement in &current_block.statements { for statement in &current_block.statements {
match &statement.kind { match &statement.kind {
StatementKind::Assign(l, r) => { StatementKind::Assign(l, r) => {
let addr = self.place_addr(l, &locals)?; let addr = self.place_addr(l, locals)?;
let result = self.eval_rvalue(r, &mut locals)?; let result = self.eval_rvalue(r, locals)?;
self.copy_from_interval_or_owned(addr, result)?; self.copy_from_interval_or_owned(addr, result)?;
locals locals.drop_flags.add_place(*l, &locals.body.projection_store);
.drop_flags
.add_place(l.clone(), &locals.body.projection_store);
} }
StatementKind::Deinit(_) => not_supported!("de-init statement"), StatementKind::Deinit(_) => not_supported!("de-init statement"),
StatementKind::StorageLive(_) StatementKind::StorageLive(_)
@ -878,20 +875,20 @@ impl Evaluator<'_> {
cleanup: _, cleanup: _,
from_hir_call: _, from_hir_call: _,
} => { } => {
let destination_interval = self.place_interval(destination, &locals)?; let destination_interval = self.place_interval(destination, locals)?;
let fn_ty = self.operand_ty(func, &locals)?; let fn_ty = self.operand_ty(func, locals)?;
let args = args let args = args
.iter() .iter()
.map(|it| self.operand_ty_and_eval(it, &mut locals)) .map(|it| self.operand_ty_and_eval(it, locals))
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
let stack_frame = match &fn_ty.kind(Interner) { let stack_frame = match &fn_ty.kind(Interner) {
TyKind::Function(_) => { TyKind::Function(_) => {
let bytes = self.eval_operand(func, &mut locals)?; let bytes = self.eval_operand(func, locals)?;
self.exec_fn_pointer( self.exec_fn_pointer(
bytes, bytes,
destination_interval, destination_interval,
&args, &args,
&locals, locals,
*target, *target,
terminator.span, terminator.span,
)? )?
@ -901,7 +898,7 @@ impl Evaluator<'_> {
generic_args, generic_args,
destination_interval, destination_interval,
&args, &args,
&locals, locals,
*target, *target,
terminator.span, terminator.span,
)?, )?,
@ -909,7 +906,7 @@ impl Evaluator<'_> {
}; };
locals locals
.drop_flags .drop_flags
.add_place(destination.clone(), &locals.body.projection_store); .add_place(*destination, &locals.body.projection_store);
if let Some(stack_frame) = stack_frame { if let Some(stack_frame) = stack_frame {
self.code_stack.push(my_stack_frame); self.code_stack.push(my_stack_frame);
current_block_idx = stack_frame.locals.body.start_block; current_block_idx = stack_frame.locals.body.start_block;
@ -924,7 +921,7 @@ impl Evaluator<'_> {
} }
TerminatorKind::SwitchInt { discr, targets } => { TerminatorKind::SwitchInt { discr, targets } => {
let val = u128::from_le_bytes(pad16( let val = u128::from_le_bytes(pad16(
self.eval_operand(discr, &mut locals)?.get(&self)?, self.eval_operand(discr, locals)?.get(self)?,
false, false,
)); ));
current_block_idx = targets.target_for_value(val); current_block_idx = targets.target_for_value(val);
@ -938,7 +935,7 @@ impl Evaluator<'_> {
)); ));
} }
TerminatorKind::Drop { place, target, unwind: _ } => { TerminatorKind::Drop { place, target, unwind: _ } => {
self.drop_place(place, &mut locals, terminator.span)?; self.drop_place(place, locals, terminator.span)?;
current_block_idx = *target; current_block_idx = *target;
} }
_ => not_supported!("unknown terminator"), _ => not_supported!("unknown terminator"),
@ -1081,7 +1078,7 @@ impl Evaluator<'_> {
} }
} }
Rvalue::UnaryOp(op, val) => { Rvalue::UnaryOp(op, val) => {
let mut c = self.eval_operand(val, locals)?.get(&self)?; let mut c = self.eval_operand(val, locals)?.get(self)?;
let mut ty = self.operand_ty(val, locals)?; let mut ty = self.operand_ty(val, locals)?;
while let TyKind::Ref(_, _, z) = ty.kind(Interner) { while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
ty = z.clone(); ty = z.clone();
@ -1124,8 +1121,8 @@ impl Evaluator<'_> {
Rvalue::CheckedBinaryOp(op, lhs, rhs) => 'binary_op: { Rvalue::CheckedBinaryOp(op, lhs, rhs) => 'binary_op: {
let lc = self.eval_operand(lhs, locals)?; let lc = self.eval_operand(lhs, locals)?;
let rc = self.eval_operand(rhs, locals)?; let rc = self.eval_operand(rhs, locals)?;
let mut lc = lc.get(&self)?; let mut lc = lc.get(self)?;
let mut rc = rc.get(&self)?; let mut rc = rc.get(self)?;
let mut ty = self.operand_ty(lhs, locals)?; let mut ty = self.operand_ty(lhs, locals)?;
while let TyKind::Ref(_, _, z) = ty.kind(Interner) { while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
ty = z.clone(); ty = z.clone();
@ -1277,12 +1274,12 @@ impl Evaluator<'_> {
} }
Rvalue::Discriminant(p) => { Rvalue::Discriminant(p) => {
let ty = self.place_ty(p, locals)?; let ty = self.place_ty(p, locals)?;
let bytes = self.eval_place(p, locals)?.get(&self)?; let bytes = self.eval_place(p, locals)?.get(self)?;
let result = self.compute_discriminant(ty, bytes)?; let result = self.compute_discriminant(ty, bytes)?;
Owned(result.to_le_bytes().to_vec()) Owned(result.to_le_bytes().to_vec())
} }
Rvalue::Repeat(it, len) => { Rvalue::Repeat(it, len) => {
let len = match try_const_usize(self.db, &len) { let len = match try_const_usize(self.db, len) {
Some(it) => it as usize, Some(it) => it as usize,
None => not_supported!("non evaluatable array len in repeat Rvalue"), None => not_supported!("non evaluatable array len in repeat Rvalue"),
}; };
@ -1308,13 +1305,13 @@ impl Evaluator<'_> {
AggregateKind::Array(_) => { AggregateKind::Array(_) => {
let mut r = vec![]; let mut r = vec![];
for it in values { for it in values {
let value = it.get(&self)?; let value = it.get(self)?;
r.extend(value); r.extend(value);
} }
Owned(r) Owned(r)
} }
AggregateKind::Tuple(ty) => { AggregateKind::Tuple(ty) => {
let layout = self.layout(&ty)?; let layout = self.layout(ty)?;
Owned(self.make_by_layout( Owned(self.make_by_layout(
layout.size.bytes_usize(), layout.size.bytes_usize(),
&layout, &layout,
@ -1329,7 +1326,7 @@ impl Evaluator<'_> {
.fields .fields
.offset(u32::from(f.local_id.into_raw()) as usize) .offset(u32::from(f.local_id.into_raw()) as usize)
.bytes_usize(); .bytes_usize();
let op = values[0].get(&self)?; let op = values[0].get(self)?;
let mut result = vec![0; layout.size.bytes_usize()]; let mut result = vec![0; layout.size.bytes_usize()];
result[offset..offset + op.len()].copy_from_slice(op); result[offset..offset + op.len()].copy_from_slice(op);
Owned(result) Owned(result)
@ -1345,7 +1342,7 @@ impl Evaluator<'_> {
)?) )?)
} }
AggregateKind::Closure(ty) => { AggregateKind::Closure(ty) => {
let layout = self.layout(&ty)?; let layout = self.layout(ty)?;
Owned(self.make_by_layout( Owned(self.make_by_layout(
layout.size.bytes_usize(), layout.size.bytes_usize(),
&layout, &layout,
@ -1390,14 +1387,11 @@ impl Evaluator<'_> {
| CastKind::PointerExposeAddress | CastKind::PointerExposeAddress
| CastKind::PointerFromExposedAddress => { | CastKind::PointerFromExposedAddress => {
let current_ty = self.operand_ty(operand, locals)?; let current_ty = self.operand_ty(operand, locals)?;
let is_signed = match current_ty.kind(Interner) { let is_signed = matches!(
TyKind::Scalar(s) => match s { current_ty.kind(Interner),
chalk_ir::Scalar::Int(_) => true, TyKind::Scalar(chalk_ir::Scalar::Int(_))
_ => false, );
}, let current = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed);
_ => false,
};
let current = pad16(self.eval_operand(operand, locals)?.get(&self)?, is_signed);
let dest_size = let dest_size =
self.size_of_sized(target_ty, locals, "destination of int to int cast")?; self.size_of_sized(target_ty, locals, "destination of int to int cast")?;
Owned(current[0..dest_size].to_vec()) Owned(current[0..dest_size].to_vec())
@ -1412,22 +1406,12 @@ impl Evaluator<'_> {
fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> { fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
let layout = self.layout(&ty)?; let layout = self.layout(&ty)?;
let enum_id = 'b: { let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else {
match ty.kind(Interner) {
TyKind::Adt(e, _) => match e.0 {
AdtId::EnumId(e) => break 'b e,
_ => (),
},
_ => (),
}
return Ok(0); return Ok(0);
}; };
match &layout.variants { match &layout.variants {
Variants::Single { index } => { Variants::Single { index } => {
let r = self.const_eval_discriminant(EnumVariantId { let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
parent: enum_id,
local_id: index.0,
})?;
Ok(r) Ok(r)
} }
Variants::Multiple { tag, tag_encoding, variants, .. } => { Variants::Multiple { tag, tag_encoding, variants, .. } => {
@ -1446,17 +1430,15 @@ impl Evaluator<'_> {
let candidate_tag = i128::from_le_bytes(pad16(tag, false)) let candidate_tag = i128::from_le_bytes(pad16(tag, false))
.wrapping_sub(*niche_start as i128) .wrapping_sub(*niche_start as i128)
as usize; as usize;
let variant = variants let idx = variants
.iter_enumerated() .iter_enumerated()
.map(|(it, _)| it) .map(|(it, _)| it)
.filter(|it| it != untagged_variant) .filter(|it| it != untagged_variant)
.nth(candidate_tag) .nth(candidate_tag)
.unwrap_or(*untagged_variant) .unwrap_or(*untagged_variant)
.0; .0;
let result = self.const_eval_discriminant(EnumVariantId { let result =
parent: enum_id, self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?;
local_id: variant,
})?;
Ok(result) Ok(result)
} }
} }
@ -1525,7 +1507,7 @@ impl Evaluator<'_> {
let mut r = Vec::with_capacity(16); let mut r = Vec::with_capacity(16);
let addr = addr.get(self)?; let addr = addr.get(self)?;
r.extend(addr.iter().copied()); r.extend(addr.iter().copied());
r.extend(len.to_le_bytes().into_iter()); r.extend(len.to_le_bytes());
Owned(r) Owned(r)
} }
t => { t => {
@ -1537,7 +1519,7 @@ impl Evaluator<'_> {
let mut r = Vec::with_capacity(16); let mut r = Vec::with_capacity(16);
let addr = addr.get(self)?; let addr = addr.get(self)?;
r.extend(addr.iter().copied()); r.extend(addr.iter().copied());
r.extend(vtable.to_le_bytes().into_iter()); r.extend(vtable.to_le_bytes());
Owned(r) Owned(r)
} }
TyKind::Adt(id, target_subst) => match &current_ty.kind(Interner) { TyKind::Adt(id, target_subst) => match &current_ty.kind(Interner) {
@ -1551,7 +1533,7 @@ impl Evaluator<'_> {
AdtId::EnumId(_) => not_supported!("unsizing enums"), AdtId::EnumId(_) => not_supported!("unsizing enums"),
}; };
let Some((last_field, _)) = let Some((last_field, _)) =
self.db.struct_data(id).variant_data.fields().iter().rev().next() self.db.struct_data(id).variant_data.fields().iter().next_back()
else { else {
not_supported!("unsizing struct without field"); not_supported!("unsizing struct without field");
}; };
@ -1579,14 +1561,16 @@ impl Evaluator<'_> {
subst: Substitution, subst: Substitution,
locals: &Locals, locals: &Locals,
) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> { ) -> Result<(usize, Arc<Layout>, Option<(usize, usize, i128)>)> {
let adt = it.adt_id(); let adt = it.adt_id(self.db.upcast());
if let DefWithBodyId::VariantId(f) = locals.body.owner { if let DefWithBodyId::VariantId(f) = locals.body.owner {
if let VariantId::EnumVariantId(it) = it { if let VariantId::EnumVariantId(it) = it {
if AdtId::from(f.parent) == adt { if let AdtId::EnumId(e) = adt {
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and if f.lookup(self.db.upcast()).parent == e {
// infinite sized type errors) we use a dummy layout // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
let i = self.const_eval_discriminant(it)?; // infinite sized type errors) we use a dummy layout
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i)))); let i = self.const_eval_discriminant(it)?;
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
}
} }
} }
} }
@ -1602,8 +1586,9 @@ impl Evaluator<'_> {
VariantId::EnumVariantId(it) => it, VariantId::EnumVariantId(it) => it,
_ => not_supported!("multi variant layout for non-enums"), _ => not_supported!("multi variant layout for non-enums"),
}; };
let rustc_enum_variant_idx = RustcEnumVariantIdx(enum_variant_id.local_id);
let mut discriminant = self.const_eval_discriminant(enum_variant_id)?; let mut discriminant = self.const_eval_discriminant(enum_variant_id)?;
let lookup = enum_variant_id.lookup(self.db.upcast());
let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize);
let variant_layout = variants[rustc_enum_variant_idx].clone(); let variant_layout = variants[rustc_enum_variant_idx].clone();
let have_tag = match tag_encoding { let have_tag = match tag_encoding {
TagEncoding::Direct => true, TagEncoding::Direct => true,
@ -1654,7 +1639,7 @@ impl Evaluator<'_> {
} }
for (i, op) in values.enumerate() { for (i, op) in values.enumerate() {
let offset = variant_layout.fields.offset(i).bytes_usize(); let offset = variant_layout.fields.offset(i).bytes_usize();
let op = op.get(&self)?; let op = op.get(self)?;
match result.get_mut(offset..offset + op.len()) { match result.get_mut(offset..offset + op.len()) {
Some(it) => it.copy_from_slice(op), Some(it) => it.copy_from_slice(op),
None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))), None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))),
@ -1677,6 +1662,7 @@ impl Evaluator<'_> {
}) })
} }
#[allow(clippy::double_parens)]
fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> { fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> {
let ty = &konst.data(Interner).ty; let ty = &konst.data(Interner).ty;
let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else { let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else {
@ -1695,7 +1681,7 @@ impl Evaluator<'_> {
} }
result_owner = self result_owner = self
.db .db
.const_eval(const_id.into(), subst, Some(self.trait_env.clone())) .const_eval(const_id, subst, Some(self.trait_env.clone()))
.map_err(|e| { .map_err(|e| {
let name = const_id.name(self.db.upcast()); let name = const_id.name(self.db.upcast());
MirEvalError::ConstEvalError(name, Box::new(e)) MirEvalError::ConstEvalError(name, Box::new(e))
@ -1778,9 +1764,8 @@ impl Evaluator<'_> {
))); )));
} }
}; };
Ok(mem.get_mut(pos..pos + size).ok_or_else(|| { mem.get_mut(pos..pos + size)
MirEvalError::UndefinedBehavior("out of bound memory write".to_string()) .ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory write".to_string()))
})?)
} }
fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> { fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> {
@ -1847,8 +1832,8 @@ impl Evaluator<'_> {
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize))); .then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
} }
if let DefWithBodyId::VariantId(f) = locals.body.owner { if let DefWithBodyId::VariantId(f) = locals.body.owner {
if let Some((adt, _)) = ty.as_adt() { if let Some((AdtId::EnumId(e), _)) = ty.as_adt() {
if AdtId::from(f.parent) == adt { if f.lookup(self.db.upcast()).parent == e {
// Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and // Computing the exact size of enums require resolving the enum discriminants. In order to prevent loops (and
// infinite sized type errors) we use a dummy size // infinite sized type errors) we use a dummy size
return Ok(Some((16, 16))); return Ok(Some((16, 16)));
@ -1856,10 +1841,10 @@ impl Evaluator<'_> {
} }
} }
let layout = self.layout(ty); let layout = self.layout(ty);
if self.assert_placeholder_ty_is_unused { if self.assert_placeholder_ty_is_unused
if matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _))) { && matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _)))
return Ok(Some((0, 1))); {
} return Ok(Some((0, 1)));
} }
let layout = layout?; let layout = layout?;
Ok(layout Ok(layout
@ -1969,14 +1954,14 @@ impl Evaluator<'_> {
if let Some(ty) = check_inner { if let Some(ty) = check_inner {
for i in 0..count { for i in 0..count {
let offset = element_size * i; let offset = element_size * i;
rec(this, &b[offset..offset + element_size], &ty, locals, mm)?; rec(this, &b[offset..offset + element_size], ty, locals, mm)?;
} }
} }
} }
} }
} }
chalk_ir::TyKind::Array(inner, len) => { chalk_ir::TyKind::Array(inner, len) => {
let len = match try_const_usize(this.db, &len) { let len = match try_const_usize(this.db, len) {
Some(it) => it as usize, Some(it) => it as usize,
None => not_supported!("non evaluatable array len in patching addresses"), None => not_supported!("non evaluatable array len in patching addresses"),
}; };
@ -2019,10 +2004,8 @@ impl Evaluator<'_> {
bytes, bytes,
e, e,
) { ) {
let data = &this.db.enum_data(e).variants[v].variant_data; let data = &this.db.enum_variant_data(v).variant_data;
let field_types = this let field_types = this.db.field_types(v.into());
.db
.field_types(EnumVariantId { parent: e, local_id: v }.into());
for (f, _) in data.fields().iter() { for (f, _) in data.fields().iter() {
let offset = let offset =
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
@ -2039,7 +2022,7 @@ impl Evaluator<'_> {
Ok(()) Ok(())
} }
let mut mm = ComplexMemoryMap::default(); let mut mm = ComplexMemoryMap::default();
rec(&self, bytes, ty, locals, &mut mm)?; rec(self, bytes, ty, locals, &mut mm)?;
Ok(mm) Ok(mm)
} }
@ -2093,14 +2076,13 @@ impl Evaluator<'_> {
} }
AdtId::UnionId(_) => (), AdtId::UnionId(_) => (),
AdtId::EnumId(e) => { AdtId::EnumId(e) => {
if let Some((variant, layout)) = detect_variant_from_bytes( if let Some((ev, layout)) = detect_variant_from_bytes(
&layout, &layout,
self.db, self.db,
self.trait_env.clone(), self.trait_env.clone(),
self.read_memory(addr, layout.size.bytes_usize())?, self.read_memory(addr, layout.size.bytes_usize())?,
e, e,
) { ) {
let ev = EnumVariantId { parent: e, local_id: variant };
for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
let offset = layout.fields.offset(i).bytes_usize(); let offset = layout.fields.offset(i).bytes_usize();
let ty = ty.clone().substitute(Interner, subst); let ty = ty.clone().substitute(Interner, subst);
@ -2123,7 +2105,7 @@ impl Evaluator<'_> {
} }
} }
TyKind::Array(inner, len) => { TyKind::Array(inner, len) => {
let len = match try_const_usize(self.db, &len) { let len = match try_const_usize(self.db, len) {
Some(it) => it as usize, Some(it) => it as usize,
None => not_supported!("non evaluatable array len in patching addresses"), None => not_supported!("non evaluatable array len in patching addresses"),
}; };
@ -2147,8 +2129,8 @@ impl Evaluator<'_> {
| TyKind::Str | TyKind::Str
| TyKind::Never | TyKind::Never
| TyKind::Closure(_, _) | TyKind::Closure(_, _)
| TyKind::Generator(_, _) | TyKind::Coroutine(_, _)
| TyKind::GeneratorWitness(_, _) | TyKind::CoroutineWitness(_, _)
| TyKind::Foreign(_) | TyKind::Foreign(_)
| TyKind::Error | TyKind::Error
| TyKind::Placeholder(_) | TyKind::Placeholder(_)
@ -2173,7 +2155,7 @@ impl Evaluator<'_> {
let next_ty = self.vtable_map.ty(id)?.clone(); let next_ty = self.vtable_map.ty(id)?.clone();
match &next_ty.kind(Interner) { match &next_ty.kind(Interner) {
TyKind::FnDef(def, generic_args) => { TyKind::FnDef(def, generic_args) => {
self.exec_fn_def(*def, generic_args, destination, args, &locals, target_bb, span) self.exec_fn_def(*def, generic_args, destination, args, locals, target_bb, span)
} }
TyKind::Closure(id, subst) => { TyKind::Closure(id, subst) => {
self.exec_closure(*id, bytes.slice(0..0), subst, destination, args, locals, span) self.exec_closure(*id, bytes.slice(0..0), subst, destination, args, locals, span)
@ -2207,7 +2189,7 @@ impl Evaluator<'_> {
closure_data.get(self)?.to_owned() closure_data.get(self)?.to_owned()
}; };
let arg_bytes = iter::once(Ok(closure_data)) let arg_bytes = iter::once(Ok(closure_data))
.chain(args.iter().map(|it| Ok(it.get(&self)?.to_owned()))) .chain(args.iter().map(|it| Ok(it.get(self)?.to_owned())))
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
let interval = self let interval = self
.interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned)) .interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned))
@ -2235,7 +2217,7 @@ impl Evaluator<'_> {
let generic_args = generic_args.clone(); let generic_args = generic_args.clone();
match def { match def {
CallableDefId::FunctionId(def) => { CallableDefId::FunctionId(def) => {
if let Some(_) = self.detect_fn_trait(def) { if self.detect_fn_trait(def).is_some() {
return self.exec_fn_trait( return self.exec_fn_trait(
def, def,
args, args,
@ -2258,7 +2240,7 @@ impl Evaluator<'_> {
} }
CallableDefId::StructId(id) => { CallableDefId::StructId(id) => {
let (size, variant_layout, tag) = let (size, variant_layout, tag) =
self.layout_of_variant(id.into(), generic_args, &locals)?; self.layout_of_variant(id.into(), generic_args, locals)?;
let result = self.make_by_layout( let result = self.make_by_layout(
size, size,
&variant_layout, &variant_layout,
@ -2270,7 +2252,7 @@ impl Evaluator<'_> {
} }
CallableDefId::EnumVariantId(id) => { CallableDefId::EnumVariantId(id) => {
let (size, variant_layout, tag) = let (size, variant_layout, tag) =
self.layout_of_variant(id.into(), generic_args, &locals)?; self.layout_of_variant(id.into(), generic_args, locals)?;
let result = self.make_by_layout( let result = self.make_by_layout(
size, size,
&variant_layout, &variant_layout,
@ -2365,7 +2347,7 @@ impl Evaluator<'_> {
} }
}), }),
); );
return self.exec_fn_with_args( self.exec_fn_with_args(
def, def,
&args_for_target, &args_for_target,
generics_for_target, generics_for_target,
@ -2373,7 +2355,7 @@ impl Evaluator<'_> {
destination, destination,
target_bb, target_bb,
span, span,
); )
} }
MirOrDynIndex::Mir(body) => self.exec_looked_up_function( MirOrDynIndex::Mir(body) => self.exec_looked_up_function(
body, body,
@ -2425,7 +2407,7 @@ impl Evaluator<'_> {
target_bb: Option<BasicBlockId>, target_bb: Option<BasicBlockId>,
span: MirSpan, span: MirSpan,
) -> Result<Option<StackFrame>> { ) -> Result<Option<StackFrame>> {
let func = args.get(0).ok_or(MirEvalError::TypeError("fn trait with no arg"))?; let func = args.first().ok_or(MirEvalError::TypeError("fn trait with no arg"))?;
let mut func_ty = func.ty.clone(); let mut func_ty = func.ty.clone();
let mut func_data = func.interval; let mut func_data = func.interval;
while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) { while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) {
@ -2441,25 +2423,10 @@ impl Evaluator<'_> {
} }
match &func_ty.kind(Interner) { match &func_ty.kind(Interner) {
TyKind::FnDef(def, subst) => { TyKind::FnDef(def, subst) => {
return self.exec_fn_def( self.exec_fn_def(*def, subst, destination, &args[1..], locals, target_bb, span)
*def,
subst,
destination,
&args[1..],
locals,
target_bb,
span,
);
} }
TyKind::Function(_) => { TyKind::Function(_) => {
return self.exec_fn_pointer( self.exec_fn_pointer(func_data, destination, &args[1..], locals, target_bb, span)
func_data,
destination,
&args[1..],
locals,
target_bb,
span,
);
} }
TyKind::Closure(closure, subst) => { TyKind::Closure(closure, subst) => {
return self.exec_closure( return self.exec_closure(
@ -2495,7 +2462,7 @@ impl Evaluator<'_> {
self.write_memory(addr, &result)?; self.write_memory(addr, &result)?;
IntervalAndTy { interval: Interval { addr, size }, ty } IntervalAndTy { interval: Interval { addr, size }, ty }
}; };
return self.exec_fn_with_args( self.exec_fn_with_args(
def, def,
&[arg0.clone(), arg1], &[arg0.clone(), arg1],
generic_args, generic_args,
@ -2503,7 +2470,7 @@ impl Evaluator<'_> {
destination, destination,
target_bb, target_bb,
span, span,
); )
} }
} }
} }
@ -2523,7 +2490,7 @@ impl Evaluator<'_> {
self.allocate_const_in_heap(locals, &konst)? self.allocate_const_in_heap(locals, &konst)?
} else { } else {
let ty = &self.db.infer(st.into())[self.db.body(st.into()).body_expr]; let ty = &self.db.infer(st.into())[self.db.body(st.into()).body_expr];
let Some((size, align)) = self.size_align_of(&ty, locals)? else { let Some((size, align)) = self.size_align_of(ty, locals)? else {
not_supported!("unsized extern static"); not_supported!("unsized extern static");
}; };
let addr = self.heap_allocate(size, align)?; let addr = self.heap_allocate(size, align)?;
@ -2540,11 +2507,13 @@ impl Evaluator<'_> {
match r { match r {
Ok(r) => Ok(r), Ok(r) => Ok(r),
Err(e) => { Err(e) => {
let data = self.db.enum_data(variant.parent); let db = self.db.upcast();
let loc = variant.lookup(db);
let enum_loc = loc.parent.lookup(db);
let name = format!( let name = format!(
"{}::{}", "{}::{}",
data.name.display(self.db.upcast()), enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
data.variants[variant.local_id].name.display(self.db.upcast()) loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
); );
Err(MirEvalError::ConstEvalError(name, Box::new(e))) Err(MirEvalError::ConstEvalError(name, Box::new(e)))
} }
@ -2635,8 +2604,8 @@ impl Evaluator<'_> {
| TyKind::Str | TyKind::Str
| TyKind::Never | TyKind::Never
| TyKind::Closure(_, _) | TyKind::Closure(_, _)
| TyKind::Generator(_, _) | TyKind::Coroutine(_, _)
| TyKind::GeneratorWitness(_, _) | TyKind::CoroutineWitness(_, _)
| TyKind::Foreign(_) | TyKind::Foreign(_)
| TyKind::Error | TyKind::Error
| TyKind::Placeholder(_) | TyKind::Placeholder(_)
@ -2679,7 +2648,7 @@ pub fn render_const_using_debug_impl(
db.upcast(), db.upcast(),
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments( &hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
hir_expand::mod_path::PathKind::Abs, hir_expand::mod_path::PathKind::Abs,
[name![core], name![fmt], name![Debug]].into_iter(), [name![core], name![fmt], name![Debug]],
)), )),
) else { ) else {
not_supported!("core::fmt::Debug not found"); not_supported!("core::fmt::Debug not found");
@ -2711,7 +2680,7 @@ pub fn render_const_using_debug_impl(
db.upcast(), db.upcast(),
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments( &hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
hir_expand::mod_path::PathKind::Abs, hir_expand::mod_path::PathKind::Abs,
[name![std], name![fmt], name![format]].into_iter(), [name![std], name![fmt], name![format]],
)), )),
) else { ) else {
not_supported!("std::fmt::format not found"); not_supported!("std::fmt::format not found");

View File

@ -60,7 +60,7 @@ impl Evaluator<'_> {
args, args,
generic_args, generic_args,
destination, destination,
&locals, locals,
span, span,
)?; )?;
return Ok(true); return Ok(true);
@ -82,7 +82,7 @@ impl Evaluator<'_> {
args, args,
generic_args, generic_args,
destination, destination,
&locals, locals,
span, span,
)?; )?;
return Ok(true); return Ok(true);
@ -100,7 +100,7 @@ impl Evaluator<'_> {
args, args,
generic_args, generic_args,
destination, destination,
&locals, locals,
span, span,
)?; )?;
return Ok(true); return Ok(true);
@ -125,7 +125,7 @@ impl Evaluator<'_> {
} }
if let Some(it) = self.detect_lang_function(def) { if let Some(it) = self.detect_lang_function(def) {
let arg_bytes = let arg_bytes =
args.iter().map(|it| Ok(it.get(&self)?.to_owned())).collect::<Result<Vec<_>>>()?; args.iter().map(|it| Ok(it.get(self)?.to_owned())).collect::<Result<Vec<_>>>()?;
let result = self.exec_lang_item(it, generic_args, &arg_bytes, locals, span)?; let result = self.exec_lang_item(it, generic_args, &arg_bytes, locals, span)?;
destination.write_from_bytes(self, &result)?; destination.write_from_bytes(self, &result)?;
return Ok(true); return Ok(true);
@ -313,7 +313,7 @@ impl Evaluator<'_> {
&hir_def::path::Path::from_known_path_with_no_generic( &hir_def::path::Path::from_known_path_with_no_generic(
ModPath::from_segments( ModPath::from_segments(
hir_expand::mod_path::PathKind::Abs, hir_expand::mod_path::PathKind::Abs,
[name![std], name![fmt], name![format]].into_iter(), [name![std], name![fmt], name![format]],
), ),
), ),
) else { ) else {
@ -347,7 +347,7 @@ impl Evaluator<'_> {
} }
DropInPlace => { DropInPlace => {
let ty = let ty =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)).ok_or( generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)).ok_or(
MirEvalError::TypeError( MirEvalError::TypeError(
"generic argument of drop_in_place is not provided", "generic argument of drop_in_place is not provided",
), ),
@ -445,7 +445,7 @@ impl Evaluator<'_> {
} }
"pthread_key_create" => { "pthread_key_create" => {
let key = self.thread_local_storage.create_key(); let key = self.thread_local_storage.create_key();
let Some(arg0) = args.get(0) else { let Some(arg0) = args.first() else {
return Err(MirEvalError::TypeError("pthread_key_create arg0 is not provided")); return Err(MirEvalError::TypeError("pthread_key_create arg0 is not provided"));
}; };
let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let arg0_addr = Address::from_bytes(arg0.get(self)?)?;
@ -466,7 +466,7 @@ impl Evaluator<'_> {
Ok(()) Ok(())
} }
"pthread_getspecific" => { "pthread_getspecific" => {
let Some(arg0) = args.get(0) else { let Some(arg0) = args.first() else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"pthread_getspecific arg0 is not provided", "pthread_getspecific arg0 is not provided",
)); ));
@ -477,7 +477,7 @@ impl Evaluator<'_> {
Ok(()) Ok(())
} }
"pthread_setspecific" => { "pthread_setspecific" => {
let Some(arg0) = args.get(0) else { let Some(arg0) = args.first() else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"pthread_setspecific arg0 is not provided", "pthread_setspecific arg0 is not provided",
)); ));
@ -728,7 +728,7 @@ impl Evaluator<'_> {
match name { match name {
"size_of" => { "size_of" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("size_of generic arg is not provided")); return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
}; };
@ -737,7 +737,7 @@ impl Evaluator<'_> {
} }
"min_align_of" | "pref_align_of" => { "min_align_of" | "pref_align_of" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("align_of generic arg is not provided")); return Err(MirEvalError::TypeError("align_of generic arg is not provided"));
}; };
@ -746,7 +746,7 @@ impl Evaluator<'_> {
} }
"size_of_val" => { "size_of_val" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("size_of_val generic arg is not provided")); return Err(MirEvalError::TypeError("size_of_val generic arg is not provided"));
}; };
@ -763,7 +763,7 @@ impl Evaluator<'_> {
} }
"min_align_of_val" => { "min_align_of_val" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"min_align_of_val generic arg is not provided", "min_align_of_val generic arg is not provided",
@ -782,7 +782,7 @@ impl Evaluator<'_> {
} }
"type_name" => { "type_name" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("type_name generic arg is not provided")); return Err(MirEvalError::TypeError("type_name generic arg is not provided"));
}; };
@ -806,7 +806,7 @@ impl Evaluator<'_> {
} }
"needs_drop" => { "needs_drop" => {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("size_of generic arg is not provided")); return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
}; };
@ -859,7 +859,7 @@ impl Evaluator<'_> {
let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false)); let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false));
let ans = lhs.wrapping_sub(rhs); let ans = lhs.wrapping_sub(rhs);
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"ptr_offset_from generic arg is not provided", "ptr_offset_from generic arg is not provided",
@ -971,7 +971,7 @@ impl Evaluator<'_> {
)); ));
}; };
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"copy_nonoverlapping generic arg is not provided", "copy_nonoverlapping generic arg is not provided",
@ -992,7 +992,7 @@ impl Evaluator<'_> {
}; };
let ty = if name == "offset" { let ty = if name == "offset" {
let Some(ty0) = let Some(ty0) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("offset generic arg is not provided")); return Err(MirEvalError::TypeError("offset generic arg is not provided"));
}; };
@ -1022,7 +1022,7 @@ impl Evaluator<'_> {
} }
} else { } else {
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"arith_offset generic arg is not provided", "arith_offset generic arg is not provided",
@ -1147,7 +1147,7 @@ impl Evaluator<'_> {
return Err(MirEvalError::TypeError("discriminant_value arg is not provided")); return Err(MirEvalError::TypeError("discriminant_value arg is not provided"));
}; };
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"discriminant_value generic arg is not provided", "discriminant_value generic arg is not provided",
@ -1207,7 +1207,7 @@ impl Evaluator<'_> {
}; };
let dst = Address::from_bytes(ptr.get(self)?)?; let dst = Address::from_bytes(ptr.get(self)?)?;
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError( return Err(MirEvalError::TypeError(
"write_via_copy generic arg is not provided", "write_via_copy generic arg is not provided",
@ -1224,7 +1224,7 @@ impl Evaluator<'_> {
let count = from_bytes!(usize, count.get(self)?); let count = from_bytes!(usize, count.get(self)?);
let val = from_bytes!(u8, val.get(self)?); let val = from_bytes!(u8, val.get(self)?);
let Some(ty) = let Some(ty) =
generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("write_bytes generic arg is not provided")); return Err(MirEvalError::TypeError("write_bytes generic arg is not provided"));
}; };
@ -1265,7 +1265,7 @@ impl Evaluator<'_> {
}; };
let field_types = &self.db.field_types(id.into()); let field_types = &self.db.field_types(id.into());
let last_field_ty = let last_field_ty =
field_types.iter().rev().next().unwrap().1.clone().substitute(Interner, subst); field_types.iter().next_back().unwrap().1.clone().substitute(Interner, subst);
let sized_part_size = let sized_part_size =
layout.fields.offset(field_types.iter().count() - 1).bytes_usize(); layout.fields.offset(field_types.iter().count() - 1).bytes_usize();
let sized_part_align = layout.align.abi.bytes() as usize; let sized_part_align = layout.align.abi.bytes() as usize;
@ -1308,10 +1308,11 @@ impl Evaluator<'_> {
// The rest of atomic intrinsics have exactly one generic arg // The rest of atomic intrinsics have exactly one generic arg
let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else {
return Err(MirEvalError::TypeError("atomic intrinsic generic arg is not provided")); return Err(MirEvalError::TypeError("atomic intrinsic generic arg is not provided"));
}; };
let Some(arg0) = args.get(0) else { let Some(arg0) = args.first() else {
return Err(MirEvalError::TypeError("atomic intrinsic arg0 is not provided")); return Err(MirEvalError::TypeError("atomic intrinsic arg0 is not provided"));
}; };
let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let arg0_addr = Address::from_bytes(arg0.get(self)?)?;

View File

@ -46,7 +46,7 @@ impl Evaluator<'_> {
match try_const_usize(self.db, len) { match try_const_usize(self.db, len) {
Some(len) => { Some(len) => {
let Some(ty) = let Some(ty) =
subst.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) subst.as_slice(Interner).first().and_then(|it| it.ty(Interner))
else { else {
return Err(MirEvalError::TypeError("simd type with no ty param")); return Err(MirEvalError::TypeError("simd type with no ty param"));
}; };
@ -106,7 +106,7 @@ impl Evaluator<'_> {
} }
} }
if is_signed { if is_signed {
if let Some((&l, &r)) = l.iter().zip(r).rev().next() { if let Some((&l, &r)) = l.iter().zip(r).next_back() {
if l != r { if l != r {
result = (l as i8).cmp(&(r as i8)); result = (l as i8).cmp(&(r as i8));
} }

View File

@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
Substitution::empty(Interner), Substitution::empty(Interner),
db.trait_environment(func_id.into()), db.trait_environment(func_id.into()),
) )
.map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?; .map_err(|e| MirEvalError::MirLowerError(func_id, e))?;
let (result, output) = interpret_mir(db, body, false, None); let (result, output) = interpret_mir(db, body, false, None);
result?; result?;
Ok((output.stdout().into_owned(), output.stderr().into_owned())) Ok((output.stdout().into_owned(), output.stderr().into_owned()))
@ -49,8 +49,8 @@ fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr
let mut err = String::new(); let mut err = String::new();
let line_index = |size: TextSize| { let line_index = |size: TextSize| {
let mut size = u32::from(size) as usize; let mut size = u32::from(size) as usize;
let mut lines = ra_fixture.lines().enumerate(); let lines = ra_fixture.lines().enumerate();
while let Some((i, l)) = lines.next() { for (i, l) in lines {
if let Some(x) = size.checked_sub(l.len()) { if let Some(x) = size.checked_sub(l.len()) {
size = x; size = x;
} else { } else {

View File

@ -69,6 +69,7 @@ struct MirLowerCtx<'a> {
drop_scopes: Vec<DropScope>, drop_scopes: Vec<DropScope>,
} }
// FIXME: Make this smaller, its stored in database queries
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum MirLowerError { pub enum MirLowerError {
ConstEvalError(Box<str>, Box<ConstEvalError>), ConstEvalError(Box<str>, Box<ConstEvalError>),
@ -258,7 +259,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
owner, owner,
closures: vec![], closures: vec![],
}; };
let ctx = MirLowerCtx {
MirLowerCtx {
result: mir, result: mir,
db, db,
infer, infer,
@ -268,8 +270,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
labeled_loop_blocks: Default::default(), labeled_loop_blocks: Default::default(),
discr_temp: None, discr_temp: None,
drop_scopes: vec![DropScope::default()], drop_scopes: vec![DropScope::default()],
}; }
ctx
} }
fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<LocalId> { fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<LocalId> {
@ -287,12 +288,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
current: BasicBlockId, current: BasicBlockId,
) -> Result<Option<(Operand, BasicBlockId)>> { ) -> Result<Option<(Operand, BasicBlockId)>> {
if !self.has_adjustments(expr_id) { if !self.has_adjustments(expr_id) {
match &self.body.exprs[expr_id] { if let Expr::Literal(l) = &self.body.exprs[expr_id] {
Expr::Literal(l) => { let ty = self.expr_ty_without_adjust(expr_id);
let ty = self.expr_ty_without_adjust(expr_id); return Ok(Some((self.lower_literal_to_operand(ty, l)?, current)));
return Ok(Some((self.lower_literal_to_operand(ty, l)?, current)));
}
_ => (),
} }
} }
let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else { let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else {
@ -344,8 +342,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
current, current,
place, place,
Rvalue::Cast( Rvalue::Cast(
CastKind::Pointer(cast.clone()), CastKind::Pointer(*cast),
Operand::Copy(p).into(), Operand::Copy(p),
last.target.clone(), last.target.clone(),
), ),
expr_id.into(), expr_id.into(),
@ -456,9 +454,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(Some(current)) Ok(Some(current))
} }
ValueNs::EnumVariantId(variant_id) => { ValueNs::EnumVariantId(variant_id) => {
let variant_data = let variant_data = &self.db.enum_variant_data(variant_id).variant_data;
&self.db.enum_data(variant_id.parent).variants[variant_id.local_id]; if variant_data.kind() == StructKind::Unit {
if variant_data.variant_data.kind() == StructKind::Unit {
let ty = self.infer.type_of_expr[expr_id].clone(); let ty = self.infer.type_of_expr[expr_id].clone();
current = self.lower_enum_variant( current = self.lower_enum_variant(
variant_id, variant_id,
@ -511,8 +508,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
return Ok(None); return Ok(None);
}; };
let start_of_then = self.new_basic_block(); let start_of_then = self.new_basic_block();
let end_of_then = let end_of_then = self.lower_expr_to_place(*then_branch, place, start_of_then)?;
self.lower_expr_to_place(*then_branch, place.clone(), start_of_then)?;
let start_of_else = self.new_basic_block(); let start_of_else = self.new_basic_block();
let end_of_else = if let Some(else_branch) = else_branch { let end_of_else = if let Some(else_branch) = else_branch {
self.lower_expr_to_place(*else_branch, place, start_of_else)? self.lower_expr_to_place(*else_branch, place, start_of_else)?
@ -539,7 +535,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
self.pattern_match(current, None, cond_place, *pat)?; self.pattern_match(current, None, cond_place, *pat)?;
self.write_bytes_to_place( self.write_bytes_to_place(
then_target, then_target,
place.clone(), place,
Box::new([1]), Box::new([1]),
TyBuilder::bool(), TyBuilder::bool(),
MirSpan::Unknown, MirSpan::Unknown,
@ -560,25 +556,19 @@ impl<'ctx> MirLowerCtx<'ctx> {
} }
Expr::Block { id: _, statements, tail, label } => { Expr::Block { id: _, statements, tail, label } => {
if let Some(label) = label { if let Some(label) = label {
self.lower_loop( self.lower_loop(current, place, Some(*label), expr_id.into(), |this, begin| {
current, if let Some(current) = this.lower_block_to_place(
place.clone(), statements,
Some(*label), begin,
expr_id.into(), *tail,
|this, begin| { place,
if let Some(current) = this.lower_block_to_place( expr_id.into(),
statements, )? {
begin, let end = this.current_loop_end()?;
*tail, this.set_goto(current, end, expr_id.into());
place, }
expr_id.into(), Ok(())
)? { })
let end = this.current_loop_end()?;
this.set_goto(current, end, expr_id.into());
}
Ok(())
},
)
} else { } else {
self.lower_block_to_place(statements, current, *tail, place, expr_id.into()) self.lower_block_to_place(statements, current, *tail, place, expr_id.into())
} }
@ -646,9 +636,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
); );
} }
TyKind::Error => { TyKind::Error => {
return Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id)) Err(MirLowerError::MissingFunctionDefinition(self.owner, expr_id))
} }
_ => return Err(MirLowerError::TypeError("function call on bad type")), _ => Err(MirLowerError::TypeError("function call on bad type")),
} }
} }
Expr::MethodCall { receiver, args, method_name, .. } => { Expr::MethodCall { receiver, args, method_name, .. } => {
@ -678,7 +668,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let mut end = None; let mut end = None;
for MatchArm { pat, guard, expr } in arms.iter() { for MatchArm { pat, guard, expr } in arms.iter() {
let (then, mut otherwise) = let (then, mut otherwise) =
self.pattern_match(current, None, cond_place.clone(), *pat)?; self.pattern_match(current, None, cond_place, *pat)?;
let then = if let &Some(guard) = guard { let then = if let &Some(guard) = guard {
let next = self.new_basic_block(); let next = self.new_basic_block();
let o = otherwise.get_or_insert_with(|| self.new_basic_block()); let o = otherwise.get_or_insert_with(|| self.new_basic_block());
@ -696,7 +686,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
} else { } else {
then then
}; };
if let Some(block) = self.lower_expr_to_place(*expr, place.clone(), then)? { if let Some(block) = self.lower_expr_to_place(*expr, place, then)? {
let r = end.get_or_insert_with(|| self.new_basic_block()); let r = end.get_or_insert_with(|| self.new_basic_block());
self.set_goto(block, *r, expr_id.into()); self.set_goto(block, *r, expr_id.into());
} }
@ -742,9 +732,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
.as_ref() .as_ref()
.ok_or(MirLowerError::BreakWithoutLoop)?, .ok_or(MirLowerError::BreakWithoutLoop)?,
}; };
let Some(c) = let Some(c) = self.lower_expr_to_place(expr, loop_data.place, current)? else {
self.lower_expr_to_place(expr, loop_data.place.clone(), current)?
else {
return Ok(None); return Ok(None);
}; };
current = c; current = c;
@ -906,7 +894,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let ty = self.expr_ty_after_adjustments(*expr); let ty = self.expr_ty_after_adjustments(*expr);
self.push_assignment( self.push_assignment(
current, current,
place.clone(), place,
Rvalue::ShallowInitBoxWithAlloc(ty), Rvalue::ShallowInitBoxWithAlloc(ty),
expr_id.into(), expr_id.into(),
); );
@ -957,10 +945,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
// for binary operator, and use without adjust to simplify our conditions. // for binary operator, and use without adjust to simplify our conditions.
let lhs_ty = self.expr_ty_without_adjust(*lhs); let lhs_ty = self.expr_ty_without_adjust(*lhs);
let rhs_ty = self.expr_ty_without_adjust(*rhs); let rhs_ty = self.expr_ty_without_adjust(*rhs);
if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. })) { if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. }))
if lhs_ty.as_raw_ptr().is_some() && rhs_ty.as_raw_ptr().is_some() { && lhs_ty.as_raw_ptr().is_some()
break 'b true; && rhs_ty.as_raw_ptr().is_some()
} {
break 'b true;
} }
let builtin_inequal_impls = matches!( let builtin_inequal_impls = matches!(
op, op,
@ -1006,11 +995,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
else { else {
return Ok(None); return Ok(None);
}; };
let r_value = Rvalue::CheckedBinaryOp( let r_value =
op.into(), Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op);
Operand::Copy(lhs_place.clone()),
rhs_op,
);
self.push_assignment(current, lhs_place, r_value, expr_id.into()); self.push_assignment(current, lhs_place, r_value, expr_id.into());
return Ok(Some(current)); return Ok(Some(current));
} else { } else {
@ -1029,7 +1015,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let start_of_then = self.new_basic_block(); let start_of_then = self.new_basic_block();
self.push_assignment( self.push_assignment(
start_of_then, start_of_then,
place.clone(), place,
lhs_op.clone().into(), lhs_op.clone().into(),
expr_id.into(), expr_id.into(),
); );
@ -1168,12 +1154,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
let tmp_ty = let tmp_ty =
capture.ty.clone().substitute(Interner, &placeholder_subst); capture.ty.clone().substitute(Interner, &placeholder_subst);
let tmp: Place = self.temp(tmp_ty, current, capture.span)?.into(); let tmp: Place = self.temp(tmp_ty, current, capture.span)?.into();
self.push_assignment( self.push_assignment(current, tmp, Rvalue::Ref(*bk, p), capture.span);
current,
tmp.clone(),
Rvalue::Ref(bk.clone(), p),
capture.span,
);
operands.push(Operand::Move(tmp)); operands.push(Operand::Move(tmp));
} }
CaptureKind::ByValue => operands.push(Operand::Move(p)), CaptureKind::ByValue => operands.push(Operand::Move(p)),
@ -1322,7 +1303,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
) { ) {
let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?; let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?;
let temp = Place::from(temp); let temp = Place::from(temp);
self.push_assignment(current, temp.clone(), rhs_op.into(), span); self.push_assignment(current, temp, rhs_op.into(), span);
return self.lower_destructing_assignment(current, lhs, temp, span); return self.lower_destructing_assignment(current, lhs, temp, span);
} }
let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)? else { let Some((lhs_place, current)) = self.lower_expr_as_place(current, lhs, false)? else {
@ -1333,11 +1314,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
} }
fn placeholder_subst(&mut self) -> Substitution { fn placeholder_subst(&mut self) -> Substitution {
let placeholder_subst = match self.owner.as_generic_def_id() { match self.owner.as_generic_def_id() {
Some(it) => TyBuilder::placeholder_subst(self.db, it), Some(it) => TyBuilder::placeholder_subst(self.db, it),
None => Substitution::empty(Interner), None => Substitution::empty(Interner),
}; }
placeholder_subst
} }
fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> { fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> {
@ -1470,7 +1450,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
} else { } else {
let name = const_id.name(self.db.upcast()); let name = const_id.name(self.db.upcast());
self.db self.db
.const_eval(const_id.into(), subst, None) .const_eval(const_id, subst, None)
.map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))? .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))?
}; };
Ok(Operand::Constant(c)) Ok(Operand::Constant(c))
@ -1612,13 +1592,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
fn discr_temp_place(&mut self, current: BasicBlockId) -> Place { fn discr_temp_place(&mut self, current: BasicBlockId) -> Place {
match &self.discr_temp { match &self.discr_temp {
Some(it) => it.clone(), Some(it) => *it,
None => { None => {
let tmp: Place = self let tmp: Place = self
.temp(TyBuilder::discr_ty(), current, MirSpan::Unknown) .temp(TyBuilder::discr_ty(), current, MirSpan::Unknown)
.expect("discr_ty is never unsized") .expect("discr_ty is never unsized")
.into(); .into();
self.discr_temp = Some(tmp.clone()); self.discr_temp = Some(tmp);
tmp tmp
} }
} }
@ -1874,11 +1854,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
match r { match r {
Ok(r) => Ok(r), Ok(r) => Ok(r),
Err(e) => { Err(e) => {
let data = self.db.enum_data(variant.parent); let db = self.db.upcast();
let loc = variant.lookup(db);
let enum_loc = loc.parent.lookup(db);
let name = format!( let name = format!(
"{}::{}", "{}::{}",
data.name.display(self.db.upcast()), enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast()),
data.variants[variant.local_id].name.display(self.db.upcast()) loc.id.item_tree(db)[loc.id.value].name.display(db.upcast()),
); );
Err(MirLowerError::ConstEvalError(name.into(), Box::new(e))) Err(MirLowerError::ConstEvalError(name.into(), Box::new(e)))
} }
@ -2039,19 +2021,16 @@ pub fn mir_body_for_closure_query(
ctx.result.walk_places(|p, store| { ctx.result.walk_places(|p, store| {
if let Some(it) = upvar_map.get(&p.local) { if let Some(it) = upvar_map.get(&p.local) {
let r = it.iter().find(|it| { let r = it.iter().find(|it| {
if p.projection.lookup(&store).len() < it.0.place.projections.len() { if p.projection.lookup(store).len() < it.0.place.projections.len() {
return false; return false;
} }
for (it, y) in p.projection.lookup(&store).iter().zip(it.0.place.projections.iter()) for (it, y) in p.projection.lookup(store).iter().zip(it.0.place.projections.iter())
{ {
match (it, y) { match (it, y) {
(ProjectionElem::Deref, ProjectionElem::Deref) => (), (ProjectionElem::Deref, ProjectionElem::Deref) => (),
(ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (), (ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (),
(ProjectionElem::ClosureField(it), ProjectionElem::ClosureField(y)) (ProjectionElem::ClosureField(it), ProjectionElem::ClosureField(y))
if it == y => if it == y => {}
{
()
}
_ => return false, _ => return false,
} }
} }
@ -2067,15 +2046,11 @@ pub fn mir_body_for_closure_query(
next_projs.push(ProjectionElem::Deref); next_projs.push(ProjectionElem::Deref);
} }
next_projs.extend( next_projs.extend(
prev_projs prev_projs.lookup(store).iter().skip(it.0.place.projections.len()).cloned(),
.lookup(&store)
.iter()
.skip(it.0.place.projections.len())
.cloned(),
); );
p.projection = store.intern(next_projs.into()); p.projection = store.intern(next_projs.into());
} }
None => err = Some(p.clone()), None => err = Some(*p),
} }
} }
}); });
@ -2104,7 +2079,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
.display(db.upcast()) .display(db.upcast())
.to_string(), .to_string(),
DefWithBodyId::VariantId(it) => { DefWithBodyId::VariantId(it) => {
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast()).to_string() db.enum_variant_data(it).name.display(db.upcast()).to_string()
} }
DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"), DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
}); });

View File

@ -148,7 +148,7 @@ impl MirLowerCtx<'_> {
let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into(); let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
temp.clone(), temp,
Operand::Static(s).into(), Operand::Static(s).into(),
expr_id.into(), expr_id.into(),
); );
@ -160,57 +160,53 @@ impl MirLowerCtx<'_> {
_ => try_rvalue(self), _ => try_rvalue(self),
} }
} }
Expr::UnaryOp { expr, op } => match op { Expr::UnaryOp { expr, op: hir_def::hir::UnaryOp::Deref } => {
hir_def::hir::UnaryOp::Deref => { let is_builtin = match self.expr_ty_without_adjust(*expr).kind(Interner) {
let is_builtin = match self.expr_ty_without_adjust(*expr).kind(Interner) { TyKind::Ref(..) | TyKind::Raw(..) => true,
TyKind::Ref(..) | TyKind::Raw(..) => true, TyKind::Adt(id, _) => {
TyKind::Adt(id, _) => { if let Some(lang_item) = self.db.lang_attr(id.0.into()) {
if let Some(lang_item) = self.db.lang_attr(id.0.into()) { lang_item == LangItem::OwnedBox
lang_item == LangItem::OwnedBox } else {
} else { false
false
}
} }
_ => false,
};
if !is_builtin {
let Some((p, current)) = self.lower_expr_as_place(current, *expr, true)?
else {
return Ok(None);
};
return self.lower_overloaded_deref(
current,
p,
self.expr_ty_after_adjustments(*expr),
self.expr_ty_without_adjust(expr_id),
expr_id.into(),
'b: {
if let Some((f, _)) = self.infer.method_resolution(expr_id) {
if let Some(deref_trait) =
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
{
if let Some(deref_fn) = self
.db
.trait_data(deref_trait)
.method_by_name(&name![deref_mut])
{
break 'b deref_fn == f;
}
}
}
false
},
);
} }
let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? _ => false,
else { };
if !is_builtin {
let Some((p, current)) = self.lower_expr_as_place(current, *expr, true)? else {
return Ok(None); return Ok(None);
}; };
r = r.project(ProjectionElem::Deref, &mut self.result.projection_store); return self.lower_overloaded_deref(
Ok(Some((r, current))) current,
p,
self.expr_ty_after_adjustments(*expr),
self.expr_ty_without_adjust(expr_id),
expr_id.into(),
'b: {
if let Some((f, _)) = self.infer.method_resolution(expr_id) {
if let Some(deref_trait) =
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
{
if let Some(deref_fn) = self
.db
.trait_data(deref_trait)
.method_by_name(&name![deref_mut])
{
break 'b deref_fn == f;
}
}
}
false
},
);
} }
_ => try_rvalue(self), let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else {
}, return Ok(None);
};
r = r.project(ProjectionElem::Deref, &mut self.result.projection_store);
Ok(Some((r, current)))
}
Expr::UnaryOp { .. } => try_rvalue(self),
Expr::Field { expr, .. } => { Expr::Field { expr, .. } => {
let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else { let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else {
return Ok(None); return Ok(None);
@ -304,7 +300,7 @@ impl MirLowerCtx<'_> {
let Some(current) = self.lower_call( let Some(current) = self.lower_call(
index_fn_op, index_fn_op,
Box::new([Operand::Copy(place), index_operand]), Box::new([Operand::Copy(place), index_operand]),
result.clone(), result,
current, current,
false, false,
span, span,
@ -338,7 +334,7 @@ impl MirLowerCtx<'_> {
let ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), source_ty.clone()).intern(Interner); let ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), source_ty.clone()).intern(Interner);
let target_ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), target_ty).intern(Interner); let target_ty_ref = TyKind::Ref(chalk_mut, static_lifetime(), target_ty).intern(Interner);
let ref_place: Place = self.temp(ty_ref, current, span)?.into(); let ref_place: Place = self.temp(ty_ref, current, span)?.into();
self.push_assignment(current, ref_place.clone(), Rvalue::Ref(borrow_kind, place), span); self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place), span);
let deref_trait = self let deref_trait = self
.resolve_lang_item(trait_lang_item)? .resolve_lang_item(trait_lang_item)?
.as_trait() .as_trait()
@ -359,7 +355,7 @@ impl MirLowerCtx<'_> {
let Some(current) = self.lower_call( let Some(current) = self.lower_call(
deref_fn_op, deref_fn_op,
Box::new([Operand::Copy(ref_place)]), Box::new([Operand::Copy(ref_place)]),
result.clone(), result,
current, current,
false, false,
span, span,

View File

@ -58,7 +58,7 @@ impl MirLowerCtx<'_> {
let (current, current_else) = self.pattern_match_inner( let (current, current_else) = self.pattern_match_inner(
current, current,
current_else, current_else,
cond_place.clone(), cond_place,
pattern, pattern,
MatchingMode::Check, MatchingMode::Check,
)?; )?;
@ -114,7 +114,7 @@ impl MirLowerCtx<'_> {
index: i as u32, index: i as u32,
})) }))
}), }),
&(&mut cond_place), &mut cond_place,
mode, mode,
)? )?
} }
@ -125,7 +125,7 @@ impl MirLowerCtx<'_> {
let (mut next, next_else) = self.pattern_match_inner( let (mut next, next_else) = self.pattern_match_inner(
current, current,
None, None,
(&mut cond_place).clone(), cond_place,
*pat, *pat,
MatchingMode::Check, MatchingMode::Check,
)?; )?;
@ -133,7 +133,7 @@ impl MirLowerCtx<'_> {
(next, _) = self.pattern_match_inner( (next, _) = self.pattern_match_inner(
next, next,
None, None,
(&mut cond_place).clone(), cond_place,
*pat, *pat,
MatchingMode::Bind, MatchingMode::Bind,
)?; )?;
@ -169,7 +169,7 @@ impl MirLowerCtx<'_> {
current, current,
pattern.into(), pattern.into(),
current_else, current_else,
AdtPatternShape::Record { args: &*args }, AdtPatternShape::Record { args },
mode, mode,
)? )?
} }
@ -183,12 +183,8 @@ impl MirLowerCtx<'_> {
self.temp(TyBuilder::bool(), current, pattern.into())?.into(); self.temp(TyBuilder::bool(), current, pattern.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
discr.clone(), discr,
Rvalue::CheckedBinaryOp( Rvalue::CheckedBinaryOp(binop, lv, Operand::Copy(cond_place)),
binop,
lv,
Operand::Copy((&mut cond_place).clone()),
),
pattern.into(), pattern.into(),
); );
let discr = Operand::Copy(discr); let discr = Operand::Copy(discr);
@ -222,8 +218,8 @@ impl MirLowerCtx<'_> {
self.temp(TyBuilder::usize(), current, pattern.into())?.into(); self.temp(TyBuilder::usize(), current, pattern.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
place_len.clone(), place_len,
Rvalue::Len((&mut cond_place).clone()), Rvalue::Len(cond_place),
pattern.into(), pattern.into(),
); );
let else_target = let else_target =
@ -252,7 +248,7 @@ impl MirLowerCtx<'_> {
self.temp(TyBuilder::bool(), current, pattern.into())?.into(); self.temp(TyBuilder::bool(), current, pattern.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
discr.clone(), discr,
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)), Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
pattern.into(), pattern.into(),
); );
@ -270,7 +266,7 @@ impl MirLowerCtx<'_> {
} }
} }
for (i, &pat) in prefix.iter().enumerate() { for (i, &pat) in prefix.iter().enumerate() {
let next_place = (&mut cond_place).project( let next_place = cond_place.project(
ProjectionElem::ConstantIndex { offset: i as u64, from_end: false }, ProjectionElem::ConstantIndex { offset: i as u64, from_end: false },
&mut self.result.projection_store, &mut self.result.projection_store,
); );
@ -280,7 +276,7 @@ impl MirLowerCtx<'_> {
if let Some(slice) = slice { if let Some(slice) = slice {
if mode == MatchingMode::Bind { if mode == MatchingMode::Bind {
if let Pat::Bind { id, subpat: _ } = self.body[*slice] { if let Pat::Bind { id, subpat: _ } = self.body[*slice] {
let next_place = (&mut cond_place).project( let next_place = cond_place.project(
ProjectionElem::Subslice { ProjectionElem::Subslice {
from: prefix.len() as u64, from: prefix.len() as u64,
to: suffix.len() as u64, to: suffix.len() as u64,
@ -299,7 +295,7 @@ impl MirLowerCtx<'_> {
} }
} }
for (i, &pat) in suffix.iter().enumerate() { for (i, &pat) in suffix.iter().enumerate() {
let next_place = (&mut cond_place).project( let next_place = cond_place.project(
ProjectionElem::ConstantIndex { offset: i as u64, from_end: true }, ProjectionElem::ConstantIndex { offset: i as u64, from_end: true },
&mut self.result.projection_store, &mut self.result.projection_store,
); );
@ -335,10 +331,8 @@ impl MirLowerCtx<'_> {
break 'b (c, x.1); break 'b (c, x.1);
} }
} }
if let ResolveValueResult::ValueNs(v, _) = pr { if let ResolveValueResult::ValueNs(ValueNs::ConstId(c), _) = pr {
if let ValueNs::ConstId(c) = v { break 'b (c, Substitution::empty(Interner));
break 'b (c, Substitution::empty(Interner));
}
} }
not_supported!("path in pattern position that is not const or variant") not_supported!("path in pattern position that is not const or variant")
}; };
@ -348,7 +342,7 @@ impl MirLowerCtx<'_> {
self.lower_const( self.lower_const(
c.into(), c.into(),
current, current,
tmp.clone(), tmp,
subst, subst,
span, span,
self.infer[pattern].clone(), self.infer[pattern].clone(),
@ -356,7 +350,7 @@ impl MirLowerCtx<'_> {
let tmp2: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into(); let tmp2: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
tmp2.clone(), tmp2,
Rvalue::CheckedBinaryOp( Rvalue::CheckedBinaryOp(
BinOp::Eq, BinOp::Eq,
Operand::Copy(tmp), Operand::Copy(tmp),
@ -390,13 +384,8 @@ impl MirLowerCtx<'_> {
}, },
Pat::Bind { id, subpat } => { Pat::Bind { id, subpat } => {
if let Some(subpat) = subpat { if let Some(subpat) = subpat {
(current, current_else) = self.pattern_match_inner( (current, current_else) =
current, self.pattern_match_inner(current, current_else, cond_place, *subpat, mode)?
current_else,
(&mut cond_place).clone(),
*subpat,
mode,
)?
} }
if mode == MatchingMode::Bind { if mode == MatchingMode::Bind {
self.pattern_match_binding( self.pattern_match_binding(
@ -475,7 +464,7 @@ impl MirLowerCtx<'_> {
let discr: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into(); let discr: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
self.push_assignment( self.push_assignment(
current, current,
discr.clone(), discr,
Rvalue::CheckedBinaryOp(BinOp::Eq, c, Operand::Copy(cond_place)), Rvalue::CheckedBinaryOp(BinOp::Eq, c, Operand::Copy(cond_place)),
pattern.into(), pattern.into(),
); );
@ -506,12 +495,7 @@ impl MirLowerCtx<'_> {
if mode == MatchingMode::Check { if mode == MatchingMode::Check {
let e = self.const_eval_discriminant(v)? as u128; let e = self.const_eval_discriminant(v)? as u128;
let tmp = self.discr_temp_place(current); let tmp = self.discr_temp_place(current);
self.push_assignment( self.push_assignment(current, tmp, Rvalue::Discriminant(cond_place), span);
current,
tmp.clone(),
Rvalue::Discriminant(cond_place.clone()),
span,
);
let next = self.new_basic_block(); let next = self.new_basic_block();
let else_target = current_else.get_or_insert_with(|| self.new_basic_block()); let else_target = current_else.get_or_insert_with(|| self.new_basic_block());
self.set_terminator( self.set_terminator(
@ -524,22 +508,9 @@ impl MirLowerCtx<'_> {
); );
current = next; current = next;
} }
let enum_data = self.db.enum_data(v.parent);
self.pattern_matching_variant_fields( self.pattern_matching_variant_fields(
shape, shape,
&enum_data.variants[v.local_id].variant_data, &self.db.enum_variant_data(v).variant_data,
variant,
current,
current_else,
&cond_place,
mode,
)?
}
VariantId::StructId(s) => {
let struct_data = self.db.struct_data(s);
self.pattern_matching_variant_fields(
shape,
&struct_data.variant_data,
variant, variant,
current, current,
current_else, current_else,
@ -547,6 +518,15 @@ impl MirLowerCtx<'_> {
mode, mode,
)? )?
} }
VariantId::StructId(s) => self.pattern_matching_variant_fields(
shape,
&self.db.struct_data(s).variant_data,
variant,
current,
current_else,
&cond_place,
mode,
)?,
VariantId::UnionId(_) => { VariantId::UnionId(_) => {
return Err(MirLowerError::TypeError("pattern matching on union")) return Err(MirLowerError::TypeError("pattern matching on union"))
} }
@ -572,7 +552,7 @@ impl MirLowerCtx<'_> {
variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?; variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?;
Ok(( Ok((
PlaceElem::Field(Either::Left(FieldId { PlaceElem::Field(Either::Left(FieldId {
parent: v.into(), parent: v,
local_id: field_id, local_id: field_id,
})), })),
x.pat, x.pat,
@ -583,7 +563,7 @@ impl MirLowerCtx<'_> {
} }
AdtPatternShape::Tuple { args, ellipsis } => { AdtPatternShape::Tuple { args, ellipsis } => {
let fields = variant_data.fields().iter().map(|(x, _)| { let fields = variant_data.fields().iter().map(|(x, _)| {
PlaceElem::Field(Either::Left(FieldId { parent: v.into(), local_id: x })) PlaceElem::Field(Either::Left(FieldId { parent: v, local_id: x }))
}); });
self.pattern_match_tuple_like( self.pattern_match_tuple_like(
current, current,

View File

@ -275,7 +275,7 @@ impl Filler<'_> {
| TerminatorKind::DropAndReplace { .. } | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::Assert { .. } | TerminatorKind::Assert { .. }
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop | TerminatorKind::CoroutineDrop
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => (), | TerminatorKind::FalseUnwind { .. } => (),
} }
@ -306,7 +306,7 @@ pub fn monomorphized_mir_body_recover(
_: &Substitution, _: &Substitution,
_: &Arc<crate::TraitEnvironment>, _: &Arc<crate::TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError> { ) -> Result<Arc<MirBody>, MirLowerError> {
return Err(MirLowerError::Loop); Err(MirLowerError::Loop)
} }
pub fn monomorphized_mir_body_for_closure_query( pub fn monomorphized_mir_body_for_closure_query(

View File

@ -7,7 +7,7 @@ use std::{
use either::Either; use either::Either;
use hir_def::{body::Body, hir::BindingId}; use hir_def::{body::Body, hir::BindingId};
use hir_expand::name::Name; use hir_expand::{name::Name, Lookup};
use la_arena::ArenaMap; use la_arena::ArenaMap;
use crate::{ use crate::{
@ -58,8 +58,14 @@ impl MirBody {
); );
} }
hir_def::DefWithBodyId::VariantId(id) => { hir_def::DefWithBodyId::VariantId(id) => {
let data = db.enum_data(id.parent); let loc = id.lookup(db.upcast());
w!(this, "enum {} = ", data.name.display(db.upcast())); let enum_loc = loc.parent.lookup(db.upcast());
w!(
this,
"enum {}::{} = ",
enum_loc.id.item_tree(db.upcast())[enum_loc.id.value].name.display(db.upcast()),
loc.id.item_tree(db.upcast())[loc.id.value].name.display(db.upcast()),
)
} }
hir_def::DefWithBodyId::InTypeConstId(id) => { hir_def::DefWithBodyId::InTypeConstId(id) => {
w!(this, "in type const {id:?} = "); w!(this, "in type const {id:?} = ");
@ -306,8 +312,7 @@ impl<'a> MirPrettyCtx<'a> {
hir_def::VariantId::EnumVariantId(e) => { hir_def::VariantId::EnumVariantId(e) => {
w!(this, "("); w!(this, "(");
f(this, local, head); f(this, local, head);
let variant_name = let variant_name = &this.db.enum_variant_data(e).name;
&this.db.enum_data(e.parent).variants[e.local_id].name;
w!( w!(
this, this,
" as {}).{}", " as {}).{}",
@ -339,7 +344,7 @@ impl<'a> MirPrettyCtx<'a> {
} }
} }
} }
f(self, p.local, &p.projection.lookup(&self.body.projection_store)); f(self, p.local, p.projection.lookup(&self.body.projection_store));
} }
fn operand(&mut self, r: &Operand) { fn operand(&mut self, r: &Operand) {

View File

@ -43,13 +43,13 @@ impl fmt::Debug for TestDB {
impl Upcast<dyn ExpandDatabase> for TestDB { impl Upcast<dyn ExpandDatabase> for TestDB {
fn upcast(&self) -> &(dyn ExpandDatabase + 'static) { fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
&*self self
} }
} }
impl Upcast<dyn DefDatabase> for TestDB { impl Upcast<dyn DefDatabase> for TestDB {
fn upcast(&self) -> &(dyn DefDatabase + 'static) { fn upcast(&self) -> &(dyn DefDatabase + 'static) {
&*self self
} }
} }

View File

@ -16,7 +16,7 @@ use base_db::{FileRange, SourceDatabaseExt};
use expect_test::Expect; use expect_test::Expect;
use hir_def::{ use hir_def::{
body::{Body, BodySourceMap, SyntheticSyntax}, body::{Body, BodySourceMap, SyntheticSyntax},
db::{DefDatabase, InternDatabase}, db::DefDatabase,
hir::{ExprId, Pat, PatId}, hir::{ExprId, Pat, PatId},
item_scope::ItemScope, item_scope::ItemScope,
nameres::DefMap, nameres::DefMap,
@ -145,7 +145,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
loc.source(&db).value.syntax().text_range().start() loc.source(&db).value.syntax().text_range().start()
} }
DefWithBodyId::VariantId(it) => { DefWithBodyId::VariantId(it) => {
let loc = db.lookup_intern_enum(it.parent); let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start() loc.source(&db).value.syntax().text_range().start()
} }
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
@ -383,7 +383,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
loc.source(&db).value.syntax().text_range().start() loc.source(&db).value.syntax().text_range().start()
} }
DefWithBodyId::VariantId(it) => { DefWithBodyId::VariantId(it) => {
let loc = db.lookup_intern_enum(it.parent); let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start() loc.source(&db).value.syntax().text_range().start()
} }
DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(), DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
@ -453,16 +453,12 @@ fn visit_module(
visit_body(db, &body, cb); visit_body(db, &body, cb);
} }
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
db.enum_data(it) db.enum_data(it).variants.iter().for_each(|&(it, _)| {
.variants let def = it.into();
.iter() cb(def);
.map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id }) let body = db.body(def);
.for_each(|it| { visit_body(db, &body, cb);
let def = it.into(); });
cb(def);
let body = db.body(def);
visit_body(db, &body, cb);
});
} }
ModuleDefId::TraitId(it) => { ModuleDefId::TraitId(it) => {
let trait_data = db.trait_data(it); let trait_data = db.trait_data(it);

View File

@ -328,7 +328,7 @@ fn foo() {
} }
#[test] #[test]
fn generator_yield_return_coerce() { fn coroutine_yield_return_coerce() {
check_no_mismatches( check_no_mismatches(
r#" r#"
fn test() { fn test() {
@ -574,6 +574,7 @@ fn two_closures_lub() {
r#" r#"
fn foo(c: i32) { fn foo(c: i32) {
let add = |a: i32, b: i32| a + b; let add = |a: i32, b: i32| a + b;
//^^^^^^^^^^^^^^^^^^^^^^ impl Fn(i32, i32) -> i32
let sub = |a, b| a - b; let sub = |a, b| a - b;
//^^^^^^^^^^^^ impl Fn(i32, i32) -> i32 //^^^^^^^^^^^^ impl Fn(i32, i32) -> i32
if c > 42 { add } else { sub }; if c > 42 { add } else { sub };

View File

@ -64,7 +64,7 @@ fn infer_macros_expanded() {
"#, "#,
expect![[r#" expect![[r#"
!0..17 '{Foo(v...,2,])}': Foo !0..17 '{Foo(v...,2,])}': Foo
!1..4 'Foo': Foo({unknown}) -> Foo !1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo
!1..16 'Foo(vec![1,2,])': Foo !1..16 'Foo(vec![1,2,])': Foo
!5..15 'vec![1,2,]': {unknown} !5..15 'vec![1,2,]': {unknown}
155..181 '{ ...,2); }': () 155..181 '{ ...,2); }': ()
@ -97,7 +97,7 @@ fn infer_legacy_textual_scoped_macros_expanded() {
"#, "#,
expect![[r#" expect![[r#"
!0..17 '{Foo(v...,2,])}': Foo !0..17 '{Foo(v...,2,])}': Foo
!1..4 'Foo': Foo({unknown}) -> Foo !1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo
!1..16 'Foo(vec![1,2,])': Foo !1..16 'Foo(vec![1,2,])': Foo
!5..15 'vec![1,2,]': {unknown} !5..15 'vec![1,2,]': {unknown}
194..250 '{ ...,2); }': () 194..250 '{ ...,2); }': ()

View File

@ -210,13 +210,13 @@ fn infer_pattern_match_ergonomics() {
37..41 'A(n)': A<i32> 37..41 'A(n)': A<i32>
39..40 'n': &i32 39..40 'n': &i32
44..49 '&A(1)': &A<i32> 44..49 '&A(1)': &A<i32>
45..46 'A': A<i32>(i32) -> A<i32> 45..46 'A': extern "rust-call" A<i32>(i32) -> A<i32>
45..49 'A(1)': A<i32> 45..49 'A(1)': A<i32>
47..48 '1': i32 47..48 '1': i32
59..63 'A(n)': A<i32> 59..63 'A(n)': A<i32>
61..62 'n': &mut i32 61..62 'n': &mut i32
66..75 '&mut A(1)': &mut A<i32> 66..75 '&mut A(1)': &mut A<i32>
71..72 'A': A<i32>(i32) -> A<i32> 71..72 'A': extern "rust-call" A<i32>(i32) -> A<i32>
71..75 'A(1)': A<i32> 71..75 'A(1)': A<i32>
73..74 '1': i32 73..74 '1': i32
"#]], "#]],
@ -531,18 +531,18 @@ impl Foo {
56..64 'Self(s,)': Foo 56..64 'Self(s,)': Foo
61..62 's': &usize 61..62 's': &usize
67..75 '&Foo(0,)': &Foo 67..75 '&Foo(0,)': &Foo
68..71 'Foo': Foo(usize) -> Foo 68..71 'Foo': extern "rust-call" Foo(usize) -> Foo
68..75 'Foo(0,)': Foo 68..75 'Foo(0,)': Foo
72..73 '0': usize 72..73 '0': usize
89..97 'Self(s,)': Foo 89..97 'Self(s,)': Foo
94..95 's': &mut usize 94..95 's': &mut usize
100..112 '&mut Foo(0,)': &mut Foo 100..112 '&mut Foo(0,)': &mut Foo
105..108 'Foo': Foo(usize) -> Foo 105..108 'Foo': extern "rust-call" Foo(usize) -> Foo
105..112 'Foo(0,)': Foo 105..112 'Foo(0,)': Foo
109..110 '0': usize 109..110 '0': usize
126..134 'Self(s,)': Foo 126..134 'Self(s,)': Foo
131..132 's': usize 131..132 's': usize
137..140 'Foo': Foo(usize) -> Foo 137..140 'Foo': extern "rust-call" Foo(usize) -> Foo
137..144 'Foo(0,)': Foo 137..144 'Foo(0,)': Foo
141..142 '0': usize 141..142 '0': usize
"#]], "#]],
@ -916,7 +916,7 @@ fn foo(foo: Foo) {
48..51 'foo': Foo 48..51 'foo': Foo
62..84 'const ... 32) }': Foo 62..84 'const ... 32) }': Foo
68..84 '{ Foo(... 32) }': Foo 68..84 '{ Foo(... 32) }': Foo
70..73 'Foo': Foo(usize) -> Foo 70..73 'Foo': extern "rust-call" Foo(usize) -> Foo
70..82 'Foo(15 + 32)': Foo 70..82 'Foo(15 + 32)': Foo
74..76 '15': usize 74..76 '15': usize
74..81 '15 + 32': usize 74..81 '15 + 32': usize

View File

@ -644,7 +644,7 @@ fn issue_4953() {
"#, "#,
expect![[r#" expect![[r#"
58..72 '{ Self(0i64) }': Foo 58..72 '{ Self(0i64) }': Foo
60..64 'Self': Foo(i64) -> Foo 60..64 'Self': extern "rust-call" Foo(i64) -> Foo
60..70 'Self(0i64)': Foo 60..70 'Self(0i64)': Foo
65..69 '0i64': i64 65..69 '0i64': i64
"#]], "#]],
@ -658,7 +658,7 @@ fn issue_4953() {
"#, "#,
expect![[r#" expect![[r#"
64..78 '{ Self(0i64) }': Foo<i64> 64..78 '{ Self(0i64) }': Foo<i64>
66..70 'Self': Foo<i64>(i64) -> Foo<i64> 66..70 'Self': extern "rust-call" Foo<i64>(i64) -> Foo<i64>
66..76 'Self(0i64)': Foo<i64> 66..76 'Self(0i64)': Foo<i64>
71..75 '0i64': i64 71..75 '0i64': i64
"#]], "#]],
@ -858,7 +858,7 @@ fn main() {
94..96 '{}': () 94..96 '{}': ()
109..160 '{ ...10); }': () 109..160 '{ ...10); }': ()
119..120 's': S<i32> 119..120 's': S<i32>
123..124 'S': S<i32>() -> S<i32> 123..124 'S': extern "rust-call" S<i32>() -> S<i32>
123..126 'S()': S<i32> 123..126 'S()': S<i32>
132..133 's': S<i32> 132..133 's': S<i32>
132..144 's.g(|_x| {})': () 132..144 's.g(|_x| {})': ()
@ -1689,18 +1689,18 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
27..85 '{ ...1,); }': () 27..85 '{ ...1,); }': ()
37..48 'S(.., a, b)': S 37..48 'S(.., a, b)': S
43..44 'a': usize 43..44 'a': usize
46..47 'b': {unknown} 46..47 'b': {unknown}
51..52 'S': S(usize) -> S 51..52 'S': extern "rust-call" S(usize) -> S
51..55 'S(1)': S 51..55 'S(1)': S
53..54 '1': usize 53..54 '1': usize
65..75 '(.., a, b)': (i32, {unknown}) 65..75 '(.., a, b)': (i32, {unknown})
70..71 'a': i32 70..71 'a': i32
73..74 'b': {unknown} 73..74 'b': {unknown}
78..82 '(1,)': (i32,) 78..82 '(1,)': (i32,)
79..80 '1': i32 79..80 '1': i32
"#]], "#]],
); );
} }
@ -2012,3 +2012,31 @@ fn rustc_test_issue_52437() {
"#, "#,
); );
} }
#[test]
fn incorrect_variant_form_through_alias_caught() {
check_types(
r#"
enum Enum { Braced {}, Unit, Tuple() }
type Alias = Enum;
fn main() {
Alias::Braced;
//^^^^^^^^^^^^^ {unknown}
let Alias::Braced = loop {};
//^^^^^^^^^^^^^ !
let Alias::Braced(..) = loop {};
//^^^^^^^^^^^^^^^^^ Enum
Alias::Unit();
//^^^^^^^^^^^^^ {unknown}
Alias::Unit{};
//^^^^^^^^^^^^^ Enum
let Alias::Unit() = loop {};
//^^^^^^^^^^^^^ Enum
let Alias::Unit{} = loop {};
//^^^^^^^^^^^^^ Enum
}
"#,
)
}

View File

@ -236,14 +236,14 @@ fn test() {
expect![[r#" expect![[r#"
71..153 '{ ...a.c; }': () 71..153 '{ ...a.c; }': ()
81..82 'c': C 81..82 'c': C
85..86 'C': C(usize) -> C 85..86 'C': extern "rust-call" C(usize) -> C
85..89 'C(1)': C 85..89 'C(1)': C
87..88 '1': usize 87..88 '1': usize
95..96 'B': B 95..96 'B': B
106..107 'a': A 106..107 'a': A
113..132 'A { b:...C(1) }': A 113..132 'A { b:...C(1) }': A
120..121 'B': B 120..121 'B': B
126..127 'C': C(usize) -> C 126..127 'C': extern "rust-call" C(usize) -> C
126..130 'C(1)': C 126..130 'C(1)': C
128..129 '1': usize 128..129 '1': usize
138..139 'a': A 138..139 'a': A
@ -303,14 +303,14 @@ unsafe fn baz(u: MyUnion) {
71..89 'MyUnio...o: 0 }': MyUnion 71..89 'MyUnio...o: 0 }': MyUnion
86..87 '0': u32 86..87 '0': u32
95..113 'unsafe...(u); }': () 95..113 'unsafe...(u); }': ()
104..107 'baz': fn baz(MyUnion) 104..107 'baz': unsafe fn baz(MyUnion)
104..110 'baz(u)': () 104..110 'baz(u)': ()
108..109 'u': MyUnion 108..109 'u': MyUnion
122..123 'u': MyUnion 122..123 'u': MyUnion
126..146 'MyUnio... 0.0 }': MyUnion 126..146 'MyUnio... 0.0 }': MyUnion
141..144 '0.0': f32 141..144 '0.0': f32
152..170 'unsafe...(u); }': () 152..170 'unsafe...(u); }': ()
161..164 'baz': fn baz(MyUnion) 161..164 'baz': unsafe fn baz(MyUnion)
161..167 'baz(u)': () 161..167 'baz(u)': ()
165..166 'u': MyUnion 165..166 'u': MyUnion
188..189 'u': MyUnion 188..189 'u': MyUnion
@ -625,12 +625,12 @@ impl E {
86..107 '{ ... }': () 86..107 '{ ... }': ()
96..100 'Self': S1 96..100 'Self': S1
134..158 '{ ... }': () 134..158 '{ ... }': ()
144..148 'Self': S2(isize) -> S2 144..148 'Self': extern "rust-call" S2(isize) -> S2
144..151 'Self(1)': S2 144..151 'Self(1)': S2
149..150 '1': isize 149..150 '1': isize
184..230 '{ ... }': () 184..230 '{ ... }': ()
194..202 'Self::V1': E 194..202 'Self::V1': E
212..220 'Self::V2': V2(u32) -> E 212..220 'Self::V2': extern "rust-call" V2(u32) -> E
212..223 'Self::V2(1)': E 212..223 'Self::V2(1)': E
221..222 '1': u32 221..222 '1': u32
"#]], "#]],
@ -856,11 +856,11 @@ fn test() {
256..277 'A::foo...42))))': &i32 256..277 'A::foo...42))))': &i32
263..276 '&&B(B(A(42)))': &&B<B<A<i32>>> 263..276 '&&B(B(A(42)))': &&B<B<A<i32>>>
264..276 '&B(B(A(42)))': &B<B<A<i32>>> 264..276 '&B(B(A(42)))': &B<B<A<i32>>>
265..266 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> 265..266 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
265..276 'B(B(A(42)))': B<B<A<i32>>> 265..276 'B(B(A(42)))': B<B<A<i32>>>
267..268 'B': B<A<i32>>(A<i32>) -> B<A<i32>> 267..268 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
267..275 'B(A(42))': B<A<i32>> 267..275 'B(A(42))': B<A<i32>>
269..270 'A': A<i32>(i32) -> A<i32> 269..270 'A': extern "rust-call" A<i32>(i32) -> A<i32>
269..274 'A(42)': A<i32> 269..274 'A(42)': A<i32>
271..273 '42': i32 271..273 '42': i32
"#]], "#]],
@ -910,16 +910,16 @@ fn test(a: A<i32>) {
253..254 'a': A<i32> 253..254 'a': A<i32>
264..310 '{ ...))); }': () 264..310 '{ ...))); }': ()
274..275 't': &i32 274..275 't': &i32
278..279 'A': A<i32>(*mut i32) -> A<i32> 278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
278..292 'A(0 as *mut _)': A<i32> 278..292 'A(0 as *mut _)': A<i32>
278..307 'A(0 as...B(a)))': &i32 278..307 'A(0 as...B(a)))': &i32
280..281 '0': i32 280..281 '0': i32
280..291 '0 as *mut _': *mut i32 280..291 '0 as *mut _': *mut i32
297..306 '&&B(B(a))': &&B<B<A<i32>>> 297..306 '&&B(B(a))': &&B<B<A<i32>>>
298..306 '&B(B(a))': &B<B<A<i32>>> 298..306 '&B(B(a))': &B<B<A<i32>>>
299..300 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> 299..300 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
299..306 'B(B(a))': B<B<A<i32>>> 299..306 'B(B(a))': B<B<A<i32>>>
301..302 'B': B<A<i32>>(A<i32>) -> B<A<i32>> 301..302 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
301..305 'B(a)': B<A<i32>> 301..305 'B(a)': B<A<i32>>
303..304 'a': A<i32> 303..304 'a': A<i32>
"#]], "#]],
@ -1273,16 +1273,16 @@ fn infer_tuple_struct_generics() {
"#, "#,
expect![[r#" expect![[r#"
75..183 '{ ...one; }': () 75..183 '{ ...one; }': ()
81..82 'A': A<i32>(i32) -> A<i32> 81..82 'A': extern "rust-call" A<i32>(i32) -> A<i32>
81..86 'A(42)': A<i32> 81..86 'A(42)': A<i32>
83..85 '42': i32 83..85 '42': i32
92..93 'A': A<u128>(u128) -> A<u128> 92..93 'A': extern "rust-call" A<u128>(u128) -> A<u128>
92..101 'A(42u128)': A<u128> 92..101 'A(42u128)': A<u128>
94..100 '42u128': u128 94..100 '42u128': u128
107..111 'Some': Some<&str>(&str) -> Option<&str> 107..111 'Some': extern "rust-call" Some<&str>(&str) -> Option<&str>
107..116 'Some("x")': Option<&str> 107..116 'Some("x")': Option<&str>
112..115 '"x"': &str 112..115 '"x"': &str
122..134 'Option::Some': Some<&str>(&str) -> Option<&str> 122..134 'Option::Some': extern "rust-call" Some<&str>(&str) -> Option<&str>
122..139 'Option...e("x")': Option<&str> 122..139 'Option...e("x")': Option<&str>
135..138 '"x"': &str 135..138 '"x"': &str
145..149 'None': Option<{unknown}> 145..149 'None': Option<{unknown}>
@ -1568,7 +1568,7 @@ fn infer_type_alias() {
204..207 'z.y': i8 204..207 'z.y': i8
298..362 '{ ... &e; }': () 298..362 '{ ... &e; }': ()
308..309 'e': Enum 308..309 'e': Enum
312..325 'm::Alias::Foo': Foo(u8) -> Enum 312..325 'm::Alias::Foo': extern "rust-call" Foo(u8) -> Enum
312..328 'm::Ali...Foo(0)': Enum 312..328 'm::Ali...Foo(0)': Enum
326..327 '0': u8 326..327 '0': u8
338..354 'm::Ali...Foo(x)': Enum 338..354 'm::Ali...Foo(x)': Enum
@ -1949,11 +1949,11 @@ fn closure_return_inferred() {
} }
#[test] #[test]
fn generator_types_inferred() { fn coroutine_types_inferred() {
check_infer( check_infer(
r#" r#"
//- minicore: generator, deref //- minicore: coroutine, deref
use core::ops::{Generator, GeneratorState}; use core::ops::{Coroutine, CoroutineState};
use core::pin::Pin; use core::pin::Pin;
fn f(v: i64) {} fn f(v: i64) {}
@ -1966,8 +1966,8 @@ fn test() {
}; };
match Pin::new(&mut g).resume(0usize) { match Pin::new(&mut g).resume(0usize) {
GeneratorState::Yielded(y) => { f(y); } CoroutineState::Yielded(y) => { f(y); }
GeneratorState::Complete(r) => {} CoroutineState::Complete(r) => {}
} }
} }
"#, "#,
@ -1992,17 +1992,17 @@ fn test() {
225..360 'match ... }': () 225..360 'match ... }': ()
231..239 'Pin::new': fn new<&mut |usize| yields i64 -> &str>(&mut |usize| yields i64 -> &str) -> Pin<&mut |usize| yields i64 -> &str> 231..239 'Pin::new': fn new<&mut |usize| yields i64 -> &str>(&mut |usize| yields i64 -> &str) -> Pin<&mut |usize| yields i64 -> &str>
231..247 'Pin::n...mut g)': Pin<&mut |usize| yields i64 -> &str> 231..247 'Pin::n...mut g)': Pin<&mut |usize| yields i64 -> &str>
231..262 'Pin::n...usize)': GeneratorState<i64, &str> 231..262 'Pin::n...usize)': CoroutineState<i64, &str>
240..246 '&mut g': &mut |usize| yields i64 -> &str 240..246 '&mut g': &mut |usize| yields i64 -> &str
245..246 'g': |usize| yields i64 -> &str 245..246 'g': |usize| yields i64 -> &str
255..261 '0usize': usize 255..261 '0usize': usize
273..299 'Genera...ded(y)': GeneratorState<i64, &str> 273..299 'Corout...ded(y)': CoroutineState<i64, &str>
297..298 'y': i64 297..298 'y': i64
303..312 '{ f(y); }': () 303..312 '{ f(y); }': ()
305..306 'f': fn f(i64) 305..306 'f': fn f(i64)
305..309 'f(y)': () 305..309 'f(y)': ()
307..308 'y': i64 307..308 'y': i64
321..348 'Genera...ete(r)': GeneratorState<i64, &str> 321..348 'Corout...ete(r)': CoroutineState<i64, &str>
346..347 'r': &str 346..347 'r': &str
352..354 '{}': () 352..354 '{}': ()
"#]], "#]],
@ -2010,11 +2010,11 @@ fn test() {
} }
#[test] #[test]
fn generator_resume_yield_return_unit() { fn coroutine_resume_yield_return_unit() {
check_no_mismatches( check_no_mismatches(
r#" r#"
//- minicore: generator, deref //- minicore: coroutine, deref
use core::ops::{Generator, GeneratorState}; use core::ops::{Coroutine, CoroutineState};
use core::pin::Pin; use core::pin::Pin;
fn test() { fn test() {
let mut g = || { let mut g = || {
@ -2022,8 +2022,8 @@ fn test() {
}; };
match Pin::new(&mut g).resume(()) { match Pin::new(&mut g).resume(()) {
GeneratorState::Yielded(()) => {} CoroutineState::Yielded(()) => {}
GeneratorState::Complete(()) => {} CoroutineState::Complete(()) => {}
} }
} }
"#, "#,
@ -2184,10 +2184,10 @@ fn main() {
103..231 '{ ... }); }': () 103..231 '{ ... }); }': ()
109..161 'async ... }': impl Future<Output = Result<(), ()>> 109..161 'async ... }': impl Future<Output = Result<(), ()>>
125..139 'return Err(())': ! 125..139 'return Err(())': !
132..135 'Err': Err<(), ()>(()) -> Result<(), ()> 132..135 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
132..139 'Err(())': Result<(), ()> 132..139 'Err(())': Result<(), ()>
136..138 '()': () 136..138 '()': ()
149..151 'Ok': Ok<(), ()>(()) -> Result<(), ()> 149..151 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
149..155 'Ok(())': Result<(), ()> 149..155 'Ok(())': Result<(), ()>
152..154 '()': () 152..154 '()': ()
167..171 'test': fn test<(), (), impl Fn() -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(impl Fn() -> impl Future<Output = Result<(), ()>>) 167..171 'test': fn test<(), (), impl Fn() -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(impl Fn() -> impl Future<Output = Result<(), ()>>)
@ -2195,10 +2195,10 @@ fn main() {
172..227 '|| asy... }': impl Fn() -> impl Future<Output = Result<(), ()>> 172..227 '|| asy... }': impl Fn() -> impl Future<Output = Result<(), ()>>
175..227 'async ... }': impl Future<Output = Result<(), ()>> 175..227 'async ... }': impl Future<Output = Result<(), ()>>
191..205 'return Err(())': ! 191..205 'return Err(())': !
198..201 'Err': Err<(), ()>(()) -> Result<(), ()> 198..201 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
198..205 'Err(())': Result<(), ()> 198..205 'Err(())': Result<(), ()>
202..204 '()': () 202..204 '()': ()
215..217 'Ok': Ok<(), ()>(()) -> Result<(), ()> 215..217 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
215..221 'Ok(())': Result<(), ()> 215..221 'Ok(())': Result<(), ()>
218..220 '()': () 218..220 '()': ()
"#]], "#]],
@ -2227,7 +2227,7 @@ fn infer_generic_from_later_assignment() {
94..127 '{ ... }': () 94..127 '{ ... }': ()
104..107 'end': Option<bool> 104..107 'end': Option<bool>
104..120 'end = ...(true)': () 104..120 'end = ...(true)': ()
110..114 'Some': Some<bool>(bool) -> Option<bool> 110..114 'Some': extern "rust-call" Some<bool>(bool) -> Option<bool>
110..120 'Some(true)': Option<bool> 110..120 'Some(true)': Option<bool>
115..119 'true': bool 115..119 'true': bool
"#]], "#]],
@ -2262,7 +2262,7 @@ fn infer_loop_break_with_val() {
111..121 'break None': ! 111..121 'break None': !
117..121 'None': Option<bool> 117..121 'None': Option<bool>
142..158 'break ...(true)': ! 142..158 'break ...(true)': !
148..152 'Some': Some<bool>(bool) -> Option<bool> 148..152 'Some': extern "rust-call" Some<bool>(bool) -> Option<bool>
148..158 'Some(true)': Option<bool> 148..158 'Some(true)': Option<bool>
153..157 'true': bool 153..157 'true': bool
"#]], "#]],
@ -2509,7 +2509,7 @@ fn generic_default_in_struct_literal() {
254..281 'OtherT...1i32 }': OtherThing<i32> 254..281 'OtherT...1i32 }': OtherThing<i32>
275..279 '1i32': i32 275..279 '1i32': i32
291..292 'b': OtherThing<i32> 291..292 'b': OtherThing<i32>
295..310 'OtherThing::Two': Two<i32>(i32) -> OtherThing<i32> 295..310 'OtherThing::Two': extern "rust-call" Two<i32>(i32) -> OtherThing<i32>
295..316 'OtherT...(1i32)': OtherThing<i32> 295..316 'OtherT...(1i32)': OtherThing<i32>
311..315 '1i32': i32 311..315 '1i32': i32
"#]], "#]],
@ -2984,7 +2984,7 @@ fn f() {
expect![[r#" expect![[r#"
72..166 '{ ... } }': () 72..166 '{ ... } }': ()
78..164 'match ... }': () 78..164 'match ... }': ()
84..92 'Foo::Bar': Bar(i32) -> Foo 84..92 'Foo::Bar': extern "rust-call" Bar(i32) -> Foo
84..95 'Foo::Bar(3)': Foo 84..95 'Foo::Bar(3)': Foo
93..94 '3': i32 93..94 '3': i32
106..119 'Qux::Bar(bar)': Foo 106..119 'Qux::Bar(bar)': Foo
@ -3043,9 +3043,9 @@ fn main() {
322..324 '{}': Foo<T> 322..324 '{}': Foo<T>
338..559 '{ ...r(); }': () 338..559 '{ ...r(); }': ()
348..353 'boxed': Box<Foo<i32>> 348..353 'boxed': Box<Foo<i32>>
356..359 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>> 356..359 'Box': extern "rust-call" Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
356..371 'Box(Foo(0_i32))': Box<Foo<i32>> 356..371 'Box(Foo(0_i32))': Box<Foo<i32>>
360..363 'Foo': Foo<i32>(i32) -> Foo<i32> 360..363 'Foo': extern "rust-call" Foo<i32>(i32) -> Foo<i32>
360..370 'Foo(0_i32)': Foo<i32> 360..370 'Foo(0_i32)': Foo<i32>
364..369 '0_i32': i32 364..369 '0_i32': i32
382..386 'bad1': &i32 382..386 'bad1': &i32

View File

@ -522,7 +522,7 @@ fn test() -> u64 {
expect![[r#" expect![[r#"
37..86 '{ ... a.1 }': u64 37..86 '{ ... a.1 }': u64
47..48 'a': S 47..48 'a': S
51..52 'S': S(i32, u64) -> S 51..52 'S': extern "rust-call" S(i32, u64) -> S
51..58 'S(4, 6)': S 51..58 'S(4, 6)': S
53..54 '4': i32 53..54 '4': i32
56..57 '6': u64 56..57 '6': u64
@ -548,7 +548,7 @@ fn test() -> u64 {
expect![[r#" expect![[r#"
43..108 '{ ...0(2) }': u64 43..108 '{ ...0(2) }': u64
53..54 'a': S 53..54 'a': S
57..58 'S': S(fn(u32) -> u64) -> S 57..58 'S': extern "rust-call" S(fn(u32) -> u64) -> S
57..74 'S(|i| ...s u64)': S 57..74 'S(|i| ...s u64)': S
59..73 '|i| 2*i as u64': impl Fn(u32) -> u64 59..73 '|i| 2*i as u64': impl Fn(u32) -> u64
60..61 'i': u32 60..61 'i': u32
@ -1026,7 +1026,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
201..202 'x': impl Trait<u64> 201..202 'x': impl Trait<u64>
208..209 'y': &impl Trait<u32> 208..209 'y': &impl Trait<u32>
219..220 'z': S<u16> 219..220 'z': S<u16>
223..224 'S': S<u16>(u16) -> S<u16> 223..224 'S': extern "rust-call" S<u16>(u16) -> S<u16>
223..227 'S(1)': S<u16> 223..227 'S(1)': S<u16>
225..226 '1': u16 225..226 '1': u16
233..236 'bar': fn bar(S<u16>) 233..236 'bar': fn bar(S<u16>)
@ -1339,7 +1339,7 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
142..147 'input': &str 142..147 'input': &str
149..150 't': T 149..150 't': T
152..154 '{}': () 152..154 '{}': ()
156..159 'Bar': Bar<u8>(u8) -> Bar<u8> 156..159 'Bar': extern "rust-call" Bar<u8>(u8) -> Bar<u8>
156..162 'Bar(C)': Bar<u8> 156..162 'Bar(C)': Bar<u8>
160..161 'C': u8 160..161 'C': u8
"#]], "#]],
@ -1958,7 +1958,7 @@ fn test() {
118..120 '{}': () 118..120 '{}': ()
136..255 '{ ... 1); }': () 136..255 '{ ... 1); }': ()
146..147 'x': Option<u32> 146..147 'x': Option<u32>
150..162 'Option::Some': Some<u32>(u32) -> Option<u32> 150..162 'Option::Some': extern "rust-call" Some<u32>(u32) -> Option<u32>
150..168 'Option...(1u32)': Option<u32> 150..168 'Option...(1u32)': Option<u32>
163..167 '1u32': u32 163..167 '1u32': u32
174..175 'x': Option<u32> 174..175 'x': Option<u32>
@ -2514,7 +2514,7 @@ fn test() -> impl Trait<i32> {
178..180 '{}': () 178..180 '{}': ()
213..309 '{ ...t()) }': S<i32> 213..309 '{ ...t()) }': S<i32>
223..225 's1': S<u32> 223..225 's1': S<u32>
228..229 'S': S<u32>(u32) -> S<u32> 228..229 'S': extern "rust-call" S<u32>(u32) -> S<u32>
228..240 'S(default())': S<u32> 228..240 'S(default())': S<u32>
230..237 'default': fn default<u32>() -> u32 230..237 'default': fn default<u32>() -> u32
230..239 'default()': u32 230..239 'default()': u32
@ -2524,11 +2524,11 @@ fn test() -> impl Trait<i32> {
263..264 'x': i32 263..264 'x': i32
272..275 'bar': fn bar<i32>(S<i32>) -> i32 272..275 'bar': fn bar<i32>(S<i32>) -> i32
272..289 'bar(S(...lt()))': i32 272..289 'bar(S(...lt()))': i32
276..277 'S': S<i32>(i32) -> S<i32> 276..277 'S': extern "rust-call" S<i32>(i32) -> S<i32>
276..288 'S(default())': S<i32> 276..288 'S(default())': S<i32>
278..285 'default': fn default<i32>() -> i32 278..285 'default': fn default<i32>() -> i32
278..287 'default()': i32 278..287 'default()': i32
295..296 'S': S<i32>(i32) -> S<i32> 295..296 'S': extern "rust-call" S<i32>(i32) -> S<i32>
295..307 'S(default())': S<i32> 295..307 'S(default())': S<i32>
297..304 'default': fn default<i32>() -> i32 297..304 'default': fn default<i32>() -> i32
297..306 'default()': i32 297..306 'default()': i32
@ -2758,7 +2758,7 @@ fn main() {
1036..1041 'x > 0': bool 1036..1041 'x > 0': bool
1040..1041 '0': i32 1040..1041 '0': i32
1042..1060 '{ Some...u32) }': Option<u32> 1042..1060 '{ Some...u32) }': Option<u32>
1044..1048 'Some': Some<u32>(u32) -> Option<u32> 1044..1048 'Some': extern "rust-call" Some<u32>(u32) -> Option<u32>
1044..1058 'Some(x as u32)': Option<u32> 1044..1058 'Some(x as u32)': Option<u32>
1049..1050 'x': i32 1049..1050 'x': i32
1049..1057 'x as u32': u32 1049..1057 'x as u32': u32
@ -2894,9 +2894,9 @@ fn test() {
175..185 'foo.test()': bool 175..185 'foo.test()': bool
191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown} 191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
191..201 'bar.test()': bool 191..201 'bar.test()': bool
207..213 'Struct': Struct(usize) -> Struct 207..213 'Struct': extern "rust-call" Struct(usize) -> Struct
207..220 'Struct.test()': bool 207..220 'Struct.test()': bool
226..239 'Enum::Variant': Variant(usize) -> Enum 226..239 'Enum::Variant': extern "rust-call" Variant(usize) -> Enum
226..246 'Enum::...test()': bool 226..246 'Enum::...test()': bool
"#]], "#]],
); );
@ -3475,12 +3475,12 @@ fn main(){
95..99 'self': Wrapper 95..99 'self': Wrapper
101..104 'rhs': u32 101..104 'rhs': u32
122..150 '{ ... }': Wrapper 122..150 '{ ... }': Wrapper
132..139 'Wrapper': Wrapper(u32) -> Wrapper 132..139 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
132..144 'Wrapper(rhs)': Wrapper 132..144 'Wrapper(rhs)': Wrapper
140..143 'rhs': u32 140..143 'rhs': u32
162..248 '{ ...um; }': () 162..248 '{ ...um; }': ()
172..179 'wrapped': Wrapper 172..179 'wrapped': Wrapper
182..189 'Wrapper': Wrapper(u32) -> Wrapper 182..189 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
182..193 'Wrapper(10)': Wrapper 182..193 'Wrapper(10)': Wrapper
190..192 '10': u32 190..192 '10': u32
203..206 'num': u32 203..206 'num': u32

View File

@ -107,10 +107,7 @@ impl DebugContext<'_> {
let name = match def { let name = match def {
CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(), CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(), CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
CallableDefId::EnumVariantId(e) => { CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(),
let enum_data = self.0.enum_data(e.parent);
enum_data.variants[e.local_id].name.clone()
}
}; };
match def { match def {
CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())), CallableDefId::FunctionId(_) => write!(fmt, "{{fn {}}}", name.display(self.0.upcast())),

Some files were not shown because too many files have changed in this diff Show More