Skip to content

Commit 63a4da6

Browse files
committed
fix method visibility check, more path res tests
1 parent 874775a commit 63a4da6

File tree

10 files changed

+188
-8
lines changed

10 files changed

+188
-8
lines changed

crates/hir-analysis/src/name_resolution/path_resolver.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,20 @@ impl<'db> PathRes<'db> {
364364

365365
pub fn is_visible_from(&self, db: &'db dyn HirAnalysisDb, from_scope: ScopeId<'db>) -> bool {
366366
match self {
367-
PathRes::Ty(ty) | PathRes::Func(ty) | PathRes::Const(ty) | PathRes::Method(ty, _) => {
367+
PathRes::Ty(ty) | PathRes::Func(ty) | PathRes::Const(ty) => {
368368
is_ty_visible_from(db, *ty, from_scope)
369369
}
370+
PathRes::Method(_, cand) => {
371+
// Method visibility depends on the method's defining scope
372+
// (function or trait method), not the receiver type.
373+
let method_scope = match cand {
374+
MethodCandidate::InherentMethod(func_def) => func_def.scope(db),
375+
MethodCandidate::TraitMethod(c) | MethodCandidate::NeedsConfirmation(c) => {
376+
c.method.0.scope(db)
377+
}
378+
};
379+
is_scope_visible_from(db, method_scope, from_scope)
380+
}
370381
r => is_scope_visible_from(db, r.as_scope(db).unwrap(), from_scope),
371382
}
372383
}
@@ -605,7 +616,7 @@ where
605616
if let Some(enum_) = ty.as_enum(db) {
606617
// We need to use the concrete enum scope instead of
607618
// parent_scope to resolve the variants in all cases,
608-
// eg when parent is `Self`. I'm not really sure why this is.
619+
// eg when parent is `Self`
609620
let query = make_query(db, path, enum_.scope());
610621
let bucket = resolve_query(db, query);
611622

@@ -884,7 +895,15 @@ pub fn resolve_name_res<'db>(
884895
PathRes::Func(TyId::foldl(db, ty, args))
885896
}
886897
ItemKind::Const(const_) => {
887-
// TODO err if any args
898+
if !args.is_empty() {
899+
return Err(PathResError::new(
900+
PathResErrorKind::ArgNumMismatch {
901+
expected: 0,
902+
given: args.len(),
903+
},
904+
path,
905+
));
906+
}
888907
let ty = if let Some(ty) = const_.ty(db).to_opt() {
889908
lower_hir_ty(db, ty, scope, assumptions)
890909
} else {
@@ -895,7 +914,8 @@ pub fn resolve_name_res<'db>(
895914

896915
ItemKind::TypeAlias(type_alias) => {
897916
let alias = lower_type_alias(db, type_alias);
898-
if args.len() < alias.params(db).len() {
917+
let expected = alias.params(db).len();
918+
if args.len() < expected {
899919
PathRes::TyAlias(
900920
alias.clone(),
901921
TyId::invalid(
@@ -906,8 +926,27 @@ pub fn resolve_name_res<'db>(
906926
},
907927
),
908928
)
929+
} else if args.len() > expected {
930+
return Err(PathResError::new(
931+
PathResErrorKind::ArgNumMismatch { expected, given: args.len() },
932+
path,
933+
));
909934
} else {
910-
PathRes::TyAlias(alias.clone(), alias.alias_to.instantiate(db, args))
935+
let instantiated = alias.alias_to.instantiate(db, args);
936+
if let TyData::Invalid(InvalidCause::TooManyGenericArgs {
937+
expected,
938+
given,
939+
}) = instantiated.data(db)
940+
{
941+
return Err(PathResError::new(
942+
PathResErrorKind::ArgNumMismatch {
943+
expected: *expected,
944+
given: *given,
945+
},
946+
path,
947+
));
948+
}
949+
PathRes::TyAlias(alias.clone(), instantiated)
911950
}
912951
}
913952

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
enum Option<T> {
2+
None,
3+
Some(T),
4+
}
5+
6+
impl Option<i32> {
7+
fn make_some(val: i32) -> Option<i32> {
8+
// Ensure `Self::Some` resolves via the enum scope, not lexical scope.
9+
Self::Some(val)
10+
}
11+
}
12+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
source: crates/hir-analysis/tests/early_path_resolution.rs
3+
assertion_line: 40
4+
expression: res
5+
input_file: test_files/early_path_resolution/enum_self_variant.fe
6+
---
7+
note:
8+
┌─ enum_self_variant.fe:3:10
9+
10+
3Some(T),
11+
^ enum_self_variant::Option::T
12+
13+
note:
14+
┌─ enum_self_variant.fe:6:6
15+
16+
6impl Option<i32> {
17+
^^^^^^ enum_self_variant::Option
18+
19+
note:
20+
┌─ enum_self_variant.fe:6:13
21+
22+
6impl Option<i32> {
23+
^^^ i32
24+
25+
note:
26+
┌─ enum_self_variant.fe:7:23
27+
28+
7fn make_some(val: i32) -> Option<i32> {
29+
^^^ i32
30+
31+
note:
32+
┌─ enum_self_variant.fe:7:31
33+
34+
7fn make_some(val: i32) -> Option<i32> {
35+
^^^^^^ enum_self_variant::Option
36+
37+
note:
38+
┌─ enum_self_variant.fe:7:38
39+
40+
7fn make_some(val: i32) -> Option<i32> {
41+
^^^ i32
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod m {
2+
pub const C: i32 = 1
3+
}
4+
5+
pub fn bad() -> i32 {
6+
// Generic arguments on a const should error with an arg count mismatch.
7+
m::C<i32>
8+
}
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: crates/hir-analysis/tests/name_resolution.rs
3+
assertion_line: 48
4+
expression: diagnostic_output
5+
input_file: test_files/name_resolution/const_generic_args.fe
6+
---
7+
error[2-0011]: incorrect number of generic arguments for `C`; expected 0, given 1
8+
┌─ const_generic_args.fe:7:8
9+
10+
7m::C<i32>
11+
│ ^^^^^^ expected 0 arguments, but 1 were given
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
mod m {
2+
pub struct S {}
3+
4+
impl S {
5+
pub fn new() -> S { S {} }
6+
7+
// Private inherent method: only callable within `m`.
8+
fn secret(self) -> i32 { 1 }
9+
10+
pub fn public(self) -> i32 { self.secret() }
11+
}
12+
13+
pub fn make() -> S { S::new() }
14+
}
15+
16+
fn ok() -> i32 {
17+
// Outside module: public method is callable
18+
m::make().public()
19+
}
20+
21+
fn bad() -> i32 {
22+
// Outside module: calling private method should be invisible
23+
let s = m::make()
24+
s.secret()
25+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
source: crates/hir-analysis/tests/visibility.rs
3+
assertion_line: 49
4+
expression: diagnostic_output
5+
input_file: test_files/visibility/method_visibility.fe
6+
---
7+
error[1-0001]: unexpected syntax while parsing block
8+
┌─ method_visibility.fe:23:22
9+
10+
23let s = m::make();
11+
^ unexpected
12+
13+
error[2-0003]: `secret` is not visible
14+
┌─ method_visibility.fe:24:7
15+
16+
8fn secret(self) -> i32 { 1 }
17+
------ `secret` is defined here
18+
·
19+
24s.secret()
20+
^^^^^^ `secret` is not visible
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mod m {
2+
pub type Alias<T> = T
3+
}
4+
5+
pub fn f(x: m::Alias<i32, u32>) {}
6+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
source: crates/hir-analysis/tests/name_resolution.rs
3+
assertion_line: 48
4+
expression: diagnostic_output
5+
input_file: test_files/name_resolution/type_alias_extra_args.fe
6+
---
7+
error[2-0011]: incorrect number of generic arguments for `Alias`; expected 1, given 2
8+
┌─ type_alias_extra_args.fe:5:16
9+
10+
5pub fn f(x: m::Alias<i32, u32>) {}
11+
^^^^^ expected 1 arguments, but 2 were given
12+

crates/uitest/fixtures/ty/def/alias_arg_mismatch.snap

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
---
22
source: crates/uitest/tests/ty.rs
3+
assertion_line: 27
34
expression: diags
4-
input_file: crates/uitest/fixtures/ty/alias_arg_mismatch.fe
5+
input_file: fixtures/ty/def/alias_arg_mismatch.fe
56
---
7+
error[2-0011]: incorrect number of generic arguments for `T2`; expected 1, given 2
8+
┌─ alias_arg_mismatch.fe:4:8
9+
10+
4u: T2<i32, u32>,
11+
^^ expected 1 arguments, but 2 were given
12+
613
error[3-0003]: all type parameters of type alias must be given
714
┌─ alias_arg_mismatch.fe:2:8
815
@@ -19,5 +26,3 @@ error[3-0003]: all type parameters of type alias must be given
1926
│ ----------------------- type alias defined here
2027
13type T2<T> = T1<T>
2128
│ ^^^^^ expected at least 2 arguments here
22-
23-

0 commit comments

Comments
 (0)