From 51c76bfa6056ffaafc56c8ca2cd9db68fe88928c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Nov 2024 12:44:01 +0100 Subject: [PATCH 1/3] chore(ci): bump codecov/codecov-action from 4 to 5 (#574) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54607b86..ac2571c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,7 +112,7 @@ jobs: args: nextest --all-features --workspace --lcov --output-path lcov.info --profile ci - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: lcov.info name: ${{ matrix.os }} From 6537d40ffe87632fb0eee068d03e28e388cf5e85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Nov 2024 12:44:11 +0100 Subject: [PATCH 2/3] chore(ci): bump peter-evans/create-pull-request from 6 to 7 (#572) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/bump-pre-release.yml | 2 +- .github/workflows/bump-release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bump-pre-release.yml b/.github/workflows/bump-pre-release.yml index 607e7c1d..808e5452 100644 --- a/.github/workflows/bump-pre-release.yml +++ b/.github/workflows/bump-pre-release.yml @@ -44,7 +44,7 @@ jobs: --exclude tools - name: Create PR - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: delete-branch: true base: "main" diff --git a/.github/workflows/bump-release.yml b/.github/workflows/bump-release.yml index 9ec6575a..6919ba77 100644 --- a/.github/workflows/bump-release.yml +++ b/.github/workflows/bump-release.yml @@ -40,7 +40,7 @@ jobs: --dependent-version upgrade \ --exclude tools - name: Create PR - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: delete-branch: true base: "main" From 0acea1cc773248366867c9936a560efbeca17859 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Sat, 30 Nov 2024 17:39:40 +0100 Subject: [PATCH 3/3] feat: infer associate functions (#575) --- crates/mun_hir/src/method_resolution.rs | 2 +- crates/mun_hir/src/ty/infer.rs | 84 ++++++++++++++++--- ...s__infer_access_hidden_assoc_function.snap | 9 ++ ..._hir__ty__tests__infer_assoc_function.snap | 11 +++ crates/mun_hir/src/ty/tests.rs | 42 ++++++++++ 5 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_access_hidden_assoc_function.snap create mode 100644 crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_assoc_function.snap diff --git a/crates/mun_hir/src/method_resolution.rs b/crates/mun_hir/src/method_resolution.rs index 7a293d28..17456782 100644 --- a/crates/mun_hir/src/method_resolution.rs +++ b/crates/mun_hir/src/method_resolution.rs @@ -161,7 +161,7 @@ impl InherentImpls { self.map.values().flatten().copied() } - // Returns all implementations defined for the specified type. + /// Returns all implementations defined for the specified type. pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { match self_ty.interned() { TyKind::Struct(s) => self.map.get(&s.id).map_or(&[], AsRef::as_ref), diff --git a/crates/mun_hir/src/ty/infer.rs b/crates/mun_hir/src/ty/infer.rs index d6673066..c326d5da 100644 --- a/crates/mun_hir/src/ty/infer.rs +++ b/crates/mun_hir/src/ty/infer.rs @@ -1,6 +1,7 @@ use std::{ops::Index, sync::Arc}; use la_arena::ArenaMap; +use mun_hir_input::ModuleId; use rustc_hash::FxHashSet; use crate::{ @@ -24,8 +25,10 @@ mod unify; use crate::{ expr::{LiteralFloat, LiteralFloatKind, LiteralInt, LiteralIntKind}, + has_module::HasModule, ids::DefWithBodyId, - resolve::{resolver_for_expr, HasResolver}, + method_resolution::lookup_method, + resolve::{resolver_for_expr, HasResolver, ResolveValueResult}, ty::{ primitives::{FloatTy, IntTy}, TyKind, @@ -184,6 +187,13 @@ impl<'a> InferenceResultBuilder<'a> { } } + /// Returns the module in which the body is defined. + pub fn module(&self) -> ModuleId { + match self.body.owner() { + DefWithBodyId::FunctionId(func) => func.module(self.db.upcast()), + } + } + /// Associate the given `ExprId` with the specified `Ty`. fn set_expr_type(&mut self, expr: ExprId, ty: Ty) { self.type_of_expr.insert(expr, ty); @@ -718,6 +728,65 @@ impl<'a> InferenceResultBuilder<'a> { } } + fn resolve_assoc_item( + &mut self, + def: TypeNs, + path: &Path, + remaining_index: usize, + id: ExprId, + ) -> Option { + // We can only resolve the last element of the path. + let name = if remaining_index == path.segments.len() - 1 { + &path.segments[remaining_index] + } else { + return None; + }; + + // Infer the type of the definitions + let type_for_def_fn = |def| self.db.type_for_def(def, Namespace::Types); + let root_ty = match def { + TypeNs::SelfType(id) => self.db.type_for_impl_self(id), + TypeNs::StructId(id) => type_for_def_fn(TypableDef::Struct(id.into())), + TypeNs::TypeAliasId(id) => type_for_def_fn(TypableDef::TypeAlias(id.into())), + TypeNs::PrimitiveType(id) => type_for_def_fn(TypableDef::PrimitiveType(id)), + }; + + // Resolve the value. + let function_id = match lookup_method(self.db, &root_ty, self.module(), name) { + Ok(value) => value, + Err(Some(value)) => { + self.diagnostics + .push(InferenceDiagnostic::PathIsPrivate { id }); + value + } + _ => return None, + }; + + Some(ValueNs::FunctionId(function_id)) + } + + fn resolve_value_path_inner( + &mut self, + resolver: &Resolver, + path: &Path, + id: ExprId, + ) -> Option { + let value_or_partial = resolver.resolve_path_as_value(self.db.upcast(), path)?; + match value_or_partial { + ResolveValueResult::ValueNs(it, vis) => { + if !vis.is_visible_from(self.db, self.module()) { + self.diagnostics + .push(diagnostics::InferenceDiagnostic::PathIsPrivate { id }); + } + + Some(it) + } + ResolveValueResult::Partial(def, remaining_index) => { + self.resolve_assoc_item(def, path, remaining_index, id) + } + } + } + fn infer_path_expr( &mut self, resolver: &Resolver, @@ -725,18 +794,7 @@ impl<'a> InferenceResultBuilder<'a> { id: ExprId, check_params: &CheckParams, ) -> Option { - if let Some((value, vis)) = resolver.resolve_path_as_value_fully(self.db.upcast(), path) { - // Check visibility of this item - if !vis.is_visible_from( - self.db, - self.resolver - .module() - .expect("resolver must have a module to be able to resolve modules"), - ) { - self.diagnostics - .push(diagnostics::InferenceDiagnostic::PathIsPrivate { id }); - } - + if let Some(value) = self.resolve_value_path_inner(resolver, path, id) { // Match based on what type of value we found match value { ValueNs::ImplSelf(i) => { diff --git a/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_access_hidden_assoc_function.snap b/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_access_hidden_assoc_function.snap new file mode 100644 index 00000000..31c593c3 --- /dev/null +++ b/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_access_hidden_assoc_function.snap @@ -0,0 +1,9 @@ +--- +source: crates/mun_hir/src/ty/tests.rs +expression: "infer(r#\"\n //- /foo.mun\n pub struct Foo {\n a: i32\n }\n\n impl Foo {\n fn new(){}\n }\n\n //- /mod.mun\n fn main() {\n foo::Foo::new();\n }\n \"#)" +--- +16..29: access of private type +10..34 '{ ...w(); }': () +16..29 'foo::Foo::new': function new() -> () +16..31 'foo::Foo::new()': () +54..56 '{}': () diff --git a/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_assoc_function.snap b/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_assoc_function.snap new file mode 100644 index 00000000..f760c8e7 --- /dev/null +++ b/crates/mun_hir/src/ty/snapshots/mun_hir__ty__tests__infer_assoc_function.snap @@ -0,0 +1,11 @@ +--- +source: crates/mun_hir/src/ty/tests.rs +expression: "infer(r#\"\n struct Foo {\n a: i32\n }\n\n impl Foo {\n fn new() -> Self {\n Self { a: 3 }\n }\n }\n\n fn main() {\n let a = Foo::new();\n }\n \"#)" +--- +102..129 '{ ...w(); }': () +112..113 'a': Foo +116..124 'Foo::new': function new() -> Foo +116..126 'Foo::new()': Foo +59..88 '{ ... }': Foo +69..82 'Self { a: 3 }': Foo +79..80 '3': i32 diff --git a/crates/mun_hir/src/ty/tests.rs b/crates/mun_hir/src/ty/tests.rs index 18cb4c7b..c5012bc0 100644 --- a/crates/mun_hir/src/ty/tests.rs +++ b/crates/mun_hir/src/ty/tests.rs @@ -696,6 +696,48 @@ fn infer_self_field() { )); } +#[test] +fn infer_assoc_function() { + insta::assert_snapshot!(infer( + r#" + struct Foo { + a: i32 + } + + impl Foo { + fn new() -> Self { + Self { a: 3 } + } + } + + fn main() { + let a = Foo::new(); + } + "# + )); +} + +#[test] +fn infer_access_hidden_assoc_function() { + insta::assert_snapshot!(infer( + r#" + //- /foo.mun + pub struct Foo { + a: i32 + } + + impl Foo { + fn new(){} + } + + //- /mod.mun + fn main() { + foo::Foo::new(); + } + "# + )); +} + #[test] fn infer_basics() { insta::assert_snapshot!(infer(