Skip to content

Commit 9ceb9f9

Browse files
asteriteRumata888
authored andcommitted
feat!: turn TypeIsMorePrivateThenItem into an error (#6953)
1 parent ca46630 commit 9ceb9f9

7 files changed

Lines changed: 97 additions & 31 deletions

File tree

compiler/noirc_frontend/src/elaborator/traits.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ impl<'context> Elaborator<'context> {
127127
parameters,
128128
return_type,
129129
where_clause,
130+
unresolved_trait.trait_def.visibility,
130131
func_id,
131132
);
132133

@@ -189,6 +190,7 @@ impl<'context> Elaborator<'context> {
189190
parameters: &[(Ident, UnresolvedType)],
190191
return_type: &FunctionReturnType,
191192
where_clause: &[UnresolvedTraitConstraint],
193+
trait_visibility: ItemVisibility,
192194
func_id: FuncId,
193195
) {
194196
let old_generic_count = self.generics.len();
@@ -205,8 +207,9 @@ impl<'context> Elaborator<'context> {
205207
where_clause,
206208
return_type,
207209
);
208-
// Trait functions are always public
209-
def.visibility = ItemVisibility::Public;
210+
211+
// Trait functions always have the same visibility as the trait they are in
212+
def.visibility = trait_visibility;
210213

211214
let mut function = NoirFunction { kind, def };
212215
self.define_function_meta(&mut function, func_id, Some(trait_id));

compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ impl<'a> ModCollector<'a> {
487487
let location = Location::new(name.span(), self.file_id);
488488
let modifiers = FunctionModifiers {
489489
name: name.to_string(),
490-
visibility: ItemVisibility::Public,
490+
visibility: trait_definition.visibility,
491491
// TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629
492492
attributes: crate::token::Attributes::empty(),
493493
is_unconstrained: *is_unconstrained,

compiler/noirc_frontend/src/hir/resolution/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
607607
},
608608
ResolverError::UnsupportedNumericGenericType(err) => err.into(),
609609
ResolverError::TypeIsMorePrivateThenItem { typ, item, span } => {
610-
Diagnostic::simple_warning(
610+
Diagnostic::simple_error(
611611
format!("Type `{typ}` is more private than item `{item}`"),
612612
String::new(),
613613
*span,

compiler/noirc_frontend/src/hir/resolution/visibility.rs

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::graph::CrateId;
2-
use crate::node_interner::{FuncId, NodeInterner, StructId};
2+
use crate::node_interner::{FuncId, NodeInterner, StructId, TraitId};
33
use crate::Type;
44

55
use std::collections::BTreeMap;
@@ -79,26 +79,47 @@ pub fn struct_member_is_visible(
7979
visibility: ItemVisibility,
8080
current_module_id: ModuleId,
8181
def_maps: &BTreeMap<CrateId, CrateDefMap>,
82+
) -> bool {
83+
type_member_is_visible(struct_id.module_id(), visibility, current_module_id, def_maps)
84+
}
85+
86+
pub fn trait_member_is_visible(
87+
trait_id: TraitId,
88+
visibility: ItemVisibility,
89+
current_module_id: ModuleId,
90+
def_maps: &BTreeMap<CrateId, CrateDefMap>,
91+
) -> bool {
92+
type_member_is_visible(trait_id.0, visibility, current_module_id, def_maps)
93+
}
94+
95+
fn type_member_is_visible(
96+
type_module_id: ModuleId,
97+
visibility: ItemVisibility,
98+
current_module_id: ModuleId,
99+
def_maps: &BTreeMap<CrateId, CrateDefMap>,
82100
) -> bool {
83101
match visibility {
84102
ItemVisibility::Public => true,
85103
ItemVisibility::PublicCrate => {
86-
struct_id.parent_module_id(def_maps).krate == current_module_id.krate
104+
let type_parent_module_id =
105+
type_module_id.parent(def_maps).expect("Expected parent module to exist");
106+
type_parent_module_id.krate == current_module_id.krate
87107
}
88108
ItemVisibility::Private => {
89-
let struct_parent_module_id = struct_id.parent_module_id(def_maps);
90-
if struct_parent_module_id.krate != current_module_id.krate {
109+
let type_parent_module_id =
110+
type_module_id.parent(def_maps).expect("Expected parent module to exist");
111+
if type_parent_module_id.krate != current_module_id.krate {
91112
return false;
92113
}
93114

94-
if struct_parent_module_id.local_id == current_module_id.local_id {
115+
if type_parent_module_id.local_id == current_module_id.local_id {
95116
return true;
96117
}
97118

98119
let def_map = &def_maps[&current_module_id.krate];
99120
module_descendent_of_target(
100121
def_map,
101-
struct_parent_module_id.local_id,
122+
type_parent_module_id.local_id,
102123
current_module_id.local_id,
103124
)
104125
}
@@ -115,35 +136,37 @@ pub fn method_call_is_visible(
115136
let modifiers = interner.function_modifiers(&func_id);
116137
match modifiers.visibility {
117138
ItemVisibility::Public => true,
118-
ItemVisibility::PublicCrate => {
119-
if object_type.is_primitive() {
120-
current_module.krate.is_stdlib()
121-
} else {
122-
interner.function_module(func_id).krate == current_module.krate
139+
ItemVisibility::PublicCrate | ItemVisibility::Private => {
140+
let func_meta = interner.function_meta(&func_id);
141+
if let Some(struct_id) = func_meta.struct_id {
142+
return struct_member_is_visible(
143+
struct_id,
144+
modifiers.visibility,
145+
current_module,
146+
def_maps,
147+
);
123148
}
124-
}
125-
ItemVisibility::Private => {
149+
150+
if let Some(trait_id) = func_meta.trait_id {
151+
return trait_member_is_visible(
152+
trait_id,
153+
modifiers.visibility,
154+
current_module,
155+
def_maps,
156+
);
157+
}
158+
126159
if object_type.is_primitive() {
127160
let func_module = interner.function_module(func_id);
128-
item_in_module_is_visible(
161+
return item_in_module_is_visible(
129162
def_maps,
130163
current_module,
131164
func_module,
132165
modifiers.visibility,
133-
)
134-
} else {
135-
let func_meta = interner.function_meta(&func_id);
136-
if let Some(struct_id) = func_meta.struct_id {
137-
struct_member_is_visible(
138-
struct_id,
139-
modifiers.visibility,
140-
current_module,
141-
def_maps,
142-
)
143-
} else {
144-
true
145-
}
166+
);
146167
}
168+
169+
true
147170
}
148171
}
149172
}

compiler/noirc_frontend/src/tests.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,6 +2842,21 @@ fn trait_constraint_on_tuple_type() {
28422842
assert_no_errors(src);
28432843
}
28442844

2845+
#[test]
2846+
fn trait_constraint_on_tuple_type_pub_crate() {
2847+
let src = r#"
2848+
pub(crate) trait Foo<A> {
2849+
fn foo(self, x: A) -> bool;
2850+
}
2851+
2852+
pub fn bar<T, U, V>(x: (T, U), y: V) -> bool where (T, U): Foo<V> {
2853+
x.foo(y)
2854+
}
2855+
2856+
fn main() {}"#;
2857+
assert_no_errors(src);
2858+
}
2859+
28452860
#[test]
28462861
fn incorrect_generic_count_on_struct_impl() {
28472862
let src = r#"

compiler/noirc_frontend/src/tests/visibility.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,29 @@ fn errors_if_pub_trait_returns_private_struct() {
229229
assert_type_is_more_private_than_item_error(src, "Bar", "foo");
230230
}
231231

232+
#[test]
233+
fn does_not_error_if_trait_with_default_visibility_returns_struct_with_default_visibility() {
234+
let src = r#"
235+
struct Foo {}
236+
237+
trait Bar {
238+
fn bar(self) -> Foo;
239+
}
240+
241+
impl Bar for Foo {
242+
fn bar(self) -> Foo {
243+
self
244+
}
245+
}
246+
247+
fn main() {
248+
let foo = Foo {};
249+
let _ = foo.bar();
250+
}
251+
"#;
252+
assert_no_errors(src);
253+
}
254+
232255
#[test]
233256
fn errors_if_trying_to_access_public_function_inside_private_module() {
234257
let src = r#"

docs/docs/noir/concepts/traits.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,5 @@ pub trait Trait {}
582582
// This trait alias is now public
583583
pub trait Baz = Foo + Bar;
584584
```
585+
586+
Trait methods have the same visibility as the trait they are in.

0 commit comments

Comments
 (0)