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

Automatic annotation of type signatures #7130

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

snobee
Copy link
Contributor

@snobee snobee commented Sep 29, 2024

Resolves #7042

I've started with all the logic in analysed_doc but I'll probably end up moving some of it into fmt when I start on that part

I'm making some assumptions here that I wanted to confirm:

  1. All definitions begin at the start of a line
  2. The left side of a type annotation is the exact same as the left side of a definition

@snobee snobee force-pushed the annotate-type-signatures branch 4 times, most recently from f03b305 to 387c509 Compare November 5, 2024 23:48
buffer
}

pub fn annotation_edits(
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've exposed this and annotations_edit() publicly to be used in the language server but It feels weird to expose them from the cli crate. If it should be in another crate what one?

crates/cli/src/format.rs Outdated Show resolved Hide resolved

let annotate_exit_code = match annotate_file(&arena, roc_file_path.to_owned()) {
Ok(()) => 0,
Err(LoadingProblem::FormattedReport(report)) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If there's a problem loading the file then it just prints out the error. I know this needs to be updated but I'm not sure what the error message should be. Should it include the loading problem or just say that there was one?

@snobee
Copy link
Contributor Author

snobee commented Nov 6, 2024

I've added some comments on the code with some questions about things that I'm not sure about

There's a test that's failing in the language server and that's on purpose. I'm pretty sure the problem is in #7126 but don't know how to check that until it's been fixed, so I'm going to consider this blocked. I'll take a look but I'm not very confident I can figure it out.

Copy link

github-actions bot commented Dec 7, 2024

Thank you for your contribution! Sometimes PRs end up staying open for a long time without activity, which can make the list of open PRs get long and time-consuming to review. To keep things manageable for reviewers, this bot automatically closes PRs that haven’t had activity in 60 days. This PR hasn’t had activity in 30 days, so it will be automatically closed if there is no more activity in the next 30 days. Keep in mind that PRs marked Closed are not deleted, so no matter what, the PR will still be right here in the repo. You can always access it and reopen it anytime you like!

@snobee
Copy link
Contributor Author

snobee commented Dec 14, 2024

This has been open long enough so I've put it up for review. There's still issues with suffixed expressions from #7126 but the code for this is independent from that.

@snobee snobee marked this pull request as ready for review December 14, 2024 00:32
@snobee snobee force-pushed the annotate-type-signatures branch from acea61b to d4e558d Compare December 14, 2024 04:49
@snobee
Copy link
Contributor Author

snobee commented Dec 14, 2024

I changed an if to an assert last minute 🙃. That should fix it

@lukewilliamboswell
Copy link
Collaborator

@snobee -- can you please merge latest main?

Apologies for leaving it so long... I think this slipped through and got forgotten about.

@snobee
Copy link
Contributor Author

snobee commented Jan 16, 2025

@lukewilliamboswell No problem 😃 Should be ready for review now!

if self.should_visit(region) {
if let Expr::Call(_, args, CalledVia::QuestionSuffix) = expr {
let Expr::Closure(ClosureData { arguments, .. }) = &args[1].1.value else {
internal_error!("Suffixed expression did not contain a closure")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Particularly for the language server, I think we should be more careful about crashing. Is there a sensible default we can use 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.

Just skipping this node and printing an error is probably the best way to handle it.

That being said, I can see that this form of question suffix desugaring was removed from the compiler, it's just the enum variant that remains. I think I can just remove this whole section instead.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@lukewilliamboswell do you know what the status is of CalledVia::QuestionSuffix?

decl.range,
);

let pos = roc_region::all::Position::new(offset as u32);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a use statement at the top for Position?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

lsp_type::Position is already imported and I must have forgot about renaming imports. I'll import as RocPosition or something

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ahh I missed that there was another thing named Position. In that case, I don't feel strongly.

let symbol = decls.symbols[index];
let expr = &decls.expressions[index].value;

use roc_problem::can::RuntimeError::ExposedButNotDefined;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this use be moved to the top?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep!

Comment on lines +409 to +410
// Generated names for errors start with `#`
.replace('#', "");
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems that if there's an error in the type, don't we want to cancel the operation, no?

Copy link
Contributor Author

@snobee snobee Jan 21, 2025

Choose a reason for hiding this comment

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

maybe? These only seem show up when a type doesn't implement an ability it's supposed to. I'm not sure how I'd go about detecting all type errors. I could try looking for

  • Error
  • FlexVar(None) or FlexAbleVar(None, ...) that show up anywhere except as arguments
  • FlexVar or FlexAbleVar that have names that start with '#'

But that still allows things like List.first(8) which has the type Result a [ListWasEmpty]. I'm not sure if that would be counted as an error or not? a doesn't come from anywhere so maybe that means it is?

This stuff is a bit over my head so maybe I'm missing something but I don't see anything in the codebase for this already

The other way to disallow errors is not from the type but if the code itself has any warnings or errors but that seems a bit heavy handed

Copy link
Collaborator

Choose a reason for hiding this comment

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

a doesn't come from anywhere so maybe that means it is?

I think (this is not really my area...) that may be fine, and the constraint is that a needs to be a fresh name (not bound in the outer scope).

Maybe @bhansconnect has more specific advice about how we should be applying types here?

Copy link
Member

Choose a reason for hiding this comment

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

I would short circuit and break out if there are any errors in types, I think it's too easy to generate wrong annotations otherwise. If the easiest method to implement it is to check if the code has any errors, I think that's fine at this moment in time

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.

Automatic annotation of top-level type signatures
4 participants