Skip to content

Commit

Permalink
Update visibility modifier errors with more information
Browse files Browse the repository at this point in the history
  • Loading branch information
cgswords committed Aug 17, 2023
1 parent 3f700f7 commit de1e5ff
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 66 deletions.
126 changes: 64 additions & 62 deletions external-crates/move/move-compiler/src/expansion/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,81 +502,83 @@ fn check_visibility_modifiers(
module_name: ModuleName,
package_name: Option<Symbol>,
) {
let has_friends = friends.len() > 0;
let mut public_friend_usage = false;
let mut public_package_usage = false;
let mut friend_definition = None;
for (_, _, friend) in friends {
friend_definition = Some(friend.loc);
}
let mut public_friend_usage = None;
let mut public_package_usage = None;
for (_, _, function) in functions {
match function.visibility {
E::Visibility::Friend(_) => {
public_friend_usage = true;
E::Visibility::Friend(loc) => {
public_friend_usage = Some(loc);
}
E::Visibility::Package(loc) => {
context
.env
.check_feature(&FeatureGate::PublicPackage, package_name, loc);
public_package_usage = true;
public_package_usage = Some(loc);
}
_ => {}
}
}
match (has_friends, public_friend_usage, public_package_usage) {
(false, false, false) => {}
(false, false, true) => {}
(true, _, false) => {}
(_, true, false) => {}
(true, _, true) => {
// ERROR: can't have friend definitions with public(package) exports.
let msg = "Invalid friend definition in module that uses 'public(package)'";
for (_, _, friend) in friends {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(friend.loc, msg)
));
}
for (_, _, function) in functions {
match function.visibility {
E::Visibility::Package(loc) => {
let msg = format!(
"Invalid visibility modifier 'public(package)'. \
Module '{}' defines friends, which can't be used with this visibility.",
module_name
);
context
.env
.add_diag(diag!(Declarations::InvalidVisibilityModifier, (loc, msg)));
}
_ => {}
}
}

// Emit any errors.
if public_package_usage.is_some()
&& (public_friend_usage.is_some() || friend_definition.is_some())
{
let friend_error_msg = format!(
"Incompatible friend definition in module '{}' that uses 'public(package)'",
module_name
).to_string();
let package_definition_msg = "'public(package)' visibility used here";
for (_, _, friend) in friends {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(friend.loc, friend_error_msg.clone()),
(public_package_usage.unwrap(), package_definition_msg.clone())
));
}
(_, true, true) => {
// ERROR: can't have friend definitions with public(package) exports.
for (_, _, function) in functions {
match function.visibility {
E::Visibility::Package(loc) => {
let msg = format!(
"Invalid visibility modifier 'public(package)'. \
Module '{}' defines functions with 'package(friend)' visibility, which \
can't be used in the same module as this visibility.",
module_name
);
context
.env
.add_diag(diag!(Declarations::InvalidVisibilityModifier, (loc, msg)));
}
E::Visibility::Friend(loc) => {
let msg = format!(
"Invalid visibility modifier 'public(friend)'. \
Module '{}' defines functions with 'package(package)' visibility, which \
can't be used in the same module as this visibility.",
module_name
);
context
.env
.add_diag(diag!(Declarations::InvalidVisibilityModifier, (loc, msg)));
}
_ => {}
let package_error_msg = format!(
"Incompatible visibility 'public(package)' in module '{}'",
module_name
);
let friend_error_msg = format!(
"Incompatible visibility 'public(friend)' in module '{}'",
module_name
);
for (_, _, function) in functions {
match function.visibility {
E::Visibility::Friend(loc) => {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(loc, friend_error_msg.clone()),
(public_package_usage.unwrap(), package_definition_msg.clone())
));
}
E::Visibility::Package(loc) if friend_definition.is_some() && public_friend_usage.is_some() => {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(loc, package_error_msg.clone()),
(friend_definition.unwrap(), "Friend module defined here"),
(public_friend_usage.unwrap(), "'public(friend)' visibility used here")
));
}
E::Visibility::Package(loc) if friend_definition.is_some() => {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(loc, package_error_msg.clone()),
(friend_definition.unwrap(), "Friend module defined here")
));
}
E::Visibility::Package(loc) => {
context.env.add_diag(diag!(
Declarations::InvalidVisibilityModifier,
(loc, package_error_msg.clone()),
(public_friend_usage.unwrap(), "'public(friend)' visibility used here")
));
}
_ => {}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@ error[E02016]: invalid visibility modifier
┌─ tests/move_2024/typing/module_call_visibility_mixed_invalid.move:10:5
10 │ public(package) fun f_package_call_package() { mod_0::f_pkg_public() }
│ ^^^^^^^^^^^^^^^ Invalid visibility modifier 'public(package)'. Module 'mod_1' defines functions with 'package(friend)' visibility, which can't be used in the same module as this visibility.
│ ^^^^^^^^^^^^^^^ Incompatible visibility 'public(package)' in module 'mod_1'
11 │ public(friend) fun f_friend_call_package() { mod_0::f_pkg_public() }
│ -------------- 'public(friend)' visibility used here

error[E02016]: invalid visibility modifier
┌─ tests/move_2024/typing/module_call_visibility_mixed_invalid.move:11:5
10 │ public(package) fun f_package_call_package() { mod_0::f_pkg_public() }
│ --------------- 'public(package)' visibility used here
11 │ public(friend) fun f_friend_call_package() { mod_0::f_pkg_public() }
│ ^^^^^^^^^^^^^^ Invalid visibility modifier 'public(friend)'. Module 'mod_1' defines functions with 'package(package)' visibility, which can't be used in the same module as this visibility.
│ ^^^^^^^^^^^^^^ Incompatible visibility 'public(friend)' in module 'mod_1'

error[E02016]: invalid visibility modifier
┌─ tests/move_2024/typing/module_call_visibility_mixed_invalid.move:17:5
17 │ friend 0x42::mod_1;
│ ^^^^^^^^^^^^^^^^^^^ Invalid friend definition in module that uses 'public(package)'
│ ^^^^^^^^^^^^^^^^^^^ Incompatible friend definition in module 'mod_2' that uses 'public(package)'
18 │
19 │ public(package) fun f_package_call_package(): u64 { 0 }
│ --------------- 'public(package)' visibility used here

error[E02016]: invalid visibility modifier
┌─ tests/move_2024/typing/module_call_visibility_mixed_invalid.move:19:5
17 │ friend 0x42::mod_1;
│ ------------------- Friend module defined here
18 │
19 │ public(package) fun f_package_call_package(): u64 { 0 }
│ ^^^^^^^^^^^^^^^ Invalid visibility modifier 'public(package)'. Module 'mod_2' defines friends, which can't be used with this visibility.
│ ^^^^^^^^^^^^^^^ Incompatible visibility 'public(package)' in module 'mod_2'

0 comments on commit de1e5ff

Please sign in to comment.