diff --git a/crates/mun_codegen/Cargo.toml b/crates/mun_codegen/Cargo.toml index 4ae8019ff..f0e448e11 100644 --- a/crates/mun_codegen/Cargo.toml +++ b/crates/mun_codegen/Cargo.toml @@ -20,7 +20,7 @@ mun_target = { version = "=0.2.0", path = "../mun_target" } mun_lld = { version = "=70.2.0", path = "../mun_lld" } anyhow = "1.0.31" thiserror = "1.0.19" -salsa="0.14" +salsa = "0.15.0" md5="0.6.1" array-init="0.1.0" tempfile = "3" diff --git a/crates/mun_codegen/src/assembly.rs b/crates/mun_codegen/src/assembly.rs index ef22a8318..453da91b4 100644 --- a/crates/mun_codegen/src/assembly.rs +++ b/crates/mun_codegen/src/assembly.rs @@ -31,7 +31,7 @@ impl Assembly { } /// Create a new temporary file that contains the linked object -pub fn assembly_query(db: &impl IrDatabase, file_id: hir::FileId) -> Arc { +pub fn assembly_query(db: &dyn IrDatabase, file_id: hir::FileId) -> Arc { let file = NamedTempFile::new().expect("could not create temp file for shared object"); let module_builder = ModuleBuilder::new(db, file_id).expect("could not create ModuleBuilder"); diff --git a/crates/mun_codegen/src/code_gen.rs b/crates/mun_codegen/src/code_gen.rs index 6d624bb72..6d77baba7 100644 --- a/crates/mun_codegen/src/code_gen.rs +++ b/crates/mun_codegen/src/code_gen.rs @@ -86,17 +86,17 @@ impl ObjectFile { } /// A struct that can be used to build an LLVM `Module`. -pub struct ModuleBuilder<'a, D: IrDatabase> { - db: &'a D, +pub struct ModuleBuilder<'a> { + db: &'a dyn IrDatabase, file_id: FileId, _target: inkwell::targets::Target, target_machine: inkwell::targets::TargetMachine, assembly_module: Arc, } -impl<'a, D: IrDatabase> ModuleBuilder<'a, D> { +impl<'a> ModuleBuilder<'a> { /// Constructs module for the given `hir::FileId` at the specified output file location. - pub fn new(db: &'a D, file_id: FileId) -> Result { + pub fn new(db: &'a dyn IrDatabase, file_id: FileId) -> Result { let target = db.target(); // Construct a module for the assembly @@ -197,14 +197,14 @@ fn optimize_module(module: &Module, optimization_lvl: OptimizationLevel) { } /// Create an inkwell TargetData from the target in the database -pub(crate) fn target_data_query(db: &impl IrDatabase) -> Arc { +pub(crate) fn target_data_query(db: &dyn IrDatabase) -> Arc { Arc::new(TargetData::create(&db.target().data_layout)) } /// Returns a mapping from struct type to a struct type in the context. This is a query because the /// value of struct type depends on the target we compile for. pub(crate) fn type_to_struct_mapping_query( - db: &impl IrDatabase, + db: &dyn IrDatabase, ) -> by_address::ByAddress> { let _ = db.target_data(); by_address::ByAddress(Arc::new(RwLock::new(HashMap::default()))) diff --git a/crates/mun_codegen/src/code_gen/symbols.rs b/crates/mun_codegen/src/code_gen/symbols.rs index 0daf79db1..7c24a007f 100644 --- a/crates/mun_codegen/src/code_gen/symbols.rs +++ b/crates/mun_codegen/src/code_gen/symbols.rs @@ -13,13 +13,13 @@ use std::collections::HashSet; use std::ffi::CString; /// Construct a `MunFunctionPrototype` struct for the specified HIR function. -fn gen_prototype_from_function( - db: &D, +fn gen_prototype_from_function( + db: &dyn IrDatabase, context: &IrValueContext, function: hir::Function, ) -> ir::FunctionPrototype { let module = context.module; - let name = function.name(db).to_string(); + let name = function.name(db.upcast()).to_string(); // Internalize the name of the function prototype let name_str = CString::new(name.clone()) @@ -27,7 +27,7 @@ fn gen_prototype_from_function( .intern(format!("fn_sig::<{}>::name", &name), context); // Get the `ir::TypeInfo` pointer for the return type of the function - let fn_sig = function.ty(db).callable_sig(db).unwrap(); + let fn_sig = function.ty(db.upcast()).callable_sig(db.upcast()).unwrap(); let return_type = gen_signature_return_type(db, context, fn_sig.ret().clone()); // Construct an array of pointers to `ir::TypeInfo`s for the arguments of the prototype @@ -95,8 +95,8 @@ fn gen_prototype_from_dispatch_entry( /// Given a function, construct a pointer to a `ir::TypeInfo` global that represents the return type /// of the function; or `null` if the return type is empty. -fn gen_signature_return_type( - db: &D, +fn gen_signature_return_type( + db: &dyn IrDatabase, context: &IrValueContext, ret_type: Ty, ) -> Value<*const ir::TypeInfo> { @@ -126,15 +126,15 @@ fn gen_signature_return_type_from_type_info( /// Construct a global that holds a reference to all functions. e.g.: /// MunFunctionDefinition[] definitions = { ... } -fn get_function_definition_array<'a, D: IrDatabase>( - db: &D, +fn get_function_definition_array<'a>( + db: &dyn IrDatabase, context: &IrValueContext, functions: impl Iterator, ) -> Global<[ir::FunctionDefinition]> { let module = context.module; functions .map(|f| { - let name = f.name(db).to_string(); + let name = f.name(db.upcast()).to_string(); // Get the function from the cloned module and modify the linkage of the function. let value = module @@ -198,7 +198,7 @@ fn gen_dispatch_table( /// `get_info` is constructed that returns a struct `MunAssemblyInfo`. See the `mun_abi` crate /// for the ABI that `get_info` exposes. pub(super) fn gen_reflection_ir( - db: &impl IrDatabase, + db: &dyn IrDatabase, context: &IrValueContext, api: &HashSet, dispatch_table: &DispatchTable, @@ -237,7 +237,7 @@ pub(super) fn gen_reflection_ir( /// Construct the actual `get_info` function. fn gen_get_info_fn( - db: &impl IrDatabase, + db: &dyn IrDatabase, context: &IrValueContext, module_info: ir::ModuleInfo, dispatch_table: ir::DispatchTable, @@ -327,7 +327,7 @@ fn gen_get_info_fn( /// Generates a method `void set_allocator_handle(void*)` that stores the argument into the global /// `allocatorHandle`. This global is used internally to reference the allocator used by this /// munlib. -fn gen_set_allocator_handle_fn(db: &impl IrDatabase, context: &IrValueContext) { +fn gen_set_allocator_handle_fn(db: &dyn IrDatabase, context: &IrValueContext) { let set_allocator_handle_fn = context.module.add_function( "set_allocator_handle", Value::::get_ir_type(context.type_context), @@ -352,7 +352,7 @@ fn gen_set_allocator_handle_fn(db: &impl IrDatabase, context: &IrValueContext) { /// Generates a `get_version` method that returns the current abi version. /// Specifically, it returns the abi version the function was generated in. -fn gen_get_version_fn(db: &impl IrDatabase, context: &IrValueContext) { +fn gen_get_version_fn(db: &dyn IrDatabase, context: &IrValueContext) { let get_version_fn = context.module.add_function( abi::GET_VERSION_FN_NAME, Value:: u32>::get_ir_type(context.type_context), diff --git a/crates/mun_codegen/src/db.rs b/crates/mun_codegen/src/db.rs index d9df8bdbe..46f71bd8c 100644 --- a/crates/mun_codegen/src/db.rs +++ b/crates/mun_codegen/src/db.rs @@ -22,7 +22,7 @@ pub type StructMapping = RwLock>; /// The `IrDatabase` enables caching of intermediate in the process of LLVM IR generation. It uses /// [salsa](https://github.com/salsa-rs/salsa) for this purpose. #[salsa::query_group(IrDatabaseStorage)] -pub trait IrDatabase: hir::HirDatabase { +pub trait IrDatabase: hir::HirDatabase + hir::Upcast { /// Get the LLVM context that should be used for all generation steps. #[salsa::input] fn context(&self) -> Arc; diff --git a/crates/mun_codegen/src/ir/adt.rs b/crates/mun_codegen/src/ir/adt.rs index 0063a3a10..91a633e80 100644 --- a/crates/mun_codegen/src/ir/adt.rs +++ b/crates/mun_codegen/src/ir/adt.rs @@ -3,14 +3,14 @@ use crate::ir::try_convert_any_to_basic; use crate::{CodeGenParams, IrDatabase}; use inkwell::types::{BasicTypeEnum, StructType}; -pub(super) fn gen_struct_decl(db: &impl IrDatabase, s: hir::Struct) -> StructType { +pub(super) fn gen_struct_decl(db: &dyn IrDatabase, s: hir::Struct) -> StructType { let struct_type = db.struct_ty(s); if struct_type.is_opaque() { let field_types: Vec = s - .fields(db) + .fields(db.upcast()) .iter() .map(|field| { - let field_type = field.ty(db); + let field_type = field.ty(db.upcast()); try_convert_any_to_basic(db.type_ir( field_type, CodeGenParams { diff --git a/crates/mun_codegen/src/ir/body.rs b/crates/mun_codegen/src/ir/body.rs index 0d9792e9a..6dbb5925d 100644 --- a/crates/mun_codegen/src/ir/body.rs +++ b/crates/mun_codegen/src/ir/body.rs @@ -35,8 +35,8 @@ pub(crate) struct ExternalGlobals { pub type_table: Option>, } -pub(crate) struct BodyIrGenerator<'a, 'b, D: IrDatabase> { - db: &'a D, +pub(crate) struct BodyIrGenerator<'a, 'b> { + db: &'a dyn IrDatabase, body: Arc, infer: Arc, builder: Builder, @@ -53,9 +53,9 @@ pub(crate) struct BodyIrGenerator<'a, 'b, D: IrDatabase> { external_globals: ExternalGlobals, } -impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { +impl<'a, 'b> BodyIrGenerator<'a, 'b> { pub fn new( - db: &'a D, + db: &'a dyn IrDatabase, function: (hir::Function, FunctionValue), function_map: &'a HashMap, dispatch_table: &'b DispatchTable, @@ -66,8 +66,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let (hir_function, ir_function) = function; // Get the type information from the `hir::Function` - let body = hir_function.body(db); - let infer = hir_function.infer(db); + let body = hir_function.body(db.upcast()); + let infer = hir_function.infer(db.upcast()); // Construct a builder for the IR function let context = db.context(); @@ -132,8 +132,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let block_ret_type = &self.infer[self.body.body_expr()]; let fn_ret_type = self .hir_function - .ty(self.db) - .callable_sig(self.db) + .ty(self.db.upcast()) + .callable_sig(self.db.upcast()) .unwrap() .ret() .clone(); @@ -147,7 +147,11 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { } pub fn gen_fn_wrapper(&mut self) { - let fn_sig = self.hir_function.ty(self.db).callable_sig(self.db).unwrap(); + let fn_sig = self + .hir_function + .ty(self.db.upcast()) + .callable_sig(self.db.upcast()) + .unwrap(); let args: Vec = fn_sig .params() .iter() @@ -155,7 +159,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { .map(|(idx, ty)| { let param = self.fn_value.get_nth_param(idx as u32).unwrap(); if let Some(s) = ty.as_struct() { - if s.data(self.db).memory_kind == abi::StructMemoryKind::Value { + if s.data(self.db.upcast()).memory_kind == abi::StructMemoryKind::Value { deref_heap_value(&self.builder, param) } else { param @@ -175,8 +179,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { if !call_return_type.is_never() { let fn_ret_type = self .hir_function - .ty(self.db) - .callable_sig(self.db) + .ty(self.db.upcast()) + .callable_sig(self.db.upcast()) .unwrap() .ret() .clone(); @@ -185,7 +189,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { self.builder.build_return(None); } else if let Some(value) = ret_value { let ret_value = if let Some(hir_struct) = fn_ret_type.as_struct() { - if hir_struct.data(self.db).memory_kind == hir::StructMemoryKind::Value { + if hir_struct.data(self.db.upcast()).memory_kind == hir::StructMemoryKind::Value + { self.gen_struct_alloc_on_heap(hir_struct, value.into_struct_value()) } else { value @@ -208,7 +213,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { tail, } => self.gen_block(expr, statements, *tail), Expr::Path(ref p) => { - let resolver = hir::resolver_for_expr(self.body.clone(), self.db, expr); + let resolver = hir::resolver_for_expr(self.body.clone(), self.db.upcast(), expr); Some(self.gen_path_expr(p, expr, &resolver)) } Expr::Literal(lit) => Some(self.gen_literal(lit, expr)), @@ -350,7 +355,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { } let struct_lit = value.into_struct_value(); - match hir_struct.data(self.db).memory_kind { + match hir_struct.data(self.db.upcast()).memory_kind { hir::StructMemoryKind::Value => struct_lit.into(), hir::StructMemoryKind::GC => { // TODO: Root memory in GC @@ -373,7 +378,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let type_info_ptr = self.type_table.gen_type_info_lookup( &self.builder, - &self.db.type_info(hir_struct.ty(self.db)), + &self.db.type_info(hir_struct.ty(self.db.upcast())), self.external_globals.type_table, ); @@ -410,7 +415,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { struct_ir_ty .ptr_type(AddressSpace::Generic) .ptr_type(AddressSpace::Generic), - &format!("{}_ptr_ptr", hir_struct.name(self.db).to_string()), + &format!("{}_ptr_ptr", hir_struct.name(self.db.upcast()).to_string()), ) .into_pointer_value(); @@ -419,7 +424,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { .builder .build_load( struct_ptr_ptr, - &format!("{}_mem_ptr", hir_struct.name(self.db).to_string()), + &format!("{}_mem_ptr", hir_struct.name(self.db.upcast()).to_string()), ) .into_pointer_value(); @@ -545,7 +550,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { resolver: &Resolver, ) -> inkwell::values::BasicValueEnum { let resolution = resolver - .resolve_path_without_assoc_items(self.db, path) + .resolve_path_without_assoc_items(self.db.upcast(), path) .take_values() .expect("unknown path"); @@ -574,7 +579,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { .. }) = ty { - if s.data(self.db).memory_kind == hir::StructMemoryKind::GC { + if s.data(self.db.upcast()).memory_kind == hir::StructMemoryKind::GC { return deref_heap_value(&self.builder, value); } } @@ -589,7 +594,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { resolver: &Resolver, ) -> inkwell::values::PointerValue { let resolution = resolver - .resolve_path_without_assoc_items(self.db, path) + .resolve_path_without_assoc_items(self.db.upcast(), path) .take_values() .expect("unknown path"); @@ -616,7 +621,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { Some(TypeCtor::Float(_ty)) => self.gen_binary_op_float(lhs, rhs, op), Some(TypeCtor::Int(ty)) => self.gen_binary_op_int(lhs, rhs, op, ty.signedness), Some(TypeCtor::Struct(s)) => { - if s.data(self.db).memory_kind == hir::StructMemoryKind::Value { + if s.data(self.db.upcast()).memory_kind == hir::StructMemoryKind::Value { self.gen_binary_op_value_struct(lhs, rhs, op) } else { self.gen_binary_op_heap_struct(lhs, rhs, op) @@ -626,8 +631,8 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let rhs_type = self.infer[rhs].clone(); unimplemented!( "unimplemented operation {0}op{1}", - lhs_type.display(self.db), - rhs_type.display(self.db) + lhs_type.display(self.db.upcast()), + rhs_type.display(self.db.upcast()) ) } } @@ -640,7 +645,10 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { Some(TypeCtor::Float(_ty)) => self.gen_unary_op_float(expr, op), Some(TypeCtor::Int(ty)) => self.gen_unary_op_int(expr, op, ty.signedness), Some(TypeCtor::Bool) => self.gen_unary_op_bool(expr, op), - _ => unimplemented!("unimplemented operation op{0}", ty.display(self.db)), + _ => unimplemented!( + "unimplemented operation op{0}", + ty.display(self.db.upcast()) + ), } } @@ -1016,7 +1024,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { let body = self.body.clone(); match &body[expr] { Expr::Path(ref p) => { - let resolver = hir::resolver_for_expr(self.body.clone(), self.db, expr); + let resolver = hir::resolver_for_expr(self.body.clone(), self.db.upcast(), expr); self.gen_path_place_expr(p, expr, &resolver) } Expr::Field { @@ -1052,17 +1060,23 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { &self.builder, function, ); - self.builder - .build_call(ptr_value, &args, &function.name(self.db).to_string()) + self.builder.build_call( + ptr_value, + &args, + &function.name(self.db.upcast()).to_string(), + ) } else { let llvm_function = self.function_map.get(&function).unwrap_or_else(|| { panic!( "missing function value for hir function: '{}'", - function.name(self.db), + function.name(self.db.upcast()), ) }); - self.builder - .build_call(*llvm_function, &args, &function.name(self.db).to_string()) + self.builder.build_call( + *llvm_function, + &args, + &function.name(self.db.upcast()).to_string(), + ) } } @@ -1283,10 +1297,10 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { .as_struct() .expect("expected a struct"); - let hir_struct_name = hir_struct.name(self.db); + let hir_struct_name = hir_struct.name(self.db.upcast()); let field_idx = hir_struct - .field(self.db, name) + .field(self.db.upcast(), name) .expect("expected a struct field") .id() .into_raw() @@ -1334,10 +1348,10 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { .as_struct() .expect("expected a struct"); - let hir_struct_name = hir_struct.name(self.db); + let hir_struct_name = hir_struct.name(self.db.upcast()); let field_idx = hir_struct - .field(self.db, name) + .field(self.db.upcast(), name) .expect("expected a struct field") .id() .into_raw() diff --git a/crates/mun_codegen/src/ir/dispatch_table.rs b/crates/mun_codegen/src/ir/dispatch_table.rs index 89c79064c..2052ddb89 100644 --- a/crates/mun_codegen/src/ir/dispatch_table.rs +++ b/crates/mun_codegen/src/ir/dispatch_table.rs @@ -73,14 +73,14 @@ impl DispatchTable { /// Generate a function lookup through the DispatchTable, equivalent to something along the /// lines of: `dispatchTable[i]`, where i is the index of the function and `dispatchTable` is a /// struct - pub fn gen_function_lookup( + pub fn gen_function_lookup( &self, - db: &D, + db: &dyn IrDatabase, table_ref: Option, builder: &inkwell::builder::Builder, function: hir::Function, ) -> PointerValue { - let function_name = function.name(db).to_string(); + let function_name = function.name(db.upcast()).to_string(); // Get the index of the function let index = *self @@ -149,8 +149,8 @@ impl DispatchTable { } /// A struct that can be used to build the dispatch table from HIR. -pub(crate) struct DispatchTableBuilder<'a, D: IrDatabase> { - db: &'a D, +pub(crate) struct DispatchTableBuilder<'a> { + db: &'a dyn IrDatabase, // The LLVM context in which all LLVM types live context: Arc, // The module in which all values live @@ -174,10 +174,10 @@ struct TypedDispatchableFunction { ir_type: FunctionType, } -impl<'a, D: IrDatabase> DispatchTableBuilder<'a, D> { +impl<'a> DispatchTableBuilder<'a> { /// Creates a new builder that can generate a dispatch function. pub fn new( - db: &'a D, + db: &'a dyn IrDatabase, module: &'a Module, intrinsics: &BTreeMap, ) -> Self { @@ -247,9 +247,9 @@ impl<'a, D: IrDatabase> DispatchTableBuilder<'a, D> { // If the function is not yet contained in the table, add it if !self.function_to_idx.contains_key(&function) { - let name = function.name(self.db).to_string(); - let hir_type = function.ty(self.db); - let sig = hir_type.callable_sig(self.db).unwrap(); + let name = function.name(self.db.upcast()).to_string(); + let hir_type = function.ty(self.db.upcast()); + let sig = hir_type.callable_sig(self.db.upcast()).unwrap(); let ir_type = self .db .type_ir( @@ -287,11 +287,11 @@ impl<'a, D: IrDatabase> DispatchTableBuilder<'a, D> { self.function_to_idx.insert(function, index); // Recurse further - let fn_body = function.body(self.db); + let fn_body = function.body(self.db.upcast()); self.collect_expr( fn_body.body_expr(), &fn_body, - function.infer(self.db).as_ref(), + function.infer(self.db.upcast()).as_ref(), ); } } @@ -329,7 +329,7 @@ impl<'a, D: IrDatabase> DispatchTableBuilder<'a, D> { match entry.function.hir { // Case external function: Convert to typed null for the given function None => function_type.const_null(), - Some(f) if f.is_extern(self.db) => function_type.const_null(), + Some(f) if f.is_extern(self.db.upcast()) => function_type.const_null(), // Case mun function: Get the function location as the initializer Some(f) => function::gen_signature( self.db, diff --git a/crates/mun_codegen/src/ir/file.rs b/crates/mun_codegen/src/ir/file.rs index b3d099604..d1db08c92 100644 --- a/crates/mun_codegen/src/ir/file.rs +++ b/crates/mun_codegen/src/ir/file.rs @@ -19,7 +19,7 @@ pub struct FileIR { } /// Generates IR for the specified file. -pub(crate) fn ir_query(db: &impl IrDatabase, file_id: FileId) -> Arc { +pub(crate) fn ir_query(db: &dyn IrDatabase, file_id: FileId) -> Arc { let llvm_module = db .context() .create_module(db.file_relative_path(file_id).as_str()); @@ -32,7 +32,7 @@ pub(crate) fn ir_query(db: &impl IrDatabase, file_id: FileId) -> Arc { let mut wrapper_functions = BTreeMap::new(); for def in db.module_data(file_id).definitions() { if let ModuleDef::Function(f) = def { - if !f.is_extern(db) { + if !f.is_extern(db.upcast()) { let fun = function::gen_signature( db, *f, @@ -43,8 +43,10 @@ pub(crate) fn ir_query(db: &impl IrDatabase, file_id: FileId) -> Arc { ); functions.insert(*f, fun); - let fn_sig = f.ty(db).callable_sig(db).unwrap(); - if !f.data(db).visibility().is_private() && !fn_sig.marshallable(db) { + let fn_sig = f.ty(db.upcast()).callable_sig(db.upcast()).unwrap(); + if !f.data(db.upcast()).visibility().is_private() + && !fn_sig.marshallable(db.upcast()) + { let wrapper_fun = function::gen_signature( db, *f, @@ -110,7 +112,7 @@ pub(crate) fn ir_query(db: &impl IrDatabase, file_id: FileId) -> Arc { // Filter private methods let api: HashSet = functions .keys() - .filter(|f| f.visibility(db) != hir::Visibility::Private) + .filter(|f| f.visibility(db.upcast()) != hir::Visibility::Private) .cloned() .collect(); diff --git a/crates/mun_codegen/src/ir/file_group.rs b/crates/mun_codegen/src/ir/file_group.rs index 94196d4fc..ef64af8ee 100644 --- a/crates/mun_codegen/src/ir/file_group.rs +++ b/crates/mun_codegen/src/ir/file_group.rs @@ -27,7 +27,7 @@ pub struct FileGroupIR { /// Generates IR that is shared among the group's files. /// TODO: Currently, a group always consists of a single file. Need to add support for multiple /// files using something like `FileGroupId`. -pub(crate) fn ir_query(db: &impl IrDatabase, file_id: hir::FileId) -> Arc { +pub(crate) fn ir_query(db: &dyn IrDatabase, file_id: hir::FileId) -> Arc { let llvm_module = db.context().create_module("group_name"); // Use a `BTreeMap` to guarantee deterministically ordered output. @@ -37,17 +37,19 @@ pub(crate) fn ir_query(db: &impl IrDatabase, file_id: hir::FileId) -> Arc { + ModuleDef::Function(f) if !f.is_extern(db.upcast()) => { intrinsics::collect_fn_body( db, &mut intrinsics_map, &mut needs_alloc, - &f.body(db), - &f.infer(db), + &f.body(db.upcast()), + &f.infer(db.upcast()), ); - let fn_sig = f.ty(db).callable_sig(db).unwrap(); - if !f.data(db).visibility().is_private() && !fn_sig.marshallable(db) { + let fn_sig = f.ty(db.upcast()).callable_sig(db.upcast()).unwrap(); + if !f.data(db.upcast()).visibility().is_private() + && !fn_sig.marshallable(db.upcast()) + { intrinsics::collect_wrapper_body(db, &mut intrinsics_map, &mut needs_alloc); } } @@ -63,9 +65,9 @@ pub(crate) fn ir_query(db: &impl IrDatabase, file_id: hir::FileId) -> Arc FunctionValue { let name = { - let name = f.name(db).to_string(); + let name = f.name(db.upcast()).to_string(); if params.make_marshallable { format!("{}_wrapper", name) } else { @@ -41,7 +41,7 @@ pub(crate) fn gen_signature( } }; - if let AnyTypeEnum::FunctionType(ty) = db.type_ir(f.ty(db), params) { + if let AnyTypeEnum::FunctionType(ty) = db.type_ir(f.ty(db.upcast()), params) { module.add_function(&name, ty, None) } else { panic!("not a function type") @@ -49,8 +49,8 @@ pub(crate) fn gen_signature( } /// Generates the body of a `hir::Function` for an associated `FunctionValue`. -pub(crate) fn gen_body<'a, 'b, D: IrDatabase>( - db: &'a D, +pub(crate) fn gen_body<'a, 'b>( + db: &'a dyn IrDatabase, function: (hir::Function, FunctionValue), llvm_functions: &'a HashMap, dispatch_table: &'b DispatchTable, @@ -74,8 +74,8 @@ pub(crate) fn gen_body<'a, 'b, D: IrDatabase>( /// Generates the body of a wrapper around `hir::Function` for its associated /// `FunctionValue` -pub(crate) fn gen_wrapper_body<'a, 'b, D: IrDatabase>( - db: &'a D, +pub(crate) fn gen_wrapper_body<'a, 'b>( + db: &'a dyn IrDatabase, function: (hir::Function, FunctionValue), llvm_functions: &'a HashMap, dispatch_table: &'b DispatchTable, diff --git a/crates/mun_codegen/src/ir/intrinsics.rs b/crates/mun_codegen/src/ir/intrinsics.rs index fc59b6a3d..2223bd92f 100644 --- a/crates/mun_codegen/src/ir/intrinsics.rs +++ b/crates/mun_codegen/src/ir/intrinsics.rs @@ -9,11 +9,7 @@ use std::sync::Arc; // Use a `BTreeMap` to guarantee deterministically ordered output pub type IntrinsicsMap = BTreeMap; -fn collect_intrinsic( - d: &D, - entries: &mut IntrinsicsMap, - intrinsic: &impl Intrinsic, -) { +fn collect_intrinsic(d: &dyn IrDatabase, entries: &mut IntrinsicsMap, intrinsic: &impl Intrinsic) { let context = d.context(); let target = d.target_data(); let prototype = intrinsic.prototype(context.as_ref(), target.as_ref()); @@ -22,8 +18,8 @@ fn collect_intrinsic( .or_insert_with(|| intrinsic.ir_type(context.as_ref(), target.as_ref())); } -fn collect_expr( - db: &D, +fn collect_expr( + db: &dyn IrDatabase, entries: &mut IntrinsicsMap, needs_alloc: &mut bool, expr_id: ExprId, @@ -52,9 +48,9 @@ fn collect_expr( } if let Expr::Path(path) = expr { - let resolver = hir::resolver_for_expr(body.clone(), db, expr_id); + let resolver = hir::resolver_for_expr(body.clone(), db.upcast(), expr_id); let resolution = resolver - .resolve_path_without_assoc_items(db, path) + .resolve_path_without_assoc_items(db.upcast(), path) .take_values() .expect("unknown path"); @@ -69,8 +65,8 @@ fn collect_expr( expr.walk_child_exprs(|expr_id| collect_expr(db, entries, needs_alloc, expr_id, body, infer)) } -pub fn collect_fn_body( - db: &D, +pub fn collect_fn_body( + db: &dyn IrDatabase, entries: &mut IntrinsicsMap, needs_alloc: &mut bool, body: &Arc, @@ -79,8 +75,8 @@ pub fn collect_fn_body( collect_expr(db, entries, needs_alloc, body.body_expr(), body, infer); } -pub fn collect_wrapper_body( - db: &D, +pub fn collect_wrapper_body( + db: &dyn IrDatabase, entries: &mut IntrinsicsMap, needs_alloc: &mut bool, ) { diff --git a/crates/mun_codegen/src/ir/ty.rs b/crates/mun_codegen/src/ir/ty.rs index 66d097e7e..1c25100e3 100644 --- a/crates/mun_codegen/src/ir/ty.rs +++ b/crates/mun_codegen/src/ir/ty.rs @@ -14,7 +14,7 @@ use inkwell::{ /// Given a mun type, construct an LLVM IR type #[rustfmt::skip] -pub(crate) fn ir_query(db: &impl IrDatabase, ty: Ty, params: CodeGenParams) -> AnyTypeEnum { +pub(crate) fn ir_query(db: &dyn IrDatabase, ty: Ty, params: CodeGenParams) -> AnyTypeEnum { let context = db.context(); match ty { Ty::Empty => AnyTypeEnum::StructType(context.struct_type(&[], false)), @@ -44,7 +44,7 @@ pub(crate) fn ir_query(db: &impl IrDatabase, ty: Ty, params: CodeGenParams) -> A } TypeCtor::Struct(s) => { let struct_ty = db.struct_ty(s); - match s.data(db).memory_kind { + match s.data(db.upcast()).memory_kind { hir::StructMemoryKind::GC => struct_ty.ptr_type(AddressSpace::Generic).ptr_type(AddressSpace::Generic).into(), hir::StructMemoryKind::Value if params.make_marshallable => struct_ty.ptr_type(AddressSpace::Generic).ptr_type(AddressSpace::Generic).into(), @@ -58,7 +58,7 @@ pub(crate) fn ir_query(db: &impl IrDatabase, ty: Ty, params: CodeGenParams) -> A } /// Returns the LLVM IR type of the specified float type -fn float_ty_query(db: &impl IrDatabase, fty: FloatTy) -> FloatType { +fn float_ty_query(db: &dyn IrDatabase, fty: FloatTy) -> FloatType { let context = db.context(); match fty.bitness.resolve(&db.target_data_layout()) { FloatBitness::X64 => context.f64_type(), @@ -67,7 +67,7 @@ fn float_ty_query(db: &impl IrDatabase, fty: FloatTy) -> FloatType { } /// Returns the LLVM IR type of the specified int type -fn int_ty_query(db: &impl IrDatabase, ity: IntTy) -> IntType { +fn int_ty_query(db: &dyn IrDatabase, ity: IntTy) -> IntType { let context = db.context(); match ity.bitness.resolve(&db.target_data_layout()) { IntBitness::X128 => context.i128_type(), @@ -80,12 +80,12 @@ fn int_ty_query(db: &impl IrDatabase, ity: IntTy) -> IntType { } /// Returns the LLVM IR type of the specified struct -pub fn struct_ty_query(db: &impl IrDatabase, s: hir::Struct) -> StructType { - let name = s.name(db).to_string(); - for field in s.fields(db).iter() { +pub fn struct_ty_query(db: &dyn IrDatabase, s: hir::Struct) -> StructType { + let name = s.name(db.upcast()).to_string(); + for field in s.fields(db.upcast()).iter() { // Ensure that salsa's cached value incorporates the struct fields let _field_type_ir = db.type_ir( - field.ty(db), + field.ty(db.upcast()), CodeGenParams { make_marshallable: false, }, @@ -96,7 +96,7 @@ pub fn struct_ty_query(db: &impl IrDatabase, s: hir::Struct) -> StructType { } /// Constructs the `TypeInfo` for the specified HIR type -pub fn type_info_query(db: &impl IrDatabase, ty: Ty) -> TypeInfo { +pub fn type_info_query(db: &dyn IrDatabase, ty: Ty) -> TypeInfo { let target = db.target_data(); match ty { Ty::Apply(ctor) => match ctor.ctor { diff --git a/crates/mun_codegen/src/ir/type_table.rs b/crates/mun_codegen/src/ir/type_table.rs index ba167e2bc..984d1e830 100644 --- a/crates/mun_codegen/src/ir/type_table.rs +++ b/crates/mun_codegen/src/ir/type_table.rs @@ -87,18 +87,18 @@ impl TypeTable { } /// Used to build a `TypeTable` from HIR. -pub(crate) struct TypeTableBuilder<'a, 'ctx, 'm, D: IrDatabase> { - db: &'a D, +pub(crate) struct TypeTableBuilder<'a, 'ctx, 'm> { + db: &'a dyn IrDatabase, target_data: Arc, value_context: &'a IrValueContext<'a, 'ctx, 'm>, dispatch_table: &'a DispatchTable, entries: BTreeSet, // Use a `BTreeSet` to guarantee deterministically ordered output } -impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { +impl<'a, 'ctx, 'm> TypeTableBuilder<'a, 'ctx, 'm> { /// Creates a new `TypeTableBuilder`. pub(crate) fn new<'f>( - db: &'a D, + db: &'a dyn IrDatabase, value_context: &'a IrValueContext<'a, 'ctx, 'm>, intrinsics: impl Iterator, dispatch_table: &'a DispatchTable, @@ -145,8 +145,13 @@ impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { /// Collects unique `TypeInfo` from the specified function signature and body. pub fn collect_fn(&mut self, hir_fn: hir::Function) { // Collect type info for exposed function - if !hir_fn.data(self.db).visibility().is_private() || self.dispatch_table.contains(hir_fn) { - let fn_sig = hir_fn.ty(self.db).callable_sig(self.db).unwrap(); + if !hir_fn.data(self.db.upcast()).visibility().is_private() + || self.dispatch_table.contains(hir_fn) + { + let fn_sig = hir_fn + .ty(self.db.upcast()) + .callable_sig(self.db.upcast()) + .unwrap(); // Collect argument types for ty in fn_sig.params().iter() { @@ -161,19 +166,19 @@ impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { } // Collect used types from body - let body = hir_fn.body(self.db); - let infer = hir_fn.infer(self.db); + let body = hir_fn.body(self.db.upcast()); + let infer = hir_fn.infer(self.db.upcast()); self.collect_expr(body.body_expr(), &body, &infer); } /// Collects unique `TypeInfo` from the specified struct type. pub fn collect_struct(&mut self, hir_struct: hir::Struct) { - let type_info = self.db.type_info(hir_struct.ty(self.db)); + let type_info = self.db.type_info(hir_struct.ty(self.db.upcast())); self.entries.insert(type_info); - let fields = hir_struct.fields(self.db); + let fields = hir_struct.fields(self.db.upcast()); for field in fields.into_iter() { - self.collect_type(self.db.type_info(field.ty(self.db))); + self.collect_type(self.db.type_info(field.ty(self.db.upcast()))); } } @@ -243,15 +248,15 @@ impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { hir_struct: hir::Struct, ) -> Value { let struct_ir = self.db.struct_ty(hir_struct); - let name = hir_struct.name(self.db).to_string(); - let fields = hir_struct.fields(self.db); + let name = hir_struct.name(self.db.upcast()).to_string(); + let fields = hir_struct.fields(self.db.upcast()); // Construct an array of field names (or null if there are no fields) let field_names = fields .iter() .enumerate() .map(|(idx, field)| { - CString::new(field.name(self.db).to_string()) + CString::new(field.name(self.db.upcast()).to_string()) .expect("field name is not a valid CString") .intern( format!("struct_info::<{}>::field_names.{}", name, idx), @@ -268,7 +273,7 @@ impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { let field_types = fields .iter() .map(|field| { - let field_type_info = self.db.type_info(field.ty(self.db)); + let field_type_info = self.db.type_info(field.ty(self.db.upcast())); self.gen_type_info(type_info_to_ir, &field_type_info) }) .into_const_private_pointer_or_null( @@ -298,7 +303,7 @@ impl<'a, 'ctx, 'm, D: IrDatabase> TypeTableBuilder<'a, 'ctx, 'm, D> { .len() .try_into() .expect("could not convert num_fields to smaller bit size"), - memory_kind: hir_struct.data(self.db).memory_kind.clone(), + memory_kind: hir_struct.data(self.db.upcast()).memory_kind.clone(), } .as_value(self.value_context) } diff --git a/crates/mun_codegen/src/mock.rs b/crates/mun_codegen/src/mock.rs index d6ff085e3..85affa3b9 100644 --- a/crates/mun_codegen/src/mock.rs +++ b/crates/mun_codegen/src/mock.rs @@ -10,26 +10,36 @@ use std::sync::Arc; hir::HirDatabaseStorage, crate::IrDatabaseStorage )] -#[derive(Default, Debug)] +#[derive(Default)] pub(crate) struct MockDatabase { - runtime: salsa::Runtime, - events: Mutex>>>, + storage: salsa::Storage, + events: Mutex>>, } impl salsa::Database for MockDatabase { - fn salsa_runtime(&self) -> &salsa::Runtime { - &self.runtime + fn salsa_event(&self, event: salsa::Event) { + let mut events = self.events.lock(); + if let Some(events) = &mut *events { + events.push(event); + } } +} - fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime { - &mut self.runtime +impl hir::Upcast for MockDatabase { + fn upcast(&self) -> &dyn hir::SourceDatabase { + &*self } +} - fn salsa_event(&self, event: impl Fn() -> salsa::Event) { - let mut events = self.events.lock(); - if let Some(events) = &mut *events { - events.push(event()); - } +impl hir::Upcast for MockDatabase { + fn upcast(&self) -> &dyn hir::DefDatabase { + &*self + } +} + +impl hir::Upcast for MockDatabase { + fn upcast(&self) -> &dyn hir::HirDatabase { + &*self } } @@ -57,7 +67,7 @@ impl MockDatabase { (db, file_id) } - pub fn log(&self, f: impl FnOnce()) -> Vec> { + pub fn log(&self, f: impl FnOnce()) -> Vec { *self.events.lock() = Some(Vec::new()); f(); self.events.lock().take().unwrap() @@ -71,7 +81,7 @@ impl MockDatabase { // This pretty horrible, but `Debug` is the only way to inspect // QueryDescriptor at the moment. salsa::EventKind::WillExecute { database_key } => { - Some(format!("{:?}", database_key)) + Some(format!("{:?}", database_key.debug(self))) } _ => None, }) diff --git a/crates/mun_codegen/src/type_info.rs b/crates/mun_codegen/src/type_info.rs index d091da03a..60344b2b8 100644 --- a/crates/mun_codegen/src/type_info.rs +++ b/crates/mun_codegen/src/type_info.rs @@ -100,18 +100,18 @@ impl TypeInfo { } } - pub fn new_struct(db: &D, s: hir::Struct, type_size: TypeSize) -> TypeInfo { - let name = s.name(db).to_string(); + pub fn new_struct(db: &dyn IrDatabase, s: hir::Struct, type_size: TypeSize) -> TypeInfo { + let name = s.name(db.upcast()).to_string(); let guid_string = { let fields: Vec = s - .fields(db) + .fields(db.upcast()) .into_iter() .map(|f| { let ty_string = f - .ty(db) - .guid_string(db) + .ty(db.upcast()) + .guid_string(db.upcast()) .expect("type should be convertible to a string"); - format!("{}: {}", f.name(db).to_string(), ty_string) + format!("{}: {}", f.name(db.upcast()).to_string(), ty_string) }) .collect(); diff --git a/crates/mun_compiler/src/db.rs b/crates/mun_compiler/src/db.rs index 5f3b16c51..d151c0096 100644 --- a/crates/mun_compiler/src/db.rs +++ b/crates/mun_compiler/src/db.rs @@ -1,6 +1,6 @@ use crate::Config; use mun_codegen::IrDatabase; -use mun_hir::{salsa, HirDatabase}; +use mun_hir::{salsa, HirDatabase, Upcast}; use std::sync::Arc; /// A compiler database is a salsa database that enables increment compilation. @@ -10,16 +10,39 @@ use std::sync::Arc; mun_hir::HirDatabaseStorage, mun_codegen::IrDatabaseStorage )] -#[derive(Debug)] pub struct CompilerDatabase { - runtime: salsa::Runtime, + storage: salsa::Storage, +} + +impl Upcast for CompilerDatabase { + fn upcast(&self) -> &dyn mun_hir::SourceDatabase { + &*self + } +} + +impl Upcast for CompilerDatabase { + fn upcast(&self) -> &dyn mun_hir::DefDatabase { + &*self + } +} + +impl Upcast for CompilerDatabase { + fn upcast(&self) -> &dyn mun_hir::HirDatabase { + &*self + } +} + +impl Upcast for CompilerDatabase { + fn upcast(&self) -> &dyn mun_codegen::IrDatabase { + &*self + } } impl CompilerDatabase { /// Constructs a new database pub fn new(config: &Config) -> Self { let mut db = CompilerDatabase { - runtime: salsa::Runtime::default(), + storage: Default::default(), }; // Set the initial configuration @@ -36,12 +59,4 @@ impl CompilerDatabase { } } -impl salsa::Database for CompilerDatabase { - fn salsa_runtime(&self) -> &salsa::Runtime { - &self.runtime - } - - fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime { - &mut self.runtime - } -} +impl salsa::Database for CompilerDatabase {} diff --git a/crates/mun_compiler/src/diagnostics.rs b/crates/mun_compiler/src/diagnostics.rs index 57945439b..f81abbad0 100644 --- a/crates/mun_compiler/src/diagnostics.rs +++ b/crates/mun_compiler/src/diagnostics.rs @@ -23,7 +23,7 @@ pub fn emit_diagnostics<'a>( } /// Constructs diagnostic messages for the given file. -pub fn diagnostics(db: &impl HirDatabase, file_id: FileId) -> Vec { +pub fn diagnostics(db: &dyn HirDatabase, file_id: FileId) -> Vec { let parse = db.parse(file_id); let mut result = Vec::new(); diff --git a/crates/mun_compiler/src/diagnostics_snippets.rs b/crates/mun_compiler/src/diagnostics_snippets.rs index b9c809559..0f2ff31e9 100644 --- a/crates/mun_compiler/src/diagnostics_snippets.rs +++ b/crates/mun_compiler/src/diagnostics_snippets.rs @@ -37,7 +37,7 @@ fn syntax_node_ptr_location( pub(crate) fn syntax_error( syntax_error: &SyntaxError, - _: &impl HirDatabase, + _: &dyn HirDatabase, _: &Parse, relative_file_path: &str, source_code: &str, @@ -71,7 +71,7 @@ pub(crate) fn syntax_error( pub(crate) fn generic_error( diagnostic: &dyn HirDiagnostic, - _: &impl HirDatabase, + _: &dyn HirDatabase, _: &Parse, relative_file_path: &str, source_code: &str, @@ -98,7 +98,7 @@ pub(crate) fn generic_error( pub(crate) fn unresolved_value_error( diagnostic: &mun_hir::diagnostics::UnresolvedValue, - _: &impl HirDatabase, + _: &dyn HirDatabase, parse: &Parse, relative_file_path: &str, source_code: &str, @@ -134,7 +134,7 @@ pub(crate) fn unresolved_value_error( pub(crate) fn unresolved_type_error( diagnostic: &mun_hir::diagnostics::UnresolvedType, - _: &impl HirDatabase, + _: &dyn HirDatabase, parse: &Parse, relative_file_path: &str, source_code: &str, @@ -171,7 +171,7 @@ pub(crate) fn unresolved_type_error( pub(crate) fn expected_function_error( diagnostic: &mun_hir::diagnostics::ExpectedFunction, - hir_database: &impl HirDatabase, + hir_database: &dyn HirDatabase, _: &Parse, relative_file_path: &str, source_code: &str, @@ -201,7 +201,7 @@ pub(crate) fn expected_function_error( pub(crate) fn mismatched_type_error( diagnostic: &mun_hir::diagnostics::MismatchedType, - hir_database: &impl HirDatabase, + hir_database: &dyn HirDatabase, _: &Parse, relative_file_path: &str, source_code: &str, @@ -232,7 +232,7 @@ pub(crate) fn mismatched_type_error( pub(crate) fn duplicate_definition_error( diagnostic: &mun_hir::diagnostics::DuplicateDefinition, - _: &impl HirDatabase, + _: &dyn HirDatabase, parse: &Parse, relative_file_path: &str, source_code: &str, @@ -289,7 +289,7 @@ pub(crate) fn duplicate_definition_error( pub(crate) fn possibly_uninitialized_variable_error( diagnostic: &mun_hir::diagnostics::PossiblyUninitializedVariable, - _: &impl HirDatabase, + _: &dyn HirDatabase, parse: &Parse, relative_file_path: &str, source_code: &str, @@ -318,7 +318,7 @@ pub(crate) fn possibly_uninitialized_variable_error( pub(crate) fn access_unknown_field_error( diagnostic: &mun_hir::diagnostics::AccessUnknownField, - hir_database: &impl HirDatabase, + hir_database: &dyn HirDatabase, parse: &Parse, relative_file_path: &str, source_code: &str, diff --git a/crates/mun_compiler/src/driver.rs b/crates/mun_compiler/src/driver.rs index 772bc3d0e..cdbadac26 100644 --- a/crates/mun_compiler/src/driver.rs +++ b/crates/mun_compiler/src/driver.rs @@ -27,7 +27,6 @@ use walkdir::WalkDir; pub const WORKSPACE: SourceRootId = SourceRootId(0); -#[derive(Debug)] pub struct Driver { db: CompilerDatabase, out_dir: PathBuf, diff --git a/crates/mun_hir/Cargo.toml b/crates/mun_hir/Cargo.toml index e0666ae10..9d4d15c60 100644 --- a/crates/mun_hir/Cargo.toml +++ b/crates/mun_hir/Cargo.toml @@ -13,7 +13,7 @@ keywords = ["game", "hot-reloading", "language", "mun", "scripting"] categories = ["game-development", "mun"] [dependencies] -salsa="0.14" +salsa = "0.15.0" superslice = "1.0" mun_syntax = { version = "=0.2.0", path = "../mun_syntax" } mun_target = { version = "=0.2.0", path = "../mun_target" } diff --git a/crates/mun_hir/src/adt.rs b/crates/mun_hir/src/adt.rs index c59248b13..42f934311 100644 --- a/crates/mun_hir/src/adt.rs +++ b/crates/mun_hir/src/adt.rs @@ -62,7 +62,7 @@ pub struct StructData { } impl StructData { - pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc { + pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { let src = id.source(db); let name = src .value diff --git a/crates/mun_hir/src/code_model.rs b/crates/mun_hir/src/code_model.rs index f7a083af1..fd818f9c9 100644 --- a/crates/mun_hir/src/code_model.rs +++ b/crates/mun_hir/src/code_model.rs @@ -39,17 +39,17 @@ impl Module { } /// Returns all the definitions declared in this module. - pub fn declarations(self, db: &impl HirDatabase) -> Vec { + pub fn declarations(self, db: &dyn HirDatabase) -> Vec { db.module_data(self.file_id).definitions.clone() } - fn resolver(self, _db: &impl DefDatabase) -> Resolver { + fn resolver(self, _db: &dyn DefDatabase) -> Resolver { Resolver::default().push_module_scope(self.file_id) } - pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { + pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { for diag in db.module_data(self.file_id).diagnostics.iter() { - diag.add_to(db, self, sink); + diag.add_to(db.upcast(), self, sink); } for decl in self.declarations(db) { #[allow(clippy::single_match)] @@ -74,7 +74,7 @@ pub struct ModuleScope { } impl ModuleData { - pub(crate) fn module_data_query(db: &impl DefDatabase, file_id: FileId) -> Arc { + pub(crate) fn module_data_query(db: &dyn DefDatabase, file_id: FileId) -> Arc { let items = db.raw_items(file_id); let mut data = ModuleData::default(); let loc_ctx = LocationCtx::new(db, file_id); @@ -155,20 +155,20 @@ pub enum Visibility { } impl DefWithBody { - pub fn infer(self, db: &impl HirDatabase) -> Arc { + pub fn infer(self, db: &dyn HirDatabase) -> Arc { db.infer(self) } - pub fn body(self, db: &impl HirDatabase) -> Arc { + pub fn body(self, db: &dyn HirDatabase) -> Arc { db.body(self) } - pub fn body_source_map(self, db: &impl HirDatabase) -> Arc { + pub fn body_source_map(self, db: &dyn HirDatabase) -> Arc { db.body_with_source_map(self).1 } /// Builds a `Resolver` for code inside this item. A `Resolver` enables name resolution. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(self, db: &dyn HirDatabase) -> Resolver { match self { DefWithBody::Function(f) => f.resolver(db), } @@ -193,27 +193,27 @@ pub enum DefWithStruct { impl_froms!(DefWithStruct: Struct); impl DefWithStruct { - pub fn fields(self, db: &impl HirDatabase) -> Vec { + pub fn fields(self, db: &dyn HirDatabase) -> Vec { match self { DefWithStruct::Struct(s) => s.fields(db), } } - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { + pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option { match self { DefWithStruct::Struct(s) => s.field(db, name), } } - pub fn module(self, db: &impl HirDatabase) -> Module { + pub fn module(self, db: &dyn HirDatabase) -> Module { match self { - DefWithStruct::Struct(s) => s.module(db), + DefWithStruct::Struct(s) => s.module(db.upcast()), } } - pub fn data(self, db: &impl HirDatabase) -> Arc { + pub fn data(self, db: &dyn HirDatabase) -> Arc { match self { - DefWithStruct::Struct(s) => s.data(db), + DefWithStruct::Struct(s) => s.data(db.upcast()), } } } @@ -235,7 +235,7 @@ pub struct FnData { } impl FnData { - pub(crate) fn fn_data_query(db: &impl DefDatabase, func: Function) -> Arc { + pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: Function) -> Arc { let src = func.source(db); let mut type_ref_builder = TypeRefBuilder::default(); let name = src @@ -305,50 +305,50 @@ impl FnData { } impl Function { - pub fn module(self, db: &impl DefDatabase) -> Module { + pub fn module(self, db: &dyn DefDatabase) -> Module { Module { file_id: self.id.file_id(db), } } - pub fn name(self, db: &impl HirDatabase) -> Name { + pub fn name(self, db: &dyn HirDatabase) -> Name { self.data(db).name.clone() } - pub fn visibility(self, db: &impl HirDatabase) -> Visibility { + pub fn visibility(self, db: &dyn HirDatabase) -> Visibility { self.data(db).visibility() } - pub fn data(self, db: &impl HirDatabase) -> Arc { + pub fn data(self, db: &dyn HirDatabase) -> Arc { db.fn_data(self) } - pub fn body(self, db: &impl HirDatabase) -> Arc { + pub fn body(self, db: &dyn HirDatabase) -> Arc { db.body(self.into()) } - pub fn ty(self, db: &impl HirDatabase) -> Ty { + pub fn ty(self, db: &dyn HirDatabase) -> Ty { db.type_for_def(self.into(), Namespace::Values) } - pub fn infer(self, db: &impl HirDatabase) -> Arc { + pub fn infer(self, db: &dyn HirDatabase) -> Arc { db.infer(self.into()) } - pub fn is_extern(self, db: &impl HirDatabase) -> bool { + pub fn is_extern(self, db: &dyn HirDatabase) -> bool { db.fn_data(self).is_extern } - pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc { + pub(crate) fn body_source_map(self, db: &dyn HirDatabase) -> Arc { db.body_with_source_map(self.into()).1 } - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(self, db: &dyn HirDatabase) -> Resolver { // take the outer scope... - self.module(db).resolver(db) + self.module(db.upcast()).resolver(db.upcast()) } - pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { + pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { let body = self.body(db); body.add_diagnostics(db, self.into(), sink); let infer = self.infer(db); @@ -370,15 +370,15 @@ pub struct StructField { } impl StructField { - pub fn ty(self, db: &impl HirDatabase) -> Ty { - let data = self.parent.data(db); + pub fn ty(self, db: &dyn HirDatabase) -> Ty { + let data = self.parent.data(db.upcast()); let type_ref_id = data.fields[self.id].type_ref; let lower = self.parent.lower(db); lower[type_ref_id].clone() } - pub fn name(self, db: &impl HirDatabase) -> Name { - self.parent.data(db).fields[self.id].name.clone() + pub fn name(self, db: &dyn HirDatabase) -> Name { + self.parent.data(db.upcast()).fields[self.id].name.clone() } pub fn id(self) -> StructFieldId { @@ -387,55 +387,55 @@ impl StructField { } impl Struct { - pub fn module(self, db: &impl DefDatabase) -> Module { + pub fn module(self, db: &dyn DefDatabase) -> Module { Module { file_id: self.id.file_id(db), } } - pub fn data(self, db: &impl DefDatabase) -> Arc { + pub fn data(self, db: &dyn DefDatabase) -> Arc { db.struct_data(self.id) } - pub fn name(self, db: &impl DefDatabase) -> Name { + pub fn name(self, db: &dyn DefDatabase) -> Name { self.data(db).name.clone() } - pub fn fields(self, db: &impl HirDatabase) -> Vec { - self.data(db) + pub fn fields(self, db: &dyn HirDatabase) -> Vec { + self.data(db.upcast()) .fields .iter() .map(|(id, _)| StructField { parent: self, id }) .collect() } - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { - self.data(db) + pub fn field(self, db: &dyn HirDatabase, name: &Name) -> Option { + self.data(db.upcast()) .fields .iter() .find(|(_, data)| data.name == *name) .map(|(id, _)| StructField { parent: self, id }) } - pub fn ty(self, db: &impl HirDatabase) -> Ty { + pub fn ty(self, db: &dyn HirDatabase) -> Ty { db.type_for_def(self.into(), Namespace::Types) } - pub fn lower(self, db: &impl HirDatabase) -> Arc { + pub fn lower(self, db: &dyn HirDatabase) -> Arc { db.lower_struct(self) } - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(self, db: &dyn HirDatabase) -> Resolver { // take the outer scope... - self.module(db).resolver(db) + self.module(db.upcast()).resolver(db.upcast()) } - pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { - let data = self.data(db); + pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { + let data = self.data(db.upcast()); let lower = self.lower(db); lower.add_diagnostics( db, - self.module(db).file_id, + self.module(db.upcast()).file_id, data.type_ref_source_map(), sink, ); @@ -458,7 +458,7 @@ mod diagnostics { }, } - fn syntax_ptr_from_def(db: &impl DefDatabase, owner: Module, kind: DefKind) -> SyntaxNodePtr { + fn syntax_ptr_from_def(db: &dyn DefDatabase, owner: Module, kind: DefKind) -> SyntaxNodePtr { match kind { DefKind::Function(id) => { SyntaxNodePtr::new(id.with_file_id(owner.file_id).to_node(db).syntax()) @@ -472,7 +472,7 @@ mod diagnostics { impl ModuleDefinitionDiagnostic { pub(super) fn add_to( &self, - db: &impl DefDatabase, + db: &dyn DefDatabase, owner: Module, sink: &mut DiagnosticSink, ) { diff --git a/crates/mun_hir/src/code_model/src.rs b/crates/mun_hir/src/code_model/src.rs index 51f9550de..00eab5ec7 100644 --- a/crates/mun_hir/src/code_model/src.rs +++ b/crates/mun_hir/src/code_model/src.rs @@ -6,19 +6,19 @@ use mun_syntax::ast; pub trait HasSource { type Ast; - fn source(self, db: &impl DefDatabase) -> InFile; + fn source(self, db: &dyn DefDatabase) -> InFile; } impl HasSource for Function { type Ast = ast::FunctionDef; - fn source(self, db: &impl DefDatabase) -> InFile { + fn source(self, db: &dyn DefDatabase) -> InFile { self.id.source(db) } } impl HasSource for Struct { type Ast = ast::StructDef; - fn source(self, db: &impl DefDatabase) -> InFile { + fn source(self, db: &dyn DefDatabase) -> InFile { self.id.source(db) } } @@ -26,7 +26,7 @@ impl HasSource for Struct { impl HasSource for StructField { type Ast = ast::RecordFieldDef; - fn source(self, db: &impl DefDatabase) -> InFile { + fn source(self, db: &dyn DefDatabase) -> InFile { let src = self.parent.source(db); let file_id = src.file_id; let field_sources = if let ast::StructKind::Record(r) = src.value.kind() { diff --git a/crates/mun_hir/src/db.rs b/crates/mun_hir/src/db.rs index 6684d3dc0..2b90e4ebd 100644 --- a/crates/mun_hir/src/db.rs +++ b/crates/mun_hir/src/db.rs @@ -19,10 +19,15 @@ use mun_target::spec::Target; pub use relative_path::RelativePathBuf; use std::sync::Arc; +// TODO(bas): In the future maybe move this to a seperate crate (mun_db?) +pub trait Upcast { + fn upcast(&self) -> &T; +} + /// Database which stores all significant input facts: source code and project model. Everything /// else in rust-analyzer is derived from these queries. #[salsa::query_group(SourceDatabaseStorage)] -pub trait SourceDatabase: std::fmt::Debug { +pub trait SourceDatabase: salsa::Database { /// Text of the file. #[salsa::input] fn file_text(&self, file_id: FileId) -> Arc; @@ -49,7 +54,7 @@ pub trait SourceDatabase: std::fmt::Debug { } #[salsa::query_group(DefDatabaseStorage)] -pub trait DefDatabase: SourceDatabase { +pub trait DefDatabase: SourceDatabase + Upcast { /// Returns the top level AST items of a file #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] fn ast_id_map(&self, file_id: FileId) -> Arc; @@ -61,6 +66,13 @@ pub trait DefDatabase: SourceDatabase { #[salsa::invoke(StructData::struct_data_query)] fn struct_data(&self, id: ids::StructId) -> Arc; + #[salsa::invoke(crate::FnData::fn_data_query)] + fn fn_data(&self, func: Function) -> Arc; + + /// Returns the module data of the specified file + #[salsa::invoke(crate::code_model::ModuleData::module_data_query)] + fn module_data(&self, file_id: FileId) -> Arc; + /// Interns a function definition #[salsa::interned] fn intern_function(&self, loc: ids::ItemLoc) -> ids::FunctionId; @@ -71,7 +83,7 @@ pub trait DefDatabase: SourceDatabase { } #[salsa::query_group(HirDatabaseStorage)] -pub trait HirDatabase: DefDatabase { +pub trait HirDatabase: DefDatabase + Upcast { /// Returns the target for code generation. #[salsa::input] fn target(&self) -> Target; @@ -92,19 +104,12 @@ pub trait HirDatabase: DefDatabase { #[salsa::invoke(crate::ty::lower::lower_struct_query)] fn lower_struct(&self, def: Struct) -> Arc; - #[salsa::invoke(crate::FnData::fn_data_query)] - fn fn_data(&self, func: Function) -> Arc; - #[salsa::invoke(crate::ty::callable_item_sig)] fn callable_sig(&self, def: CallableDef) -> FnSig; #[salsa::invoke(crate::ty::type_for_def)] fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; - /// Returns the module data of the specified file - #[salsa::invoke(crate::code_model::ModuleData::module_data_query)] - fn module_data(&self, file_id: FileId) -> Arc; - #[salsa::invoke(crate::expr::body_hir_query)] fn body(&self, def: DefWithBody) -> Arc; @@ -115,17 +120,17 @@ pub trait HirDatabase: DefDatabase { ) -> (Arc, Arc); } -fn parse_query(db: &impl SourceDatabase, file_id: FileId) -> Parse { +fn parse_query(db: &dyn SourceDatabase, file_id: FileId) -> Parse { let text = db.file_text(file_id); SourceFile::parse(&*text) } -fn line_index_query(db: &impl SourceDatabase, file_id: FileId) -> Arc { +fn line_index_query(db: &dyn SourceDatabase, file_id: FileId) -> Arc { let text = db.file_text(file_id); Arc::new(LineIndex::new(text.as_ref())) } -fn target_data_layout(db: &impl HirDatabase) -> Arc { +fn target_data_layout(db: &dyn HirDatabase) -> Arc { let target = db.target(); let data_layout = abi::TargetDataLayout::parse(&target) .expect("unable to create TargetDataLayout from target"); diff --git a/crates/mun_hir/src/diagnostics.rs b/crates/mun_hir/src/diagnostics.rs index 2eaa7a8c6..848ef9da8 100644 --- a/crates/mun_hir/src/diagnostics.rs +++ b/crates/mun_hir/src/diagnostics.rs @@ -24,11 +24,11 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { pub trait AstDiagnostic { type AST; - fn ast(&self, db: &impl HirDatabase) -> Self::AST; + fn ast(&self, db: &dyn HirDatabase) -> Self::AST; } impl dyn Diagnostic { - pub fn syntax_node(&self, db: &impl HirDatabase) -> SyntaxNode { + pub fn syntax_node(&self, db: &dyn HirDatabase) -> SyntaxNode { let node = db.parse(self.source().file_id).syntax_node(); self.source().value.to_node(&node) } diff --git a/crates/mun_hir/src/display.rs b/crates/mun_hir/src/display.rs index 63ec9d7e1..b895b9f4a 100644 --- a/crates/mun_hir/src/display.rs +++ b/crates/mun_hir/src/display.rs @@ -2,14 +2,14 @@ use std::fmt; use crate::db::HirDatabase; -pub struct HirFormatter<'a, 'b, DB> { - pub db: &'a DB, +pub struct HirFormatter<'a, 'b> { + pub db: &'a dyn HirDatabase, fmt: &'a mut fmt::Formatter<'b>, } pub trait HirDisplay { - fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result; - fn display<'a, DB>(&'a self, db: &'a DB) -> HirDisplayWrapper<'a, DB, Self> + fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result; + fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> where Self: Sized, { @@ -17,10 +17,7 @@ pub trait HirDisplay { } } -impl<'a, 'b, DB> HirFormatter<'a, 'b, DB> -where - DB: HirDatabase, -{ +impl<'a, 'b> HirFormatter<'a, 'b> { pub fn write_joined( &mut self, iter: impl IntoIterator, @@ -43,11 +40,10 @@ where } } -pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T); +pub struct HirDisplayWrapper<'a, T>(&'a dyn HirDatabase, &'a T); -impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> +impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T> where - DB: HirDatabase, T: HirDisplay, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/crates/mun_hir/src/expr.rs b/crates/mun_hir/src/expr.rs index 4277f2849..d18497ad8 100644 --- a/crates/mun_hir/src/expr.rs +++ b/crates/mun_hir/src/expr.rs @@ -94,7 +94,7 @@ impl Body { /// Adds all the `InferenceDiagnostic`s of the result to the `DiagnosticSink`. pub(crate) fn add_diagnostics( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, owner: DefWithBody, sink: &mut DiagnosticSink, ) { @@ -433,8 +433,8 @@ impl Pat { // Queries -pub(crate) struct ExprCollector { - db: DB, +pub(crate) struct ExprCollector<'a> { + db: &'a dyn HirDatabase, owner: DefWithBody, exprs: Arena, pats: Arena, @@ -447,11 +447,8 @@ pub(crate) struct ExprCollector { diagnostics: Vec, } -impl<'a, DB> ExprCollector<&'a DB> -where - DB: HirDatabase, -{ - pub fn new(owner: DefWithBody, file_id: FileId, db: &'a DB) -> Self { +impl<'a> ExprCollector<'a> { + pub fn new(owner: DefWithBody, file_id: FileId, db: &'a dyn HirDatabase) -> Self { ExprCollector { owner, db, @@ -916,14 +913,14 @@ where } pub(crate) fn body_with_source_map_query( - db: &impl HirDatabase, + db: &dyn HirDatabase, def: DefWithBody, ) -> (Arc, Arc) { let mut collector; match def { DefWithBody::Function(ref f) => { - let src = f.source(db); + let src = f.source(db.upcast()); collector = ExprCollector::new(def, src.file_id, db); collector.collect_fn_body(&src.value) } @@ -933,19 +930,19 @@ pub(crate) fn body_with_source_map_query( (Arc::new(body), Arc::new(source_map)) } -pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { +pub(crate) fn body_hir_query(db: &dyn HirDatabase, def: DefWithBody) -> Arc { db.body_with_source_map(def).0 } // needs arbitrary_self_types to be a method... or maybe move to the def? -pub fn resolver_for_expr(body: Arc, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { +pub fn resolver_for_expr(body: Arc, db: &dyn HirDatabase, expr_id: ExprId) -> Resolver { let scopes = db.expr_scopes(body.owner); resolver_for_scope(body, db, scopes.scope_for(expr_id)) } pub(crate) fn resolver_for_scope( body: Arc, - db: &impl HirDatabase, + db: &dyn HirDatabase, scope_id: Option, ) -> Resolver { let mut r = body.owner.resolver(db); @@ -1385,7 +1382,7 @@ mod diagnostics { impl ExprDiagnostic { pub(crate) fn add_to( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, owner: DefWithBody, sink: &mut DiagnosticSink, ) { diff --git a/crates/mun_hir/src/expr/scope.rs b/crates/mun_hir/src/expr/scope.rs index be9feffe7..399bd14ce 100644 --- a/crates/mun_hir/src/expr/scope.rs +++ b/crates/mun_hir/src/expr/scope.rs @@ -42,7 +42,7 @@ pub(crate) struct ScopeData { } impl ExprScopes { - pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { + pub(crate) fn expr_scopes_query(db: &dyn HirDatabase, def: DefWithBody) -> Arc { let body = db.body(def); let res = ExprScopes::new(body); Arc::new(res) diff --git a/crates/mun_hir/src/expr/validator.rs b/crates/mun_hir/src/expr/validator.rs index 1e9452cee..d80b3750f 100644 --- a/crates/mun_hir/src/expr/validator.rs +++ b/crates/mun_hir/src/expr/validator.rs @@ -12,16 +12,16 @@ mod uninitialized_access; #[cfg(test)] mod tests; -pub struct ExprValidator<'d, DB: HirDatabase> { +pub struct ExprValidator<'a> { func: Function, infer: Arc, body: Arc, body_source_map: Arc, - db: &'d DB, + db: &'a dyn HirDatabase, } -impl<'d, DB: HirDatabase> ExprValidator<'d, DB> { - pub fn new(func: Function, db: &'d DB) -> Self { +impl<'a> ExprValidator<'a> { + pub fn new(func: Function, db: &'a dyn HirDatabase) -> Self { let (body, body_source_map) = db.body_with_source_map(func.into()); ExprValidator { func, @@ -49,7 +49,7 @@ impl<'d, DB: HirDatabase> ExprValidator<'d, DB> { _ => sink.push(ExternCannotHaveBody { func: self .func - .source(self.db) + .source(self.db.upcast()) .map(|f| SyntaxNodePtr::new(f.syntax())), }), } @@ -64,7 +64,7 @@ impl<'d, DB: HirDatabase> ExprValidator<'d, DB> { .map(|ptr| ptr.syntax_node_ptr()) .unwrap(); sink.push(ExternNonPrimitiveParam { - param: InFile::new(self.func.source(self.db).file_id, arg_ptr), + param: InFile::new(self.func.source(self.db.upcast()).file_id, arg_ptr), }) } } @@ -77,7 +77,7 @@ impl<'d, DB: HirDatabase> ExprValidator<'d, DB> { .map(|ptr| ptr.syntax_node_ptr()) .unwrap(); sink.push(ExternNonPrimitiveParam { - param: InFile::new(self.func.source(self.db).file_id, arg_ptr), + param: InFile::new(self.func.source(self.db.upcast()).file_id, arg_ptr), }) } } diff --git a/crates/mun_hir/src/expr/validator/literal_out_of_range.rs b/crates/mun_hir/src/expr/validator/literal_out_of_range.rs index c926159b9..f842ebd6a 100644 --- a/crates/mun_hir/src/expr/validator/literal_out_of_range.rs +++ b/crates/mun_hir/src/expr/validator/literal_out_of_range.rs @@ -2,9 +2,9 @@ use super::ExprValidator; use crate::diagnostics::{DiagnosticSink, LiteralOutOfRange}; use crate::ty::ResolveBitness; use crate::{ty_app, TypeCtor}; -use crate::{Expr, HirDatabase, HirDisplay, Literal}; +use crate::{Expr, HirDisplay, Literal}; -impl<'d, D: HirDatabase> ExprValidator<'d, D> { +impl<'a> ExprValidator<'a> { /// Iterates over all expressions to determine if one of the literals has a value that is out of /// range of its type. pub fn validate_literal_ranges(&self, sink: &mut DiagnosticSink) { diff --git a/crates/mun_hir/src/expr/validator/tests.rs b/crates/mun_hir/src/expr/validator/tests.rs index da0cceee6..6341c6442 100644 --- a/crates/mun_hir/src/expr/validator/tests.rs +++ b/crates/mun_hir/src/expr/validator/tests.rs @@ -1,4 +1,4 @@ -use crate::db::SourceDatabase; +use crate::db::{SourceDatabase, Upcast}; use crate::expr::validator::ExprValidator; use crate::{diagnostics::DiagnosticSink, ids::LocationCtx, mock::MockDatabase, Function}; use mun_syntax::{ast, AstNode}; @@ -76,7 +76,7 @@ fn diagnostics(content: &str) -> String { write!(diags, "{}: {}\n", diag.highlight_range(), diag.message()).unwrap(); }); - let ctx = LocationCtx::new(&db, file_id); + let ctx = LocationCtx::new(db.upcast(), file_id); for node in source_file.syntax().descendants() { if let Some(def) = ast::FunctionDef::cast(node.clone()) { let fun = Function { diff --git a/crates/mun_hir/src/expr/validator/uninitialized_access.rs b/crates/mun_hir/src/expr/validator/uninitialized_access.rs index 274ef2bdc..b2ca46f8f 100644 --- a/crates/mun_hir/src/expr/validator/uninitialized_access.rs +++ b/crates/mun_hir/src/expr/validator/uninitialized_access.rs @@ -1,6 +1,6 @@ use super::ExprValidator; use crate::diagnostics::{DiagnosticSink, PossiblyUninitializedVariable}; -use crate::{BinaryOp, Expr, ExprId, HirDatabase, PatId, Path, Resolution, Resolver, Statement}; +use crate::{BinaryOp, Expr, ExprId, PatId, Path, Resolution, Resolver, Statement}; use std::collections::HashSet; #[derive(Copy, Clone, PartialEq, Eq)] @@ -10,7 +10,7 @@ enum ExprKind { Both, } -impl<'d, D: HirDatabase> ExprValidator<'d, D> { +impl<'d> ExprValidator<'d> { /// Validates that all binding access has previously been initialized. pub(super) fn validate_uninitialized_access(&self, sink: &mut DiagnosticSink) { let mut initialized_patterns = HashSet::new(); @@ -214,7 +214,7 @@ impl<'d, D: HirDatabase> ExprValidator<'d, D> { if initialized_patterns.get(&pat).is_none() { let (_, body_source_map) = self.db.body_with_source_map(self.func.into()); sink.push(PossiblyUninitializedVariable { - file: self.func.module(self.db).file_id(), + file: self.func.module(self.db.upcast()).file_id(), pat: body_source_map .expr_syntax(expr) .unwrap() diff --git a/crates/mun_hir/src/ids.rs b/crates/mun_hir/src/ids.rs index 287c998c3..5ea811d0b 100644 --- a/crates/mun_hir/src/ids.rs +++ b/crates/mun_hir/src/ids.rs @@ -48,8 +48,11 @@ pub(crate) struct LocationCtx { file_id: FileId, } -impl<'a, DB: DefDatabase> LocationCtx<&'a DB> { - pub(crate) fn new(db: &'a DB, file_id: FileId) -> LocationCtx<&'a DB> { +impl<'a> LocationCtx<&'a dyn DefDatabase> { + pub(crate) fn new( + db: &'a dyn DefDatabase, + file_id: FileId, + ) -> LocationCtx<&'a dyn DefDatabase> { LocationCtx { db, file_id } } @@ -63,29 +66,29 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> { } pub(crate) trait AstItemDef: salsa::InternKey + Clone { - fn intern(db: &impl DefDatabase, loc: ItemLoc) -> Self; - fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc; + fn intern(db: &dyn DefDatabase, loc: ItemLoc) -> Self; + fn lookup_intern(self, db: &dyn DefDatabase) -> ItemLoc; - fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self { + fn from_ast(ctx: LocationCtx<&dyn DefDatabase>, ast: &N) -> Self { let items = ctx.db.ast_id_map(ctx.file_id); let item_id = items.ast_id(ast); Self::from_ast_id(ctx, item_id) } - fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId) -> Self { + fn from_ast_id(ctx: LocationCtx<&dyn DefDatabase>, ast_id: FileAstId) -> Self { let loc = ItemLoc { ast_id: ast_id.with_file_id(ctx.file_id), }; Self::intern(ctx.db, loc) } - fn source(self, db: &impl DefDatabase) -> InFile { + fn source(self, db: &dyn DefDatabase) -> InFile { let loc = self.lookup_intern(db); let ast = loc.ast_id.to_node(db); InFile::new(loc.ast_id.file_id, ast) } - fn file_id(self, db: &impl DefDatabase) -> FileId { + fn file_id(self, db: &dyn DefDatabase) -> FileId { self.lookup_intern(db).ast_id.file_id } } @@ -95,10 +98,10 @@ pub struct FunctionId(salsa::InternId); impl_intern_key!(FunctionId); impl AstItemDef for FunctionId { - fn intern(db: &impl DefDatabase, loc: ItemLoc) -> Self { + fn intern(db: &dyn DefDatabase, loc: ItemLoc) -> Self { db.intern_function(loc) } - fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc { + fn lookup_intern(self, db: &dyn DefDatabase) -> ItemLoc { db.lookup_intern_function(self) } } @@ -108,11 +111,11 @@ pub struct StructId(salsa::InternId); impl_intern_key!(StructId); impl AstItemDef for StructId { - fn intern(db: &impl DefDatabase, loc: ItemLoc) -> Self { + fn intern(db: &dyn DefDatabase, loc: ItemLoc) -> Self { db.intern_struct(loc) } - fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc { + fn lookup_intern(self, db: &dyn DefDatabase) -> ItemLoc { db.lookup_intern_struct(self) } } diff --git a/crates/mun_hir/src/in_file.rs b/crates/mun_hir/src/in_file.rs index 115ac71e0..a5dee8583 100644 --- a/crates/mun_hir/src/in_file.rs +++ b/crates/mun_hir/src/in_file.rs @@ -30,7 +30,7 @@ impl InFile { pub fn as_ref(&self) -> InFile<&T> { self.with_value(&self.value) } - pub fn file_syntax(&self, db: &impl SourceDatabase) -> SyntaxNode { + pub fn file_syntax(&self, db: &dyn SourceDatabase) -> SyntaxNode { db.parse(self.file_id).syntax_node() } } diff --git a/crates/mun_hir/src/lib.rs b/crates/mun_hir/src/lib.rs index 30e250f31..c37127544 100644 --- a/crates/mun_hir/src/lib.rs +++ b/crates/mun_hir/src/lib.rs @@ -45,7 +45,7 @@ pub use crate::{ builtin_type::{FloatBitness, IntBitness, Signedness}, db::{ DefDatabase, DefDatabaseStorage, HirDatabase, HirDatabaseStorage, SourceDatabase, - SourceDatabaseStorage, + SourceDatabaseStorage, Upcast, }, display::HirDisplay, expr::{ diff --git a/crates/mun_hir/src/mock.rs b/crates/mun_hir/src/mock.rs index c05d1bd0f..e5d9fdf2c 100644 --- a/crates/mun_hir/src/mock.rs +++ b/crates/mun_hir/src/mock.rs @@ -1,7 +1,7 @@ -use crate::db::HirDatabase; use crate::db::SourceDatabase; +use crate::db::{HirDatabase, Upcast}; use crate::input::{SourceRoot, SourceRootId}; -use crate::{FileId, RelativePathBuf}; +use crate::{DefDatabase, FileId, RelativePathBuf}; use mun_target::spec::Target; use parking_lot::Mutex; use std::sync::Arc; @@ -12,26 +12,30 @@ use std::sync::Arc; crate::DefDatabaseStorage, crate::HirDatabaseStorage )] -#[derive(Default, Debug)] +#[derive(Default)] pub(crate) struct MockDatabase { - runtime: salsa::Runtime, - events: Mutex>>>, + storage: salsa::Storage, + events: Mutex>>, } impl salsa::Database for MockDatabase { - fn salsa_runtime(&self) -> &salsa::Runtime { - &self.runtime + fn salsa_event(&self, event: salsa::Event) { + let mut events = self.events.lock(); + if let Some(events) = &mut *events { + events.push(event); + } } +} - fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime { - &mut self.runtime +impl Upcast for MockDatabase { + fn upcast(&self) -> &dyn DefDatabase { + &*self } +} - fn salsa_event(&self, event: impl Fn() -> salsa::Event) { - let mut events = self.events.lock(); - if let Some(events) = &mut *events { - events.push(event()); - } +impl Upcast for MockDatabase { + fn upcast(&self) -> &dyn SourceDatabase { + &*self } } @@ -58,7 +62,7 @@ impl MockDatabase { } impl MockDatabase { - pub fn log(&self, f: impl FnOnce()) -> Vec> { + pub fn log(&self, f: impl FnOnce()) -> Vec { *self.events.lock() = Some(Vec::new()); f(); self.events.lock().take().unwrap() @@ -72,7 +76,7 @@ impl MockDatabase { // This pretty horrible, but `Debug` is the only way to inspect // QueryDescriptor at the moment. salsa::EventKind::WillExecute { database_key } => { - Some(format!("{:?}", database_key)) + Some(format!("{:?}", database_key.debug(self))) } _ => None, }) diff --git a/crates/mun_hir/src/name_resolution.rs b/crates/mun_hir/src/name_resolution.rs index 15a1a4aa7..c8a734de9 100644 --- a/crates/mun_hir/src/name_resolution.rs +++ b/crates/mun_hir/src/name_resolution.rs @@ -43,7 +43,7 @@ impl ModuleScope { } } -pub(crate) fn module_scope_query(db: &impl HirDatabase, file_id: FileId) -> Arc { +pub(crate) fn module_scope_query(db: &dyn HirDatabase, file_id: FileId) -> Arc { let mut scope = ModuleScope::default(); let defs = db.module_data(file_id); for def in defs.definitions() { @@ -58,7 +58,7 @@ pub(crate) fn module_scope_query(db: &impl HirDatabase, file_id: FileId) -> Arc< } ModuleDef::Struct(s) => { scope.items.insert( - s.name(db), + s.name(db.upcast()), Resolution { def: PerNs::both(*def, *def), }, diff --git a/crates/mun_hir/src/raw.rs b/crates/mun_hir/src/raw.rs index 6d1dddc76..d22585ff6 100644 --- a/crates/mun_hir/src/raw.rs +++ b/crates/mun_hir/src/raw.rs @@ -43,7 +43,7 @@ impl Index for RawItems { } impl RawItems { - pub(crate) fn raw_file_items_query(db: &impl DefDatabase, file_id: FileId) -> Arc { + pub(crate) fn raw_file_items_query(db: &dyn DefDatabase, file_id: FileId) -> Arc { let mut items = RawItems::default(); let source_file = db.parse(file_id).tree(); diff --git a/crates/mun_hir/src/resolve.rs b/crates/mun_hir/src/resolve.rs index 7177dfe5b..af3695a33 100644 --- a/crates/mun_hir/src/resolve.rs +++ b/crates/mun_hir/src/resolve.rs @@ -60,7 +60,7 @@ pub enum Resolution { } impl Resolver { - pub fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs { + pub fn resolve_name(&self, db: &dyn HirDatabase, name: &Name) -> PerNs { let mut resolution = PerNs::none(); for scope in self.scopes.iter().rev() { resolution = resolution.or(scope.resolve_name(db, name)); @@ -75,7 +75,7 @@ impl Resolver { /// otherwise returns `PerNs::none` pub fn resolve_path_without_assoc_items( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, path: &Path, ) -> PerNs { if let Some(name) = path.as_ident() { @@ -87,7 +87,7 @@ impl Resolver { } impl Scope { - fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs { + fn resolve_name(&self, db: &dyn HirDatabase, name: &Name) -> PerNs { match self { Scope::ModuleScope(m) => db .module_scope(m.file_id) @@ -109,7 +109,7 @@ impl Scope { } } - // fn collect_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, PerNs)) { + // fn collect_names(&self, db: &dyn HirDatabase, f: &mut dyn FnMut(Name, PerNs)) { // match self { // Scope::ModuleScope(m) => { // // FIXME: should we provide `self` here? diff --git a/crates/mun_hir/src/source_id.rs b/crates/mun_hir/src/source_id.rs index f7ac74776..a5d28d5ab 100644 --- a/crates/mun_hir/src/source_id.rs +++ b/crates/mun_hir/src/source_id.rs @@ -62,13 +62,13 @@ pub struct ErasedFileAstId(RawId); impl_arena_id!(ErasedFileAstId); impl AstIdMap { - pub(crate) fn ast_id_map_query(db: &impl DefDatabase, file_id: FileId) -> Arc { + pub(crate) fn ast_id_map_query(db: &dyn DefDatabase, file_id: FileId) -> Arc { let map = AstIdMap::from_source(&db.parse(file_id).tree().syntax()); Arc::new(map) } pub(crate) fn file_item_query( - db: &impl DefDatabase, + db: &dyn DefDatabase, file_id: FileId, ast_id: ErasedFileAstId, ) -> SyntaxNode { diff --git a/crates/mun_hir/src/tests.rs b/crates/mun_hir/src/tests.rs index 798ff636e..1dc5e0007 100644 --- a/crates/mun_hir/src/tests.rs +++ b/crates/mun_hir/src/tests.rs @@ -1,5 +1,4 @@ -use crate::db::HirDatabase; -use crate::db::SourceDatabase; +use crate::db::{DefDatabase, SourceDatabase}; use crate::mock::MockDatabase; use std::sync::Arc; diff --git a/crates/mun_hir/src/ty.rs b/crates/mun_hir/src/ty.rs index 1362662a9..9a30b8a03 100644 --- a/crates/mun_hir/src/ty.rs +++ b/crates/mun_hir/src/ty.rs @@ -131,7 +131,7 @@ impl Ty { } } - pub fn callable_sig(&self, db: &impl HirDatabase) -> Option { + pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option { match self { Ty::Apply(a_ty) => match a_ty.ctor { TypeCtor::FnDef(def) => Some(db.callable_sig(def)), @@ -144,12 +144,12 @@ impl Ty { /// Returns the type's name as a string, if one exists. /// /// This name needs to be unique as it is used to generate a type's `Guid`. - pub fn guid_string(&self, db: &impl HirDatabase) -> Option { + pub fn guid_string(&self, db: &dyn HirDatabase) -> Option { self.as_simple().and_then(|ty_ctor| match ty_ctor { TypeCtor::Struct(s) => { - let name = s.name(db).to_string(); + let name = s.name(db.upcast()).to_string(); - Some(if s.data(db).memory_kind == StructMemoryKind::GC { + Some(if s.data(db.upcast()).memory_kind == StructMemoryKind::GC { format!("struct {}", name) } else { let fields: Vec = s @@ -230,10 +230,10 @@ impl FnSig { &self.params_and_return[self.params_and_return.len() - 1] } - pub fn marshallable(&self, db: &impl HirDatabase) -> bool { + pub fn marshallable(&self, db: &dyn HirDatabase) -> bool { for ty in self.params_and_return.iter() { if let Some(s) = ty.as_struct() { - if s.data(db).memory_kind == StructMemoryKind::Value { + if s.data(db.upcast()).memory_kind == StructMemoryKind::Value { return false; } } @@ -243,7 +243,7 @@ impl FnSig { } impl HirDisplay for Ty { - fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self { Ty::Apply(a_ty) => a_ty.hir_fmt(f), Ty::Unknown => write!(f, "{{unknown}}"), @@ -258,12 +258,12 @@ impl HirDisplay for Ty { } impl HirDisplay for ApplicationTy { - fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { match self.ctor { TypeCtor::Float(ty) => write!(f, "{}", ty), TypeCtor::Int(ty) => write!(f, "{}", ty), TypeCtor::Bool => write!(f, "bool"), - TypeCtor::Struct(def) => write!(f, "{}", def.name(f.db)), + TypeCtor::Struct(def) => write!(f, "{}", def.name(f.db.upcast())), TypeCtor::Never => write!(f, "never"), TypeCtor::FnDef(CallableDef::Function(def)) => { let sig = fn_sig_for_fn(f.db, def); @@ -275,7 +275,7 @@ impl HirDisplay for ApplicationTy { } TypeCtor::FnDef(CallableDef::Struct(def)) => { let sig = fn_sig_for_struct_constructor(f.db, def); - let name = def.name(f.db); + let name = def.name(f.db.upcast()); write!(f, "ctor {}", name)?; write!(f, "(")?; f.write_joined(sig.params(), ", ")?; @@ -286,7 +286,7 @@ impl HirDisplay for ApplicationTy { } impl HirDisplay for &Ty { - fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { HirDisplay::hir_fmt(*self, f) } } diff --git a/crates/mun_hir/src/ty/infer.rs b/crates/mun_hir/src/ty/infer.rs index 9d9432e92..29905aa04 100644 --- a/crates/mun_hir/src/ty/infer.rs +++ b/crates/mun_hir/src/ty/infer.rs @@ -72,7 +72,7 @@ impl InferenceResult { /// Adds all the `InferenceDiagnostic`s of the result to the `DiagnosticSink`. pub(crate) fn add_diagnostics( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, owner: Function, sink: &mut DiagnosticSink, ) { @@ -84,7 +84,7 @@ impl InferenceResult { /// The entry point of type inference. This method takes a body and infers the types of all the /// expressions and patterns. Diagnostics are also reported and stored in the `InferenceResult`. -pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { +pub fn infer_query(db: &dyn HirDatabase, def: DefWithBody) -> Arc { let body = def.body(db); let resolver = def.resolver(db); let mut ctx = InferenceResultBuilder::new(db, body, resolver); @@ -131,8 +131,8 @@ enum ActiveLoop { } /// The inference context contains all information needed during type inference. -struct InferenceResultBuilder<'a, D: HirDatabase> { - db: &'a D, +struct InferenceResultBuilder<'a> { + db: &'a dyn HirDatabase, body: Arc, resolver: Resolver, @@ -152,9 +152,9 @@ struct InferenceResultBuilder<'a, D: HirDatabase> { return_ty: Ty, } -impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { +impl<'a> InferenceResultBuilder<'a> { /// Construct a new `InferenceContext` from a `Body` and a `Resolver` for that body. - fn new(db: &'a D, body: Arc, resolver: Resolver) -> Self { + fn new(db: &'a dyn HirDatabase, body: Arc, resolver: Resolver) -> Self { InferenceResultBuilder { type_of_expr: ArenaMap::default(), type_of_pat: ArenaMap::default(), @@ -204,7 +204,7 @@ impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { } } -impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { +impl<'a> InferenceResultBuilder<'a> { /// Collect all the parameter patterns from the body. After calling this method the `return_ty` /// will have a valid value, also all parameters are added inferred. fn infer_signature(&mut self) { @@ -549,7 +549,7 @@ impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { match callee_ty { ty_app!(TypeCtor::Struct(s)) => { // Erroneously found either a unit struct or tuple struct literal - let struct_data = s.data(self.db); + let struct_data = s.data(self.db.upcast()); self.diagnostics .push(InferenceDiagnostic::MismatchedStructLit { id: tgt_expr, @@ -593,7 +593,7 @@ impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { /// Checks whether the specified struct type is a unit struct. fn check_unit_struct_lit(&mut self, tgt_expr: ExprId, expected: Struct) { - let struct_data = expected.data(self.db); + let struct_data = expected.data(self.db.upcast()); if struct_data.kind != StructKind::Unit { self.diagnostics .push(InferenceDiagnostic::MismatchedStructLit { @@ -632,7 +632,7 @@ impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { // Checks whether the passed fields match the fields of a struct definition. fn check_record_lit(&mut self, tgt_expr: ExprId, expected: Struct, fields: &[RecordLitField]) { - let struct_data = expected.data(self.db); + let struct_data = expected.data(self.db.upcast()); if struct_data.kind != StructKind::Record { self.diagnostics .push(InferenceDiagnostic::MismatchedStructLit { @@ -1093,11 +1093,11 @@ mod diagnostics { impl InferenceDiagnostic { pub(crate) fn add_to( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, owner: Function, sink: &mut DiagnosticSink, ) { - let file = owner.source(db).file_id; + let file = owner.source(db.upcast()).file_id; let body = owner.body_source_map(db); match self { InferenceDiagnostic::UnresolvedValue { id } => { diff --git a/crates/mun_hir/src/ty/infer/coerce.rs b/crates/mun_hir/src/ty/infer/coerce.rs index f005a6b00..45709671a 100644 --- a/crates/mun_hir/src/ty/infer/coerce.rs +++ b/crates/mun_hir/src/ty/infer/coerce.rs @@ -1,7 +1,7 @@ use super::InferenceResultBuilder; -use crate::{HirDatabase, Ty, TypeCtor}; +use crate::{Ty, TypeCtor}; -impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { +impl<'a> InferenceResultBuilder<'a> { /// Unify two types, but may coerce the first one to the second using implicit coercion rules if /// needed. pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { diff --git a/crates/mun_hir/src/ty/infer/place_expr.rs b/crates/mun_hir/src/ty/infer/place_expr.rs index 903506ca4..2f352ef19 100644 --- a/crates/mun_hir/src/ty/infer/place_expr.rs +++ b/crates/mun_hir/src/ty/infer/place_expr.rs @@ -1,9 +1,7 @@ -use crate::{ - ty::infer::InferenceResultBuilder, Expr, ExprId, HirDatabase, Path, Resolution, Resolver, -}; +use crate::{ty::infer::InferenceResultBuilder, Expr, ExprId, Path, Resolution, Resolver}; use std::sync::Arc; -impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { +impl<'a> InferenceResultBuilder<'a> { /// Checks if the specified expression is a place-expression. A place expression represents a /// memory location. pub(super) fn check_place_expression(&mut self, resolver: &Resolver, expr: ExprId) -> bool { diff --git a/crates/mun_hir/src/ty/infer/unify.rs b/crates/mun_hir/src/ty/infer/unify.rs index c3dba01bd..5d00317c6 100644 --- a/crates/mun_hir/src/ty/infer/unify.rs +++ b/crates/mun_hir/src/ty/infer/unify.rs @@ -1,8 +1,8 @@ use crate::ty::infer::InferenceResultBuilder; -use crate::{HirDatabase, Ty}; +use crate::Ty; use std::borrow::Cow; -impl<'a, D: HirDatabase> InferenceResultBuilder<'a, D> { +impl<'a> InferenceResultBuilder<'a> { /// If `ty` is a type variable, and it has been instantiated, then return the instantiated type; /// otherwise returns `ty`. pub(crate) fn replace_if_possible<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { diff --git a/crates/mun_hir/src/ty/lower.rs b/crates/mun_hir/src/ty/lower.rs index 48fbf0960..f784a617c 100644 --- a/crates/mun_hir/src/ty/lower.rs +++ b/crates/mun_hir/src/ty/lower.rs @@ -34,7 +34,7 @@ impl LowerBatchResult { /// Adds all the `LowerDiagnostic`s of the result to the `DiagnosticSink`. pub(crate) fn add_diagnostics( &self, - db: &impl HirDatabase, + db: &dyn HirDatabase, file_id: FileId, source_map: &TypeRefSourceMap, sink: &mut DiagnosticSink, @@ -47,7 +47,7 @@ impl LowerBatchResult { impl Ty { pub(crate) fn from_hir( - db: &impl HirDatabase, + db: &dyn HirDatabase, resolver: &Resolver, type_ref_map: &TypeRefMap, type_ref: TypeRefId, @@ -59,7 +59,7 @@ impl Ty { } fn from_hir_with_diagnostics( - db: &impl HirDatabase, + db: &dyn HirDatabase, resolver: &Resolver, type_ref_map: &TypeRefMap, diagnostics: &mut Vec, @@ -80,7 +80,7 @@ impl Ty { } pub(crate) fn from_hir_path( - db: &impl HirDatabase, + db: &dyn HirDatabase, resolver: &Resolver, path: &Path, ) -> Option { @@ -108,7 +108,7 @@ impl Ty { } pub fn types_from_hir( - db: &impl HirDatabase, + db: &dyn HirDatabase, resolver: &Resolver, type_ref_map: &TypeRefMap, ) -> Arc { @@ -124,8 +124,8 @@ pub fn types_from_hir( Arc::new(result) } -pub fn lower_struct_query(db: &impl HirDatabase, s: Struct) -> Arc { - let data = s.data(db); +pub fn lower_struct_query(db: &dyn HirDatabase, s: Struct) -> Arc { + let data = s.data(db.upcast()); types_from_hir(db, &s.resolver(db), data.type_ref_map()) } @@ -191,7 +191,7 @@ impl CallableDef { /// `struct Foo(usize)`, we have two types: The type of the struct itself, and /// the constructor function `(usize) -> Foo` which lives in the values /// namespace. -pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { +pub(crate) fn type_for_def(db: &dyn HirDatabase, def: TypableDef, ns: Namespace) -> Ty { match (def, ns) { (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f), (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t), @@ -215,18 +215,18 @@ fn type_for_builtin(def: BuiltinType) -> Ty { /// Build the declared type of a function. This should not need to look at the /// function body. -fn type_for_fn(_db: &impl HirDatabase, def: Function) -> Ty { +fn type_for_fn(_db: &dyn HirDatabase, def: Function) -> Ty { Ty::simple(TypeCtor::FnDef(def.into())) } -pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { +pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> FnSig { match def { CallableDef::Function(f) => fn_sig_for_fn(db, f), CallableDef::Struct(s) => fn_sig_for_struct_constructor(db, s), } } -pub(crate) fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { +pub(crate) fn fn_sig_for_fn(db: &dyn HirDatabase, def: Function) -> FnSig { let data = def.data(db); let resolver = def.resolver(db); let params = data @@ -238,8 +238,8 @@ pub(crate) fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { FnSig::from_params_and_return(params, ret) } -pub(crate) fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { - let data = def.data(db); +pub(crate) fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: Struct) -> FnSig { + let data = def.data(db.upcast()); let resolver = def.resolver(db); let params = data .fields @@ -251,7 +251,7 @@ pub(crate) fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) } /// Build the type of a struct constructor. -fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { +fn type_for_struct_constructor(db: &dyn HirDatabase, def: Struct) -> Ty { let struct_data = db.struct_data(def.id); if struct_data.kind == StructKind::Tuple { Ty::simple(TypeCtor::FnDef(def.into())) @@ -260,7 +260,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { } } -fn type_for_struct(_db: &impl HirDatabase, def: Struct) -> Ty { +fn type_for_struct(_db: &dyn HirDatabase, def: Struct) -> Ty { Ty::simple(TypeCtor::Struct(def)) } @@ -280,7 +280,7 @@ pub mod diagnostics { impl LowerDiagnostic { pub(crate) fn add_to( &self, - _db: &impl HirDatabase, + _db: &dyn HirDatabase, file_id: FileId, source_map: &TypeRefSourceMap, sink: &mut DiagnosticSink, diff --git a/crates/mun_language_server/Cargo.toml b/crates/mun_language_server/Cargo.toml index d263031ba..644aaf6f7 100644 --- a/crates/mun_language_server/Cargo.toml +++ b/crates/mun_language_server/Cargo.toml @@ -25,7 +25,7 @@ futures = "0.3" anyhow = "1.0" thiserror = "1.0" ra_vfs = "0.6.1" -salsa = "0.14" +salsa = "0.15.0" hir = { version = "=0.2.0", path="../mun_hir", package="mun_hir" } rayon = "1.3" num_cpus = "1.13.0" diff --git a/crates/mun_language_server/src/db.rs b/crates/mun_language_server/src/db.rs index b8fbe6698..ba331fa6b 100644 --- a/crates/mun_language_server/src/db.rs +++ b/crates/mun_language_server/src/db.rs @@ -1,9 +1,9 @@ #![allow(clippy::enum_variant_names)] // This is a HACK because we use salsa use crate::cancelation::Canceled; -use hir::{DefDatabaseStorage, HirDatabase, HirDatabaseStorage, SourceDatabaseStorage}; +use hir::{DefDatabaseStorage, HirDatabase, HirDatabaseStorage, SourceDatabaseStorage, Upcast}; use mun_target::spec::Target; -use salsa::{Database, Runtime, Snapshot}; +use salsa::{Database, Snapshot}; use std::panic; /// The `AnalysisDatabase` provides the database for all analyses. A database is given input and @@ -18,15 +18,14 @@ use std::panic; /// With this struct we can reuse a lot of functionality from the compiler which should provide a /// better user experience. #[salsa::database(SourceDatabaseStorage, DefDatabaseStorage, HirDatabaseStorage)] -#[derive(Debug)] pub(crate) struct AnalysisDatabase { - runtime: salsa::Runtime, + storage: salsa::Storage, } impl AnalysisDatabase { pub fn new() -> Self { let mut db = AnalysisDatabase { - runtime: Default::default(), + storage: Default::default(), }; db.set_target(Target::host_target().expect("could not determine host target spec")); @@ -36,16 +35,8 @@ impl AnalysisDatabase { } impl salsa::Database for AnalysisDatabase { - fn salsa_runtime(&self) -> &Runtime { - &self.runtime - } - - fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime { - &mut self.runtime - } - - fn salsa_event(&self, event: impl Fn() -> salsa::Event) { - match event().kind { + fn salsa_event(&self, event: salsa::Event) { + match event.kind { salsa::EventKind::DidValidateMemoizedValue { .. } | salsa::EventKind::WillExecute { .. } => { self.check_canceled(); @@ -55,6 +46,24 @@ impl salsa::Database for AnalysisDatabase { } } +impl Upcast for AnalysisDatabase { + fn upcast(&self) -> &dyn hir::SourceDatabase { + &*self + } +} + +impl Upcast for AnalysisDatabase { + fn upcast(&self) -> &dyn hir::DefDatabase { + &*self + } +} + +impl Upcast for AnalysisDatabase { + fn upcast(&self) -> &dyn hir::HirDatabase { + &*self + } +} + impl AnalysisDatabase { fn check_canceled(&self) { if self.salsa_runtime().is_current_revision_canceled() { @@ -77,7 +86,7 @@ impl AnalysisDatabase { impl salsa::ParallelDatabase for AnalysisDatabase { fn snapshot(&self) -> Snapshot { Snapshot::new(AnalysisDatabase { - runtime: self.runtime.snapshot(self), + storage: self.storage.snapshot(), }) } }