Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[move-compiler] Added preliminary support for writing linters #12650

Merged
merged 5 commits into from Jun 27, 2023

Conversation

awelc
Copy link
Contributor

@awelc awelc commented Jun 23, 2023

Description

Added support for writing linters:

  • integration with Sui CLI
  • a simple testing harness
  • an example linter to signal sharing of potentially owned objects

Test Plan

Additional testing framework being part of this PR can be used to test individual linters.


If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process.

Type of Change (Check all that apply)

  • protocol change
  • user-visible impact
  • breaking change for a client SDKs
  • breaking change for FNs (FN binary must upgrade)
  • breaking change for validators or node operators (must upgrade binaries)
  • breaking change for on-chain data layout
  • necessitate either a data wipe or data migration

Release notes

Developers may now opt into running linters when building/testing/publishing/upgrading packages via CLI by specifying the --lint flag.

@awelc awelc requested a review from tnowacki June 23, 2023 11:10
@awelc awelc self-assigned this Jun 23, 2023
@vercel
Copy link

vercel bot commented Jun 23, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

6 Ignored Deployments
Name Status Preview Comments Updated (UTC)
explorer ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm
explorer-storybook ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm
multisig-toolkit ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm
sui-kiosk ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm
sui-wallet-kit ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm
wallet-adapter ⬜️ Ignored (Inspect) Jun 27, 2023 2:39pm

Copy link
Contributor

@tnowacki tnowacki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outstanding! Thanks!

Just a few minor things, and mostly looking for your thoughts/feedback on a few things

self.build_and_lint(path, false)
}

pub fn build_and_lint(self, path: PathBuf, lint: bool) -> SuiResult<CompiledPackage> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should lint here be a flag on self: BuildConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Adding a function felt less-invasive but considering that in most cases BuildConfig is created with a single function, it does not matter much, and having a flag in BuildConfig does look cleaner. Thanks!

crates/sui-move-build/src/linters/share_owned.rs Outdated Show resolved Hide resolved
Comment on lines 142 to 143
let msg = "You may be trying to share an owned object.";
let uid_msg = "This argument should in most cases come from an object created within the same function.";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine? Maybe?
Just brainstorming:

Suggested change
let msg = "You may be trying to share an owned object.";
let uid_msg = "This argument should in most cases come from an object created within the same function.";
let msg = "Potential abort from sharing an object not created this transaction.";
let uid_msg = "Creating a fresh object in this same function will ensure this does not abort.";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went for yet another variant combining (sort of) the two proposals.

(f.arguments.exp.loc, uid_msg)
);
if let Value::NotFreshObj(l) = args[0] {
d.add_secondary_label((l, "A potentially shared object coming from here"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
d.add_secondary_label((l, "A potentially shared object coming from here"))
d.add_secondary_label((l, "A potentially owned object coming from here"))

Is this flipped?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh...

if let L::Unpack(_, _, fields) = l_ {
for (f, l) in fields {
let v = if is_obj(l) {
<Self::State as SimpleDomain>::Value::NotFreshObj(f.loc())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange, does just Value::NotFreshObj error here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it happens, it does... Probably copypasta and/or some artifact of an earlier implementation based off a branch.

};
self.lvalue(context, state, l, v)
}
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts on the bool thing? (where true is skip and false is continue)

I came up with it and I find it a bit confusing reading it lol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't give it that much thought but I found it pretty sensible to work with.

Ok(())
}

fn run_tests(path: &Path) -> anyhow::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@@ -743,6 +743,36 @@ fn has_compiled_module_magic_number(path: &str) -> bool {
num_bytes_read == BinaryConstants::MOVE_MAGIC_SIZE && magic == BinaryConstants::MOVE_MAGIC
}

pub fn move_check_for_errors(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really relevant for this PR just a comment:
We might want to rename it and flesh out this API (as it also does warnings now... this function is super old fwiw)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

Comment on lines +58 to +83
if update_baseline {
if has_diags {
fs::write(exp_path, rendered_diags)?;
} else if exp_path.is_file() {
fs::remove_file(exp_path)?;
}
return Ok(());
}

let exp_exists = exp_path.is_file();
if exp_exists {
let expected_diags = fs::read_to_string(exp_path)?;
if rendered_diags != expected_diags {
let msg = format!(
"Expected output differ from the actual one:\n{}",
format_diff(expected_diags, rendered_diags),
);
anyhow::bail!(add_update_baseline_fix(msg));
}
} else {
let msg = format!("Unexpected output :\n{}", rendered_diags);
anyhow::bail!(add_update_baseline_fix(msg));
}

Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not relevant for this PR, but I've copy-pasted this so many times. We should maybe make a library for this or something idk

Comment on lines +38 to +44
const SHARE_OWNED_DIAG: DiagnosticInfo = custom(
"Lint ",
Severity::Warning,
/* category */ 1,
/* code */ 1,
"possible owned object share",
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any feedback you have for making this easier to manage? (specifically on the category/code side of things)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not at the moment, but I will think about it when writing more lints!

@awelc awelc merged commit bbf4187 into main Jun 27, 2023
35 checks passed
@awelc awelc deleted the aw/linter-framework branch June 27, 2023 16:26
@awelc awelc mentioned this pull request Jul 10, 2023
6 tasks
ebmifa pushed a commit that referenced this pull request Jul 12, 2023
## Description 

Added support for writing linters:
- integration with Sui CLI
- a simple testing harness
- an example linter to signal sharing of potentially owned objects

## Test Plan 

Additional testing framework being part of this PR can be used to test
individual linters.

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [x] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

Developers may now opt into running linters when
building/testing/publishing/upgrading packages via CLI by specifying the
`--lint` flag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants