Merge commit 'a9116523604c998e7781f60d3b5a6f586e0414a9' into sync-from-ra

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

View File

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

View File

@ -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",
]

View File

@ -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"

View File

@ -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 {

View File

@ -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,

View File

@ -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> {

View File

@ -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
}

View File

@ -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 => {

View File

@ -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,
);
});
}
}

View File

@ -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),
)
}

View File

@ -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,
)

View File

@ -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" => {

View File

@ -28,7 +28,7 @@ pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
pub const 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();

View File

@ -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));
}

View File

@ -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(),

View File

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

View File

@ -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 {

View File

@ -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)
)
}
}

View File

@ -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>,
}

View File

@ -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"),
}
}

View File

@ -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<'_> {

View File

@ -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;
"#]],
)

View File

@ -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;

View File

@ -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,

View File

@ -35,9 +35,9 @@ macro_rules! f {
};
}
struct#FileId(0):1@58..64\2# MyTraitMap2#FileId(0):2@31..42\0# {#FileId(0):1@72..73\2#
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#
"#]],
);
}

View File

@ -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, "#");

View File

@ -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#&#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#"#]],
);
}

View File

@ -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();

View File

@ -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,

View File

@ -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,

View File

@ -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),
);
)
}
}
}

View File

@ -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");

View File

@ -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)),
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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),
}

View File

@ -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;

View File

@ -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()
}

View File

@ -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() {

View File

@ -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)]

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -218,6 +218,9 @@ pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc<RealSpanMa
let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)];
let 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
}

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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 {

View File

@ -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}};
}

View File

@ -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

View File

@ -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)
}

View File

@ -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)

View File

@ -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,
})

View File

@ -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;
}

View File

@ -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.

View File

@ -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,
})
})

View File

@ -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(

View File

@ -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()))?

View File

@ -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.

View File

@ -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

View File

@ -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() {

View File

@ -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()),

View File

@ -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?

View File

@ -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;
}

View File

@ -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),

View File

@ -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()

View File

@ -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(

View File

@ -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()))
}

View File

@ -250,9 +250,7 @@ impl<'a> InferenceTable<'a> {
// and registering an obligation. But it needs chalk support, so we handle the most basic
// 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) {

View File

@ -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 {

View File

@ -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;
}
};
}

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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
}
}
}

View File

@ -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> {

View File

@ -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();

View File

@ -103,15 +103,15 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
}
}
impl From<chalk_ir::GeneratorId<Interner>> for crate::db::InternedGeneratorId {
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())
}
}

View File

@ -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

View File

@ -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 => (),

View File

@ -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 {

View File

@ -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 &current_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 &current_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");

View File

@ -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)?)?;

View File

@ -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));
}

View File

@ -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 {

View File

@ -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:?}"),
});

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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) {

View File

@ -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
}
}

View File

@ -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);

View File

@ -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 };

View File

@ -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); }': ()

View File

@ -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

View File

@ -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
}
"#,
)
}

View File

@ -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

View File

@ -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

View File

@ -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