mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Auto merge of #120198 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer` r? `@ghost`
This commit is contained in:
commit
ef71f1047e
@ -8,6 +8,7 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
max_line_length = 100
|
||||
|
||||
[*.md]
|
||||
indent_size = 2
|
||||
|
@ -160,9 +160,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3"
|
||||
checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -172,9 +172,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484"
|
||||
checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"chalk-derive",
|
||||
@ -183,9 +183,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chalk-recursive"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847"
|
||||
checksum = "4c4559e5c9b200240453b07d893f9c3c74413b53b0d33cbe272c68b0b77aa1c3"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
@ -196,9 +196,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6"
|
||||
checksum = "0882e68ce9eb5a0a2413806538494d19df6ee520ab17d1faf489e952f32e98b8"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
@ -1001,9 +1001,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
@ -1532,6 +1532,7 @@ dependencies = [
|
||||
"lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lsp-types",
|
||||
"mbe",
|
||||
"memchr",
|
||||
"mimalloc",
|
||||
"nohash-hasher",
|
||||
"num_cpus",
|
||||
@ -1712,9 +1713,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c"
|
||||
checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -105,7 +105,7 @@ dissimilar = "1.0.7"
|
||||
either = "1.9.0"
|
||||
expect-test = "1.4.0"
|
||||
hashbrown = { version = "0.14", features = [
|
||||
"inline-more",
|
||||
"inline-more",
|
||||
], default-features = false }
|
||||
indexmap = "2.1.0"
|
||||
itertools = "0.12.0"
|
||||
@ -118,11 +118,11 @@ semver = "1.0.14"
|
||||
serde = { version = "1.0.192", features = ["derive"] }
|
||||
serde_json = "1.0.108"
|
||||
smallvec = { version = "1.10.0", features = [
|
||||
"const_new",
|
||||
"union",
|
||||
"const_generics",
|
||||
"const_new",
|
||||
"union",
|
||||
"const_generics",
|
||||
] }
|
||||
smol_str = "0.2.0"
|
||||
smol_str = "0.2.1"
|
||||
text-size = "1.1.1"
|
||||
tracing = "0.1.40"
|
||||
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
|
||||
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]
|
||||
collapsible_if = "allow"
|
||||
needless_pass_by_value = "allow"
|
||||
nonminimal_bool = "allow"
|
||||
redundant_pattern_matching = "allow"
|
||||
# FIXME Remove the tidy test once the lint table is stable
|
||||
|
||||
## lint groups
|
||||
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"
|
||||
|
@ -9,7 +9,7 @@
|
||||
use std::{fmt, mem, ops, str::FromStr};
|
||||
|
||||
use cfg::CfgOptions;
|
||||
use la_arena::{Arena, Idx};
|
||||
use la_arena::{Arena, Idx, RawIdx};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use semver::Version;
|
||||
use syntax::SmolStr;
|
||||
@ -157,6 +157,10 @@ impl CrateOrigin {
|
||||
pub fn is_lib(&self) -> bool {
|
||||
matches!(self, CrateOrigin::Library { .. })
|
||||
}
|
||||
|
||||
pub fn is_lang(&self) -> bool {
|
||||
matches!(self, CrateOrigin::Lang { .. })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -174,7 +178,7 @@ impl From<&str> for LangCrateOrigin {
|
||||
match s {
|
||||
"alloc" => LangCrateOrigin::Alloc,
|
||||
"core" => LangCrateOrigin::Core,
|
||||
"proc-macro" => LangCrateOrigin::ProcMacro,
|
||||
"proc-macro" | "proc_macro" => LangCrateOrigin::ProcMacro,
|
||||
"std" => LangCrateOrigin::Std,
|
||||
"test" => LangCrateOrigin::Test,
|
||||
_ => LangCrateOrigin::Other,
|
||||
@ -257,6 +261,7 @@ impl ReleaseChannel {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(str: &str) -> Option<Self> {
|
||||
Some(match str {
|
||||
"" | "stable" => ReleaseChannel::Stable,
|
||||
@ -326,7 +331,7 @@ impl CrateData {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(_) = opts.next() {
|
||||
if opts.next().is_some() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -522,7 +527,7 @@ impl CrateGraph {
|
||||
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)]
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateId, &mut CrateData)> + '_ {
|
||||
self.arena.iter_mut()
|
||||
@ -619,7 +624,12 @@ impl CrateGraph {
|
||||
/// 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.
|
||||
/// 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 mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
|
||||
for topo in topo {
|
||||
@ -630,7 +640,7 @@ impl CrateGraph {
|
||||
let res = self.arena.iter().find_map(|(id, data)| {
|
||||
match (&data.origin, &crate_data.origin) {
|
||||
(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));
|
||||
}
|
||||
}
|
||||
@ -642,8 +652,8 @@ impl CrateGraph {
|
||||
// version and discard the library one as the local version may have
|
||||
// dev-dependencies that we want to keep resolving. See #15656 for more
|
||||
// information.
|
||||
if data.eq_ignoring_origin_and_deps(&crate_data, true) {
|
||||
return Some((id, if a.is_local() { false } else { true }));
|
||||
if data.eq_ignoring_origin_and_deps(crate_data, true) {
|
||||
return Some((id, !a.is_local()));
|
||||
}
|
||||
}
|
||||
(_, _) => return None,
|
||||
@ -670,6 +680,8 @@ impl CrateGraph {
|
||||
|
||||
*proc_macros =
|
||||
mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect();
|
||||
|
||||
on_finished(&id_map);
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
|
@ -24,12 +24,12 @@ use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase,
|
||||
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
|
||||
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode},
|
||||
lang_item::LangItem,
|
||||
nameres::{ModuleOrigin, ModuleSource},
|
||||
src::{HasChildSource, HasSource},
|
||||
AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId,
|
||||
LocalFieldId, Lookup, MacroId, VariantId,
|
||||
AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId,
|
||||
VariantId,
|
||||
};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner {
|
||||
impl Attrs {
|
||||
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(
|
||||
db: &dyn DefDatabase,
|
||||
v: VariantId,
|
||||
@ -108,29 +81,11 @@ impl Attrs {
|
||||
let crate_graph = db.crate_graph();
|
||||
let (fields, item_tree, krate) = match v {
|
||||
VariantId::EnumVariantId(it) => {
|
||||
let e = it.parent;
|
||||
let loc = e.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let loc = it.lookup(db);
|
||||
let krate = loc.parent.lookup(db).container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let enum_ = &item_tree[loc.id.value];
|
||||
|
||||
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)
|
||||
let variant = &item_tree[loc.id.value];
|
||||
(variant.fields.clone(), item_tree, krate)
|
||||
}
|
||||
VariantId::StructId(it) => {
|
||||
let loc = it.lookup(db);
|
||||
@ -401,10 +356,12 @@ impl AttrsWithOwner {
|
||||
AttrDefId::FieldId(it) => {
|
||||
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
|
||||
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 {
|
||||
AdtId::StructId(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),
|
||||
},
|
||||
AttrDefId::FunctionId(id) => any_has_attrs(db, id),
|
||||
AttrDefId::EnumVariantId(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::EnumVariantId(id) => any_has_attrs(db, id),
|
||||
AttrDefId::StaticId(id) => any_has_attrs(db, id),
|
||||
AttrDefId::ConstId(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)
|
||||
}
|
||||
|
||||
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 mod_item = N::id_to_mod_item(id.value);
|
||||
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),
|
||||
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>,
|
||||
) -> RawAttrs {
|
||||
@ -668,7 +623,7 @@ fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
|
||||
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),
|
||||
lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>,
|
||||
) -> RawAttrs {
|
||||
@ -676,20 +631,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>(
|
||||
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(
|
||||
db: &dyn DefDatabase,
|
||||
def: VariantId,
|
||||
|
@ -26,7 +26,7 @@ use crate::{
|
||||
},
|
||||
nameres::DefMap,
|
||||
path::{ModPath, Path},
|
||||
src::{HasChildSource, HasSource},
|
||||
src::HasSource,
|
||||
BlockId, DefWithBodyId, HasModule, Lookup,
|
||||
};
|
||||
|
||||
@ -37,7 +37,7 @@ pub struct Body {
|
||||
pub pats: Arena<Pat>,
|
||||
pub bindings: Arena<Binding>,
|
||||
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.
|
||||
pub binding_owners: FxHashMap<BindingId, ExprId>,
|
||||
/// The patterns for the function's parameters. While the parameter types are
|
||||
@ -160,8 +160,9 @@ impl Body {
|
||||
src.map(|it| it.body())
|
||||
}
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
let src = v.parent.child_source(db);
|
||||
src.map(|it| it[v.local_id].expr())
|
||||
let s = v.lookup(db);
|
||||
let src = s.source(db);
|
||||
src.map(|it| it.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, .. } => {
|
||||
args.iter().copied().for_each(|p| f(p));
|
||||
args.iter().copied().for_each(f);
|
||||
}
|
||||
Pat::Ref { pat, .. } => f(*pat),
|
||||
Pat::Slice { prefix, slice, suffix } => {
|
||||
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, .. } => {
|
||||
args.iter().for_each(|RecordFieldPat { pat, .. }| f(*pat));
|
||||
@ -368,7 +369,7 @@ impl BodySourceMap {
|
||||
}
|
||||
|
||||
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> {
|
||||
@ -377,11 +378,11 @@ impl BodySourceMap {
|
||||
}
|
||||
|
||||
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 {
|
||||
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> {
|
||||
|
@ -81,7 +81,7 @@ pub(super) fn lower(
|
||||
expander,
|
||||
current_try_block_label: None,
|
||||
is_lowering_assignee_expr: false,
|
||||
is_lowering_generator: false,
|
||||
is_lowering_coroutine: false,
|
||||
label_ribs: Vec::new(),
|
||||
current_binding_owner: None,
|
||||
}
|
||||
@ -99,7 +99,7 @@ struct ExprCollector<'a> {
|
||||
source_map: BodySourceMap,
|
||||
|
||||
is_lowering_assignee_expr: bool,
|
||||
is_lowering_generator: bool,
|
||||
is_lowering_coroutine: bool,
|
||||
|
||||
current_try_block_label: Option<LabelId>,
|
||||
// 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)
|
||||
}
|
||||
ast::Expr::YieldExpr(e) => {
|
||||
self.is_lowering_generator = true;
|
||||
self.is_lowering_coroutine = true;
|
||||
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||
self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
|
||||
}
|
||||
@ -525,18 +525,18 @@ impl ExprCollector<'_> {
|
||||
.and_then(|r| r.ty())
|
||||
.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 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() {
|
||||
Movability::Static
|
||||
} else {
|
||||
Movability::Movable
|
||||
};
|
||||
ClosureKind::Generator(movability)
|
||||
ClosureKind::Coroutine(movability)
|
||||
} else if e.async_token().is_some() {
|
||||
ClosureKind::Async
|
||||
} else {
|
||||
@ -544,7 +544,7 @@ impl ExprCollector<'_> {
|
||||
};
|
||||
let capture_by =
|
||||
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_try_block_label = prev_try_block_label;
|
||||
this.body.exprs[result_expr_id] = Expr::Closure {
|
||||
@ -776,11 +776,10 @@ impl ExprCollector<'_> {
|
||||
None => self.collect_expr_opt(e.condition()),
|
||||
};
|
||||
|
||||
let break_expr =
|
||||
self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone());
|
||||
let break_expr = self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr);
|
||||
let if_expr = self.alloc_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)
|
||||
}
|
||||
@ -811,19 +810,19 @@ impl ExprCollector<'_> {
|
||||
return self.alloc_expr(Expr::Missing, syntax_ptr);
|
||||
};
|
||||
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(
|
||||
Expr::Call {
|
||||
callee: into_iter_fn_expr,
|
||||
args: Box::new([head]),
|
||||
is_assignee_expr: false,
|
||||
},
|
||||
syntax_ptr.clone(),
|
||||
syntax_ptr,
|
||||
);
|
||||
let none_arm = MatchArm {
|
||||
pat: self.alloc_pat_desugared(Pat::Path(Box::new(option_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 {
|
||||
path: Some(Box::new(option_some)),
|
||||
@ -839,27 +838,25 @@ impl ExprCollector<'_> {
|
||||
}),
|
||||
};
|
||||
let iter_name = Name::generate_new_name();
|
||||
let iter_expr =
|
||||
self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr.clone());
|
||||
let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
|
||||
let iter_expr_mut = self.alloc_expr(
|
||||
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(
|
||||
Expr::Call {
|
||||
callee: iter_next_fn_expr,
|
||||
args: Box::new([iter_expr_mut]),
|
||||
is_assignee_expr: false,
|
||||
},
|
||||
syntax_ptr.clone(),
|
||||
syntax_ptr,
|
||||
);
|
||||
let loop_inner = self.alloc_expr(
|
||||
Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
|
||||
syntax_ptr.clone(),
|
||||
syntax_ptr,
|
||||
);
|
||||
let loop_outer =
|
||||
self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr.clone());
|
||||
let loop_outer = self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr);
|
||||
let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable);
|
||||
let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
|
||||
self.add_definition_to_binding(iter_binding, iter_pat);
|
||||
@ -868,7 +865,7 @@ impl ExprCollector<'_> {
|
||||
expr: iterator,
|
||||
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);
|
||||
};
|
||||
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(
|
||||
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_binding =
|
||||
@ -914,7 +911,7 @@ impl ExprCollector<'_> {
|
||||
ellipsis: 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_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated);
|
||||
@ -928,18 +925,18 @@ impl ExprCollector<'_> {
|
||||
}),
|
||||
guard: None,
|
||||
expr: {
|
||||
let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr.clone());
|
||||
let callee = self.alloc_expr(Expr::Path(try_from_residual), 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);
|
||||
let result = self.alloc_expr(
|
||||
Expr::Call { callee, args: Box::new([it]), is_assignee_expr: false },
|
||||
syntax_ptr.clone(),
|
||||
syntax_ptr,
|
||||
);
|
||||
self.alloc_expr(
|
||||
match self.current_try_block_label {
|
||||
Some(label) => Expr::Break { expr: Some(result), label: Some(label) },
|
||||
None => Expr::Return { expr: Some(result) },
|
||||
},
|
||||
syntax_ptr.clone(),
|
||||
syntax_ptr,
|
||||
)
|
||||
},
|
||||
};
|
||||
@ -1847,8 +1844,8 @@ impl ExprCollector<'_> {
|
||||
flags as u128,
|
||||
Some(BuiltinUint::U32),
|
||||
)));
|
||||
let precision = self.make_count(&precision, argmap);
|
||||
let width = self.make_count(&width, argmap);
|
||||
let precision = self.make_count(precision, argmap);
|
||||
let width = self.make_count(width, argmap);
|
||||
|
||||
let format_placeholder_new = {
|
||||
let format_placeholder_new =
|
||||
@ -1994,7 +1991,7 @@ impl ExprCollector<'_> {
|
||||
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
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);
|
||||
id
|
||||
}
|
||||
@ -2022,7 +2019,7 @@ impl ExprCollector<'_> {
|
||||
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
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);
|
||||
id
|
||||
}
|
||||
@ -2037,7 +2034,7 @@ impl ExprCollector<'_> {
|
||||
fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
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);
|
||||
id
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use itertools::Itertools;
|
||||
use syntax::ast::HasName;
|
||||
|
||||
use crate::{
|
||||
hir::{
|
||||
@ -19,35 +18,30 @@ use super::*;
|
||||
pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String {
|
||||
let header = match owner {
|
||||
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!(
|
||||
"fn {}",
|
||||
item_tree_id.item_tree(db)[item_tree_id.value].name.display(db.upcast())
|
||||
"const {} = ",
|
||||
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::VariantId(it) => {
|
||||
let src = it.parent.child_source(db);
|
||||
let variant = &src.value[it.local_id];
|
||||
match &variant.name() {
|
||||
Some(name) => name.to_string(),
|
||||
None => "_".to_string(),
|
||||
}
|
||||
let loc = it.lookup(db);
|
||||
let enum_loc = loc.parent.lookup(db);
|
||||
format!(
|
||||
"enum {}::{}",
|
||||
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 } => {
|
||||
match closure_kind {
|
||||
ClosureKind::Generator(Movability::Static) => {
|
||||
ClosureKind::Coroutine(Movability::Static) => {
|
||||
w!(self, "static ");
|
||||
}
|
||||
ClosureKind::Async => {
|
||||
|
@ -13,8 +13,8 @@ use crate::{
|
||||
item_scope::ItemScope,
|
||||
nameres::DefMap,
|
||||
src::{HasChildSource, HasSource},
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
|
||||
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, ExternCrateId, FieldId, ImplId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId, UseId, VariantId,
|
||||
};
|
||||
|
||||
pub trait ChildBySource {
|
||||
@ -204,13 +204,22 @@ impl ChildBySource for VariantId {
|
||||
}
|
||||
|
||||
impl ChildBySource for EnumId {
|
||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
|
||||
let arena_map = self.child_source(db);
|
||||
let arena_map = arena_map.as_ref();
|
||||
for (local_id, source) in arena_map.value.iter() {
|
||||
let id = EnumVariantId { parent: *self, local_id };
|
||||
res[keys::VARIANT].insert(source.clone(), id)
|
||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||
let loc = &self.lookup(db);
|
||||
if file_id != loc.id.file_id() {
|
||||
return;
|
||||
}
|
||||
|
||||
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,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ use crate::{
|
||||
macro_call_as_call_id,
|
||||
nameres::{
|
||||
attr_resolution::ResolvedAttr,
|
||||
diagnostics::DefDiagnostic,
|
||||
diagnostics::{DefDiagnostic, DefDiagnostics},
|
||||
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
|
||||
DefMap, MacroSubNs,
|
||||
},
|
||||
@ -233,6 +233,7 @@ pub struct TraitData {
|
||||
}
|
||||
|
||||
impl TraitData {
|
||||
#[inline]
|
||||
pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
|
||||
db.trait_data_with_diagnostics(tr).0
|
||||
}
|
||||
@ -240,13 +241,10 @@ impl TraitData {
|
||||
pub(crate) fn trait_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
tr: TraitId,
|
||||
) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) {
|
||||
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
|
||||
) -> (Arc<TraitData>, DefDiagnostics) {
|
||||
let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
|
||||
let item_tree = tree_id.item_tree(db);
|
||||
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 is_auto = tr_def.is_auto;
|
||||
let is_unsafe = tr_def.is_unsafe;
|
||||
@ -274,7 +272,7 @@ impl TraitData {
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
fundamental,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
|
||||
@ -333,6 +331,7 @@ pub struct ImplData {
|
||||
}
|
||||
|
||||
impl ImplData {
|
||||
#[inline]
|
||||
pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> {
|
||||
db.impl_data_with_diagnostics(id).0
|
||||
}
|
||||
@ -340,7 +339,7 @@ impl ImplData {
|
||||
pub(crate) fn impl_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: ImplId,
|
||||
) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) {
|
||||
) -> (Arc<ImplData>, DefDiagnostics) {
|
||||
let _p = profile::span("impl_data_with_diagnostics_query");
|
||||
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
|
||||
|
||||
@ -367,7 +366,7 @@ impl ImplData {
|
||||
is_unsafe,
|
||||
attribute_calls,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -21,15 +21,14 @@ use crate::{
|
||||
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||
lang_item::LangItem,
|
||||
lower::LowerCtx,
|
||||
nameres::diagnostics::DefDiagnostic,
|
||||
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
|
||||
src::HasChildSource,
|
||||
src::HasSource,
|
||||
trace::Trace,
|
||||
tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
|
||||
type_ref::TypeRef,
|
||||
visibility::RawVisibility,
|
||||
EnumId, EnumLoc, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId,
|
||||
UnionId, VariantId,
|
||||
EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
|
||||
};
|
||||
|
||||
/// Note that we use `StructData` for unions as well!
|
||||
@ -43,7 +42,7 @@ pub struct StructData {
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct StructFlags: u8 {
|
||||
const NO_FLAGS = 0;
|
||||
/// Indicates whether the struct is `PhantomData`.
|
||||
@ -65,7 +64,7 @@ bitflags! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EnumData {
|
||||
pub name: Name,
|
||||
pub variants: Arena<EnumVariantData>,
|
||||
pub variants: Box<[(EnumVariantId, Name)]>,
|
||||
pub repr: Option<ReprOptions>,
|
||||
pub visibility: RawVisibility,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
@ -75,7 +74,6 @@ pub struct EnumData {
|
||||
pub struct EnumVariantData {
|
||||
pub name: Name,
|
||||
pub variant_data: Arc<VariantData>,
|
||||
pub tree_id: la_arena::Idx<crate::item_tree::Variant>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -182,6 +180,7 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
|
||||
}
|
||||
|
||||
impl StructData {
|
||||
#[inline]
|
||||
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
|
||||
db.struct_data_with_diagnostics(id).0
|
||||
}
|
||||
@ -189,7 +188,7 @@ impl StructData {
|
||||
pub(crate) fn struct_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: StructId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
) -> (Arc<StructData>, DefDiagnostics) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
@ -234,10 +233,11 @@ impl StructData {
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
flags,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
|
||||
db.union_data_with_diagnostics(id).0
|
||||
}
|
||||
@ -245,7 +245,7 @@ impl StructData {
|
||||
pub(crate) fn union_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: UnionId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
) -> (Arc<StructData>, DefDiagnostics) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
@ -280,24 +280,16 @@ impl StructData {
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
flags,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl 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 krate = loc.container.krate;
|
||||
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 rustc_has_incoherent_inherent_impls = item_tree
|
||||
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||
@ -305,53 +297,21 @@ impl EnumData {
|
||||
.exists();
|
||||
|
||||
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 {
|
||||
name: var.name.clone(),
|
||||
variant_data: Arc::new(var_data),
|
||||
tree_id,
|
||||
});
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
loc.container.local_id,
|
||||
InFile::new(loc.id.file_id(), var.ast_id.erase()),
|
||||
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(),
|
||||
)
|
||||
Arc::new(EnumData {
|
||||
name: enum_.name.clone(),
|
||||
variants: loc.container.def_map(db).enum_definitions[&e]
|
||||
.iter()
|
||||
.map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
|
||||
.collect(),
|
||||
repr,
|
||||
visibility: item_tree[enum_.visibility].clone(),
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
||||
let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
|
||||
pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
|
||||
let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
|
||||
Some(id)
|
||||
}
|
||||
|
||||
@ -363,82 +323,48 @@ impl EnumData {
|
||||
}
|
||||
}
|
||||
|
||||
impl HasChildSource<LocalEnumVariantId> for EnumId {
|
||||
type Value = ast::Variant;
|
||||
fn child_source(
|
||||
&self,
|
||||
impl EnumVariantData {
|
||||
#[inline]
|
||||
pub(crate) fn enum_variant_data_query(
|
||||
db: &dyn DefDatabase,
|
||||
) -> InFile<ArenaMap<LocalEnumVariantId, Self::Value>> {
|
||||
let loc = &self.lookup(db);
|
||||
let src = loc.source(db);
|
||||
let mut trace = Trace::new_for_map();
|
||||
lower_enum(db, &mut trace, &src, loc);
|
||||
src.with_value(trace.into_map())
|
||||
e: EnumVariantId,
|
||||
) -> Arc<EnumVariantData> {
|
||||
db.enum_variant_data_with_diagnostics(e).0
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_enum(
|
||||
db: &dyn DefDatabase,
|
||||
trace: &mut Trace<EnumVariantData, ast::Variant>,
|
||||
ast: &InFile<ast::Enum>,
|
||||
loc: &EnumLoc,
|
||||
) {
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let krate = loc.container.krate;
|
||||
pub(crate) fn enum_variant_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
e: EnumVariantId,
|
||||
) -> (Arc<EnumVariantData>, DefDiagnostics) {
|
||||
let loc = e.lookup(db);
|
||||
let container = loc.parent.lookup(db).container;
|
||||
let krate = 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 cfg_options = &db.crate_graph()[krate].cfg_options;
|
||||
let variants = ast
|
||||
.value
|
||||
.variant_list()
|
||||
.into_iter()
|
||||
.flat_map(|it| it.variants())
|
||||
.zip(item_tree_variants)
|
||||
.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,
|
||||
},
|
||||
let (var_data, diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&variant.fields,
|
||||
Some(item_tree[loc.parent.lookup(db).id.value].visibility),
|
||||
);
|
||||
|
||||
(
|
||||
Arc::new(EnumVariantData {
|
||||
name: variant.name.clone(),
|
||||
variant_data: Arc::new(var_data),
|
||||
}),
|
||||
DefDiagnostics::new(diagnostics),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
const EMPTY: &Arena<FieldData> = &Arena::new();
|
||||
match &self {
|
||||
@ -468,14 +394,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
|
||||
let item_tree;
|
||||
let (src, fields, container) = match *self {
|
||||
VariantId::EnumVariantId(it) => {
|
||||
// I don't really like the fact that we call into parent source
|
||||
// here, this might add to more queries then necessary.
|
||||
let lookup = it.parent.lookup(db);
|
||||
let lookup = it.lookup(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;
|
||||
let fields = &item_tree[tree_id].fields;
|
||||
(src.map(|map| map[it.local_id].kind()), fields, lookup.container)
|
||||
(
|
||||
lookup.source(db).map(|it| it.kind()),
|
||||
&item_tree[lookup.id.value].fields,
|
||||
lookup.parent.lookup(db).container,
|
||||
)
|
||||
}
|
||||
VariantId::StructId(it) => {
|
||||
let lookup = it.lookup(db);
|
||||
@ -490,11 +415,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
|
||||
let lookup = it.lookup(db);
|
||||
item_tree = lookup.id.item_tree(db);
|
||||
(
|
||||
lookup.source(db).map(|it| {
|
||||
it.record_field_list()
|
||||
.map(ast::StructKind::Record)
|
||||
.unwrap_or(ast::StructKind::Unit)
|
||||
}),
|
||||
lookup.source(db).map(|it| it.kind()),
|
||||
&item_tree[lookup.id.value].fields,
|
||||
lookup.container,
|
||||
)
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
attr::{Attrs, AttrsWithOwner},
|
||||
body::{scope::ExprScopes, Body, BodySourceMap},
|
||||
data::{
|
||||
adt::{EnumData, StructData},
|
||||
adt::{EnumData, EnumVariantData, StructData},
|
||||
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
|
||||
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
|
||||
},
|
||||
@ -19,15 +19,15 @@ use crate::{
|
||||
import_map::ImportMap,
|
||||
item_tree::{AttrOwner, ItemTree},
|
||||
lang_item::{self, LangItem, LangItemTarget, LangItems},
|
||||
nameres::{diagnostics::DefDiagnostic, DefMap},
|
||||
nameres::{diagnostics::DefDiagnostics, DefMap},
|
||||
visibility::{self, Visibility},
|
||||
AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
|
||||
EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
|
||||
FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId,
|
||||
LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags,
|
||||
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
|
||||
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc,
|
||||
VariantId,
|
||||
EnumId, EnumLoc, EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId,
|
||||
ExternCrateLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId,
|
||||
InTypeConstLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc,
|
||||
MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc,
|
||||
TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
|
||||
UseId, UseLoc, VariantId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase {
|
||||
#[salsa::interned]
|
||||
fn intern_enum(&self, loc: EnumLoc) -> EnumId;
|
||||
#[salsa::interned]
|
||||
fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId;
|
||||
#[salsa::interned]
|
||||
fn intern_const(&self, loc: ConstLoc) -> ConstId;
|
||||
#[salsa::interned]
|
||||
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)]
|
||||
fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
|
||||
|
||||
/// Computes the block-level `DefMap`, returning `None` when `block` doesn't contain any inner
|
||||
/// 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`.
|
||||
/// Computes the block-level `DefMap`.
|
||||
#[salsa::invoke(DefMap::block_def_map_query)]
|
||||
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
|
||||
|
||||
@ -115,36 +103,46 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
|
||||
// region:data
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(StructData::struct_data_query)]
|
||||
fn struct_data(&self, id: StructId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
|
||||
fn struct_data_with_diagnostics(&self, id: StructId)
|
||||
-> (Arc<StructData>, Arc<[DefDiagnostic]>);
|
||||
fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc<StructData>, DefDiagnostics);
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(StructData::union_data_query)]
|
||||
fn union_data(&self, id: UnionId) -> Arc<StructData>;
|
||||
|
||||
#[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)]
|
||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
|
||||
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
|
||||
#[salsa::transparent]
|
||||
#[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)]
|
||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||
|
||||
#[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)]
|
||||
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
|
||||
|
||||
#[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)]
|
||||
fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>;
|
||||
@ -189,18 +187,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
|
||||
// region:attrs
|
||||
|
||||
#[salsa::invoke(Attrs::variants_attrs_query)]
|
||||
fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
|
||||
|
||||
#[salsa::invoke(Attrs::fields_attrs_query)]
|
||||
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)]
|
||||
fn fields_attrs_source_map(
|
||||
&self,
|
||||
@ -211,7 +200,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
fn attrs(&self, def: AttrDefId) -> Attrs;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(lang_item::lang_attr_query)]
|
||||
#[salsa::invoke(lang_item::lang_attr)]
|
||||
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
|
||||
|
||||
// endregion:attrs
|
||||
@ -239,6 +228,11 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
#[salsa::invoke(LangItems::crate_lang_items_query)]
|
||||
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;
|
||||
}
|
||||
|
||||
@ -265,10 +259,8 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let segments = tt.split(|tt| match tt {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => true,
|
||||
_ => false,
|
||||
});
|
||||
let segments =
|
||||
tt.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','));
|
||||
for output in segments.skip(1) {
|
||||
match output {
|
||||
[tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "no_std" => {
|
||||
|
@ -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 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 RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
|
||||
pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
|
||||
|
@ -2,7 +2,10 @@
|
||||
|
||||
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 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 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) {
|
||||
let data = ctx.db.enum_data(variant.parent);
|
||||
path.push_segment(data.variants[variant.local_id].name.clone());
|
||||
if let Some(mut path) =
|
||||
find_path_inner(ctx, ItemInNs::Types(variant.lookup(ctx.db).parent.into()), from)
|
||||
{
|
||||
path.push_segment(ctx.db.enum_variant_data(variant).name.clone());
|
||||
return Some(path);
|
||||
}
|
||||
// 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(_) =
|
||||
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));
|
||||
}
|
||||
|
@ -400,9 +400,8 @@ impl GenericParams {
|
||||
params
|
||||
.type_or_consts
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.filter(|(idx, _)| enabled((*idx).into()))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
lifetimes: all_lifetimes_enabled
|
||||
@ -411,9 +410,8 @@ impl GenericParams {
|
||||
params
|
||||
.lifetimes
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.filter(|(idx, _)| enabled((*idx).into()))
|
||||
.map(|(_, param)| param.clone())
|
||||
.collect()
|
||||
}),
|
||||
where_predicates: params.where_predicates.clone(),
|
||||
|
@ -300,7 +300,7 @@ pub struct InlineAsm {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ClosureKind {
|
||||
Closure,
|
||||
Generator(Movability),
|
||||
Coroutine(Movability),
|
||||
Async,
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ use hir_expand::{
|
||||
AstId,
|
||||
};
|
||||
use intern::Interned;
|
||||
use syntax::ast::{self, HasName};
|
||||
use syntax::ast::{self, HasName, IsString};
|
||||
|
||||
use crate::{
|
||||
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
|
||||
@ -120,7 +120,12 @@ pub enum TypeRef {
|
||||
Array(Box<TypeRef>, ConstRef),
|
||||
Slice(Box<TypeRef>),
|
||||
/// 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>>),
|
||||
DynTrait(Vec<Interned<TypeBound>>),
|
||||
Macro(AstId<ast::MacroCall>),
|
||||
@ -225,8 +230,17 @@ impl TypeRef {
|
||||
} else {
|
||||
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));
|
||||
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...
|
||||
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)) {
|
||||
f(type_ref);
|
||||
match type_ref {
|
||||
TypeRef::Fn(params, _, _) => {
|
||||
TypeRef::Fn(params, _, _, _) => {
|
||||
params.iter().for_each(|(_, param_type)| go(param_type, f))
|
||||
}
|
||||
TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),
|
||||
@ -396,11 +410,7 @@ impl ConstRef {
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
param: &ast::ConstParam,
|
||||
) -> Option<Self> {
|
||||
let default = param.default_val();
|
||||
match default {
|
||||
Some(_) => Some(Self::from_const_arg(lower_ctx, default)),
|
||||
None => None,
|
||||
}
|
||||
param.default_val().map(|default| Self::from_const_arg(lower_ctx, Some(default)))
|
||||
}
|
||||
|
||||
pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {
|
||||
|
@ -294,14 +294,14 @@ impl SearchMode {
|
||||
pub fn check(self, query: &str, case_sensitive: bool, candidate: &str) -> bool {
|
||||
match self {
|
||||
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 => {
|
||||
query.len() <= candidate.len() && {
|
||||
let prefix = &candidate[..query.len() as usize];
|
||||
if case_sensitive {
|
||||
prefix == query
|
||||
} 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 {
|
||||
match (is_trait_assoc_item, self.assoc_mode) {
|
||||
!matches!(
|
||||
(is_trait_assoc_item, self.assoc_mode),
|
||||
(IsTraitAssocItem::Yes, AssocSearchMode::Exclude)
|
||||
| (IsTraitAssocItem::No, AssocSearchMode::AssocItemsOnly) => false,
|
||||
_ => true,
|
||||
}
|
||||
| (IsTraitAssocItem::No, AssocSearchMode::AssocItemsOnly)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ mod tests;
|
||||
use std::{
|
||||
fmt::{self, Debug},
|
||||
hash::{Hash, Hasher},
|
||||
ops::Index,
|
||||
ops::{Index, Range},
|
||||
};
|
||||
|
||||
use ast::{AstNode, HasName, StructKind};
|
||||
@ -308,7 +308,7 @@ pub enum AttrOwner {
|
||||
/// Inner attributes of the source file.
|
||||
TopLevel,
|
||||
|
||||
Variant(Idx<Variant>),
|
||||
Variant(FileItemTreeId<Variant>),
|
||||
Field(Idx<Field>),
|
||||
Param(Idx<Param>),
|
||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||
@ -329,7 +329,7 @@ macro_rules! from_attrs {
|
||||
|
||||
from_attrs!(
|
||||
ModItem(ModItem),
|
||||
Variant(Idx<Variant>),
|
||||
Variant(FileItemTreeId<Variant>),
|
||||
Field(Idx<Field>),
|
||||
Param(Idx<Param>),
|
||||
TypeOrConstParamData(Idx<TypeOrConstParamData>),
|
||||
@ -337,7 +337,7 @@ from_attrs!(
|
||||
);
|
||||
|
||||
/// Trait implemented by all item nodes in the item tree.
|
||||
pub trait ItemTreeNode: Clone {
|
||||
pub trait ItemTreeModItemNode: Clone {
|
||||
type Source: AstIdNode + Into<ast::Item>;
|
||||
|
||||
fn ast_id(&self) -> FileAstId<Self::Source>;
|
||||
@ -352,35 +352,44 @@ pub trait ItemTreeNode: Clone {
|
||||
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> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
|
||||
impl<N> Clone for FileItemTreeId<N> {
|
||||
fn clone(&self) -> Self {
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
@ -415,12 +424,12 @@ impl TreeId {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ItemTreeId<N: ItemTreeNode> {
|
||||
pub struct ItemTreeId<N> {
|
||||
tree: TreeId,
|
||||
pub value: FileItemTreeId<N>,
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> ItemTreeId<N> {
|
||||
impl<N> ItemTreeId<N> {
|
||||
pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
|
||||
Self { tree, value: idx }
|
||||
}
|
||||
@ -436,24 +445,31 @@ impl<N: ItemTreeNode> ItemTreeId<N> {
|
||||
pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
|
||||
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: ItemTreeNode> Clone for ItemTreeId<N> {
|
||||
impl<N> Copy for ItemTreeId<N> {}
|
||||
impl<N> Clone for ItemTreeId<N> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
|
||||
impl<N> PartialEq for ItemTreeId<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
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) {
|
||||
self.tree.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;
|
||||
|
||||
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;
|
||||
fn index(&self, id: FileItemTreeId<N>) -> &N {
|
||||
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)]
|
||||
pub struct Use {
|
||||
pub visibility: RawVisibilityId,
|
||||
@ -678,7 +701,7 @@ pub struct Enum {
|
||||
pub name: Name,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: Interned<GenericParams>,
|
||||
pub variants: IdxRange<Variant>,
|
||||
pub variants: Range<FileItemTreeId<Variant>>,
|
||||
pub ast_id: FileAstId<ast::Enum>,
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
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::{
|
||||
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
|
||||
@ -13,7 +13,7 @@ use crate::{
|
||||
|
||||
use super::*;
|
||||
|
||||
fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
|
||||
fn id<N: ItemTreeModItemNode>(index: Idx<N>) -> FileItemTreeId<N> {
|
||||
FileItemTreeId(index)
|
||||
}
|
||||
|
||||
@ -253,25 +253,27 @@ impl<'a> Ctx<'a> {
|
||||
let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
|
||||
let variants = match &enum_.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 };
|
||||
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();
|
||||
for variant in variants.variants() {
|
||||
if let Some(data) = self.lower_variant(&variant) {
|
||||
let idx = self.data().variants.alloc(data);
|
||||
self.add_attrs(
|
||||
idx.into(),
|
||||
FileItemTreeId(idx).into(),
|
||||
RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
|
||||
);
|
||||
}
|
||||
}
|
||||
let end = self.next_variant_idx();
|
||||
IdxRange::new(start..end)
|
||||
FileItemTreeId(start)..FileItemTreeId(end)
|
||||
}
|
||||
|
||||
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
||||
@ -719,16 +721,10 @@ enum HasImplicitSelf {
|
||||
}
|
||||
|
||||
fn lower_abi(abi: ast::Abi) -> Interned<str> {
|
||||
// FIXME: Abi::abi() -> Option<SyntaxToken>?
|
||||
match abi.syntax().last_token() {
|
||||
Some(tok) if tok.kind() == SyntaxKind::STRING => {
|
||||
// FIXME: Better way to unescape?
|
||||
Interned::new_str(tok.text().trim_matches('"'))
|
||||
}
|
||||
_ => {
|
||||
// `extern` default to be `extern "C"`.
|
||||
Interned::new_str("C")
|
||||
}
|
||||
match abi.abi_string() {
|
||||
Some(tok) => Interned::new_str(tok.text_without_quotes()),
|
||||
// `extern` default to be `extern "C"`.
|
||||
_ => Interned::new_str("C"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use span::ErasedFileAstId;
|
||||
|
||||
use crate::{
|
||||
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
|
||||
pretty::{print_path, print_type_bounds, print_type_ref},
|
||||
@ -118,7 +120,11 @@ impl Printer<'_> {
|
||||
w!(self, "{{");
|
||||
self.indented(|this| {
|
||||
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_visibility(*visibility);
|
||||
w!(this, "{}: ", name.display(self.db.upcast()));
|
||||
@ -132,7 +138,11 @@ impl Printer<'_> {
|
||||
w!(self, "(");
|
||||
self.indented(|this| {
|
||||
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_visibility(*visibility);
|
||||
w!(this, "{}: ", name.display(self.db.upcast()));
|
||||
@ -200,14 +210,16 @@ impl Printer<'_> {
|
||||
|
||||
match item {
|
||||
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);
|
||||
w!(self, "use ");
|
||||
self.print_use_tree(use_tree);
|
||||
wln!(self, ";");
|
||||
}
|
||||
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);
|
||||
w!(self, "extern crate {}", name.display(self.db.upcast()));
|
||||
if let Some(alias) = alias {
|
||||
@ -216,7 +228,8 @@ impl Printer<'_> {
|
||||
wln!(self, ";");
|
||||
}
|
||||
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 ");
|
||||
if let Some(abi) = abi {
|
||||
w!(self, "\"{}\" ", abi);
|
||||
@ -237,9 +250,10 @@ impl Printer<'_> {
|
||||
abi,
|
||||
params,
|
||||
ret_type,
|
||||
ast_id: _,
|
||||
ast_id,
|
||||
flags,
|
||||
} = &self.tree[it];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
if flags.contains(FnFlags::HAS_DEFAULT_KW) {
|
||||
w!(self, "default ");
|
||||
@ -263,7 +277,12 @@ impl Printer<'_> {
|
||||
self.indented(|this| {
|
||||
for param in params.clone() {
|
||||
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) => {
|
||||
if flags.contains(FnFlags::HAS_SELF_PARAM) {
|
||||
w!(this, "self: ");
|
||||
@ -288,7 +307,8 @@ impl Printer<'_> {
|
||||
}
|
||||
}
|
||||
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);
|
||||
w!(self, "struct {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
@ -300,7 +320,8 @@ impl Printer<'_> {
|
||||
}
|
||||
}
|
||||
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);
|
||||
w!(self, "union {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
@ -312,14 +333,16 @@ impl Printer<'_> {
|
||||
}
|
||||
}
|
||||
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);
|
||||
w!(self, "enum {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
self.print_where_clause_and_opening_brace(generic_params);
|
||||
self.indented(|this| {
|
||||
for variant in variants.clone() {
|
||||
let Variant { name, fields, ast_id: _ } = &this.tree[variant];
|
||||
for variant in FileItemTreeId::range_iter(variants.clone()) {
|
||||
let Variant { name, fields, ast_id } = &this.tree[variant];
|
||||
this.print_ast_id(ast_id.erase());
|
||||
this.print_attrs_of(variant, "\n");
|
||||
w!(this, "{}", name.display(self.db.upcast()));
|
||||
this.print_fields(fields);
|
||||
@ -329,7 +352,8 @@ impl Printer<'_> {
|
||||
wln!(self, "}}");
|
||||
}
|
||||
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);
|
||||
w!(self, "const ");
|
||||
match name {
|
||||
@ -341,7 +365,8 @@ impl Printer<'_> {
|
||||
wln!(self, " = _;");
|
||||
}
|
||||
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);
|
||||
w!(self, "static ");
|
||||
if *mutable {
|
||||
@ -353,15 +378,9 @@ impl Printer<'_> {
|
||||
wln!(self);
|
||||
}
|
||||
ModItem::Trait(it) => {
|
||||
let Trait {
|
||||
name,
|
||||
visibility,
|
||||
is_auto,
|
||||
is_unsafe,
|
||||
items,
|
||||
generic_params,
|
||||
ast_id: _,
|
||||
} = &self.tree[it];
|
||||
let Trait { name, visibility, is_auto, is_unsafe, items, generic_params, ast_id } =
|
||||
&self.tree[it];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
if *is_unsafe {
|
||||
w!(self, "unsafe ");
|
||||
@ -380,7 +399,8 @@ impl Printer<'_> {
|
||||
wln!(self, "}}");
|
||||
}
|
||||
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);
|
||||
w!(self, "trait {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
@ -397,8 +417,9 @@ impl Printer<'_> {
|
||||
is_unsafe,
|
||||
items,
|
||||
generic_params,
|
||||
ast_id: _,
|
||||
ast_id,
|
||||
} = &self.tree[it];
|
||||
self.print_ast_id(ast_id.erase());
|
||||
if *is_unsafe {
|
||||
w!(self, "unsafe");
|
||||
}
|
||||
@ -422,8 +443,9 @@ impl Printer<'_> {
|
||||
wln!(self, "}}");
|
||||
}
|
||||
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.print_ast_id(ast_id.erase());
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "type {}", name.display(self.db.upcast()));
|
||||
self.print_generic_params(generic_params);
|
||||
@ -440,7 +462,8 @@ impl Printer<'_> {
|
||||
wln!(self);
|
||||
}
|
||||
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);
|
||||
w!(self, "mod {}", name.display(self.db.upcast()));
|
||||
match kind {
|
||||
@ -459,15 +482,24 @@ impl Printer<'_> {
|
||||
}
|
||||
}
|
||||
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()));
|
||||
}
|
||||
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()));
|
||||
}
|
||||
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);
|
||||
wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast()));
|
||||
}
|
||||
@ -583,6 +615,10 @@ impl Printer<'_> {
|
||||
});
|
||||
true
|
||||
}
|
||||
|
||||
fn print_ast_id(&mut self, ast_id: ErasedFileAstId) {
|
||||
wln!(self, "// AstId: {:?}", ast_id.into_raw());
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Printer<'_> {
|
||||
|
@ -34,17 +34,23 @@ use a::{c, d::{e}};
|
||||
#![no_std]
|
||||
#![doc = " another file comment"]
|
||||
|
||||
// AstId: 1
|
||||
pub(self) extern crate self as renamed;
|
||||
|
||||
// AstId: 2
|
||||
pub(super) extern crate bli;
|
||||
|
||||
// AstId: 3
|
||||
pub use crate::path::{nested, items as renamed, Trait as _};
|
||||
|
||||
// AstId: 4
|
||||
pub(self) use globs::*;
|
||||
|
||||
#[doc = " docs on import"]
|
||||
// AstId: 5
|
||||
pub(self) use crate::{A, B};
|
||||
|
||||
// AstId: 6
|
||||
pub(self) use a::{c, d::{e}};
|
||||
"##]],
|
||||
);
|
||||
@ -68,14 +74,18 @@ extern "C" {
|
||||
"#,
|
||||
expect![[r##"
|
||||
#[on_extern_block]
|
||||
// AstId: 1
|
||||
extern "C" {
|
||||
#[on_extern_type]
|
||||
// AstId: 2
|
||||
pub(self) type ExType;
|
||||
|
||||
#[on_extern_static]
|
||||
// AstId: 3
|
||||
pub(self) static EX_STATIC: u8 = _;
|
||||
|
||||
#[on_extern_fn]
|
||||
// AstId: 4
|
||||
pub(self) fn ex_fn() -> ();
|
||||
}
|
||||
"##]],
|
||||
@ -112,38 +122,52 @@ enum E {
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r##"
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct Unit;
|
||||
|
||||
#[derive(Debug)]
|
||||
// AstId: 2
|
||||
pub(self) struct Struct {
|
||||
// AstId: 6
|
||||
#[doc = " fld docs"]
|
||||
pub(self) fld: (),
|
||||
}
|
||||
|
||||
// AstId: 3
|
||||
pub(self) struct Tuple(
|
||||
// AstId: 7
|
||||
#[attr]
|
||||
pub(self) 0: u8,
|
||||
);
|
||||
|
||||
// AstId: 4
|
||||
pub(self) union Ize {
|
||||
// AstId: 8
|
||||
pub(self) a: (),
|
||||
// AstId: 9
|
||||
pub(self) b: (),
|
||||
}
|
||||
|
||||
// AstId: 5
|
||||
pub(self) enum E {
|
||||
// AstId: 10
|
||||
#[doc = " comment on Unit"]
|
||||
Unit,
|
||||
// AstId: 11
|
||||
#[doc = " comment on Tuple"]
|
||||
Tuple(
|
||||
// AstId: 13
|
||||
pub(self) 0: u8,
|
||||
),
|
||||
// AstId: 12
|
||||
Struct {
|
||||
// AstId: 14
|
||||
#[doc = " comment on a: u8"]
|
||||
pub(self) a: u8,
|
||||
},
|
||||
}
|
||||
"##]],
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
@ -166,26 +190,35 @@ trait Tr: SuperTrait + 'lifetime {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub static mut ST: () = _;
|
||||
|
||||
// AstId: 2
|
||||
pub(self) const _: Anon = _;
|
||||
|
||||
#[attr]
|
||||
#[inner_attr_in_fn]
|
||||
// AstId: 3
|
||||
pub(self) fn f(
|
||||
#[attr]
|
||||
// AstId: 5
|
||||
u8,
|
||||
// AstId: 6
|
||||
(),
|
||||
) -> () { ... }
|
||||
|
||||
// AstId: 4
|
||||
pub(self) trait Tr<Self>
|
||||
where
|
||||
Self: SuperTrait,
|
||||
Self: 'lifetime
|
||||
{
|
||||
// AstId: 8
|
||||
pub(self) type Assoc: AssocBound = Default;
|
||||
|
||||
// AstId: 9
|
||||
pub(self) fn method(
|
||||
// AstId: 10
|
||||
self: &Self,
|
||||
) -> ();
|
||||
}
|
||||
@ -211,12 +244,16 @@ mod outline;
|
||||
expect![[r##"
|
||||
#[doc = " outer"]
|
||||
#[doc = " inner"]
|
||||
// AstId: 1
|
||||
pub(self) mod inline {
|
||||
// AstId: 3
|
||||
pub(self) use super::*;
|
||||
|
||||
// AstId: 4
|
||||
pub(self) fn fn_in_module() -> () { ... }
|
||||
}
|
||||
|
||||
// AstId: 2
|
||||
pub(self) mod outline;
|
||||
"##]],
|
||||
);
|
||||
@ -235,10 +272,13 @@ pub macro m2() {}
|
||||
m!();
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
macro_rules! m { ... }
|
||||
|
||||
// AstId: 2
|
||||
pub macro m2 { ... }
|
||||
|
||||
// AstId: 3, Span: 0:3@0..5#0, ExpandTo: Items
|
||||
m!(...);
|
||||
"#]],
|
||||
);
|
||||
@ -258,12 +298,19 @@ struct S {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S {
|
||||
// AstId: 2
|
||||
pub(self) a: self::Ty,
|
||||
// AstId: 3
|
||||
pub(self) b: super::SuperTy,
|
||||
// AstId: 4
|
||||
pub(self) c: super::super::SuperSuperTy,
|
||||
// AstId: 5
|
||||
pub(self) d: ::abs::Path,
|
||||
// AstId: 6
|
||||
pub(self) e: crate::Crate,
|
||||
// AstId: 7
|
||||
pub(self) f: plain::path::Ty,
|
||||
}
|
||||
"#]],
|
||||
@ -282,10 +329,15 @@ struct S {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S {
|
||||
// AstId: 2
|
||||
pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>,
|
||||
// AstId: 3
|
||||
pub(self) b: Qualified::<Self=Fully>::Syntax,
|
||||
// AstId: 4
|
||||
pub(self) c: <TypeAnchored>::Path::<'a>,
|
||||
// AstId: 5
|
||||
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> {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S<'a, 'b, T, const K: u8>
|
||||
where
|
||||
T: Copy,
|
||||
T: 'a,
|
||||
T: 'b
|
||||
{
|
||||
// AstId: 8
|
||||
pub(self) field: &'a &'b T,
|
||||
}
|
||||
|
||||
// AstId: 2
|
||||
pub(self) struct Tuple<T, U>(
|
||||
// AstId: 9
|
||||
pub(self) 0: T,
|
||||
// AstId: 10
|
||||
pub(self) 1: U,
|
||||
)
|
||||
where
|
||||
T: Copy,
|
||||
U: ?Sized;
|
||||
|
||||
// AstId: 3
|
||||
impl<'a, 'b, T, const K: u8> S::<'a, 'b, T, K>
|
||||
where
|
||||
T: Copy,
|
||||
T: 'a,
|
||||
T: 'b
|
||||
{
|
||||
// AstId: 12
|
||||
pub(self) fn f<G>(
|
||||
// AstId: 13
|
||||
impl Copy,
|
||||
) -> impl Copy
|
||||
where
|
||||
G: 'a { ... }
|
||||
}
|
||||
|
||||
// AstId: 4
|
||||
pub(self) enum Enum<'a, T, const U: u8> {
|
||||
}
|
||||
|
||||
// AstId: 5
|
||||
pub(self) union Union<'a, T, const U: u8> {
|
||||
}
|
||||
|
||||
// AstId: 6
|
||||
pub(self) trait Tr<'a, Self, T>
|
||||
where
|
||||
Self: Super,
|
||||
@ -366,6 +429,7 @@ fn generics_with_attributes() {
|
||||
struct S<#[cfg(never)] T>;
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S<#[cfg(never)] T>;
|
||||
"#]],
|
||||
)
|
||||
@ -378,6 +442,7 @@ fn pub_self() {
|
||||
pub(self) struct S;
|
||||
"#,
|
||||
expect![[r#"
|
||||
// AstId: 1
|
||||
pub(self) struct S;
|
||||
"#]],
|
||||
)
|
||||
|
@ -125,12 +125,8 @@ impl LangItems {
|
||||
}
|
||||
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
||||
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
|
||||
db.enum_data(e).variants.iter().for_each(|(local_id, _)| {
|
||||
lang_items.collect_lang_item(
|
||||
db,
|
||||
EnumVariantId { parent: e, local_id },
|
||||
LangItemTarget::EnumVariant,
|
||||
);
|
||||
crate_def_map.enum_definitions[&e].iter().for_each(|&id| {
|
||||
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
|
||||
});
|
||||
}
|
||||
ModuleDefId::AdtId(AdtId::StructId(s)) => {
|
||||
@ -188,15 +184,51 @@ impl LangItems {
|
||||
T: Into<AttrDefId> + Copy,
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 {
|
||||
@ -228,6 +260,7 @@ macro_rules! language_item_table {
|
||||
}
|
||||
|
||||
/// Opposite of [`LangItem::name`]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
$( stringify!($name) => Some(LangItem::$variant), )*
|
||||
@ -334,8 +367,8 @@ language_item_table! {
|
||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
||||
|
||||
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
GeneratorState, sym::generator_state, gen_state, Target::Enum, GenericRequirement::None;
|
||||
Generator, sym::generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
|
||||
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
||||
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
|
||||
|
||||
|
@ -99,8 +99,8 @@ use crate::{
|
||||
data::adt::VariantData,
|
||||
db::DefDatabase,
|
||||
item_tree::{
|
||||
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
|
||||
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use,
|
||||
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeModItemNode, Macro2,
|
||||
MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
|
||||
},
|
||||
};
|
||||
|
||||
@ -213,28 +213,28 @@ impl ModuleId {
|
||||
pub type LocalModuleId = Idx<nameres::ModuleData>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ItemLoc<N: ItemTreeNode> {
|
||||
pub struct ItemLoc<N: ItemTreeModItemNode> {
|
||||
pub container: ModuleId,
|
||||
pub id: ItemTreeId<N>,
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> Clone for ItemLoc<N> {
|
||||
impl<N: ItemTreeModItemNode> Clone for ItemLoc<N> {
|
||||
fn clone(&self) -> Self {
|
||||
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 {
|
||||
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) {
|
||||
self.container.hash(state);
|
||||
self.id.hash(state);
|
||||
@ -242,28 +242,28 @@ impl<N: ItemTreeNode> Hash for ItemLoc<N> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AssocItemLoc<N: ItemTreeNode> {
|
||||
pub struct AssocItemLoc<N: ItemTreeModItemNode> {
|
||||
pub container: ItemContainerId,
|
||||
pub id: ItemTreeId<N>,
|
||||
}
|
||||
|
||||
impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
|
||||
impl<N: ItemTreeModItemNode> Clone for AssocItemLoc<N> {
|
||||
fn clone(&self) -> Self {
|
||||
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 {
|
||||
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) {
|
||||
self.container.hash(state);
|
||||
self.id.hash(state);
|
||||
@ -297,14 +297,16 @@ pub struct EnumId(salsa::InternId);
|
||||
pub type EnumLoc = ItemLoc<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)]
|
||||
pub struct EnumVariantId {
|
||||
pub parent: EnumId,
|
||||
pub local_id: LocalEnumVariantId,
|
||||
}
|
||||
pub struct EnumVariantId(salsa::InternId);
|
||||
|
||||
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)]
|
||||
pub struct FieldId {
|
||||
@ -731,9 +733,7 @@ pub struct InTypeConstLoc {
|
||||
|
||||
impl PartialEq for InTypeConstLoc {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
&& self.owner == other.owner
|
||||
&& &*self.expected_ty == &*other.expected_ty
|
||||
self.id == other.id && self.owner == other.owner && *self.expected_ty == *other.expected_ty
|
||||
}
|
||||
}
|
||||
|
||||
@ -953,23 +953,21 @@ impl VariantId {
|
||||
match self {
|
||||
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()
|
||||
}
|
||||
VariantId::EnumVariantId(it) => db.enum_variant_data(it).variant_data.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
|
||||
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::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 {
|
||||
VariantId::EnumVariantId(it) => it.parent.into(),
|
||||
VariantId::EnumVariantId(it) => it.lookup(db).parent.into(),
|
||||
VariantId::StructId(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 {
|
||||
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 {
|
||||
#[inline]
|
||||
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
||||
self.lookup(db).container
|
||||
}
|
||||
@ -1016,7 +1030,7 @@ impl HasModule for ExternCrateId {
|
||||
impl HasModule for VariantId {
|
||||
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
||||
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::UnionId(it) => it.lookup(db).container,
|
||||
}
|
||||
@ -1045,7 +1059,7 @@ impl HasModule for TypeOwnerId {
|
||||
TypeOwnerId::TraitAliasId(it) => it.lookup(db).container,
|
||||
TypeOwnerId::TypeAliasId(it) => it.lookup(db).module(db),
|
||||
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::StaticId(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),
|
||||
}
|
||||
}
|
||||
@ -1071,19 +1085,21 @@ impl HasModule for GenericDefId {
|
||||
GenericDefId::TraitAliasId(it) => it.lookup(db).container,
|
||||
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModule for TypeAliasId {
|
||||
#[inline]
|
||||
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
||||
self.lookup(db).module(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasModule for TraitId {
|
||||
#[inline]
|
||||
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
|
||||
self.lookup(db).container
|
||||
}
|
||||
@ -1098,7 +1114,7 @@ impl ModuleDefId {
|
||||
ModuleDefId::ModuleId(id) => *id,
|
||||
ModuleDefId::FunctionId(id) => id.lookup(db).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::StaticId(id) => id.lookup(db).module(db),
|
||||
ModuleDefId::TraitId(id) => id.lookup(db).container,
|
||||
@ -1117,7 +1133,7 @@ impl AttrDefId {
|
||||
AttrDefId::FieldId(it) => it.parent.module(db).krate,
|
||||
AttrDefId::AdtId(it) => it.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::ConstId(it) => it.lookup(db).module(db).krate,
|
||||
AttrDefId::TraitId(it) => it.lookup(db).container.krate,
|
||||
|
@ -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#
|
||||
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#
|
||||
}#FileId(0):1@132..133\2#
|
||||
struct#0:1@58..64#2# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#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#
|
||||
}#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#
|
||||
1#FileId(0):2@50..51\0#;#FileId(0):2@51..52\0#
|
||||
1.0#FileId(0):2@61..64\0#;#FileId(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#
|
||||
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#
|
||||
}#FileId(0):2@110..111\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#0:2@50..51#0#;#0:2@51..52#0#
|
||||
1.0#0:2@61..64#0#;#0:2@64..65#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#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#
|
||||
}#0:2@110..111#0#
|
||||
|
||||
|
||||
"#]],
|
||||
@ -171,7 +171,7 @@ 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]
|
||||
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#
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -291,15 +291,8 @@ fn pretty_print_macro_expansion(
|
||||
let span = map.span_for_range(token.text_range());
|
||||
format_to!(res, "#");
|
||||
if show_spans {
|
||||
format_to!(
|
||||
res,
|
||||
"{:?}:{:?}@{:?}",
|
||||
span.anchor.file_id,
|
||||
span.anchor.ast_id.into_raw(),
|
||||
span.range,
|
||||
);
|
||||
}
|
||||
if show_ctxt {
|
||||
format_to!(res, "{span}",);
|
||||
} else if show_ctxt {
|
||||
format_to!(res, "\\{}", span.ctx);
|
||||
}
|
||||
format_to!(res, "#");
|
||||
|
@ -181,8 +181,8 @@ fn foo(&self) {
|
||||
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#
|
||||
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#
|
||||
}#FileId(0):1@76..77\0#"#]],
|
||||
fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#0# )#0:1@57..58#0# {#0:1@59..60#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#
|
||||
}#0:1@76..77#0#"#]],
|
||||
);
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ use crate::{
|
||||
path::ModPath,
|
||||
per_ns::PerNs,
|
||||
visibility::{Visibility, VisibilityExplicity},
|
||||
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup,
|
||||
MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
|
||||
AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
|
||||
LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
|
||||
};
|
||||
|
||||
/// 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.
|
||||
/// ExternCrateId being None implies it being imported from the general prelude import.
|
||||
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
|
||||
/// attributes.
|
||||
@ -370,6 +371,7 @@ impl DefMap {
|
||||
macro_use_prelude: FxHashMap::default(),
|
||||
derive_helpers_in_scope: FxHashMap::default(),
|
||||
diagnostics: Vec::new(),
|
||||
enum_definitions: FxHashMap::default(),
|
||||
data: Arc::new(DefMapCrateData {
|
||||
extern_prelude: FxHashMap::default(),
|
||||
exported_derives: FxHashMap::default(),
|
||||
@ -612,12 +614,14 @@ impl DefMap {
|
||||
krate: _,
|
||||
prelude: _,
|
||||
data: _,
|
||||
enum_definitions,
|
||||
} = self;
|
||||
|
||||
macro_use_prelude.shrink_to_fit();
|
||||
diagnostics.shrink_to_fit();
|
||||
modules.shrink_to_fit();
|
||||
derive_helpers_in_scope.shrink_to_fit();
|
||||
enum_definitions.shrink_to_fit();
|
||||
for (_, module) in modules.iter_mut() {
|
||||
module.children.shrink_to_fit();
|
||||
module.scope.shrink_to_fit();
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! `DefCollector::collect` contains the fixed-point iteration loop which
|
||||
//! 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 cfg::{CfgExpr, CfgOptions};
|
||||
@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
|
||||
use la_arena::Idx;
|
||||
use limit::Limit;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use span::{Span, SyntaxContextId};
|
||||
use span::{ErasedFileAstId, Span, SyntaxContextId};
|
||||
use stdx::always;
|
||||
use syntax::{ast, SmolStr};
|
||||
use triomphe::Arc;
|
||||
@ -35,8 +35,8 @@ use crate::{
|
||||
derive_macro_as_call_id,
|
||||
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
|
||||
item_tree::{
|
||||
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
|
||||
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
|
||||
ItemTreeModItemNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id, macro_call_as_call_id_with_eager,
|
||||
nameres::{
|
||||
@ -51,7 +51,7 @@ use crate::{
|
||||
per_ns::PerNs,
|
||||
tt,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
|
||||
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
|
||||
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
|
||||
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
|
||||
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
|
||||
@ -980,24 +980,26 @@ impl DefCollector<'_> {
|
||||
cov_mark::hit!(glob_enum);
|
||||
// glob import from enum => just import all the variants
|
||||
|
||||
// XXX: urgh, so this works by accident! Here, we look at
|
||||
// the enum data, and, in theory, this might require us to
|
||||
// look back at the crate_def_map, creating a cycle. For
|
||||
// example, `enum E { crate::some_macro!(); }`. Luckily, the
|
||||
// only kind of macro that is allowed inside enum is a
|
||||
// `cfg_macro`, and we don't need to run name resolution for
|
||||
// it, but this is sheer luck!
|
||||
let enum_data = self.db.enum_data(e);
|
||||
let resolutions = enum_data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(local_id, variant_data)| {
|
||||
let name = variant_data.name.clone();
|
||||
let variant = EnumVariantId { parent: e, local_id };
|
||||
let res = PerNs::both(variant.into(), variant.into(), vis, None);
|
||||
(Some(name), res)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// We need to check if the def map the enum is from is us, if it is we can't
|
||||
// call the def-map query since we are currently constructing it!
|
||||
let loc = e.lookup(self.db);
|
||||
let tree = loc.id.item_tree(self.db);
|
||||
let current_def_map = self.def_map.krate == loc.container.krate
|
||||
&& self.def_map.block_id() == loc.container.block;
|
||||
let def_map;
|
||||
let resolutions = if current_def_map {
|
||||
&self.def_map.enum_definitions[&e]
|
||||
} else {
|
||||
def_map = loc.container.def_map(self.db);
|
||||
&def_map.enum_definitions[&e]
|
||||
}
|
||||
.iter()
|
||||
.map(|&variant| {
|
||||
let name = tree[variant.lookup(self.db).id.value].name.clone();
|
||||
let res = PerNs::both(variant.into(), variant.into(), vis, None);
|
||||
(Some(name), res)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
|
||||
}
|
||||
Some(d) => {
|
||||
@ -1404,7 +1406,7 @@ impl DefCollector<'_> {
|
||||
}
|
||||
if let errors @ [_, ..] = &*value {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1577,7 +1579,10 @@ impl ModCollector<'_, '_> {
|
||||
let attrs = self.item_tree.attrs(db, krate, item.into());
|
||||
if let Some(cfg) = attrs.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;
|
||||
}
|
||||
}
|
||||
@ -1708,17 +1713,47 @@ impl ModCollector<'_, '_> {
|
||||
}
|
||||
ModItem::Enum(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]);
|
||||
update_def(
|
||||
self.def_collector,
|
||||
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
|
||||
.intern(db)
|
||||
.into(),
|
||||
&it.name,
|
||||
vis,
|
||||
false,
|
||||
);
|
||||
update_def(self.def_collector, enum_.into(), &it.name, vis, false);
|
||||
|
||||
let mut index = 0;
|
||||
let variants = FileItemTreeId::range_iter(it.variants.clone())
|
||||
.filter_map(|variant| {
|
||||
let is_enabled = self
|
||||
.item_tree
|
||||
.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) => {
|
||||
let it = &self.item_tree[id];
|
||||
@ -1905,31 +1940,40 @@ impl ModCollector<'_, '_> {
|
||||
let is_enabled = item_tree
|
||||
.top_level_attrs(db, krate)
|
||||
.cfg()
|
||||
.map_or(true, |cfg| self.is_cfg_enabled(&cfg));
|
||||
if is_enabled {
|
||||
let module_id = self.push_child_module(
|
||||
module.name.clone(),
|
||||
ast_id.value,
|
||||
Some((file_id, is_mod_rs)),
|
||||
&self.item_tree[module.visibility],
|
||||
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,
|
||||
.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(
|
||||
ast_id.map(|it| it.erase()),
|
||||
&cfg,
|
||||
);
|
||||
}
|
||||
.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);
|
||||
Ok(()) => {
|
||||
let module_id = self.push_child_module(
|
||||
module.name.clone(),
|
||||
ast_id.value,
|
||||
Some((file_id, is_mod_rs)),
|
||||
&self.item_tree[module.visibility],
|
||||
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,
|
||||
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;
|
||||
|
||||
// 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() {
|
||||
macs.last().map(|&mac| {
|
||||
if let Some(&mac) = macs.last() {
|
||||
target.scope.define_legacy_macro(name.clone(), mac);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2360,10 +2404,7 @@ impl ModCollector<'_, '_> {
|
||||
self.def_collector.cfg_options.check(cfg) != Some(false)
|
||||
}
|
||||
|
||||
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
|
||||
let ast_id = item.ast_id(self.item_tree);
|
||||
|
||||
let ast_id = InFile::new(self.file_id(), ast_id.erase());
|
||||
fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile<ErasedFileAstId>, cfg: &CfgExpr) {
|
||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
self.module_id,
|
||||
ast_id,
|
||||
|
@ -40,6 +40,23 @@ pub enum DefDiagnosticKind {
|
||||
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)]
|
||||
pub struct DefDiagnostic {
|
||||
pub in_module: LocalModuleId,
|
||||
|
@ -11,18 +11,18 @@
|
||||
//! `ReachedFixedPoint` signals about this.
|
||||
|
||||
use base_db::Edition;
|
||||
use hir_expand::name::Name;
|
||||
use hir_expand::{name::Name, Lookup};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
data::adt::VariantData,
|
||||
db::DefDatabase,
|
||||
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
|
||||
item_tree::Fields,
|
||||
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
|
||||
path::{ModPath, PathKind},
|
||||
per_ns::PerNs,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId,
|
||||
AdtId, CrateId, LocalModuleId, ModuleDefId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@ -355,29 +355,42 @@ impl DefMap {
|
||||
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
|
||||
// enum variant
|
||||
cov_mark::hit!(can_import_enum_variant);
|
||||
let enum_data = db.enum_data(e);
|
||||
match enum_data.variant(segment) {
|
||||
Some(local_id) => {
|
||||
let variant = EnumVariantId { parent: e, local_id };
|
||||
match &*enum_data.variants[local_id].variant_data {
|
||||
VariantData::Record(_) => {
|
||||
PerNs::types(variant.into(), Visibility::Public, None)
|
||||
}
|
||||
VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
|
||||
variant.into(),
|
||||
variant.into(),
|
||||
Visibility::Public,
|
||||
None,
|
||||
),
|
||||
let def_map;
|
||||
|
||||
let loc = e.lookup(db);
|
||||
let tree = loc.id.item_tree(db);
|
||||
let current_def_map =
|
||||
self.krate == loc.container.krate && self.block_id() == loc.container.block;
|
||||
let res = if current_def_map {
|
||||
&self.enum_definitions[&e]
|
||||
} else {
|
||||
def_map = loc.container.def_map(db);
|
||||
&def_map.enum_definitions[&e]
|
||||
}
|
||||
.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 => {
|
||||
return ResolvePathResult::with(
|
||||
PerNs::types(e.into(), vis, imp),
|
||||
ReachedFixedPoint::Yes,
|
||||
Some(i),
|
||||
Some(self.krate),
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1348,8 +1348,8 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
|
||||
|
||||
let actual = def_map
|
||||
.macro_use_prelude
|
||||
.iter()
|
||||
.map(|(name, _)| name.display(&db).to_string())
|
||||
.keys()
|
||||
.map(|name| name.display(&db).to_string())
|
||||
.sorted()
|
||||
.join("\n");
|
||||
|
||||
|
@ -154,7 +154,7 @@ impl Path {
|
||||
|
||||
pub fn mod_path(&self) -> Option<&ModPath> {
|
||||
match self {
|
||||
Path::Normal { mod_path, .. } => Some(&mod_path),
|
||||
Path::Normal { mod_path, .. } => Some(mod_path),
|
||||
Path::LangItem(..) => None,
|
||||
}
|
||||
}
|
||||
@ -219,13 +219,13 @@ impl<'a> PathSegments<'a> {
|
||||
}
|
||||
pub fn skip(&self, len: usize) -> PathSegments<'a> {
|
||||
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..)),
|
||||
}
|
||||
}
|
||||
pub fn take(&self, len: usize) -> PathSegments<'a> {
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
|
||||
)
|
||||
})
|
||||
.map(Interned::new);
|
||||
if let Some(_) = args {
|
||||
if args.is_some() {
|
||||
generic_args.resize(segments.len(), None);
|
||||
generic_args.push(args);
|
||||
}
|
||||
|
@ -39,11 +39,9 @@ pub(crate) fn print_path(db: &dyn DefDatabase, path: &Path, buf: &mut dyn Write)
|
||||
LangItemTarget::Trait(it) => {
|
||||
write!(buf, "{}", db.trait_data(it).name.display(db.upcast()))?
|
||||
}
|
||||
LangItemTarget::EnumVariant(it) => write!(
|
||||
buf,
|
||||
"{}",
|
||||
db.enum_data(it.parent).variants[it.local_id].name.display(db.upcast())
|
||||
)?,
|
||||
LangItemTarget::EnumVariant(it) => {
|
||||
write!(buf, "{}", db.enum_variant_data(it).name.display(db.upcast()))?
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(s) = s {
|
||||
@ -194,12 +192,17 @@ pub(crate) fn print_type_ref(
|
||||
print_type_ref(db, elem, buf)?;
|
||||
write!(buf, "]")?;
|
||||
}
|
||||
TypeRef::Fn(args_and_ret, varargs, is_unsafe) => {
|
||||
TypeRef::Fn(args_and_ret, varargs, is_unsafe, abi) => {
|
||||
let ((_, return_type), args) =
|
||||
args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
|
||||
if *is_unsafe {
|
||||
write!(buf, "unsafe ")?;
|
||||
}
|
||||
if let Some(abi) = abi {
|
||||
buf.write_str("extern ")?;
|
||||
buf.write_str(abi)?;
|
||||
buf.write_char(' ')?;
|
||||
}
|
||||
write!(buf, "fn(")?;
|
||||
for (i, (_, typeref)) in args.iter().enumerate() {
|
||||
if i != 0 {
|
||||
|
@ -239,8 +239,7 @@ impl Resolver {
|
||||
db: &dyn DefDatabase,
|
||||
visibility: &RawVisibility,
|
||||
) -> Option<Visibility> {
|
||||
let within_impl =
|
||||
self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
|
||||
let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_)));
|
||||
match visibility {
|
||||
RawVisibility::Module(_, _) => {
|
||||
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())
|
||||
}
|
||||
|
||||
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
|
||||
.def_map
|
||||
.extern_prelude()
|
||||
@ -1111,7 +1110,7 @@ impl HasResolver for DefWithBodyId {
|
||||
DefWithBodyId::ConstId(c) => c.resolver(db),
|
||||
DefWithBodyId::FunctionId(f) => f.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),
|
||||
}
|
||||
}
|
||||
@ -1137,7 +1136,7 @@ impl HasResolver for GenericDefId {
|
||||
GenericDefId::TraitAliasId(inner) => inner.resolver(db),
|
||||
GenericDefId::TypeAliasId(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),
|
||||
}
|
||||
}
|
||||
@ -1145,14 +1144,14 @@ impl HasResolver for GenericDefId {
|
||||
|
||||
impl HasResolver for EnumVariantId {
|
||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||
self.parent.resolver(db)
|
||||
self.lookup(db).parent.resolver(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasResolver for VariantId {
|
||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||
match self {
|
||||
VariantId::EnumVariantId(it) => it.parent.resolver(db),
|
||||
VariantId::EnumVariantId(it) => it.resolver(db),
|
||||
VariantId::StructId(it) => it.resolver(db),
|
||||
VariantId::UnionId(it) => it.resolver(db),
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ use la_arena::ArenaMap;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc,
|
||||
MacroRulesLoc, ProcMacroLoc, UseId,
|
||||
db::DefDatabase, item_tree::ItemTreeModItemNode, AssocItemLoc, EnumVariantLoc, ItemLoc, Lookup,
|
||||
Macro2Loc, MacroRulesLoc, ProcMacroLoc, UseId,
|
||||
};
|
||||
|
||||
pub trait HasSource {
|
||||
@ -14,7 +14,7 @@ pub trait HasSource {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
type Value = ast::MacroDef;
|
||||
|
||||
|
@ -18,6 +18,7 @@ pub(crate) struct Trace<T, V> {
|
||||
}
|
||||
|
||||
impl<T, V> Trace<T, V> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new_for_arena() -> Trace<T, V> {
|
||||
Trace { arena: Some(Arena::default()), map: None, len: 0 }
|
||||
}
|
||||
@ -41,6 +42,7 @@ impl<T, V> Trace<T, V> {
|
||||
id
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn into_arena(mut self) -> Arena<T> {
|
||||
self.arena.take().unwrap()
|
||||
}
|
||||
|
@ -222,13 +222,7 @@ pub(crate) fn field_visibilities_query(
|
||||
db: &dyn DefDatabase,
|
||||
variant_id: VariantId,
|
||||
) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
|
||||
let var_data = match variant_id {
|
||||
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 var_data = variant_id.variant_data(db);
|
||||
let resolver = variant_id.module(db).resolver(db);
|
||||
let mut res = ArenaMap::default();
|
||||
for (field_id, field_data) in var_data.fields().iter() {
|
||||
|
@ -191,7 +191,7 @@ impl AstIdMap {
|
||||
|
||||
/// The [`AstId`] of the root node
|
||||
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> {
|
||||
@ -213,11 +213,11 @@ impl AstIdMap {
|
||||
}
|
||||
|
||||
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 {
|
||||
self.arena[id].clone()
|
||||
self.arena[id]
|
||||
}
|
||||
|
||||
fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId {
|
||||
@ -239,9 +239,7 @@ impl AstIdMap {
|
||||
}
|
||||
|
||||
fn hash_ptr(ptr: &SyntaxNodePtr) -> u64 {
|
||||
let mut hasher = BuildHasherDefault::<FxHasher>::default().build_hasher();
|
||||
ptr.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
BuildHasherDefault::<FxHasher>::default().hash_one(ptr)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
|
@ -31,7 +31,7 @@ impl ops::Deref for RawAttrs {
|
||||
|
||||
fn deref(&self) -> &[Attr] {
|
||||
match &self.entries {
|
||||
Some(it) => &*it,
|
||||
Some(it) => it,
|
||||
None => &[],
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ impl RawAttrs {
|
||||
Self {
|
||||
entries: Some(Arc::from_iter(a.iter().cloned().chain(b.iter().map(|it| {
|
||||
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)
|
||||
<< AttrId::AST_INDEX_BITS;
|
||||
it
|
||||
|
@ -425,7 +425,7 @@ fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<t
|
||||
let name = &adt.name;
|
||||
let patterns = adt.shape.as_pattern(span, name);
|
||||
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);
|
||||
quote! {span =>
|
||||
#pat #fat_arrow #expr,
|
||||
|
@ -125,7 +125,7 @@ fn mk_pound(span: Span) -> tt::Subtree {
|
||||
vec![crate::tt::Leaf::Punct(crate::tt::Punct {
|
||||
char: '#',
|
||||
spacing: crate::tt::Spacing::Alone,
|
||||
span: span,
|
||||
span,
|
||||
})
|
||||
.into()],
|
||||
span,
|
||||
@ -279,9 +279,9 @@ fn format_args_expand_general(
|
||||
let pound = mk_pound(span);
|
||||
let mut tt = tt.clone();
|
||||
tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
|
||||
return ExpandResult::ok(quote! {span =>
|
||||
ExpandResult::ok(quote! {span =>
|
||||
builtin #pound format_args #tt
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fn asm_expand(
|
||||
@ -392,6 +392,7 @@ fn unreachable_expand(
|
||||
ExpandResult::ok(call)
|
||||
}
|
||||
|
||||
#[allow(clippy::never_loop)]
|
||||
fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
|
||||
// To determine the edition, we check the first span up the expansion
|
||||
// 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> {
|
||||
tt.token_trees
|
||||
.get(0)
|
||||
.first()
|
||||
.and_then(|tt| match tt {
|
||||
tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it),
|
||||
_ => None,
|
||||
|
@ -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 ast_id_map = db.ast_id_map(file_id.into());
|
||||
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(
|
||||
tree.items()
|
||||
.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.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(
|
||||
mbe::ParseError::Expected("expected a token tree".into()),
|
||||
@ -648,8 +651,8 @@ fn decl_macro_expander(
|
||||
map.as_ref(),
|
||||
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(
|
||||
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)
|
||||
}
|
||||
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.
|
||||
// Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
|
||||
@ -743,10 +746,10 @@ fn macro_expand(
|
||||
};
|
||||
}
|
||||
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, _) => {
|
||||
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);
|
||||
res
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ pub(crate) fn fixup_syntax(
|
||||
|
||||
let node_range = node.text_range();
|
||||
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
|
||||
let original_tree = mbe::syntax_node_to_token_tree(&node, span_map, call_site);
|
||||
let idx = original.len() as u32;
|
||||
|
@ -77,7 +77,7 @@ macro_rules! impl_intern_lookup {
|
||||
impl $crate::Intern for $loc {
|
||||
type Database<'db> = dyn $db + 'db;
|
||||
type ID = $id;
|
||||
fn intern<'db>(self, db: &Self::Database<'db>) -> $id {
|
||||
fn intern(self, db: &Self::Database<'_>) -> $id {
|
||||
db.$intern(self)
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ macro_rules! impl_intern_lookup {
|
||||
impl $crate::Lookup for $id {
|
||||
type Database<'db> = dyn $db + 'db;
|
||||
type Data = $loc;
|
||||
fn lookup<'db>(&self, db: &Self::Database<'db>) -> $loc {
|
||||
fn lookup(&self, db: &Self::Database<'_>) -> $loc {
|
||||
db.$lookup(*self)
|
||||
}
|
||||
}
|
||||
@ -96,13 +96,13 @@ macro_rules! impl_intern_lookup {
|
||||
pub trait Intern {
|
||||
type Database<'db>: ?Sized;
|
||||
type ID;
|
||||
fn intern<'db>(self, db: &Self::Database<'db>) -> Self::ID;
|
||||
fn intern(self, db: &Self::Database<'_>) -> Self::ID;
|
||||
}
|
||||
|
||||
pub trait Lookup {
|
||||
type Database<'db>: ?Sized;
|
||||
type Data;
|
||||
fn lookup<'db>(&self, db: &Self::Database<'db>) -> Self::Data;
|
||||
fn lookup(&self, db: &Self::Database<'_>) -> Self::Data;
|
||||
}
|
||||
|
||||
impl_intern_lookup!(
|
||||
@ -425,7 +425,7 @@ impl MacroDefId {
|
||||
|
||||
pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> {
|
||||
match self.kind {
|
||||
MacroDefKind::ProcMacro(.., id) => return Either::Right(id),
|
||||
MacroDefKind::ProcMacro(.., id) => Either::Right(id),
|
||||
MacroDefKind::Declarative(id)
|
||||
| MacroDefKind::BuiltIn(_, 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.
|
||||
pub fn map_range_down<'a>(
|
||||
&'a self,
|
||||
pub fn map_range_down(
|
||||
&self,
|
||||
span: Span,
|
||||
) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + 'a>> {
|
||||
) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + '_>> {
|
||||
let tokens = self
|
||||
.exp_map
|
||||
.ranges_with_span(span)
|
||||
|
@ -301,7 +301,7 @@ pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) ->
|
||||
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;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
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
|
||||
/// 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`
|
||||
const fn new_inline(text: &str) -> Name {
|
||||
Name::new_text(SmolStr::new_inline(text))
|
||||
const fn new_static(text: &'static str) -> Name {
|
||||
Name::new_text(SmolStr::new_static(text))
|
||||
}
|
||||
|
||||
/// 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
|
||||
// escaped form.
|
||||
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()),
|
||||
}
|
||||
@ -99,7 +99,7 @@ impl Name {
|
||||
/// 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.
|
||||
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
|
||||
@ -119,7 +119,7 @@ impl Name {
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
static CNT: AtomicUsize = AtomicUsize::new(0);
|
||||
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.
|
||||
@ -260,7 +260,7 @@ pub mod known {
|
||||
$(
|
||||
#[allow(bad_style)]
|
||||
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
|
||||
pub const SELF_PARAM: super::Name = super::Name::new_inline("self");
|
||||
pub const SELF_TYPE: 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_static("Self");
|
||||
|
||||
pub const STATIC_LIFETIME: super::Name = super::Name::new_inline("'static");
|
||||
pub const DOLLAR_CRATE: super::Name = super::Name::new_inline("$crate");
|
||||
pub const STATIC_LIFETIME: super::Name = super::Name::new_static("'static");
|
||||
pub const DOLLAR_CRATE: super::Name = super::Name::new_static("$crate");
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! name {
|
||||
|
@ -1,11 +1,13 @@
|
||||
//! A simplified version of quote-crate like quasi quote macro
|
||||
#![allow(clippy::crate_in_macro_def)]
|
||||
|
||||
use span::Span;
|
||||
use syntax::format_smolstr;
|
||||
|
||||
use crate::name::Name;
|
||||
|
||||
pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
|
||||
tt::Ident { text: syntax::SmolStr::new_inline("$crate"), span }
|
||||
pub(crate) const fn dollar_crate(span: Span) -> tt::Ident<Span> {
|
||||
tt::Ident { text: syntax::SmolStr::new_static("$crate"), span }
|
||||
}
|
||||
|
||||
// A helper macro quote macro
|
||||
@ -17,13 +19,13 @@ pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
|
||||
#[macro_export]
|
||||
macro_rules! __quote {
|
||||
($span:ident) => {
|
||||
Vec::<crate::tt::TokenTree>::new()
|
||||
Vec::<$crate::tt::TokenTree>::new()
|
||||
};
|
||||
|
||||
( @SUBTREE($span:ident) $delim:ident $($tt:tt)* ) => {
|
||||
{
|
||||
let children = $crate::__quote!($span $($tt)*);
|
||||
crate::tt::Subtree {
|
||||
$crate::tt::Subtree {
|
||||
delimiter: crate::tt::Delimiter {
|
||||
kind: crate::tt::DelimiterKind::$delim,
|
||||
open: $span,
|
||||
@ -214,8 +216,8 @@ impl_to_to_tokentrees! {
|
||||
_span: crate::tt::Literal => self { self };
|
||||
_span: crate::tt::Ident => self { self };
|
||||
_span: crate::tt::Punct => self { self };
|
||||
span: &str => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span}};
|
||||
span: String => 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_smolstr!("\"{}\"", self.escape_default()), span}};
|
||||
span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}};
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,10 @@ oorandom = "11.1.3"
|
||||
tracing.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
scoped-tls = "1.0.0"
|
||||
chalk-solve = { version = "0.95.0", default-features = false }
|
||||
chalk-ir = "0.95.0"
|
||||
chalk-recursive = { version = "0.95.0", default-features = false }
|
||||
chalk-derive = "0.95.0"
|
||||
chalk-solve = { version = "0.96.0", default-features = false }
|
||||
chalk-ir = "0.96.0"
|
||||
chalk-recursive = { version = "0.96.0", default-features = false }
|
||||
chalk-derive = "0.96.0"
|
||||
la-arena.workspace = true
|
||||
once_cell = "1.17.0"
|
||||
triomphe.workspace = true
|
||||
|
@ -227,21 +227,21 @@ impl TyBuilder<()> {
|
||||
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:
|
||||
/// - resume type of generator
|
||||
/// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
|
||||
/// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
|
||||
/// A coroutine's substitution consists of:
|
||||
/// - resume type of coroutine
|
||||
/// - yield type of coroutine ([`Coroutine::Yield`](std::ops::Coroutine::Yield))
|
||||
/// - return type of coroutine ([`Coroutine::Return`](std::ops::Coroutine::Return))
|
||||
/// - generic parameters in scope on `parent`
|
||||
/// in this order.
|
||||
///
|
||||
/// This method prepopulates the builder with placeholder substitution of `parent`, so you
|
||||
/// 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 =
|
||||
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();
|
||||
TyBuilder::new((), params, parent_subst)
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
||||
well_known_trait: rust_ir::WellKnownTrait,
|
||||
) -> Option<chalk_ir::TraitId<Interner>> {
|
||||
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_,
|
||||
_ => 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 {
|
||||
format!("fn_{}", fn_def_id.0)
|
||||
}
|
||||
fn generator_datum(
|
||||
fn coroutine_datum(
|
||||
&self,
|
||||
id: chalk_ir::GeneratorId<Interner>,
|
||||
) -> Arc<chalk_solve::rust_ir::GeneratorDatum<Interner>> {
|
||||
let (parent, expr) = self.db.lookup_intern_generator(id.into());
|
||||
id: chalk_ir::CoroutineId<Interner>,
|
||||
) -> Arc<chalk_solve::rust_ir::CoroutineDatum<Interner>> {
|
||||
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
|
||||
// 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.
|
||||
let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build();
|
||||
// `resume_type`, `yield_type`, and `return_type` of the coroutine in question.
|
||||
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))
|
||||
.intern(Interner),
|
||||
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] {
|
||||
hir_def::hir::Expr::Closure {
|
||||
closure_kind: hir_def::hir::ClosureKind::Generator(movability),
|
||||
closure_kind: hir_def::hir::ClosureKind::Coroutine(movability),
|
||||
..
|
||||
} => movability,
|
||||
_ => unreachable!("non generator expression interned as generator"),
|
||||
_ => unreachable!("non coroutine expression interned as coroutine"),
|
||||
};
|
||||
let movability = match movability {
|
||||
Movability::Static => rust_ir::Movability::Static,
|
||||
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,
|
||||
id: chalk_ir::GeneratorId<Interner>,
|
||||
) -> Arc<chalk_solve::rust_ir::GeneratorWitnessDatum<Interner>> {
|
||||
id: chalk_ir::CoroutineId<Interner>,
|
||||
) -> Arc<chalk_solve::rust_ir::CoroutineWitnessDatum<Interner>> {
|
||||
// FIXME: calculate 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());
|
||||
// See the comment in `generator_datum()` for unknown types.
|
||||
let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build();
|
||||
let (parent, _) = self.db.lookup_intern_coroutine(id.into());
|
||||
// See the comment in `coroutine_datum()` for unknown types.
|
||||
let subst = TyBuilder::subst_for_coroutine(self.db, parent).fill_with_unknown().build();
|
||||
let it = subst
|
||||
.iter(Interner)
|
||||
.map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
|
||||
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> {
|
||||
@ -617,7 +617,7 @@ fn well_known_trait_from_lang_item(item: LangItem) -> Option<WellKnownTrait> {
|
||||
LangItem::Fn => WellKnownTrait::Fn,
|
||||
LangItem::FnMut => WellKnownTrait::FnMut,
|
||||
LangItem::FnOnce => WellKnownTrait::FnOnce,
|
||||
LangItem::Generator => WellKnownTrait::Generator,
|
||||
LangItem::Coroutine => WellKnownTrait::Coroutine,
|
||||
LangItem::Sized => WellKnownTrait::Sized,
|
||||
LangItem::Unpin => WellKnownTrait::Unpin,
|
||||
LangItem::Unsize => WellKnownTrait::Unsize,
|
||||
@ -639,7 +639,7 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem {
|
||||
WellKnownTrait::Fn => LangItem::Fn,
|
||||
WellKnownTrait::FnMut => LangItem::FnMut,
|
||||
WellKnownTrait::FnOnce => LangItem::FnOnce,
|
||||
WellKnownTrait::Generator => LangItem::Generator,
|
||||
WellKnownTrait::Coroutine => LangItem::Coroutine,
|
||||
WellKnownTrait::Sized => LangItem::Sized,
|
||||
WellKnownTrait::Tuple => LangItem::Tuple,
|
||||
WellKnownTrait::Unpin => LangItem::Unpin,
|
||||
@ -819,7 +819,11 @@ pub(crate) fn fn_def_datum_query(
|
||||
};
|
||||
let datum = FnDefDatum {
|
||||
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),
|
||||
};
|
||||
Arc::new(datum)
|
||||
|
@ -202,11 +202,7 @@ impl TyExt for Ty {
|
||||
fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
|
||||
match self.kind(Interner) {
|
||||
TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
|
||||
TyKind::FnDef(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::FnDef(def, parameters) => Some(CallableSig::from_def(db, *def, parameters)),
|
||||
TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db),
|
||||
_ => None,
|
||||
}
|
||||
@ -218,7 +214,7 @@ impl TyExt for Ty {
|
||||
// invariant ensured by `TyLoweringContext::lower_dyn_trait()`.
|
||||
// FIXME: dyn types may not have principal trait and we don't want to return auto trait
|
||||
// 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() {
|
||||
WhereClause::Implemented(trait_ref) => Some(trait_ref),
|
||||
_ => None,
|
||||
@ -427,7 +423,7 @@ pub trait DynTyExt {
|
||||
|
||||
impl DynTyExt for DynTy {
|
||||
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),
|
||||
_ => None,
|
||||
})
|
||||
|
@ -10,7 +10,7 @@ use hir_def::{
|
||||
type_ref::LiteralConstRef,
|
||||
ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
|
||||
};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use hir_expand::Lookup;
|
||||
use stdx::never;
|
||||
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::Placeholder(_) => None,
|
||||
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) => {
|
||||
let ec = db.const_eval(*c, subst.clone(), None).ok()?;
|
||||
try_const_usize(db, &ec)
|
||||
@ -256,12 +256,13 @@ pub(crate) fn const_eval_discriminant_variant(
|
||||
let def = variant_id.into();
|
||||
let body = db.body(def);
|
||||
if body.exprs[body.body_expr] == Expr::Missing {
|
||||
let prev_idx: u32 = variant_id.local_id.into_raw().into();
|
||||
let prev_idx = prev_idx.checked_sub(1).map(RawIdx::from).map(Idx::from_raw);
|
||||
let loc = variant_id.lookup(db.upcast());
|
||||
let prev_idx = loc.index.checked_sub(1);
|
||||
let value = match prev_idx {
|
||||
Some(local_id) => {
|
||||
let prev_variant = EnumVariantId { local_id, parent: variant_id.parent };
|
||||
1 + db.const_eval_discriminant(prev_variant)?
|
||||
Some(prev_idx) => {
|
||||
1 + db.const_eval_discriminant(
|
||||
db.enum_data(loc.parent).variants[prev_idx as usize].0,
|
||||
)?
|
||||
}
|
||||
_ => 0,
|
||||
};
|
||||
@ -297,7 +298,7 @@ pub(crate) fn eval_to_const(
|
||||
body[expr].walk_child_exprs(|idx| r |= has_closure(body, idx));
|
||||
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.
|
||||
return unknown_const(infer[expr].clone());
|
||||
}
|
||||
@ -307,7 +308,7 @@ pub(crate) fn eval_to_const(
|
||||
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 {
|
||||
return result;
|
||||
}
|
||||
|
@ -86,8 +86,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
#[salsa::cycle(crate::lower::ty_recover)]
|
||||
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)]
|
||||
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::cycle(crate::lower::impl_self_ty_recover)]
|
||||
@ -199,7 +201,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
#[salsa::interned]
|
||||
fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
|
||||
#[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)]
|
||||
fn associated_ty_data(
|
||||
@ -292,7 +294,7 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
|
||||
.display(db.upcast())
|
||||
.to_string(),
|
||||
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:?}"),
|
||||
});
|
||||
@ -335,8 +337,8 @@ pub struct InternedClosureId(salsa::InternId);
|
||||
impl_intern_key!(InternedClosureId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedGeneratorId(salsa::InternId);
|
||||
impl_intern_key!(InternedGeneratorId);
|
||||
pub struct InternedCoroutineId(salsa::InternId);
|
||||
impl_intern_key!(InternedCoroutineId);
|
||||
|
||||
/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
|
||||
/// we have different IDs for struct and enum variant constructors.
|
||||
|
@ -387,7 +387,7 @@ impl<'a> DeclValidator<'a> {
|
||||
|
||||
for (id, replacement) in pats_replacements {
|
||||
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 ident_pat = ptr.to_node(&root);
|
||||
let parent = match ident_pat.syntax().parent() {
|
||||
@ -582,11 +582,11 @@ impl<'a> DeclValidator<'a> {
|
||||
// Check the field names.
|
||||
let enum_fields_replacements = data
|
||||
.variants
|
||||
.values()
|
||||
.filter_map(|variant| {
|
||||
.iter()
|
||||
.filter_map(|(_, name)| {
|
||||
Some(Replacement {
|
||||
current_name: variant.name.clone(),
|
||||
suggested_text: to_camel_case(&variant.name.to_smol_str())?,
|
||||
current_name: name.clone(),
|
||||
suggested_text: to_camel_case(&name.to_smol_str())?,
|
||||
expected_case: CaseType::UpperCamelCase,
|
||||
})
|
||||
})
|
||||
|
@ -114,35 +114,27 @@ impl ExprValidator {
|
||||
) {
|
||||
// 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() {
|
||||
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 {
|
||||
Expr::MethodCall { receiver, .. } => {
|
||||
let (callee, _) = match self.infer.method_resolution(call_id) {
|
||||
Some(it) => it,
|
||||
None => return,
|
||||
};
|
||||
|
||||
if filter_map_next_checker
|
||||
.get_or_insert_with(|| {
|
||||
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,
|
||||
},
|
||||
);
|
||||
}
|
||||
if filter_map_next_checker
|
||||
.get_or_insert_with(|| {
|
||||
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(
|
||||
|
@ -318,8 +318,7 @@ impl HirDisplay for Pat {
|
||||
if let Some(variant) = variant {
|
||||
match variant {
|
||||
VariantId::EnumVariantId(v) => {
|
||||
let data = f.db.enum_data(v.parent);
|
||||
write!(f, "{}", data.variants[v.local_id].name.display(f.db.upcast()))?;
|
||||
write!(f, "{}", f.db.enum_variant_data(v).name.display(f.db.upcast()))?;
|
||||
}
|
||||
VariantId::StructId(s) => {
|
||||
write!(f, "{}", f.db.struct_data(s).name.display(f.db.upcast()))?
|
||||
|
@ -594,7 +594,7 @@ impl SplitWildcard {
|
||||
let mut ctors: SmallVec<[_; 1]> = enum_data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(local_id, _)| EnumVariantId { parent: *enum_id, local_id })
|
||||
.map(|&(variant, _)| variant)
|
||||
.filter(|&variant| {
|
||||
// If `exhaustive_patterns` is enabled, we exclude variants known to be
|
||||
// uninhabited.
|
||||
|
@ -409,7 +409,7 @@ impl<'p> Matrix<'p> {
|
||||
|
||||
/// Number of columns of this matrix. `None` is the matrix is empty.
|
||||
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
|
||||
|
@ -8,7 +8,7 @@ use std::{
|
||||
};
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{BoundVar, TyKind};
|
||||
use chalk_ir::{BoundVar, Safety, TyKind};
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
db::DefDatabase,
|
||||
@ -20,8 +20,7 @@ use hir_def::{
|
||||
path::{Path, PathKind},
|
||||
type_ref::{TraitBoundModifier, TypeBound, TypeRef},
|
||||
visibility::Visibility,
|
||||
EnumVariantId, HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId,
|
||||
TraitId,
|
||||
HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::{Internable, Interned};
|
||||
@ -42,7 +41,7 @@ use crate::{
|
||||
primitive, to_assoc_type_id,
|
||||
utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
|
||||
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,
|
||||
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
|
||||
};
|
||||
@ -276,7 +275,7 @@ impl DisplayTarget {
|
||||
pub enum DisplaySourceCodeError {
|
||||
PathNotFound,
|
||||
UnknownType,
|
||||
Generator,
|
||||
Coroutine,
|
||||
OpaqueType,
|
||||
}
|
||||
|
||||
@ -428,7 +427,7 @@ impl HirDisplay for Const {
|
||||
Ok(())
|
||||
}
|
||||
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) => {
|
||||
write!(f, "{}", c.name(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());
|
||||
match ty.kind(Interner) {
|
||||
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 => {
|
||||
let it = u128::from_le_bytes(pad16(b, false)) as u32;
|
||||
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 {
|
||||
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:?}")
|
||||
}
|
||||
TyKind::Slice(ty) => {
|
||||
@ -508,7 +507,7 @@ fn render_const_scalar(
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
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("]")
|
||||
}
|
||||
@ -534,9 +533,7 @@ fn render_const_scalar(
|
||||
write!(f, "&{}", data.name.display(f.db.upcast()))?;
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
return f.write_str("<unsized-enum-or-union>");
|
||||
}
|
||||
_ => f.write_str("<unsized-enum-or-union>"),
|
||||
},
|
||||
_ => {
|
||||
let addr = usize::from_le_bytes(match b.try_into() {
|
||||
@ -580,7 +577,7 @@ fn render_const_scalar(
|
||||
continue;
|
||||
};
|
||||
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(")")
|
||||
}
|
||||
@ -613,16 +610,15 @@ fn render_const_scalar(
|
||||
else {
|
||||
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()))?;
|
||||
let field_types =
|
||||
f.db.field_types(EnumVariantId { parent: e, local_id: var_id }.into());
|
||||
let field_types = f.db.field_types(var_id.into());
|
||||
render_variant_after_name(
|
||||
&data.variant_data,
|
||||
f,
|
||||
&field_types,
|
||||
f.db.trait_environment(adt.0.into()),
|
||||
&var_layout,
|
||||
var_layout,
|
||||
subst,
|
||||
b,
|
||||
memory_map,
|
||||
@ -653,14 +649,14 @@ fn render_const_scalar(
|
||||
f.write_str(", ")?;
|
||||
}
|
||||
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("]")
|
||||
}
|
||||
TyKind::Never => f.write_str("!"),
|
||||
TyKind::Closure(_, _) => f.write_str("<closure>"),
|
||||
TyKind::Generator(_, _) => f.write_str("<generator>"),
|
||||
TyKind::GeneratorWitness(_, _) => f.write_str("<generator-witness>"),
|
||||
TyKind::Coroutine(_, _) => f.write_str("<coroutine>"),
|
||||
TyKind::CoroutineWitness(_, _) => f.write_str("<coroutine-witness>"),
|
||||
// The below arms are unreachable, since const eval will bail out before here.
|
||||
TyKind::Foreign(_) => f.write_str("<extern-type>"),
|
||||
TyKind::Error
|
||||
@ -720,7 +716,7 @@ fn render_variant_after_name(
|
||||
}
|
||||
write!(f, ")")?;
|
||||
}
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
VariantData::Unit => Ok(()),
|
||||
}
|
||||
@ -866,7 +862,7 @@ impl HirDisplay for Ty {
|
||||
write!(f, ",)")?;
|
||||
} else {
|
||||
write!(f, "(")?;
|
||||
f.write_joined(&*substs.as_slice(Interner), ", ")?;
|
||||
f.write_joined(substs.as_slice(Interner), ", ")?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
}
|
||||
@ -883,20 +879,29 @@ impl HirDisplay for Ty {
|
||||
// function pointer type.
|
||||
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 {
|
||||
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) => {
|
||||
f.start_location_link(def.into());
|
||||
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast()))?
|
||||
}
|
||||
CallableDefId::EnumVariantId(e) => write!(
|
||||
f,
|
||||
"{}",
|
||||
db.enum_data(e.parent).variants[e.local_id].name.display(f.db.upcast())
|
||||
)?,
|
||||
CallableDefId::EnumVariantId(e) => {
|
||||
f.start_location_link(def.into());
|
||||
write!(f, "{}", db.enum_variant_data(e).name.display(f.db.upcast()))?
|
||||
}
|
||||
};
|
||||
f.end_location_link();
|
||||
if parameters.len(Interner) > 0 {
|
||||
@ -1038,7 +1043,7 @@ impl HirDisplay for Ty {
|
||||
f.start_location_link(t.into());
|
||||
}
|
||||
write!(f, "Future")?;
|
||||
if let Some(_) = future_trait {
|
||||
if future_trait.is_some() {
|
||||
f.end_location_link();
|
||||
}
|
||||
write!(f, "<")?;
|
||||
@ -1046,7 +1051,7 @@ impl HirDisplay for Ty {
|
||||
f.start_location_link(t.into());
|
||||
}
|
||||
write!(f, "Output")?;
|
||||
if let Some(_) = output {
|
||||
if output.is_some() {
|
||||
f.end_location_link();
|
||||
}
|
||||
write!(f, " = ")?;
|
||||
@ -1205,17 +1210,16 @@ impl HirDisplay for Ty {
|
||||
write!(f, "{{unknown}}")?;
|
||||
}
|
||||
TyKind::InferenceVar(..) => write!(f, "_")?,
|
||||
TyKind::Generator(_, subst) => {
|
||||
TyKind::Coroutine(_, subst) => {
|
||||
if f.display_target.is_source_code() {
|
||||
return Err(HirDisplayError::DisplaySourceCodeError(
|
||||
DisplaySourceCodeError::Generator,
|
||||
DisplaySourceCodeError::Coroutine,
|
||||
));
|
||||
}
|
||||
let subst = subst.as_slice(Interner);
|
||||
let a: Option<SmallVec<[&Ty; 3]>> = subst
|
||||
.get(subst.len() - 3..)
|
||||
.map(|args| args.iter().map(|arg| arg.ty(Interner)).collect())
|
||||
.flatten();
|
||||
.and_then(|args| args.iter().map(|arg| arg.ty(Interner)).collect());
|
||||
|
||||
if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
|
||||
write!(f, "|")?;
|
||||
@ -1229,10 +1233,10 @@ impl HirDisplay for Ty {
|
||||
ret_ty.hir_fmt(f)?;
|
||||
} else {
|
||||
// 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(())
|
||||
}
|
||||
@ -1323,9 +1327,19 @@ fn hir_fmt_generics(
|
||||
|
||||
impl HirDisplay for CallableSig {
|
||||
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(")?;
|
||||
f.write_joined(self.params(), ", ")?;
|
||||
if self.is_varargs {
|
||||
if is_varargs {
|
||||
if self.params().is_empty() {
|
||||
write!(f, "...")?;
|
||||
} else {
|
||||
@ -1426,7 +1440,7 @@ fn write_bounds_like_dyn_trait(
|
||||
f.start_location_link(trait_.into());
|
||||
write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast()))?;
|
||||
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 let Some(args) =
|
||||
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")?;
|
||||
}
|
||||
if let Some(_) = sized_trait {
|
||||
if sized_trait.is_some() {
|
||||
f.end_location_link();
|
||||
}
|
||||
}
|
||||
@ -1690,11 +1704,15 @@ impl HirDisplay for TypeRef {
|
||||
inner.hir_fmt(f)?;
|
||||
write!(f, "]")?;
|
||||
}
|
||||
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
|
||||
// FIXME: Function pointer qualifiers.
|
||||
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe, ref abi) => {
|
||||
if is_unsafe {
|
||||
write!(f, "unsafe ")?;
|
||||
}
|
||||
if let Some(abi) = abi {
|
||||
f.write_str("extern \"")?;
|
||||
f.write_str(abi)?;
|
||||
f.write_str("\" ")?;
|
||||
}
|
||||
write!(f, "fn(")?;
|
||||
if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
|
||||
for index in 0..function_parameters.len() {
|
||||
|
@ -40,8 +40,8 @@ use hir_def::{
|
||||
path::{ModPath, Path},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
type_ref::TypeRef,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, ItemContainerId, Lookup,
|
||||
TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
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::StaticId(s) => ctx.collect_static(&db.static_data(s)),
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() {
|
||||
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
||||
true => BuiltinType::Int(BuiltinInt::Isize),
|
||||
false => BuiltinType::Uint(BuiltinUint::Usize),
|
||||
ctx.return_ty = TyBuilder::builtin(
|
||||
match db.enum_data(v.lookup(db.upcast()).parent).variant_body_type() {
|
||||
hir_def::layout::IntegerType::Pointer(signed) => match signed {
|
||||
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) => {
|
||||
// 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.
|
||||
/// <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 {
|
||||
#[default]
|
||||
Move,
|
||||
Ref(Mutability),
|
||||
}
|
||||
@ -170,12 +173,6 @@ impl BindingMode {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BindingMode {
|
||||
fn default() -> Self {
|
||||
BindingMode::Move
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct InferOk<T> {
|
||||
value: T,
|
||||
@ -534,7 +531,7 @@ pub(crate) struct InferenceContext<'a> {
|
||||
/// expressions. If `None`, this is in a context where return is
|
||||
/// inappropriate, such as a const expression.
|
||||
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)>,
|
||||
diverges: Diverges,
|
||||
breakables: Vec<BreakableContext>,
|
||||
@ -570,10 +567,10 @@ enum BreakableKind {
|
||||
Border,
|
||||
}
|
||||
|
||||
fn find_breakable<'c>(
|
||||
ctxs: &'c mut [BreakableContext],
|
||||
fn find_breakable(
|
||||
ctxs: &mut [BreakableContext],
|
||||
label: Option<LabelId>,
|
||||
) -> Option<&'c mut BreakableContext> {
|
||||
) -> Option<&mut BreakableContext> {
|
||||
let mut ctxs = ctxs
|
||||
.iter_mut()
|
||||
.rev()
|
||||
@ -584,10 +581,10 @@ fn find_breakable<'c>(
|
||||
}
|
||||
}
|
||||
|
||||
fn find_continuable<'c>(
|
||||
ctxs: &'c mut [BreakableContext],
|
||||
fn find_continuable(
|
||||
ctxs: &mut [BreakableContext],
|
||||
label: Option<LabelId>,
|
||||
) -> Option<&'c mut BreakableContext> {
|
||||
) -> Option<&mut BreakableContext> {
|
||||
match label {
|
||||
Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
|
||||
None => find_breakable(ctxs, label),
|
||||
@ -823,8 +820,8 @@ impl<'a> InferenceContext<'a> {
|
||||
ImplTraitId::ReturnTypeImplTrait(_, idx) => idx,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let bounds = (*rpits)
|
||||
.map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.into_iter()));
|
||||
let bounds =
|
||||
(*rpits).map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.iter()));
|
||||
let var = self.table.new_type_var();
|
||||
let var_subst = Substitution::from1(Interner, var.clone());
|
||||
for bound in bounds {
|
||||
@ -1062,7 +1059,7 @@ impl<'a> InferenceContext<'a> {
|
||||
Some(ResolveValueResult::ValueNs(value, _)) => match value {
|
||||
ValueNs::EnumVariantId(var) => {
|
||||
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));
|
||||
return (ty, Some(var.into()));
|
||||
}
|
||||
@ -1105,7 +1102,7 @@ impl<'a> InferenceContext<'a> {
|
||||
}
|
||||
TypeNs::EnumVariantId(var) => {
|
||||
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));
|
||||
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() {
|
||||
let enum_data = self.db.enum_data(id);
|
||||
let name = current_segment.first().unwrap().name;
|
||||
if let Some(local_id) = enum_data.variant(name) {
|
||||
let variant = EnumVariantId { parent: id, local_id };
|
||||
if let Some(variant) = enum_data.variant(name) {
|
||||
return if remaining_segments.len() == 1 {
|
||||
(ty, Some(variant.into()))
|
||||
} else {
|
||||
@ -1247,8 +1243,7 @@ impl<'a> InferenceContext<'a> {
|
||||
// this could be an enum variant or associated type
|
||||
if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
|
||||
let enum_data = self.db.enum_data(enum_id);
|
||||
if let Some(local_id) = enum_data.variant(segment) {
|
||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
||||
if let Some(variant) = enum_data.variant(segment) {
|
||||
return (ty, Some(variant.into()));
|
||||
}
|
||||
}
|
||||
@ -1458,10 +1453,10 @@ impl Expectation {
|
||||
match self {
|
||||
Expectation::HasType(ety) => {
|
||||
let ety = table.resolve_ty_shallow(ety);
|
||||
if !ety.is_ty_var() {
|
||||
Expectation::HasType(ety)
|
||||
} else {
|
||||
if ety.is_ty_var() {
|
||||
Expectation::None
|
||||
} else {
|
||||
Expectation::HasType(ety)
|
||||
}
|
||||
}
|
||||
Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),
|
||||
|
@ -31,7 +31,6 @@ impl CastCheck {
|
||||
// Note that this type of cast is actually split into a coercion to a
|
||||
// pointer type and a cast:
|
||||
// &[T; N] -> *[T; N] -> *T
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Check other kinds of non-coercion casts and report error if any?
|
||||
|
@ -27,14 +27,14 @@ use crate::{
|
||||
static_lifetime, to_chalk_trait_id,
|
||||
traits::FnTrait,
|
||||
utils::{self, generics, Generics},
|
||||
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig,
|
||||
Interner, Substitution, Ty, TyExt,
|
||||
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnAbi, FnPointer,
|
||||
FnSig, Interner, Substitution, Ty, TyExt,
|
||||
};
|
||||
|
||||
use super::{Expectation, 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(
|
||||
&mut self,
|
||||
closure_expr: ExprId,
|
||||
@ -50,8 +50,8 @@ impl InferenceContext<'_> {
|
||||
// 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);
|
||||
|
||||
// Generators are not Fn* so return early.
|
||||
if matches!(closure_ty.kind(Interner), TyKind::Generator(..)) {
|
||||
// Coroutines are not Fn* so return early.
|
||||
if matches!(closure_ty.kind(Interner), TyKind::Coroutine(..)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -98,7 +98,11 @@ impl InferenceContext<'_> {
|
||||
cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature);
|
||||
return Some(FnPointer {
|
||||
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)),
|
||||
});
|
||||
}
|
||||
@ -138,13 +142,10 @@ impl HirPlace {
|
||||
mut current_capture: CaptureKind,
|
||||
len: usize,
|
||||
) -> CaptureKind {
|
||||
match current_capture {
|
||||
CaptureKind::ByRef(BorrowKind::Mut { .. }) => {
|
||||
if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) {
|
||||
current_capture = CaptureKind::ByRef(BorrowKind::Unique);
|
||||
}
|
||||
if let CaptureKind::ByRef(BorrowKind::Mut { .. }) = current_capture {
|
||||
if self.projections[len..].iter().any(|it| *it == ProjectionElem::Deref) {
|
||||
current_capture = CaptureKind::ByRef(BorrowKind::Unique);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
current_capture
|
||||
}
|
||||
@ -330,12 +331,10 @@ impl InferenceContext<'_> {
|
||||
match &self.body[tgt_expr] {
|
||||
Expr::Path(p) => {
|
||||
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 ResolveValueResult::ValueNs(v, _) = r {
|
||||
if let ValueNs::LocalBinding(b) = v {
|
||||
return Some(HirPlace { local: b, projections: vec![] });
|
||||
}
|
||||
}
|
||||
if let Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(b), _)) =
|
||||
resolver.resolve_path_in_value_ns(self.db.upcast(), p)
|
||||
{
|
||||
return Some(HirPlace { local: b, projections: vec![] });
|
||||
}
|
||||
}
|
||||
Expr::Field { expr, name: _ } => {
|
||||
@ -666,7 +665,7 @@ impl InferenceContext<'_> {
|
||||
| Pat::Or(_) => (),
|
||||
Pat::TupleStruct { .. } | Pat::Record { .. } => {
|
||||
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 {
|
||||
hir_def::AdtId::EnumId(e) => self.db.enum_data(e).variants.len() != 1,
|
||||
_ => false,
|
||||
@ -815,8 +814,7 @@ impl InferenceContext<'_> {
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain((0..cnt).map(|_| ProjectionElem::Deref))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
.collect::<Vec<_>>();
|
||||
match &self.body[pat] {
|
||||
Pat::Missing | Pat::Wild => (),
|
||||
Pat::Tuple { args, ellipsis } => {
|
||||
@ -858,7 +856,7 @@ impl InferenceContext<'_> {
|
||||
};
|
||||
let mut p = place.clone();
|
||||
p.projections.push(ProjectionElem::Field(Either::Left(FieldId {
|
||||
parent: variant.into(),
|
||||
parent: variant,
|
||||
local_id,
|
||||
})));
|
||||
self.consume_with_pat(p, arg);
|
||||
@ -902,7 +900,7 @@ impl InferenceContext<'_> {
|
||||
for (arg, (i, _)) in it {
|
||||
let mut p = place.clone();
|
||||
p.projections.push(ProjectionElem::Field(Either::Left(FieldId {
|
||||
parent: variant.into(),
|
||||
parent: variant,
|
||||
local_id: i,
|
||||
})));
|
||||
self.consume_with_pat(p, *arg);
|
||||
@ -1007,7 +1005,7 @@ impl InferenceContext<'_> {
|
||||
let mut deferred_closures = mem::take(&mut self.deferred_closures);
|
||||
let mut dependents_count: FxHashMap<ClosureId, usize> =
|
||||
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 {
|
||||
*dependents_count.entry(*dep).or_default() += 1;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use crate::{
|
||||
},
|
||||
static_lifetime,
|
||||
utils::ClosureSubst,
|
||||
Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution,
|
||||
Canonical, DomainGoal, FnAbi, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution,
|
||||
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) {
|
||||
TyKind::Function(fn_ty) => TyKind::Function(FnPointer {
|
||||
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(),
|
||||
})
|
||||
.intern(Interner),
|
||||
|
@ -39,9 +39,9 @@ use crate::{
|
||||
static_lifetime, to_chalk_trait_id,
|
||||
traits::FnTrait,
|
||||
utils::{generics, Generics},
|
||||
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnPointer, FnSig, FnSubst,
|
||||
Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt,
|
||||
TyKind,
|
||||
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig,
|
||||
FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder,
|
||||
TyExt, TyKind,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -224,7 +224,11 @@ impl InferenceContext<'_> {
|
||||
|
||||
let sig_ty = TyKind::Function(FnPointer {
|
||||
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::from_iter(Interner, sig_tys.iter().cloned())
|
||||
.shifted_in(Interner),
|
||||
@ -233,7 +237,7 @@ impl InferenceContext<'_> {
|
||||
.intern(Interner);
|
||||
|
||||
let (id, ty, resume_yield_tys) = match closure_kind {
|
||||
ClosureKind::Generator(_) => {
|
||||
ClosureKind::Coroutine(_) => {
|
||||
// FIXME: report error when there are more than 1 parameter.
|
||||
let resume_ty = match sig_tys.first() {
|
||||
// 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 subst = TyBuilder::subst_for_generator(self.db, self.owner)
|
||||
let subst = TyBuilder::subst_for_coroutine(self.db, self.owner)
|
||||
.push(resume_ty.clone())
|
||||
.push(yield_ty.clone())
|
||||
.push(ret_ty.clone())
|
||||
.build();
|
||||
|
||||
let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into();
|
||||
let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner);
|
||||
let coroutine_id = self.db.intern_coroutine((self.owner, tgt_expr)).into();
|
||||
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 => {
|
||||
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
|
||||
@ -276,7 +280,7 @@ impl InferenceContext<'_> {
|
||||
|
||||
// Now go through the argument patterns
|
||||
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
|
||||
@ -435,7 +439,7 @@ impl InferenceContext<'_> {
|
||||
ty
|
||||
}
|
||||
&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 {
|
||||
expr: tgt_expr,
|
||||
is_break: false,
|
||||
@ -503,7 +507,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
resume_ty
|
||||
} else {
|
||||
// FIXME: report error (yield expr in non-generator)
|
||||
// FIXME: report error (yield expr in non-coroutine)
|
||||
self.result.standard_types.unknown.clone()
|
||||
}
|
||||
}
|
||||
@ -942,7 +946,7 @@ impl InferenceContext<'_> {
|
||||
derefed_callee: &Ty,
|
||||
adjustments: &mut Vec<Adjustment>,
|
||||
callee_ty: &Ty,
|
||||
params: &Vec<Ty>,
|
||||
params: &[Ty],
|
||||
tgt_expr: ExprId,
|
||||
) {
|
||||
match fn_x {
|
||||
@ -1081,8 +1085,7 @@ impl InferenceContext<'_> {
|
||||
let inner_exp = expected
|
||||
.to_option(table)
|
||||
.as_ref()
|
||||
.map(|e| e.as_adt())
|
||||
.flatten()
|
||||
.and_then(|e| e.as_adt())
|
||||
.filter(|(e_adt, _)| e_adt == &box_id)
|
||||
.map(|(_, subts)| {
|
||||
let g = subts.at(Interner, 0);
|
||||
@ -1245,7 +1248,7 @@ impl InferenceContext<'_> {
|
||||
.build();
|
||||
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.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()));
|
||||
@ -1320,7 +1323,7 @@ impl InferenceContext<'_> {
|
||||
.unwrap_or_else(|| this.table.new_type_var());
|
||||
|
||||
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()))
|
||||
} else {
|
||||
this.infer_expr_coerce(
|
||||
@ -1541,7 +1544,7 @@ impl InferenceContext<'_> {
|
||||
self.check_method_call(
|
||||
tgt_expr,
|
||||
&[],
|
||||
self.db.value_ty(func.into()),
|
||||
self.db.value_ty(func.into()).unwrap(),
|
||||
substs,
|
||||
ty,
|
||||
expected,
|
||||
@ -1586,7 +1589,7 @@ impl InferenceContext<'_> {
|
||||
item: func.into(),
|
||||
})
|
||||
}
|
||||
(ty, self.db.value_ty(func.into()), substs)
|
||||
(ty, self.db.value_ty(func.into()).unwrap(), substs)
|
||||
}
|
||||
None => {
|
||||
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
|
||||
// type-check the functions. This isn't really the right way to do this.
|
||||
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 expected_iter = expected_inputs
|
||||
.iter()
|
||||
|
@ -93,7 +93,7 @@ impl InferenceContext<'_> {
|
||||
ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(Interner));
|
||||
|
||||
match def {
|
||||
_ if subs.len() == 0 => {}
|
||||
_ if subs.is_empty() => {}
|
||||
Some(def) => {
|
||||
let field_types = self.db.field_types(def);
|
||||
let variant_data = def.variant_data(self.db.upcast());
|
||||
@ -223,13 +223,13 @@ impl InferenceContext<'_> {
|
||||
) -> Ty {
|
||||
let expected = self.resolve_ty_shallow(expected);
|
||||
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 {
|
||||
Some(idx) => (subs.split_at(idx), expectations.len().saturating_sub(subs.len())),
|
||||
None => ((&subs[..], &[][..]), 0),
|
||||
None => ((subs, &[][..]), 0),
|
||||
};
|
||||
let mut expectations_iter = expectations
|
||||
.iter()
|
||||
@ -423,7 +423,7 @@ impl InferenceContext<'_> {
|
||||
self.result.binding_modes.insert(pat, mode);
|
||||
|
||||
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(),
|
||||
};
|
||||
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_binding_ty(binding, bound_ty);
|
||||
return inner_ty;
|
||||
inner_ty
|
||||
}
|
||||
|
||||
fn infer_slice_pat(
|
||||
|
@ -4,7 +4,7 @@ use chalk_ir::cast::Cast;
|
||||
use hir_def::{
|
||||
path::{Path, PathSegment},
|
||||
resolver::{ResolveValueResult, TypeNs, ValueNs},
|
||||
AdtId, AssocItemId, EnumVariantId, GenericDefId, ItemContainerId, Lookup,
|
||||
AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use stdx::never;
|
||||
@ -34,7 +34,7 @@ impl InferenceContext<'_> {
|
||||
|
||||
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);
|
||||
Some(ty)
|
||||
}
|
||||
@ -98,7 +98,7 @@ impl InferenceContext<'_> {
|
||||
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
|
||||
// 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!(
|
||||
parent_substs.is_none() && binders.is_empty(Interner),
|
||||
"non-empty binders for non-generic def",
|
||||
@ -389,14 +389,13 @@ impl InferenceContext<'_> {
|
||||
name: &Name,
|
||||
id: ExprOrPatId,
|
||||
) -> 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() {
|
||||
Some((AdtId::EnumId(e), subst)) => (e, subst),
|
||||
_ => return None,
|
||||
};
|
||||
let enum_data = self.db.enum_data(enum_id);
|
||||
let local_id = enum_data.variant(name)?;
|
||||
let variant = EnumVariantId { parent: enum_id, local_id };
|
||||
let variant = enum_data.variant(name)?;
|
||||
self.write_variant_resolution(id, variant.into());
|
||||
Some((ValueNs::EnumVariantId(variant), subst.clone()))
|
||||
}
|
||||
|
@ -250,9 +250,7 @@ impl<'a> InferenceTable<'a> {
|
||||
// and registering an obligation. But it needs chalk support, so we handle the most basic
|
||||
// case (a non associated const without generic parameters) manually.
|
||||
if subst.len(Interner) == 0 {
|
||||
if let Ok(eval) =
|
||||
self.db.const_eval((*c_id).into(), subst.clone(), None)
|
||||
{
|
||||
if let Ok(eval) = self.db.const_eval(*c_id, subst.clone(), None) {
|
||||
eval
|
||||
} else {
|
||||
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> {
|
||||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
||||
let canonicalized = self.canonicalize(in_env);
|
||||
let solution =
|
||||
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value);
|
||||
solution
|
||||
|
||||
self.db.trait_solve(self.trait_env.krate, self.trait_env.block, canonicalized.value)
|
||||
}
|
||||
|
||||
pub(crate) fn register_obligation(&mut self, goal: Goal) {
|
||||
|
@ -7,7 +7,7 @@ use chalk_ir::{
|
||||
};
|
||||
use hir_def::{
|
||||
attr::Attrs, data::adt::VariantData, visibility::Visibility, AdtId, EnumVariantId, HasModule,
|
||||
Lookup, ModuleId, VariantId,
|
||||
ModuleId, VariantId,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
@ -30,17 +30,15 @@ pub(crate) fn is_enum_variant_uninhabited_from(
|
||||
target_mod: ModuleId,
|
||||
db: &dyn HirDatabase,
|
||||
) -> bool {
|
||||
let enum_data = db.enum_data(variant.parent);
|
||||
let vars_attrs = db.variants_attrs(variant.parent);
|
||||
let is_local = variant.parent.lookup(db.upcast()).container.krate() == target_mod.krate();
|
||||
let is_local = variant.module(db.upcast()).krate() == target_mod.krate();
|
||||
|
||||
let mut uninhabited_from =
|
||||
UninhabitedFrom { target_mod, db, max_depth: 500, recursive_ty: FxHashSet::default() };
|
||||
let inhabitedness = uninhabited_from.visit_variant(
|
||||
variant.into(),
|
||||
&enum_data.variants[variant.local_id].variant_data,
|
||||
&db.enum_variant_data(variant).variant_data,
|
||||
subst,
|
||||
&vars_attrs[variant.local_id],
|
||||
&db.attrs(variant.into()),
|
||||
is_local,
|
||||
);
|
||||
inhabitedness == BREAK_VISIBLY_UNINHABITED
|
||||
@ -117,15 +115,14 @@ impl UninhabitedFrom<'_> {
|
||||
self.visit_variant(s.into(), &struct_data.variant_data, subst, &attrs, is_local)
|
||||
}
|
||||
AdtId::EnumId(e) => {
|
||||
let vars_attrs = self.db.variants_attrs(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(
|
||||
EnumVariantId { parent: e, local_id }.into(),
|
||||
&enum_var.variant_data,
|
||||
variant.into(),
|
||||
&self.db.enum_variant_data(variant).variant_data,
|
||||
subst,
|
||||
&vars_attrs[local_id],
|
||||
&self.db.attrs(variant.into()),
|
||||
is_local,
|
||||
);
|
||||
match variant_inhabitedness {
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
use crate::{
|
||||
chalk_db, tls, AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData,
|
||||
ConstScalar, Constraint, Constraints, FnDefId, GenericArg, GenericArgData, Goal, GoalData,
|
||||
Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause,
|
||||
ConstScalar, Constraint, Constraints, FnAbi, FnDefId, GenericArg, GenericArgData, Goal,
|
||||
GoalData, Goals, InEnvironment, Lifetime, LifetimeData, OpaqueTy, OpaqueTyId, ProgramClause,
|
||||
ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
|
||||
Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds,
|
||||
};
|
||||
@ -71,7 +71,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||
type DefId = InternId;
|
||||
type InternedAdtId = hir_def::AdtId;
|
||||
type Identifier = TypeAliasId;
|
||||
type FnAbi = ();
|
||||
type FnAbi = FnAbi;
|
||||
|
||||
fn debug_adt_id(
|
||||
type_kind_id: chalk_db::AdtId,
|
||||
@ -387,7 +387,7 @@ impl chalk_ir::interner::HasInterner for Interner {
|
||||
macro_rules! has_interner {
|
||||
($t:ty) => {
|
||||
impl HasInterner for $t {
|
||||
type Interner = crate::Interner;
|
||||
type Interner = $crate::Interner;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use hir_def::{
|
||||
Abi, FieldsShape, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions, Scalar, Size,
|
||||
StructKind, TargetDataLayout, WrappingRange,
|
||||
},
|
||||
LocalEnumVariantId, LocalFieldId, StructId,
|
||||
LocalFieldId, StructId,
|
||||
};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use rustc_abi::AddressSpace;
|
||||
@ -32,15 +32,15 @@ mod adt;
|
||||
mod target;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
|
||||
pub struct RustcEnumVariantIdx(pub usize);
|
||||
|
||||
impl rustc_index::Idx for RustcEnumVariantIdx {
|
||||
fn new(idx: usize) -> Self {
|
||||
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
||||
RustcEnumVariantIdx(idx)
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
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 result = match ty.kind(Interner) {
|
||||
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)?
|
||||
}
|
||||
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 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)
|
||||
.ok_or(LayoutError::Unknown)?
|
||||
}
|
||||
TyKind::Generator(_, _) | TyKind::GeneratorWitness(_, _) => {
|
||||
TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
|
||||
return Err(LayoutError::NotImplemented)
|
||||
}
|
||||
TyKind::Error => return Err(LayoutError::HasErrorType),
|
||||
|
@ -6,9 +6,8 @@ use base_db::salsa::Cycle;
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
|
||||
AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
|
||||
AdtId, VariantId,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
use rustc_index::IndexVec;
|
||||
use smallvec::SmallVec;
|
||||
use triomphe::Arc;
|
||||
@ -22,8 +21,8 @@ use crate::{
|
||||
|
||||
use super::LayoutCx;
|
||||
|
||||
pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx {
|
||||
RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0)))
|
||||
pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx {
|
||||
RustcEnumVariantIdx(0)
|
||||
}
|
||||
|
||||
pub fn layout_of_adt_query(
|
||||
@ -62,12 +61,7 @@ pub fn layout_of_adt_query(
|
||||
let r = data
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(idx, v)| {
|
||||
handle_variant(
|
||||
EnumVariantId { parent: e, local_id: idx }.into(),
|
||||
&v.variant_data,
|
||||
)
|
||||
})
|
||||
.map(|&(v, _)| handle_variant(v.into(), &db.enum_variant_data(v).variant_data))
|
||||
.collect::<Result<SmallVec<_>, _>>()?;
|
||||
(r, data.repr.unwrap_or_default())
|
||||
}
|
||||
@ -86,11 +80,10 @@ pub fn layout_of_adt_query(
|
||||
matches!(def, AdtId::EnumId(..)),
|
||||
is_unsafe_cell(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, _)| {
|
||||
let AdtId::EnumId(e) = def else { return None };
|
||||
let d =
|
||||
db.const_eval_discriminant(EnumVariantId { parent: e, local_id: id.0 }).ok()?;
|
||||
let d = db.const_eval_discriminant(db.enum_data(e).variants[id.0].0).ok()?;
|
||||
Some((id, d))
|
||||
}),
|
||||
// FIXME: The current code for niche-filling relies on variant indices
|
||||
|
@ -12,7 +12,7 @@ pub fn target_data_layout_query(
|
||||
) -> Option<Arc<TargetDataLayout>> {
|
||||
let crate_graph = db.crate_graph();
|
||||
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 {
|
||||
// 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
|
||||
|
@ -366,11 +366,11 @@ fn return_position_impl_trait() {
|
||||
}
|
||||
let waker = Arc::new(EmptyWaker).into();
|
||||
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! {
|
||||
struct Foo<T>(T, T, (T, T));
|
||||
|
@ -1,3 +1,6 @@
|
||||
#![allow(clippy::match_single_binding)]
|
||||
#![allow(clippy::no_effect)]
|
||||
|
||||
use crate::size_and_align_expr;
|
||||
|
||||
#[test]
|
||||
@ -36,7 +39,7 @@ fn ref_simple() {
|
||||
let mut y: i32 = 5;
|
||||
]
|
||||
|x: i32| {
|
||||
y = y + x;
|
||||
y += x;
|
||||
y
|
||||
}
|
||||
}
|
||||
@ -66,7 +69,7 @@ fn ref_simple() {
|
||||
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));
|
||||
let _y: X = X(2, 5, (7, 3));
|
||||
move |x: i64| {
|
||||
match _y {
|
||||
_ => x,
|
||||
}
|
||||
x
|
||||
}
|
||||
}
|
||||
size_and_align_expr! {
|
||||
@ -264,8 +265,8 @@ fn regression_15623() {
|
||||
let c = 5;
|
||||
move || {
|
||||
let 0 = a else { return b; };
|
||||
let y = c;
|
||||
y
|
||||
|
||||
c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ impl MemoryMap {
|
||||
let mut transform = |(addr, val): (&usize, &Box<[u8]>)| {
|
||||
let addr = *addr;
|
||||
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 {
|
||||
MemoryMap::Empty => Ok(Default::default()),
|
||||
@ -351,10 +351,157 @@ pub struct CallableSig {
|
||||
params_and_return: Arc<[Ty]>,
|
||||
is_varargs: bool,
|
||||
safety: Safety,
|
||||
abi: FnAbi,
|
||||
}
|
||||
|
||||
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.
|
||||
pub type PolyFnSig = Binders<CallableSig>;
|
||||
|
||||
@ -364,11 +511,17 @@ impl CallableSig {
|
||||
ret: Ty,
|
||||
is_varargs: bool,
|
||||
safety: Safety,
|
||||
abi: FnAbi,
|
||||
) -> CallableSig {
|
||||
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 {
|
||||
CallableSig {
|
||||
// FIXME: what to do about lifetime params? -> return PolyFnSig
|
||||
@ -385,13 +538,14 @@ impl CallableSig {
|
||||
),
|
||||
is_varargs: fn_ptr.sig.variadic,
|
||||
safety: fn_ptr.sig.safety,
|
||||
abi: fn_ptr.sig.abi,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_fn_ptr(&self) -> FnPointer {
|
||||
FnPointer {
|
||||
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(
|
||||
Interner,
|
||||
self.params_and_return.iter().cloned(),
|
||||
@ -420,6 +574,7 @@ impl TypeFoldable<Interner> for CallableSig {
|
||||
params_and_return: folded.into(),
|
||||
is_varargs: self.is_varargs,
|
||||
safety: self.safety,
|
||||
abi: self.abi,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -704,7 +859,7 @@ pub fn callable_sig_from_fnonce(
|
||||
let params =
|
||||
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> {
|
||||
|
@ -58,7 +58,7 @@ use crate::{
|
||||
InTypeConstIdMetadata,
|
||||
},
|
||||
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,
|
||||
Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
|
||||
};
|
||||
@ -279,14 +279,14 @@ impl<'a> TyLoweringContext<'a> {
|
||||
.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| {
|
||||
Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
|
||||
});
|
||||
TyKind::Function(FnPointer {
|
||||
num_binders: 0, // FIXME lower `for<'a> fn()` correctly
|
||||
sig: FnSig {
|
||||
abi: (),
|
||||
abi: abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
|
||||
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
|
||||
variadic,
|
||||
},
|
||||
@ -762,7 +762,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||
Some(segment) if segment.args_and_bindings.is_some() => Some(segment),
|
||||
_ => last,
|
||||
};
|
||||
(segment, Some(var.parent.into()))
|
||||
(segment, Some(var.lookup(self.db.upcast()).parent.into()))
|
||||
}
|
||||
};
|
||||
if let Some(segment) = segment {
|
||||
@ -1192,11 +1192,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||
return None;
|
||||
}
|
||||
|
||||
if bounds.first().and_then(|b| b.trait_id()).is_none() {
|
||||
// When there's no trait bound, that's an error. This happens when the trait refs
|
||||
// are unresolved.
|
||||
return None;
|
||||
}
|
||||
bounds.first().and_then(|b| b.trait_id())?;
|
||||
|
||||
// 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.
|
||||
@ -1241,7 +1237,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||
});
|
||||
crate::wrap_empty_binders(clause)
|
||||
});
|
||||
predicates.extend(sized_clause.into_iter());
|
||||
predicates.extend(sized_clause);
|
||||
predicates.shrink_to_fit();
|
||||
}
|
||||
predicates
|
||||
@ -1339,7 +1335,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
||||
),
|
||||
_ => None,
|
||||
});
|
||||
if let Some(_) = res {
|
||||
if res.is_some() {
|
||||
return res;
|
||||
}
|
||||
// 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 {
|
||||
VariantId::StructId(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 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);
|
||||
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)));
|
||||
@ -1677,6 +1675,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
|
||||
ret,
|
||||
data.is_varargs(),
|
||||
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)
|
||||
}
|
||||
@ -1721,50 +1720,65 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
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();
|
||||
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.
|
||||
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);
|
||||
if let StructKind::Unit = struct_data.variant_data.kind() {
|
||||
return type_for_adt(db, def.into());
|
||||
match struct_data.variant_data.kind() {
|
||||
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 {
|
||||
let enum_data = db.enum_data(def.parent);
|
||||
let var_data = &enum_data.variants[def.local_id];
|
||||
let var_data = db.enum_variant_data(def);
|
||||
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())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
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();
|
||||
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
|
||||
let (ret, binders) =
|
||||
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.
|
||||
fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> Binders<Ty> {
|
||||
let enum_data = db.enum_data(def.parent);
|
||||
let var_data = &enum_data.variants[def.local_id].variant_data;
|
||||
if let StructKind::Unit = var_data.kind() {
|
||||
return type_for_adt(db, def.parent.into());
|
||||
fn type_for_enum_variant_constructor(
|
||||
db: &dyn HirDatabase,
|
||||
def: EnumVariantId,
|
||||
) -> Option<Binders<Ty>> {
|
||||
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> {
|
||||
@ -1812,7 +1826,7 @@ impl CallableDefId {
|
||||
match self {
|
||||
CallableDefId::FunctionId(f) => f.lookup(db).module(db),
|
||||
CallableDefId::StructId(s) => s.lookup(db).container,
|
||||
CallableDefId::EnumVariantId(e) => e.parent.lookup(db).container,
|
||||
CallableDefId::EnumVariantId(e) => e.module(db),
|
||||
}
|
||||
.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))
|
||||
}
|
||||
|
||||
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 {
|
||||
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::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::ConstId(it) => type_for_const(db, it),
|
||||
ValueTyDefId::StaticId(it) => type_for_static(db, it),
|
||||
ValueTyDefId::ConstId(it) => Some(type_for_const(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> {
|
||||
let impl_loc = impl_id.lookup(db.upcast());
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
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 ctx = TyLoweringContext::new(db, &resolver, impl_id.into())
|
||||
.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>> {
|
||||
let impl_loc = impl_id.lookup(db.upcast());
|
||||
let impl_data = db.impl_data(impl_id);
|
||||
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())
|
||||
.with_type_param_mode(ParamLoweringMode::Variable);
|
||||
let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
|
||||
|
@ -103,15 +103,15 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<chalk_ir::GeneratorId<Interner>> for crate::db::InternedGeneratorId {
|
||||
fn from(id: chalk_ir::GeneratorId<Interner>) -> Self {
|
||||
impl From<chalk_ir::CoroutineId<Interner>> for crate::db::InternedCoroutineId {
|
||||
fn from(id: chalk_ir::CoroutineId<Interner>) -> Self {
|
||||
Self::from_intern_id(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::db::InternedGeneratorId> for chalk_ir::GeneratorId<Interner> {
|
||||
fn from(id: crate::db::InternedGeneratorId) -> Self {
|
||||
chalk_ir::GeneratorId(id.as_intern_id())
|
||||
impl From<crate::db::InternedCoroutineId> for chalk_ir::CoroutineId<Interner> {
|
||||
fn from(id: crate::db::InternedCoroutineId) -> Self {
|
||||
chalk_ir::CoroutineId(id.as_intern_id())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ impl TyFingerprint {
|
||||
TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
|
||||
TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
|
||||
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 {
|
||||
Some(ty) => return TyFingerprint::for_trait_impl(ty),
|
||||
None => TyFingerprint::Unit,
|
||||
@ -96,8 +96,8 @@ impl TyFingerprint {
|
||||
| TyKind::OpaqueType(_, _)
|
||||
| TyKind::FnDef(_, _)
|
||||
| TyKind::Closure(_, _)
|
||||
| TyKind::Generator(..)
|
||||
| TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
|
||||
| TyKind::Coroutine(..)
|
||||
| TyKind::CoroutineWitness(..) => TyFingerprint::Unnameable,
|
||||
TyKind::Function(fn_ptr) => {
|
||||
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::Array(inner, _) = inner.kind(Interner) {
|
||||
break 'it TyKind::Ref(
|
||||
m.clone(),
|
||||
*m,
|
||||
l.clone(),
|
||||
TyKind::Slice(inner.clone()).intern(Interner),
|
||||
)
|
||||
@ -953,7 +953,7 @@ pub fn iterate_method_candidates_dyn(
|
||||
let ty = table.instantiate_canonical(ty.clone());
|
||||
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(
|
||||
&receiver_ty,
|
||||
adj,
|
||||
@ -964,8 +964,7 @@ pub fn iterate_method_candidates_dyn(
|
||||
name,
|
||||
callback,
|
||||
)
|
||||
});
|
||||
result
|
||||
})
|
||||
}
|
||||
LookupMode::Path => {
|
||||
// No autoderef for path lookups
|
||||
|
@ -159,7 +159,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||
}
|
||||
_ => {
|
||||
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) {
|
||||
@ -168,7 +168,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||
}
|
||||
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) {
|
||||
@ -183,14 +183,14 @@ impl<V, T> ProjectionElem<V, T> {
|
||||
}),
|
||||
_ => {
|
||||
never!("Only tuple has tuple field");
|
||||
return TyKind::Error.intern(Interner);
|
||||
TyKind::Error.intern(Interner)
|
||||
}
|
||||
},
|
||||
ProjectionElem::ClosureField(f) => match &base.kind(Interner) {
|
||||
TyKind::Closure(id, subst) => closure_field(*id, subst, *f),
|
||||
_ => {
|
||||
never!("Only closure has closure field");
|
||||
return TyKind::Error.intern(Interner);
|
||||
TyKind::Error.intern(Interner)
|
||||
}
|
||||
},
|
||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => {
|
||||
@ -198,7 +198,7 @@ impl<V, T> ProjectionElem<V, T> {
|
||||
TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
|
||||
_ => {
|
||||
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(),
|
||||
_ => {
|
||||
never!("Subslice projection should only happen on slice and array");
|
||||
return TyKind::Error.intern(Interner);
|
||||
TyKind::Error.intern(Interner)
|
||||
}
|
||||
},
|
||||
ProjectionElem::OpaqueCast(_) => {
|
||||
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 {
|
||||
fn is_parent(&self, child: &Place, store: &ProjectionStore) -> bool {
|
||||
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
|
||||
@ -333,7 +333,7 @@ pub enum AggregateKind {
|
||||
Adt(VariantId, Substitution),
|
||||
Union(UnionId, FieldId),
|
||||
Closure(Ty),
|
||||
//Generator(LocalDefId, SubstsRef, Movability),
|
||||
//Coroutine(LocalDefId, SubstsRef, Movability),
|
||||
}
|
||||
|
||||
#[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
|
||||
/// aliasing model.
|
||||
///
|
||||
/// If the body is a generator body, this has slightly different semantics; it instead causes a
|
||||
/// `GeneratorState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
|
||||
/// If the body is a coroutine body, this has slightly different semantics; it instead causes a
|
||||
/// `CoroutineState::Returned(_0)` to be created (as if by an `Aggregate` rvalue) and assigned
|
||||
/// to the return place.
|
||||
Return,
|
||||
|
||||
@ -566,14 +566,14 @@ pub enum TerminatorKind {
|
||||
|
||||
/// Marks a suspend point.
|
||||
///
|
||||
/// Like `Return` terminators in generator bodies, this computes `value` and then a
|
||||
/// `GeneratorState::Yielded(value)` as if by `Aggregate` rvalue. That value is then assigned to
|
||||
/// Like `Return` terminators in coroutine bodies, this computes `value` and then a
|
||||
/// `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
|
||||
/// 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`
|
||||
/// 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`?
|
||||
Yield {
|
||||
@ -583,21 +583,21 @@ pub enum TerminatorKind {
|
||||
resume: BasicBlockId,
|
||||
/// The place to store the resume argument in.
|
||||
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>,
|
||||
},
|
||||
|
||||
/// 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`.
|
||||
///
|
||||
/// **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.
|
||||
///
|
||||
/// **Needs clarification**: Are there type system constraints on these terminators? Should
|
||||
/// 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
|
||||
/// conservative.
|
||||
@ -989,8 +989,8 @@ pub enum Rvalue {
|
||||
/// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
|
||||
/// has a destructor.
|
||||
///
|
||||
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
|
||||
/// generator lowering, `Generator` aggregate kinds are disallowed too.
|
||||
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Coroutine`. After
|
||||
/// coroutine lowering, `Coroutine` aggregate kinds are disallowed too.
|
||||
Aggregate(AggregateKind, Box<[Operand]>),
|
||||
|
||||
/// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
|
||||
@ -1140,7 +1140,7 @@ impl MirBody {
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::UnwindResume
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::CoroutineDrop
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable => (),
|
||||
|
@ -53,7 +53,7 @@ fn all_mir_bodies(
|
||||
match db.mir_body_for_closure(c) {
|
||||
Ok(body) => {
|
||||
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),
|
||||
}
|
||||
@ -61,7 +61,7 @@ fn all_mir_bodies(
|
||||
match db.mir_body(def) {
|
||||
Ok(body) => {
|
||||
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),
|
||||
}
|
||||
@ -159,7 +159,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::UnwindResume
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::CoroutineDrop
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
@ -257,7 +257,7 @@ fn ever_initialized_map(
|
||||
for statement in &block.statements {
|
||||
match &statement.kind {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -295,30 +295,23 @@ fn ever_initialized_map(
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable => (),
|
||||
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
|
||||
{
|
||||
is_ever_initialized = true;
|
||||
}
|
||||
target
|
||||
.into_iter()
|
||||
.chain(cleanup.into_iter())
|
||||
.for_each(|&it| process(it, is_ever_initialized));
|
||||
target.iter().chain(cleanup).for_each(|&it| process(it, is_ever_initialized));
|
||||
}
|
||||
TerminatorKind::Drop { target, unwind, place: _ } => {
|
||||
iter::once(target)
|
||||
.into_iter()
|
||||
.chain(unwind.into_iter())
|
||||
.for_each(|&it| process(it, is_ever_initialized));
|
||||
iter::once(target).chain(unwind).for_each(|&it| process(it, is_ever_initialized));
|
||||
}
|
||||
TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::CoroutineDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::FalseUnwind { .. } => {
|
||||
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>) {
|
||||
match &mut result[local] {
|
||||
it @ MutabilityReason::Unused => {
|
||||
*it = MutabilityReason::Not;
|
||||
}
|
||||
_ => (),
|
||||
if let it @ MutabilityReason::Unused = &mut result[local] {
|
||||
*it = MutabilityReason::Not;
|
||||
};
|
||||
}
|
||||
|
||||
@ -439,7 +429,7 @@ fn mutability_of_locals(
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::CoroutineDrop
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
@ -452,7 +442,7 @@ fn mutability_of_locals(
|
||||
for arg in args.iter() {
|
||||
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() {
|
||||
push_mut_span(destination.local, MirSpan::Unknown, &mut result);
|
||||
} else {
|
||||
|
@ -272,6 +272,7 @@ const STACK_OFFSET: usize = 1 << 30;
|
||||
const HEAP_OFFSET: usize = 1 << 29;
|
||||
|
||||
impl Address {
|
||||
#[allow(clippy::double_parens)]
|
||||
fn from_bytes(it: &[u8]) -> Result<Self> {
|
||||
Ok(Address::from_usize(from_bytes!(usize, it)))
|
||||
}
|
||||
@ -291,12 +292,11 @@ impl Address {
|
||||
}
|
||||
|
||||
fn to_usize(&self) -> usize {
|
||||
let as_num = match self {
|
||||
match self {
|
||||
Stack(it) => *it + STACK_OFFSET,
|
||||
Heap(it) => *it + HEAP_OFFSET,
|
||||
Invalid(it) => *it,
|
||||
};
|
||||
as_num
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
// 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);
|
||||
return true;
|
||||
}
|
||||
@ -551,7 +550,7 @@ pub fn interpret_mir(
|
||||
memory_map.vtable.shrink_to_fit();
|
||||
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 })
|
||||
}
|
||||
@ -562,12 +561,12 @@ const EXECUTION_LIMIT: usize = 100_000;
|
||||
const EXECUTION_LIMIT: usize = 10_000_000;
|
||||
|
||||
impl Evaluator<'_> {
|
||||
pub fn new<'a>(
|
||||
db: &'a dyn HirDatabase,
|
||||
pub fn new(
|
||||
db: &dyn HirDatabase,
|
||||
owner: DefWithBodyId,
|
||||
assert_placeholder_ty_is_unused: bool,
|
||||
trait_env: Option<Arc<TraitEnvironment>>,
|
||||
) -> Evaluator<'a> {
|
||||
) -> Evaluator<'_> {
|
||||
let crate_id = owner.module(db.upcast()).krate();
|
||||
Evaluator {
|
||||
stack: vec![0],
|
||||
@ -585,7 +584,7 @@ impl Evaluator<'_> {
|
||||
assert_placeholder_ty_is_unused,
|
||||
stack_depth_limit: 100,
|
||||
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()),
|
||||
projected_ty_cache: RefCell::new(Default::default()),
|
||||
not_special_fn_cache: RefCell::new(Default::default()),
|
||||
@ -752,7 +751,7 @@ impl Evaluator<'_> {
|
||||
Variants::Multiple { variants, .. } => {
|
||||
&variants[match f.parent {
|
||||
hir_def::VariantId::EnumVariantId(it) => {
|
||||
RustcEnumVariantIdx(it.local_id)
|
||||
RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize)
|
||||
}
|
||||
_ => {
|
||||
return Err(MirEvalError::TypeError(
|
||||
@ -816,8 +815,8 @@ impl Evaluator<'_> {
|
||||
})
|
||||
}
|
||||
|
||||
fn interpret_mir<'slf>(
|
||||
&'slf mut self,
|
||||
fn interpret_mir(
|
||||
&mut self,
|
||||
body: Arc<MirBody>,
|
||||
args: impl Iterator<Item = IntervalOrOwned>,
|
||||
) -> Result<Interval> {
|
||||
@ -837,7 +836,7 @@ impl Evaluator<'_> {
|
||||
not_supported!("missing stack frame");
|
||||
};
|
||||
let e = (|| {
|
||||
let mut locals = &mut my_stack_frame.locals;
|
||||
let locals = &mut my_stack_frame.locals;
|
||||
let body = locals.body.clone();
|
||||
loop {
|
||||
let current_block = &body.basic_blocks[current_block_idx];
|
||||
@ -849,12 +848,10 @@ impl Evaluator<'_> {
|
||||
for statement in ¤t_block.statements {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(l, r) => {
|
||||
let addr = self.place_addr(l, &locals)?;
|
||||
let result = self.eval_rvalue(r, &mut locals)?;
|
||||
let addr = self.place_addr(l, locals)?;
|
||||
let result = self.eval_rvalue(r, locals)?;
|
||||
self.copy_from_interval_or_owned(addr, result)?;
|
||||
locals
|
||||
.drop_flags
|
||||
.add_place(l.clone(), &locals.body.projection_store);
|
||||
locals.drop_flags.add_place(*l, &locals.body.projection_store);
|
||||
}
|
||||
StatementKind::Deinit(_) => not_supported!("de-init statement"),
|
||||
StatementKind::StorageLive(_)
|
||||
@ -878,20 +875,20 @@ impl Evaluator<'_> {
|
||||
cleanup: _,
|
||||
from_hir_call: _,
|
||||
} => {
|
||||
let destination_interval = self.place_interval(destination, &locals)?;
|
||||
let fn_ty = self.operand_ty(func, &locals)?;
|
||||
let destination_interval = self.place_interval(destination, locals)?;
|
||||
let fn_ty = self.operand_ty(func, locals)?;
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|it| self.operand_ty_and_eval(it, &mut locals))
|
||||
.map(|it| self.operand_ty_and_eval(it, locals))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let stack_frame = match &fn_ty.kind(Interner) {
|
||||
TyKind::Function(_) => {
|
||||
let bytes = self.eval_operand(func, &mut locals)?;
|
||||
let bytes = self.eval_operand(func, locals)?;
|
||||
self.exec_fn_pointer(
|
||||
bytes,
|
||||
destination_interval,
|
||||
&args,
|
||||
&locals,
|
||||
locals,
|
||||
*target,
|
||||
terminator.span,
|
||||
)?
|
||||
@ -901,7 +898,7 @@ impl Evaluator<'_> {
|
||||
generic_args,
|
||||
destination_interval,
|
||||
&args,
|
||||
&locals,
|
||||
locals,
|
||||
*target,
|
||||
terminator.span,
|
||||
)?,
|
||||
@ -909,7 +906,7 @@ impl Evaluator<'_> {
|
||||
};
|
||||
locals
|
||||
.drop_flags
|
||||
.add_place(destination.clone(), &locals.body.projection_store);
|
||||
.add_place(*destination, &locals.body.projection_store);
|
||||
if let Some(stack_frame) = stack_frame {
|
||||
self.code_stack.push(my_stack_frame);
|
||||
current_block_idx = stack_frame.locals.body.start_block;
|
||||
@ -924,7 +921,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
TerminatorKind::SwitchInt { discr, targets } => {
|
||||
let val = u128::from_le_bytes(pad16(
|
||||
self.eval_operand(discr, &mut locals)?.get(&self)?,
|
||||
self.eval_operand(discr, locals)?.get(self)?,
|
||||
false,
|
||||
));
|
||||
current_block_idx = targets.target_for_value(val);
|
||||
@ -938,7 +935,7 @@ impl Evaluator<'_> {
|
||||
));
|
||||
}
|
||||
TerminatorKind::Drop { place, target, unwind: _ } => {
|
||||
self.drop_place(place, &mut locals, terminator.span)?;
|
||||
self.drop_place(place, locals, terminator.span)?;
|
||||
current_block_idx = *target;
|
||||
}
|
||||
_ => not_supported!("unknown terminator"),
|
||||
@ -1081,7 +1078,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
}
|
||||
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)?;
|
||||
while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
|
||||
ty = z.clone();
|
||||
@ -1124,8 +1121,8 @@ impl Evaluator<'_> {
|
||||
Rvalue::CheckedBinaryOp(op, lhs, rhs) => 'binary_op: {
|
||||
let lc = self.eval_operand(lhs, locals)?;
|
||||
let rc = self.eval_operand(rhs, locals)?;
|
||||
let mut lc = lc.get(&self)?;
|
||||
let mut rc = rc.get(&self)?;
|
||||
let mut lc = lc.get(self)?;
|
||||
let mut rc = rc.get(self)?;
|
||||
let mut ty = self.operand_ty(lhs, locals)?;
|
||||
while let TyKind::Ref(_, _, z) = ty.kind(Interner) {
|
||||
ty = z.clone();
|
||||
@ -1277,12 +1274,12 @@ impl Evaluator<'_> {
|
||||
}
|
||||
Rvalue::Discriminant(p) => {
|
||||
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)?;
|
||||
Owned(result.to_le_bytes().to_vec())
|
||||
}
|
||||
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,
|
||||
None => not_supported!("non evaluatable array len in repeat Rvalue"),
|
||||
};
|
||||
@ -1308,13 +1305,13 @@ impl Evaluator<'_> {
|
||||
AggregateKind::Array(_) => {
|
||||
let mut r = vec![];
|
||||
for it in values {
|
||||
let value = it.get(&self)?;
|
||||
let value = it.get(self)?;
|
||||
r.extend(value);
|
||||
}
|
||||
Owned(r)
|
||||
}
|
||||
AggregateKind::Tuple(ty) => {
|
||||
let layout = self.layout(&ty)?;
|
||||
let layout = self.layout(ty)?;
|
||||
Owned(self.make_by_layout(
|
||||
layout.size.bytes_usize(),
|
||||
&layout,
|
||||
@ -1329,7 +1326,7 @@ impl Evaluator<'_> {
|
||||
.fields
|
||||
.offset(u32::from(f.local_id.into_raw()) as usize)
|
||||
.bytes_usize();
|
||||
let op = values[0].get(&self)?;
|
||||
let op = values[0].get(self)?;
|
||||
let mut result = vec![0; layout.size.bytes_usize()];
|
||||
result[offset..offset + op.len()].copy_from_slice(op);
|
||||
Owned(result)
|
||||
@ -1345,7 +1342,7 @@ impl Evaluator<'_> {
|
||||
)?)
|
||||
}
|
||||
AggregateKind::Closure(ty) => {
|
||||
let layout = self.layout(&ty)?;
|
||||
let layout = self.layout(ty)?;
|
||||
Owned(self.make_by_layout(
|
||||
layout.size.bytes_usize(),
|
||||
&layout,
|
||||
@ -1390,14 +1387,11 @@ impl Evaluator<'_> {
|
||||
| CastKind::PointerExposeAddress
|
||||
| CastKind::PointerFromExposedAddress => {
|
||||
let current_ty = self.operand_ty(operand, locals)?;
|
||||
let is_signed = match current_ty.kind(Interner) {
|
||||
TyKind::Scalar(s) => match s {
|
||||
chalk_ir::Scalar::Int(_) => true,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
let current = pad16(self.eval_operand(operand, locals)?.get(&self)?, is_signed);
|
||||
let is_signed = matches!(
|
||||
current_ty.kind(Interner),
|
||||
TyKind::Scalar(chalk_ir::Scalar::Int(_))
|
||||
);
|
||||
let current = pad16(self.eval_operand(operand, locals)?.get(self)?, is_signed);
|
||||
let dest_size =
|
||||
self.size_of_sized(target_ty, locals, "destination of int to int cast")?;
|
||||
Owned(current[0..dest_size].to_vec())
|
||||
@ -1412,22 +1406,12 @@ impl Evaluator<'_> {
|
||||
|
||||
fn compute_discriminant(&self, ty: Ty, bytes: &[u8]) -> Result<i128> {
|
||||
let layout = self.layout(&ty)?;
|
||||
let enum_id = 'b: {
|
||||
match ty.kind(Interner) {
|
||||
TyKind::Adt(e, _) => match e.0 {
|
||||
AdtId::EnumId(e) => break 'b e,
|
||||
_ => (),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
let &TyKind::Adt(chalk_ir::AdtId(AdtId::EnumId(e)), _) = ty.kind(Interner) else {
|
||||
return Ok(0);
|
||||
};
|
||||
match &layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let r = self.const_eval_discriminant(EnumVariantId {
|
||||
parent: enum_id,
|
||||
local_id: index.0,
|
||||
})?;
|
||||
let r = self.const_eval_discriminant(self.db.enum_data(e).variants[index.0].0)?;
|
||||
Ok(r)
|
||||
}
|
||||
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||
@ -1446,17 +1430,15 @@ impl Evaluator<'_> {
|
||||
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
|
||||
.wrapping_sub(*niche_start as i128)
|
||||
as usize;
|
||||
let variant = variants
|
||||
let idx = variants
|
||||
.iter_enumerated()
|
||||
.map(|(it, _)| it)
|
||||
.filter(|it| it != untagged_variant)
|
||||
.nth(candidate_tag)
|
||||
.unwrap_or(*untagged_variant)
|
||||
.0;
|
||||
let result = self.const_eval_discriminant(EnumVariantId {
|
||||
parent: enum_id,
|
||||
local_id: variant,
|
||||
})?;
|
||||
let result =
|
||||
self.const_eval_discriminant(self.db.enum_data(e).variants[idx].0)?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
@ -1525,7 +1507,7 @@ impl Evaluator<'_> {
|
||||
let mut r = Vec::with_capacity(16);
|
||||
let addr = addr.get(self)?;
|
||||
r.extend(addr.iter().copied());
|
||||
r.extend(len.to_le_bytes().into_iter());
|
||||
r.extend(len.to_le_bytes());
|
||||
Owned(r)
|
||||
}
|
||||
t => {
|
||||
@ -1537,7 +1519,7 @@ impl Evaluator<'_> {
|
||||
let mut r = Vec::with_capacity(16);
|
||||
let addr = addr.get(self)?;
|
||||
r.extend(addr.iter().copied());
|
||||
r.extend(vtable.to_le_bytes().into_iter());
|
||||
r.extend(vtable.to_le_bytes());
|
||||
Owned(r)
|
||||
}
|
||||
TyKind::Adt(id, target_subst) => match ¤t_ty.kind(Interner) {
|
||||
@ -1551,7 +1533,7 @@ impl Evaluator<'_> {
|
||||
AdtId::EnumId(_) => not_supported!("unsizing enums"),
|
||||
};
|
||||
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 {
|
||||
not_supported!("unsizing struct without field");
|
||||
};
|
||||
@ -1579,14 +1561,16 @@ impl Evaluator<'_> {
|
||||
subst: Substitution,
|
||||
locals: &Locals,
|
||||
) -> 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 VariantId::EnumVariantId(it) = it {
|
||||
if AdtId::from(f.parent) == adt {
|
||||
// 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 layout
|
||||
let i = self.const_eval_discriminant(it)?;
|
||||
return Ok((16, self.layout(&TyBuilder::unit())?, Some((0, 16, i))));
|
||||
if let AdtId::EnumId(e) = 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
|
||||
// infinite sized type errors) we use a dummy layout
|
||||
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,
|
||||
_ => 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 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 have_tag = match tag_encoding {
|
||||
TagEncoding::Direct => true,
|
||||
@ -1654,7 +1639,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
for (i, op) in values.enumerate() {
|
||||
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()) {
|
||||
Some(it) => it.copy_from_slice(op),
|
||||
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> {
|
||||
let ty = &konst.data(Interner).ty;
|
||||
let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else {
|
||||
@ -1695,7 +1681,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
result_owner = self
|
||||
.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| {
|
||||
let name = const_id.name(self.db.upcast());
|
||||
MirEvalError::ConstEvalError(name, Box::new(e))
|
||||
@ -1778,9 +1764,8 @@ impl Evaluator<'_> {
|
||||
)));
|
||||
}
|
||||
};
|
||||
Ok(mem.get_mut(pos..pos + size).ok_or_else(|| {
|
||||
MirEvalError::UndefinedBehavior("out of bound memory write".to_string())
|
||||
})?)
|
||||
mem.get_mut(pos..pos + size)
|
||||
.ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory write".to_string()))
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner {
|
||||
if let Some((adt, _)) = ty.as_adt() {
|
||||
if AdtId::from(f.parent) == adt {
|
||||
if let Some((AdtId::EnumId(e), _)) = ty.as_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
|
||||
// infinite sized type errors) we use a dummy size
|
||||
return Ok(Some((16, 16)));
|
||||
@ -1856,10 +1841,10 @@ impl Evaluator<'_> {
|
||||
}
|
||||
}
|
||||
let layout = self.layout(ty);
|
||||
if self.assert_placeholder_ty_is_unused {
|
||||
if matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _))) {
|
||||
return Ok(Some((0, 1)));
|
||||
}
|
||||
if self.assert_placeholder_ty_is_unused
|
||||
&& matches!(layout, Err(MirEvalError::LayoutError(LayoutError::HasPlaceholder, _)))
|
||||
{
|
||||
return Ok(Some((0, 1)));
|
||||
}
|
||||
let layout = layout?;
|
||||
Ok(layout
|
||||
@ -1969,14 +1954,14 @@ impl Evaluator<'_> {
|
||||
if let Some(ty) = check_inner {
|
||||
for i in 0..count {
|
||||
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) => {
|
||||
let len = match try_const_usize(this.db, &len) {
|
||||
let len = match try_const_usize(this.db, len) {
|
||||
Some(it) => it as usize,
|
||||
None => not_supported!("non evaluatable array len in patching addresses"),
|
||||
};
|
||||
@ -2019,10 +2004,8 @@ impl Evaluator<'_> {
|
||||
bytes,
|
||||
e,
|
||||
) {
|
||||
let data = &this.db.enum_data(e).variants[v].variant_data;
|
||||
let field_types = this
|
||||
.db
|
||||
.field_types(EnumVariantId { parent: e, local_id: v }.into());
|
||||
let data = &this.db.enum_variant_data(v).variant_data;
|
||||
let field_types = this.db.field_types(v.into());
|
||||
for (f, _) in data.fields().iter() {
|
||||
let offset =
|
||||
l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
|
||||
@ -2039,7 +2022,7 @@ impl Evaluator<'_> {
|
||||
Ok(())
|
||||
}
|
||||
let mut mm = ComplexMemoryMap::default();
|
||||
rec(&self, bytes, ty, locals, &mut mm)?;
|
||||
rec(self, bytes, ty, locals, &mut mm)?;
|
||||
Ok(mm)
|
||||
}
|
||||
|
||||
@ -2093,14 +2076,13 @@ impl Evaluator<'_> {
|
||||
}
|
||||
AdtId::UnionId(_) => (),
|
||||
AdtId::EnumId(e) => {
|
||||
if let Some((variant, layout)) = detect_variant_from_bytes(
|
||||
if let Some((ev, layout)) = detect_variant_from_bytes(
|
||||
&layout,
|
||||
self.db,
|
||||
self.trait_env.clone(),
|
||||
self.read_memory(addr, layout.size.bytes_usize())?,
|
||||
e,
|
||||
) {
|
||||
let ev = EnumVariantId { parent: e, local_id: variant };
|
||||
for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
|
||||
let offset = layout.fields.offset(i).bytes_usize();
|
||||
let ty = ty.clone().substitute(Interner, subst);
|
||||
@ -2123,7 +2105,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
}
|
||||
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,
|
||||
None => not_supported!("non evaluatable array len in patching addresses"),
|
||||
};
|
||||
@ -2147,8 +2129,8 @@ impl Evaluator<'_> {
|
||||
| TyKind::Str
|
||||
| TyKind::Never
|
||||
| TyKind::Closure(_, _)
|
||||
| TyKind::Generator(_, _)
|
||||
| TyKind::GeneratorWitness(_, _)
|
||||
| TyKind::Coroutine(_, _)
|
||||
| TyKind::CoroutineWitness(_, _)
|
||||
| TyKind::Foreign(_)
|
||||
| TyKind::Error
|
||||
| TyKind::Placeholder(_)
|
||||
@ -2173,7 +2155,7 @@ impl Evaluator<'_> {
|
||||
let next_ty = self.vtable_map.ty(id)?.clone();
|
||||
match &next_ty.kind(Interner) {
|
||||
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) => {
|
||||
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()
|
||||
};
|
||||
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<_>>>()?;
|
||||
let interval = self
|
||||
.interpret_mir(mir_body, arg_bytes.into_iter().map(IntervalOrOwned::Owned))
|
||||
@ -2235,7 +2217,7 @@ impl Evaluator<'_> {
|
||||
let generic_args = generic_args.clone();
|
||||
match 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(
|
||||
def,
|
||||
args,
|
||||
@ -2258,7 +2240,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
CallableDefId::StructId(id) => {
|
||||
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(
|
||||
size,
|
||||
&variant_layout,
|
||||
@ -2270,7 +2252,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
CallableDefId::EnumVariantId(id) => {
|
||||
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(
|
||||
size,
|
||||
&variant_layout,
|
||||
@ -2365,7 +2347,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
}),
|
||||
);
|
||||
return self.exec_fn_with_args(
|
||||
self.exec_fn_with_args(
|
||||
def,
|
||||
&args_for_target,
|
||||
generics_for_target,
|
||||
@ -2373,7 +2355,7 @@ impl Evaluator<'_> {
|
||||
destination,
|
||||
target_bb,
|
||||
span,
|
||||
);
|
||||
)
|
||||
}
|
||||
MirOrDynIndex::Mir(body) => self.exec_looked_up_function(
|
||||
body,
|
||||
@ -2425,7 +2407,7 @@ impl Evaluator<'_> {
|
||||
target_bb: Option<BasicBlockId>,
|
||||
span: MirSpan,
|
||||
) -> 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_data = func.interval;
|
||||
while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) {
|
||||
@ -2441,25 +2423,10 @@ impl Evaluator<'_> {
|
||||
}
|
||||
match &func_ty.kind(Interner) {
|
||||
TyKind::FnDef(def, subst) => {
|
||||
return self.exec_fn_def(
|
||||
*def,
|
||||
subst,
|
||||
destination,
|
||||
&args[1..],
|
||||
locals,
|
||||
target_bb,
|
||||
span,
|
||||
);
|
||||
self.exec_fn_def(*def, subst, destination, &args[1..], locals, target_bb, span)
|
||||
}
|
||||
TyKind::Function(_) => {
|
||||
return self.exec_fn_pointer(
|
||||
func_data,
|
||||
destination,
|
||||
&args[1..],
|
||||
locals,
|
||||
target_bb,
|
||||
span,
|
||||
);
|
||||
self.exec_fn_pointer(func_data, destination, &args[1..], locals, target_bb, span)
|
||||
}
|
||||
TyKind::Closure(closure, subst) => {
|
||||
return self.exec_closure(
|
||||
@ -2495,7 +2462,7 @@ impl Evaluator<'_> {
|
||||
self.write_memory(addr, &result)?;
|
||||
IntervalAndTy { interval: Interval { addr, size }, ty }
|
||||
};
|
||||
return self.exec_fn_with_args(
|
||||
self.exec_fn_with_args(
|
||||
def,
|
||||
&[arg0.clone(), arg1],
|
||||
generic_args,
|
||||
@ -2503,7 +2470,7 @@ impl Evaluator<'_> {
|
||||
destination,
|
||||
target_bb,
|
||||
span,
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2523,7 +2490,7 @@ impl Evaluator<'_> {
|
||||
self.allocate_const_in_heap(locals, &konst)?
|
||||
} else {
|
||||
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");
|
||||
};
|
||||
let addr = self.heap_allocate(size, align)?;
|
||||
@ -2540,11 +2507,13 @@ impl Evaluator<'_> {
|
||||
match r {
|
||||
Ok(r) => Ok(r),
|
||||
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!(
|
||||
"{}::{}",
|
||||
data.name.display(self.db.upcast()),
|
||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
||||
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()),
|
||||
);
|
||||
Err(MirEvalError::ConstEvalError(name, Box::new(e)))
|
||||
}
|
||||
@ -2635,8 +2604,8 @@ impl Evaluator<'_> {
|
||||
| TyKind::Str
|
||||
| TyKind::Never
|
||||
| TyKind::Closure(_, _)
|
||||
| TyKind::Generator(_, _)
|
||||
| TyKind::GeneratorWitness(_, _)
|
||||
| TyKind::Coroutine(_, _)
|
||||
| TyKind::CoroutineWitness(_, _)
|
||||
| TyKind::Foreign(_)
|
||||
| TyKind::Error
|
||||
| TyKind::Placeholder(_)
|
||||
@ -2679,7 +2648,7 @@ pub fn render_const_using_debug_impl(
|
||||
db.upcast(),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
|
||||
hir_expand::mod_path::PathKind::Abs,
|
||||
[name![core], name![fmt], name![Debug]].into_iter(),
|
||||
[name![core], name![fmt], name![Debug]],
|
||||
)),
|
||||
) else {
|
||||
not_supported!("core::fmt::Debug not found");
|
||||
@ -2711,7 +2680,7 @@ pub fn render_const_using_debug_impl(
|
||||
db.upcast(),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
|
||||
hir_expand::mod_path::PathKind::Abs,
|
||||
[name![std], name![fmt], name![format]].into_iter(),
|
||||
[name![std], name![fmt], name![format]],
|
||||
)),
|
||||
) else {
|
||||
not_supported!("std::fmt::format not found");
|
||||
|
@ -60,7 +60,7 @@ impl Evaluator<'_> {
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
&locals,
|
||||
locals,
|
||||
span,
|
||||
)?;
|
||||
return Ok(true);
|
||||
@ -82,7 +82,7 @@ impl Evaluator<'_> {
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
&locals,
|
||||
locals,
|
||||
span,
|
||||
)?;
|
||||
return Ok(true);
|
||||
@ -100,7 +100,7 @@ impl Evaluator<'_> {
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
&locals,
|
||||
locals,
|
||||
span,
|
||||
)?;
|
||||
return Ok(true);
|
||||
@ -125,7 +125,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
if let Some(it) = self.detect_lang_function(def) {
|
||||
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)?;
|
||||
destination.write_from_bytes(self, &result)?;
|
||||
return Ok(true);
|
||||
@ -313,7 +313,7 @@ impl Evaluator<'_> {
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(
|
||||
ModPath::from_segments(
|
||||
hir_expand::mod_path::PathKind::Abs,
|
||||
[name![std], name![fmt], name![format]].into_iter(),
|
||||
[name![std], name![fmt], name![format]],
|
||||
),
|
||||
),
|
||||
) else {
|
||||
@ -347,7 +347,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
DropInPlace => {
|
||||
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(
|
||||
"generic argument of drop_in_place is not provided",
|
||||
),
|
||||
@ -445,7 +445,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"pthread_key_create" => {
|
||||
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"));
|
||||
};
|
||||
let arg0_addr = Address::from_bytes(arg0.get(self)?)?;
|
||||
@ -466,7 +466,7 @@ impl Evaluator<'_> {
|
||||
Ok(())
|
||||
}
|
||||
"pthread_getspecific" => {
|
||||
let Some(arg0) = args.get(0) else {
|
||||
let Some(arg0) = args.first() else {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"pthread_getspecific arg0 is not provided",
|
||||
));
|
||||
@ -477,7 +477,7 @@ impl Evaluator<'_> {
|
||||
Ok(())
|
||||
}
|
||||
"pthread_setspecific" => {
|
||||
let Some(arg0) = args.get(0) else {
|
||||
let Some(arg0) = args.first() else {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"pthread_setspecific arg0 is not provided",
|
||||
));
|
||||
@ -728,7 +728,7 @@ impl Evaluator<'_> {
|
||||
match name {
|
||||
"size_of" => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("size_of generic arg is not provided"));
|
||||
};
|
||||
@ -737,7 +737,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"min_align_of" | "pref_align_of" => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("align_of generic arg is not provided"));
|
||||
};
|
||||
@ -746,7 +746,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"size_of_val" => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("size_of_val generic arg is not provided"));
|
||||
};
|
||||
@ -763,7 +763,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"min_align_of_val" => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"min_align_of_val generic arg is not provided",
|
||||
@ -782,7 +782,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"type_name" => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("type_name generic arg is not provided"));
|
||||
};
|
||||
@ -806,7 +806,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
"needs_drop" => {
|
||||
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 {
|
||||
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 ans = lhs.wrapping_sub(rhs);
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"ptr_offset_from generic arg is not provided",
|
||||
@ -971,7 +971,7 @@ impl Evaluator<'_> {
|
||||
));
|
||||
};
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"copy_nonoverlapping generic arg is not provided",
|
||||
@ -992,7 +992,7 @@ impl Evaluator<'_> {
|
||||
};
|
||||
let ty = if name == "offset" {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("offset generic arg is not provided"));
|
||||
};
|
||||
@ -1022,7 +1022,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"arith_offset generic arg is not provided",
|
||||
@ -1147,7 +1147,7 @@ impl Evaluator<'_> {
|
||||
return Err(MirEvalError::TypeError("discriminant_value arg is not provided"));
|
||||
};
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"discriminant_value generic arg is not provided",
|
||||
@ -1207,7 +1207,7 @@ impl Evaluator<'_> {
|
||||
};
|
||||
let dst = Address::from_bytes(ptr.get(self)?)?;
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError(
|
||||
"write_via_copy generic arg is not provided",
|
||||
@ -1224,7 +1224,7 @@ impl Evaluator<'_> {
|
||||
let count = from_bytes!(usize, count.get(self)?);
|
||||
let val = from_bytes!(u8, val.get(self)?);
|
||||
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 {
|
||||
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 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 =
|
||||
layout.fields.offset(field_types.iter().count() - 1).bytes_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
|
||||
|
||||
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"));
|
||||
};
|
||||
let Some(arg0) = args.get(0) else {
|
||||
let Some(arg0) = args.first() else {
|
||||
return Err(MirEvalError::TypeError("atomic intrinsic arg0 is not provided"));
|
||||
};
|
||||
let arg0_addr = Address::from_bytes(arg0.get(self)?)?;
|
||||
|
@ -46,7 +46,7 @@ impl Evaluator<'_> {
|
||||
match try_const_usize(self.db, len) {
|
||||
Some(len) => {
|
||||
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 {
|
||||
return Err(MirEvalError::TypeError("simd type with no ty param"));
|
||||
};
|
||||
@ -106,7 +106,7 @@ impl Evaluator<'_> {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
result = (l as i8).cmp(&(r as i8));
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
|
||||
Substitution::empty(Interner),
|
||||
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);
|
||||
result?;
|
||||
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 line_index = |size: TextSize| {
|
||||
let mut size = u32::from(size) as usize;
|
||||
let mut lines = ra_fixture.lines().enumerate();
|
||||
while let Some((i, l)) = lines.next() {
|
||||
let lines = ra_fixture.lines().enumerate();
|
||||
for (i, l) in lines {
|
||||
if let Some(x) = size.checked_sub(l.len()) {
|
||||
size = x;
|
||||
} else {
|
||||
|
@ -69,6 +69,7 @@ struct MirLowerCtx<'a> {
|
||||
drop_scopes: Vec<DropScope>,
|
||||
}
|
||||
|
||||
// FIXME: Make this smaller, its stored in database queries
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MirLowerError {
|
||||
ConstEvalError(Box<str>, Box<ConstEvalError>),
|
||||
@ -258,7 +259,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
owner,
|
||||
closures: vec![],
|
||||
};
|
||||
let ctx = MirLowerCtx {
|
||||
|
||||
MirLowerCtx {
|
||||
result: mir,
|
||||
db,
|
||||
infer,
|
||||
@ -268,8 +270,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
labeled_loop_blocks: Default::default(),
|
||||
discr_temp: None,
|
||||
drop_scopes: vec![DropScope::default()],
|
||||
};
|
||||
ctx
|
||||
}
|
||||
}
|
||||
|
||||
fn temp(&mut self, ty: Ty, current: BasicBlockId, span: MirSpan) -> Result<LocalId> {
|
||||
@ -287,12 +288,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
current: BasicBlockId,
|
||||
) -> Result<Option<(Operand, BasicBlockId)>> {
|
||||
if !self.has_adjustments(expr_id) {
|
||||
match &self.body.exprs[expr_id] {
|
||||
Expr::Literal(l) => {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
return Ok(Some((self.lower_literal_to_operand(ty, l)?, current)));
|
||||
}
|
||||
_ => (),
|
||||
if let Expr::Literal(l) = &self.body.exprs[expr_id] {
|
||||
let ty = self.expr_ty_without_adjust(expr_id);
|
||||
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 {
|
||||
@ -344,8 +342,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
current,
|
||||
place,
|
||||
Rvalue::Cast(
|
||||
CastKind::Pointer(cast.clone()),
|
||||
Operand::Copy(p).into(),
|
||||
CastKind::Pointer(*cast),
|
||||
Operand::Copy(p),
|
||||
last.target.clone(),
|
||||
),
|
||||
expr_id.into(),
|
||||
@ -456,9 +454,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
Ok(Some(current))
|
||||
}
|
||||
ValueNs::EnumVariantId(variant_id) => {
|
||||
let variant_data =
|
||||
&self.db.enum_data(variant_id.parent).variants[variant_id.local_id];
|
||||
if variant_data.variant_data.kind() == StructKind::Unit {
|
||||
let variant_data = &self.db.enum_variant_data(variant_id).variant_data;
|
||||
if variant_data.kind() == StructKind::Unit {
|
||||
let ty = self.infer.type_of_expr[expr_id].clone();
|
||||
current = self.lower_enum_variant(
|
||||
variant_id,
|
||||
@ -511,8 +508,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
return Ok(None);
|
||||
};
|
||||
let start_of_then = self.new_basic_block();
|
||||
let end_of_then =
|
||||
self.lower_expr_to_place(*then_branch, place.clone(), start_of_then)?;
|
||||
let end_of_then = self.lower_expr_to_place(*then_branch, place, start_of_then)?;
|
||||
let start_of_else = self.new_basic_block();
|
||||
let end_of_else = if let Some(else_branch) = else_branch {
|
||||
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.write_bytes_to_place(
|
||||
then_target,
|
||||
place.clone(),
|
||||
place,
|
||||
Box::new([1]),
|
||||
TyBuilder::bool(),
|
||||
MirSpan::Unknown,
|
||||
@ -560,25 +556,19 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
}
|
||||
Expr::Block { id: _, statements, tail, label } => {
|
||||
if let Some(label) = label {
|
||||
self.lower_loop(
|
||||
current,
|
||||
place.clone(),
|
||||
Some(*label),
|
||||
expr_id.into(),
|
||||
|this, begin| {
|
||||
if let Some(current) = this.lower_block_to_place(
|
||||
statements,
|
||||
begin,
|
||||
*tail,
|
||||
place,
|
||||
expr_id.into(),
|
||||
)? {
|
||||
let end = this.current_loop_end()?;
|
||||
this.set_goto(current, end, expr_id.into());
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
self.lower_loop(current, place, Some(*label), expr_id.into(), |this, begin| {
|
||||
if let Some(current) = this.lower_block_to_place(
|
||||
statements,
|
||||
begin,
|
||||
*tail,
|
||||
place,
|
||||
expr_id.into(),
|
||||
)? {
|
||||
let end = this.current_loop_end()?;
|
||||
this.set_goto(current, end, expr_id.into());
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
} else {
|
||||
self.lower_block_to_place(statements, current, *tail, place, expr_id.into())
|
||||
}
|
||||
@ -646,9 +636,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
);
|
||||
}
|
||||
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, .. } => {
|
||||
@ -678,7 +668,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
let mut end = None;
|
||||
for MatchArm { pat, guard, expr } in arms.iter() {
|
||||
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 next = self.new_basic_block();
|
||||
let o = otherwise.get_or_insert_with(|| self.new_basic_block());
|
||||
@ -696,7 +686,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
} else {
|
||||
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());
|
||||
self.set_goto(block, *r, expr_id.into());
|
||||
}
|
||||
@ -742,9 +732,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
.as_ref()
|
||||
.ok_or(MirLowerError::BreakWithoutLoop)?,
|
||||
};
|
||||
let Some(c) =
|
||||
self.lower_expr_to_place(expr, loop_data.place.clone(), current)?
|
||||
else {
|
||||
let Some(c) = self.lower_expr_to_place(expr, loop_data.place, current)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
current = c;
|
||||
@ -906,7 +894,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
let ty = self.expr_ty_after_adjustments(*expr);
|
||||
self.push_assignment(
|
||||
current,
|
||||
place.clone(),
|
||||
place,
|
||||
Rvalue::ShallowInitBoxWithAlloc(ty),
|
||||
expr_id.into(),
|
||||
);
|
||||
@ -957,10 +945,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
// for binary operator, and use without adjust to simplify our conditions.
|
||||
let lhs_ty = self.expr_ty_without_adjust(*lhs);
|
||||
let rhs_ty = self.expr_ty_without_adjust(*rhs);
|
||||
if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. })) {
|
||||
if lhs_ty.as_raw_ptr().is_some() && rhs_ty.as_raw_ptr().is_some() {
|
||||
break 'b true;
|
||||
}
|
||||
if matches!(op, BinaryOp::CmpOp(syntax::ast::CmpOp::Eq { .. }))
|
||||
&& lhs_ty.as_raw_ptr().is_some()
|
||||
&& rhs_ty.as_raw_ptr().is_some()
|
||||
{
|
||||
break 'b true;
|
||||
}
|
||||
let builtin_inequal_impls = matches!(
|
||||
op,
|
||||
@ -1006,11 +995,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
let r_value = Rvalue::CheckedBinaryOp(
|
||||
op.into(),
|
||||
Operand::Copy(lhs_place.clone()),
|
||||
rhs_op,
|
||||
);
|
||||
let r_value =
|
||||
Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op);
|
||||
self.push_assignment(current, lhs_place, r_value, expr_id.into());
|
||||
return Ok(Some(current));
|
||||
} else {
|
||||
@ -1029,7 +1015,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
let start_of_then = self.new_basic_block();
|
||||
self.push_assignment(
|
||||
start_of_then,
|
||||
place.clone(),
|
||||
place,
|
||||
lhs_op.clone().into(),
|
||||
expr_id.into(),
|
||||
);
|
||||
@ -1168,12 +1154,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
let tmp_ty =
|
||||
capture.ty.clone().substitute(Interner, &placeholder_subst);
|
||||
let tmp: Place = self.temp(tmp_ty, current, capture.span)?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
tmp.clone(),
|
||||
Rvalue::Ref(bk.clone(), p),
|
||||
capture.span,
|
||||
);
|
||||
self.push_assignment(current, tmp, Rvalue::Ref(*bk, p), capture.span);
|
||||
operands.push(Operand::Move(tmp));
|
||||
}
|
||||
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 = 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);
|
||||
}
|
||||
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 {
|
||||
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),
|
||||
None => Substitution::empty(Interner),
|
||||
};
|
||||
placeholder_subst
|
||||
}
|
||||
}
|
||||
|
||||
fn push_field_projection(&mut self, place: &mut Place, expr_id: ExprId) -> Result<()> {
|
||||
@ -1470,7 +1450,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
} else {
|
||||
let name = const_id.name(self.db.upcast());
|
||||
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)))?
|
||||
};
|
||||
Ok(Operand::Constant(c))
|
||||
@ -1612,13 +1592,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
|
||||
fn discr_temp_place(&mut self, current: BasicBlockId) -> Place {
|
||||
match &self.discr_temp {
|
||||
Some(it) => it.clone(),
|
||||
Some(it) => *it,
|
||||
None => {
|
||||
let tmp: Place = self
|
||||
.temp(TyBuilder::discr_ty(), current, MirSpan::Unknown)
|
||||
.expect("discr_ty is never unsized")
|
||||
.into();
|
||||
self.discr_temp = Some(tmp.clone());
|
||||
self.discr_temp = Some(tmp);
|
||||
tmp
|
||||
}
|
||||
}
|
||||
@ -1874,11 +1854,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||
match r {
|
||||
Ok(r) => Ok(r),
|
||||
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!(
|
||||
"{}::{}",
|
||||
data.name.display(self.db.upcast()),
|
||||
data.variants[variant.local_id].name.display(self.db.upcast())
|
||||
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()),
|
||||
);
|
||||
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| {
|
||||
if let Some(it) = upvar_map.get(&p.local) {
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
(ProjectionElem::Deref, ProjectionElem::Deref) => (),
|
||||
(ProjectionElem::Field(it), ProjectionElem::Field(y)) if it == y => (),
|
||||
(ProjectionElem::ClosureField(it), ProjectionElem::ClosureField(y))
|
||||
if it == y =>
|
||||
{
|
||||
()
|
||||
}
|
||||
if it == y => {}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
@ -2067,15 +2046,11 @@ pub fn mir_body_for_closure_query(
|
||||
next_projs.push(ProjectionElem::Deref);
|
||||
}
|
||||
next_projs.extend(
|
||||
prev_projs
|
||||
.lookup(&store)
|
||||
.iter()
|
||||
.skip(it.0.place.projections.len())
|
||||
.cloned(),
|
||||
prev_projs.lookup(store).iter().skip(it.0.place.projections.len()).cloned(),
|
||||
);
|
||||
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())
|
||||
.to_string(),
|
||||
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:?}"),
|
||||
});
|
||||
|
@ -148,7 +148,7 @@ impl MirLowerCtx<'_> {
|
||||
let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
temp.clone(),
|
||||
temp,
|
||||
Operand::Static(s).into(),
|
||||
expr_id.into(),
|
||||
);
|
||||
@ -160,57 +160,53 @@ impl MirLowerCtx<'_> {
|
||||
_ => try_rvalue(self),
|
||||
}
|
||||
}
|
||||
Expr::UnaryOp { expr, op } => match op {
|
||||
hir_def::hir::UnaryOp::Deref => {
|
||||
let is_builtin = match self.expr_ty_without_adjust(*expr).kind(Interner) {
|
||||
TyKind::Ref(..) | TyKind::Raw(..) => true,
|
||||
TyKind::Adt(id, _) => {
|
||||
if let Some(lang_item) = self.db.lang_attr(id.0.into()) {
|
||||
lang_item == LangItem::OwnedBox
|
||||
} else {
|
||||
false
|
||||
}
|
||||
Expr::UnaryOp { expr, op: hir_def::hir::UnaryOp::Deref } => {
|
||||
let is_builtin = match self.expr_ty_without_adjust(*expr).kind(Interner) {
|
||||
TyKind::Ref(..) | TyKind::Raw(..) => true,
|
||||
TyKind::Adt(id, _) => {
|
||||
if let Some(lang_item) = self.db.lang_attr(id.0.into()) {
|
||||
lang_item == LangItem::OwnedBox
|
||||
} else {
|
||||
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)?
|
||||
else {
|
||||
_ => false,
|
||||
};
|
||||
if !is_builtin {
|
||||
let Some((p, 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)))
|
||||
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
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => 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, .. } => {
|
||||
let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else {
|
||||
return Ok(None);
|
||||
@ -304,7 +300,7 @@ impl MirLowerCtx<'_> {
|
||||
let Some(current) = self.lower_call(
|
||||
index_fn_op,
|
||||
Box::new([Operand::Copy(place), index_operand]),
|
||||
result.clone(),
|
||||
result,
|
||||
current,
|
||||
false,
|
||||
span,
|
||||
@ -338,7 +334,7 @@ impl MirLowerCtx<'_> {
|
||||
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 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
|
||||
.resolve_lang_item(trait_lang_item)?
|
||||
.as_trait()
|
||||
@ -359,7 +355,7 @@ impl MirLowerCtx<'_> {
|
||||
let Some(current) = self.lower_call(
|
||||
deref_fn_op,
|
||||
Box::new([Operand::Copy(ref_place)]),
|
||||
result.clone(),
|
||||
result,
|
||||
current,
|
||||
false,
|
||||
span,
|
||||
|
@ -58,7 +58,7 @@ impl MirLowerCtx<'_> {
|
||||
let (current, current_else) = self.pattern_match_inner(
|
||||
current,
|
||||
current_else,
|
||||
cond_place.clone(),
|
||||
cond_place,
|
||||
pattern,
|
||||
MatchingMode::Check,
|
||||
)?;
|
||||
@ -114,7 +114,7 @@ impl MirLowerCtx<'_> {
|
||||
index: i as u32,
|
||||
}))
|
||||
}),
|
||||
&(&mut cond_place),
|
||||
&mut cond_place,
|
||||
mode,
|
||||
)?
|
||||
}
|
||||
@ -125,7 +125,7 @@ impl MirLowerCtx<'_> {
|
||||
let (mut next, next_else) = self.pattern_match_inner(
|
||||
current,
|
||||
None,
|
||||
(&mut cond_place).clone(),
|
||||
cond_place,
|
||||
*pat,
|
||||
MatchingMode::Check,
|
||||
)?;
|
||||
@ -133,7 +133,7 @@ impl MirLowerCtx<'_> {
|
||||
(next, _) = self.pattern_match_inner(
|
||||
next,
|
||||
None,
|
||||
(&mut cond_place).clone(),
|
||||
cond_place,
|
||||
*pat,
|
||||
MatchingMode::Bind,
|
||||
)?;
|
||||
@ -169,7 +169,7 @@ impl MirLowerCtx<'_> {
|
||||
current,
|
||||
pattern.into(),
|
||||
current_else,
|
||||
AdtPatternShape::Record { args: &*args },
|
||||
AdtPatternShape::Record { args },
|
||||
mode,
|
||||
)?
|
||||
}
|
||||
@ -183,12 +183,8 @@ impl MirLowerCtx<'_> {
|
||||
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
discr.clone(),
|
||||
Rvalue::CheckedBinaryOp(
|
||||
binop,
|
||||
lv,
|
||||
Operand::Copy((&mut cond_place).clone()),
|
||||
),
|
||||
discr,
|
||||
Rvalue::CheckedBinaryOp(binop, lv, Operand::Copy(cond_place)),
|
||||
pattern.into(),
|
||||
);
|
||||
let discr = Operand::Copy(discr);
|
||||
@ -222,8 +218,8 @@ impl MirLowerCtx<'_> {
|
||||
self.temp(TyBuilder::usize(), current, pattern.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
place_len.clone(),
|
||||
Rvalue::Len((&mut cond_place).clone()),
|
||||
place_len,
|
||||
Rvalue::Len(cond_place),
|
||||
pattern.into(),
|
||||
);
|
||||
let else_target =
|
||||
@ -252,7 +248,7 @@ impl MirLowerCtx<'_> {
|
||||
self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
discr.clone(),
|
||||
discr,
|
||||
Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
|
||||
pattern.into(),
|
||||
);
|
||||
@ -270,7 +266,7 @@ impl MirLowerCtx<'_> {
|
||||
}
|
||||
}
|
||||
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 },
|
||||
&mut self.result.projection_store,
|
||||
);
|
||||
@ -280,7 +276,7 @@ impl MirLowerCtx<'_> {
|
||||
if let Some(slice) = slice {
|
||||
if mode == MatchingMode::Bind {
|
||||
if let Pat::Bind { id, subpat: _ } = self.body[*slice] {
|
||||
let next_place = (&mut cond_place).project(
|
||||
let next_place = cond_place.project(
|
||||
ProjectionElem::Subslice {
|
||||
from: prefix.len() as u64,
|
||||
to: suffix.len() as u64,
|
||||
@ -299,7 +295,7 @@ impl MirLowerCtx<'_> {
|
||||
}
|
||||
}
|
||||
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 },
|
||||
&mut self.result.projection_store,
|
||||
);
|
||||
@ -335,10 +331,8 @@ impl MirLowerCtx<'_> {
|
||||
break 'b (c, x.1);
|
||||
}
|
||||
}
|
||||
if let ResolveValueResult::ValueNs(v, _) = pr {
|
||||
if let ValueNs::ConstId(c) = v {
|
||||
break 'b (c, Substitution::empty(Interner));
|
||||
}
|
||||
if let ResolveValueResult::ValueNs(ValueNs::ConstId(c), _) = pr {
|
||||
break 'b (c, Substitution::empty(Interner));
|
||||
}
|
||||
not_supported!("path in pattern position that is not const or variant")
|
||||
};
|
||||
@ -348,7 +342,7 @@ impl MirLowerCtx<'_> {
|
||||
self.lower_const(
|
||||
c.into(),
|
||||
current,
|
||||
tmp.clone(),
|
||||
tmp,
|
||||
subst,
|
||||
span,
|
||||
self.infer[pattern].clone(),
|
||||
@ -356,7 +350,7 @@ impl MirLowerCtx<'_> {
|
||||
let tmp2: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
tmp2.clone(),
|
||||
tmp2,
|
||||
Rvalue::CheckedBinaryOp(
|
||||
BinOp::Eq,
|
||||
Operand::Copy(tmp),
|
||||
@ -390,13 +384,8 @@ impl MirLowerCtx<'_> {
|
||||
},
|
||||
Pat::Bind { id, subpat } => {
|
||||
if let Some(subpat) = subpat {
|
||||
(current, current_else) = self.pattern_match_inner(
|
||||
current,
|
||||
current_else,
|
||||
(&mut cond_place).clone(),
|
||||
*subpat,
|
||||
mode,
|
||||
)?
|
||||
(current, current_else) =
|
||||
self.pattern_match_inner(current, current_else, cond_place, *subpat, mode)?
|
||||
}
|
||||
if mode == MatchingMode::Bind {
|
||||
self.pattern_match_binding(
|
||||
@ -475,7 +464,7 @@ impl MirLowerCtx<'_> {
|
||||
let discr: Place = self.temp(TyBuilder::bool(), current, pattern.into())?.into();
|
||||
self.push_assignment(
|
||||
current,
|
||||
discr.clone(),
|
||||
discr,
|
||||
Rvalue::CheckedBinaryOp(BinOp::Eq, c, Operand::Copy(cond_place)),
|
||||
pattern.into(),
|
||||
);
|
||||
@ -506,12 +495,7 @@ impl MirLowerCtx<'_> {
|
||||
if mode == MatchingMode::Check {
|
||||
let e = self.const_eval_discriminant(v)? as u128;
|
||||
let tmp = self.discr_temp_place(current);
|
||||
self.push_assignment(
|
||||
current,
|
||||
tmp.clone(),
|
||||
Rvalue::Discriminant(cond_place.clone()),
|
||||
span,
|
||||
);
|
||||
self.push_assignment(current, tmp, Rvalue::Discriminant(cond_place), span);
|
||||
let next = self.new_basic_block();
|
||||
let else_target = current_else.get_or_insert_with(|| self.new_basic_block());
|
||||
self.set_terminator(
|
||||
@ -524,22 +508,9 @@ impl MirLowerCtx<'_> {
|
||||
);
|
||||
current = next;
|
||||
}
|
||||
let enum_data = self.db.enum_data(v.parent);
|
||||
self.pattern_matching_variant_fields(
|
||||
shape,
|
||||
&enum_data.variants[v.local_id].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,
|
||||
&self.db.enum_variant_data(v).variant_data,
|
||||
variant,
|
||||
current,
|
||||
current_else,
|
||||
@ -547,6 +518,15 @@ impl MirLowerCtx<'_> {
|
||||
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(_) => {
|
||||
return Err(MirLowerError::TypeError("pattern matching on union"))
|
||||
}
|
||||
@ -572,7 +552,7 @@ impl MirLowerCtx<'_> {
|
||||
variant_data.field(&x.name).ok_or(MirLowerError::UnresolvedField)?;
|
||||
Ok((
|
||||
PlaceElem::Field(Either::Left(FieldId {
|
||||
parent: v.into(),
|
||||
parent: v,
|
||||
local_id: field_id,
|
||||
})),
|
||||
x.pat,
|
||||
@ -583,7 +563,7 @@ impl MirLowerCtx<'_> {
|
||||
}
|
||||
AdtPatternShape::Tuple { args, ellipsis } => {
|
||||
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(
|
||||
current,
|
||||
|
@ -275,7 +275,7 @@ impl Filler<'_> {
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::CoroutineDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::FalseUnwind { .. } => (),
|
||||
}
|
||||
@ -306,7 +306,7 @@ pub fn monomorphized_mir_body_recover(
|
||||
_: &Substitution,
|
||||
_: &Arc<crate::TraitEnvironment>,
|
||||
) -> Result<Arc<MirBody>, MirLowerError> {
|
||||
return Err(MirLowerError::Loop);
|
||||
Err(MirLowerError::Loop)
|
||||
}
|
||||
|
||||
pub fn monomorphized_mir_body_for_closure_query(
|
||||
|
@ -7,7 +7,7 @@ use std::{
|
||||
|
||||
use either::Either;
|
||||
use hir_def::{body::Body, hir::BindingId};
|
||||
use hir_expand::name::Name;
|
||||
use hir_expand::{name::Name, Lookup};
|
||||
use la_arena::ArenaMap;
|
||||
|
||||
use crate::{
|
||||
@ -58,8 +58,14 @@ impl MirBody {
|
||||
);
|
||||
}
|
||||
hir_def::DefWithBodyId::VariantId(id) => {
|
||||
let data = db.enum_data(id.parent);
|
||||
w!(this, "enum {} = ", data.name.display(db.upcast()));
|
||||
let loc = id.lookup(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) => {
|
||||
w!(this, "in type const {id:?} = ");
|
||||
@ -306,8 +312,7 @@ impl<'a> MirPrettyCtx<'a> {
|
||||
hir_def::VariantId::EnumVariantId(e) => {
|
||||
w!(this, "(");
|
||||
f(this, local, head);
|
||||
let variant_name =
|
||||
&this.db.enum_data(e.parent).variants[e.local_id].name;
|
||||
let variant_name = &this.db.enum_variant_data(e).name;
|
||||
w!(
|
||||
this,
|
||||
" 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) {
|
||||
|
@ -43,13 +43,13 @@ impl fmt::Debug for TestDB {
|
||||
|
||||
impl Upcast<dyn ExpandDatabase> for TestDB {
|
||||
fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Upcast<dyn DefDatabase> for TestDB {
|
||||
fn upcast(&self) -> &(dyn DefDatabase + 'static) {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ use base_db::{FileRange, SourceDatabaseExt};
|
||||
use expect_test::Expect;
|
||||
use hir_def::{
|
||||
body::{Body, BodySourceMap, SyntheticSyntax},
|
||||
db::{DefDatabase, InternDatabase},
|
||||
db::DefDatabase,
|
||||
hir::{ExprId, Pat, PatId},
|
||||
item_scope::ItemScope,
|
||||
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()
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
let loc = db.lookup_intern_enum(it.parent);
|
||||
let loc = it.lookup(&db);
|
||||
loc.source(&db).value.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()
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
let loc = db.lookup_intern_enum(it.parent);
|
||||
let loc = it.lookup(&db);
|
||||
loc.source(&db).value.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);
|
||||
}
|
||||
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
|
||||
db.enum_data(it)
|
||||
.variants
|
||||
.iter()
|
||||
.map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id })
|
||||
.for_each(|it| {
|
||||
let def = it.into();
|
||||
cb(def);
|
||||
let body = db.body(def);
|
||||
visit_body(db, &body, cb);
|
||||
});
|
||||
db.enum_data(it).variants.iter().for_each(|&(it, _)| {
|
||||
let def = it.into();
|
||||
cb(def);
|
||||
let body = db.body(def);
|
||||
visit_body(db, &body, cb);
|
||||
});
|
||||
}
|
||||
ModuleDefId::TraitId(it) => {
|
||||
let trait_data = db.trait_data(it);
|
||||
|
@ -328,7 +328,7 @@ fn foo() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generator_yield_return_coerce() {
|
||||
fn coroutine_yield_return_coerce() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
fn test() {
|
||||
@ -574,6 +574,7 @@ fn two_closures_lub() {
|
||||
r#"
|
||||
fn foo(c: i32) {
|
||||
let add = |a: i32, b: i32| a + b;
|
||||
//^^^^^^^^^^^^^^^^^^^^^^ impl Fn(i32, i32) -> i32
|
||||
let sub = |a, b| a - b;
|
||||
//^^^^^^^^^^^^ impl Fn(i32, i32) -> i32
|
||||
if c > 42 { add } else { sub };
|
||||
|
@ -64,7 +64,7 @@ fn infer_macros_expanded() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
!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
|
||||
!5..15 'vec![1,2,]': {unknown}
|
||||
155..181 '{ ...,2); }': ()
|
||||
@ -97,7 +97,7 @@ fn infer_legacy_textual_scoped_macros_expanded() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
!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
|
||||
!5..15 'vec![1,2,]': {unknown}
|
||||
194..250 '{ ...,2); }': ()
|
||||
|
@ -210,13 +210,13 @@ fn infer_pattern_match_ergonomics() {
|
||||
37..41 'A(n)': A<i32>
|
||||
39..40 'n': &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>
|
||||
47..48 '1': i32
|
||||
59..63 'A(n)': A<i32>
|
||||
61..62 'n': &mut 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>
|
||||
73..74 '1': i32
|
||||
"#]],
|
||||
@ -531,18 +531,18 @@ impl Foo {
|
||||
56..64 'Self(s,)': Foo
|
||||
61..62 's': &usize
|
||||
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
|
||||
72..73 '0': usize
|
||||
89..97 'Self(s,)': Foo
|
||||
94..95 's': &mut usize
|
||||
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
|
||||
109..110 '0': usize
|
||||
126..134 'Self(s,)': Foo
|
||||
131..132 's': usize
|
||||
137..140 'Foo': Foo(usize) -> Foo
|
||||
137..140 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
137..144 'Foo(0,)': Foo
|
||||
141..142 '0': usize
|
||||
"#]],
|
||||
@ -916,7 +916,7 @@ fn foo(foo: Foo) {
|
||||
48..51 'foo': Foo
|
||||
62..84 'const ... 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
|
||||
74..76 '15': usize
|
||||
74..81 '15 + 32': usize
|
||||
|
@ -644,7 +644,7 @@ fn issue_4953() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
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
|
||||
65..69 '0i64': i64
|
||||
"#]],
|
||||
@ -658,7 +658,7 @@ fn issue_4953() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
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>
|
||||
71..75 '0i64': i64
|
||||
"#]],
|
||||
@ -858,7 +858,7 @@ fn main() {
|
||||
94..96 '{}': ()
|
||||
109..160 '{ ...10); }': ()
|
||||
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>
|
||||
132..133 's': S<i32>
|
||||
132..144 's.g(|_x| {})': ()
|
||||
@ -1689,18 +1689,18 @@ fn main() {
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
27..85 '{ ...1,); }': ()
|
||||
37..48 'S(.., a, b)': S
|
||||
43..44 'a': usize
|
||||
46..47 'b': {unknown}
|
||||
51..52 'S': S(usize) -> S
|
||||
51..55 'S(1)': S
|
||||
53..54 '1': usize
|
||||
65..75 '(.., a, b)': (i32, {unknown})
|
||||
70..71 'a': i32
|
||||
73..74 'b': {unknown}
|
||||
78..82 '(1,)': (i32,)
|
||||
79..80 '1': i32
|
||||
27..85 '{ ...1,); }': ()
|
||||
37..48 'S(.., a, b)': S
|
||||
43..44 'a': usize
|
||||
46..47 'b': {unknown}
|
||||
51..52 'S': extern "rust-call" S(usize) -> S
|
||||
51..55 'S(1)': S
|
||||
53..54 '1': usize
|
||||
65..75 '(.., a, b)': (i32, {unknown})
|
||||
70..71 'a': i32
|
||||
73..74 'b': {unknown}
|
||||
78..82 '(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
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
|
@ -236,14 +236,14 @@ fn test() {
|
||||
expect![[r#"
|
||||
71..153 '{ ...a.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
|
||||
87..88 '1': usize
|
||||
95..96 'B': B
|
||||
106..107 'a': A
|
||||
113..132 'A { b:...C(1) }': A
|
||||
120..121 'B': B
|
||||
126..127 'C': C(usize) -> C
|
||||
126..127 'C': extern "rust-call" C(usize) -> C
|
||||
126..130 'C(1)': C
|
||||
128..129 '1': usize
|
||||
138..139 'a': A
|
||||
@ -303,14 +303,14 @@ unsafe fn baz(u: MyUnion) {
|
||||
71..89 'MyUnio...o: 0 }': MyUnion
|
||||
86..87 '0': u32
|
||||
95..113 'unsafe...(u); }': ()
|
||||
104..107 'baz': fn baz(MyUnion)
|
||||
104..107 'baz': unsafe fn baz(MyUnion)
|
||||
104..110 'baz(u)': ()
|
||||
108..109 'u': MyUnion
|
||||
122..123 'u': MyUnion
|
||||
126..146 'MyUnio... 0.0 }': MyUnion
|
||||
141..144 '0.0': f32
|
||||
152..170 'unsafe...(u); }': ()
|
||||
161..164 'baz': fn baz(MyUnion)
|
||||
161..164 'baz': unsafe fn baz(MyUnion)
|
||||
161..167 'baz(u)': ()
|
||||
165..166 'u': MyUnion
|
||||
188..189 'u': MyUnion
|
||||
@ -625,12 +625,12 @@ impl E {
|
||||
86..107 '{ ... }': ()
|
||||
96..100 'Self': S1
|
||||
134..158 '{ ... }': ()
|
||||
144..148 'Self': S2(isize) -> S2
|
||||
144..148 'Self': extern "rust-call" S2(isize) -> S2
|
||||
144..151 'Self(1)': S2
|
||||
149..150 '1': isize
|
||||
184..230 '{ ... }': ()
|
||||
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
|
||||
221..222 '1': u32
|
||||
"#]],
|
||||
@ -856,11 +856,11 @@ fn test() {
|
||||
256..277 'A::foo...42))))': &i32
|
||||
263..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>>>
|
||||
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>>
|
||||
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>
|
||||
271..273 '42': i32
|
||||
"#]],
|
||||
@ -910,16 +910,16 @@ fn test(a: A<i32>) {
|
||||
253..254 'a': A<i32>
|
||||
264..310 '{ ...))); }': ()
|
||||
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..307 'A(0 as...B(a)))': &i32
|
||||
280..281 '0': i32
|
||||
280..291 '0 as *mut _': *mut i32
|
||||
297..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>>>
|
||||
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>>
|
||||
303..304 'a': A<i32>
|
||||
"#]],
|
||||
@ -1273,16 +1273,16 @@ fn infer_tuple_struct_generics() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
135..138 '"x"': &str
|
||||
145..149 'None': Option<{unknown}>
|
||||
@ -1568,7 +1568,7 @@ fn infer_type_alias() {
|
||||
204..207 'z.y': i8
|
||||
298..362 '{ ... &e; }': ()
|
||||
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
|
||||
326..327 '0': u8
|
||||
338..354 'm::Ali...Foo(x)': Enum
|
||||
@ -1949,11 +1949,11 @@ fn closure_return_inferred() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generator_types_inferred() {
|
||||
fn coroutine_types_inferred() {
|
||||
check_infer(
|
||||
r#"
|
||||
//- minicore: generator, deref
|
||||
use core::ops::{Generator, GeneratorState};
|
||||
//- minicore: coroutine, deref
|
||||
use core::ops::{Coroutine, CoroutineState};
|
||||
use core::pin::Pin;
|
||||
|
||||
fn f(v: i64) {}
|
||||
@ -1966,8 +1966,8 @@ fn test() {
|
||||
};
|
||||
|
||||
match Pin::new(&mut g).resume(0usize) {
|
||||
GeneratorState::Yielded(y) => { f(y); }
|
||||
GeneratorState::Complete(r) => {}
|
||||
CoroutineState::Yielded(y) => { f(y); }
|
||||
CoroutineState::Complete(r) => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
@ -1992,17 +1992,17 @@ fn test() {
|
||||
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..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
|
||||
245..246 'g': |usize| yields i64 -> &str
|
||||
255..261 '0usize': usize
|
||||
273..299 'Genera...ded(y)': GeneratorState<i64, &str>
|
||||
273..299 'Corout...ded(y)': CoroutineState<i64, &str>
|
||||
297..298 'y': i64
|
||||
303..312 '{ f(y); }': ()
|
||||
305..306 'f': fn f(i64)
|
||||
305..309 'f(y)': ()
|
||||
307..308 'y': i64
|
||||
321..348 'Genera...ete(r)': GeneratorState<i64, &str>
|
||||
321..348 'Corout...ete(r)': CoroutineState<i64, &str>
|
||||
346..347 'r': &str
|
||||
352..354 '{}': ()
|
||||
"#]],
|
||||
@ -2010,11 +2010,11 @@ fn test() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generator_resume_yield_return_unit() {
|
||||
fn coroutine_resume_yield_return_unit() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
//- minicore: generator, deref
|
||||
use core::ops::{Generator, GeneratorState};
|
||||
//- minicore: coroutine, deref
|
||||
use core::ops::{Coroutine, CoroutineState};
|
||||
use core::pin::Pin;
|
||||
fn test() {
|
||||
let mut g = || {
|
||||
@ -2022,8 +2022,8 @@ fn test() {
|
||||
};
|
||||
|
||||
match Pin::new(&mut g).resume(()) {
|
||||
GeneratorState::Yielded(()) => {}
|
||||
GeneratorState::Complete(()) => {}
|
||||
CoroutineState::Yielded(()) => {}
|
||||
CoroutineState::Complete(()) => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
@ -2184,10 +2184,10 @@ fn main() {
|
||||
103..231 '{ ... }); }': ()
|
||||
109..161 'async ... }': impl Future<Output = Result<(), ()>>
|
||||
125..139 'return Err(())': !
|
||||
132..135 'Err': Err<(), ()>(()) -> Result<(), ()>
|
||||
132..135 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
|
||||
132..139 'Err(())': Result<(), ()>
|
||||
136..138 '()': ()
|
||||
149..151 'Ok': Ok<(), ()>(()) -> Result<(), ()>
|
||||
149..151 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
|
||||
149..155 'Ok(())': Result<(), ()>
|
||||
152..154 '()': ()
|
||||
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<(), ()>>
|
||||
175..227 'async ... }': impl Future<Output = Result<(), ()>>
|
||||
191..205 'return Err(())': !
|
||||
198..201 'Err': Err<(), ()>(()) -> Result<(), ()>
|
||||
198..201 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
|
||||
198..205 'Err(())': Result<(), ()>
|
||||
202..204 '()': ()
|
||||
215..217 'Ok': Ok<(), ()>(()) -> Result<(), ()>
|
||||
215..217 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
|
||||
215..221 'Ok(())': Result<(), ()>
|
||||
218..220 '()': ()
|
||||
"#]],
|
||||
@ -2227,7 +2227,7 @@ fn infer_generic_from_later_assignment() {
|
||||
94..127 '{ ... }': ()
|
||||
104..107 'end': Option<bool>
|
||||
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>
|
||||
115..119 'true': bool
|
||||
"#]],
|
||||
@ -2262,7 +2262,7 @@ fn infer_loop_break_with_val() {
|
||||
111..121 'break None': !
|
||||
117..121 'None': Option<bool>
|
||||
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>
|
||||
153..157 'true': bool
|
||||
"#]],
|
||||
@ -2509,7 +2509,7 @@ fn generic_default_in_struct_literal() {
|
||||
254..281 'OtherT...1i32 }': OtherThing<i32>
|
||||
275..279 '1i32': 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>
|
||||
311..315 '1i32': i32
|
||||
"#]],
|
||||
@ -2984,7 +2984,7 @@ fn f() {
|
||||
expect![[r#"
|
||||
72..166 '{ ... } }': ()
|
||||
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
|
||||
93..94 '3': i32
|
||||
106..119 'Qux::Bar(bar)': Foo
|
||||
@ -3043,9 +3043,9 @@ fn main() {
|
||||
322..324 '{}': Foo<T>
|
||||
338..559 '{ ...r(); }': ()
|
||||
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>>
|
||||
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>
|
||||
364..369 '0_i32': i32
|
||||
382..386 'bad1': &i32
|
||||
|
@ -522,7 +522,7 @@ fn test() -> u64 {
|
||||
expect![[r#"
|
||||
37..86 '{ ... a.1 }': u64
|
||||
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
|
||||
53..54 '4': i32
|
||||
56..57 '6': u64
|
||||
@ -548,7 +548,7 @@ fn test() -> u64 {
|
||||
expect![[r#"
|
||||
43..108 '{ ...0(2) }': u64
|
||||
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
|
||||
59..73 '|i| 2*i as u64': impl Fn(u32) -> u64
|
||||
60..61 'i': u32
|
||||
@ -1026,7 +1026,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
|
||||
201..202 'x': impl Trait<u64>
|
||||
208..209 'y': &impl Trait<u32>
|
||||
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>
|
||||
225..226 '1': 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
|
||||
149..150 't': T
|
||||
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>
|
||||
160..161 'C': u8
|
||||
"#]],
|
||||
@ -1958,7 +1958,7 @@ fn test() {
|
||||
118..120 '{}': ()
|
||||
136..255 '{ ... 1); }': ()
|
||||
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>
|
||||
163..167 '1u32': u32
|
||||
174..175 'x': Option<u32>
|
||||
@ -2514,7 +2514,7 @@ fn test() -> impl Trait<i32> {
|
||||
178..180 '{}': ()
|
||||
213..309 '{ ...t()) }': S<i32>
|
||||
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>
|
||||
230..237 'default': fn default<u32>() -> u32
|
||||
230..239 'default()': u32
|
||||
@ -2524,11 +2524,11 @@ fn test() -> impl Trait<i32> {
|
||||
263..264 'x': i32
|
||||
272..275 'bar': fn bar<i32>(S<i32>) -> 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>
|
||||
278..285 'default': fn default<i32>() -> 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>
|
||||
297..304 'default': fn default<i32>() -> i32
|
||||
297..306 'default()': i32
|
||||
@ -2758,7 +2758,7 @@ fn main() {
|
||||
1036..1041 'x > 0': bool
|
||||
1040..1041 '0': i32
|
||||
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>
|
||||
1049..1050 'x': i32
|
||||
1049..1057 'x as u32': u32
|
||||
@ -2894,9 +2894,9 @@ fn test() {
|
||||
175..185 'foo.test()': bool
|
||||
191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
|
||||
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
|
||||
226..239 'Enum::Variant': Variant(usize) -> Enum
|
||||
226..239 'Enum::Variant': extern "rust-call" Variant(usize) -> Enum
|
||||
226..246 'Enum::...test()': bool
|
||||
"#]],
|
||||
);
|
||||
@ -3475,12 +3475,12 @@ fn main(){
|
||||
95..99 'self': Wrapper
|
||||
101..104 'rhs': u32
|
||||
122..150 '{ ... }': Wrapper
|
||||
132..139 'Wrapper': Wrapper(u32) -> Wrapper
|
||||
132..139 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
|
||||
132..144 'Wrapper(rhs)': Wrapper
|
||||
140..143 'rhs': u32
|
||||
162..248 '{ ...um; }': ()
|
||||
172..179 'wrapped': Wrapper
|
||||
182..189 'Wrapper': Wrapper(u32) -> Wrapper
|
||||
182..189 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
|
||||
182..193 'Wrapper(10)': Wrapper
|
||||
190..192 '10': u32
|
||||
203..206 'num': u32
|
||||
|
@ -107,10 +107,7 @@ impl DebugContext<'_> {
|
||||
let name = match def {
|
||||
CallableDefId::FunctionId(ff) => self.0.function_data(ff).name.clone(),
|
||||
CallableDefId::StructId(s) => self.0.struct_data(s).name.clone(),
|
||||
CallableDefId::EnumVariantId(e) => {
|
||||
let enum_data = self.0.enum_data(e.parent);
|
||||
enum_data.variants[e.local_id].name.clone()
|
||||
}
|
||||
CallableDefId::EnumVariantId(e) => self.0.enum_variant_data(e).name.clone(),
|
||||
};
|
||||
match def {
|
||||
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
Loading…
Reference in New Issue
Block a user