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

Impl rewrite_result for ast nodes in items.rs #6212

Merged
merged 2 commits into from
Jul 4, 2024

Conversation

ding-young
Copy link
Contributor

Tracked by #6206

Description

  • added RewriteError and blanket implementation for rewrite_result
  • above 6 ast nodes that implements rewrite, replaced rewrite function body with rewrite_result for 4 nodes;
    ast::Local, ast::FieldDef, ast::Param, ast::FnRetTy

Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Looks like we're on the right track with this. Left a few suggestions for way that we could improve things.

src/rewrite.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated
Comment on lines 2127 to 2132
let inner_width = shape.width.checked_sub(3).ok_or_else(|| {
RewriteError::ExceedsMaxWidth {
configured_width: shape.width,
span: self.span(),
}
})?;
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't something we need to address right now, but I've noticed a lot of .ok_or_else(|| { RewriteError::ExceedsMaxWidth {..} }) calls throughout the code.

I wonder if we can make this a little more ergonomic. Here are three ideas I have:

  1. Define new helper methods on Shape

  2. Add a macro that will handle some of this boilerplate

  3. Define an extension trait so we can more easily convert from Option<T> -> Result<T, RewriteError>.
    Here's one idea that I had:

    /// Extension trait used to conveniently convert to RewriteError
    pub(crate) trait RewriteErrorExtension<T> {
        fn max_with_error(self, width: usize, span: Span) -> Result<T, RewriteError>;
        fn unknown_error(self) -> Result<T, RewriteError>;
    }
    
    impl<T> RewriteErrorExtension<T> for Option<T> {
        fn max_with_error(self, width: usize, span: Span) -> Result<T, RewriteError> {
            self.ok_or_else(|| RewriteError::ExceedsMaxWidth {
                configured_width: width,
                span: span,
            })
        }
    
        fn unknown_error(self) -> Result<T, RewriteError> {
            self.ok_or_else(|| RewriteError::Unknown)
        }
    }

src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
@ding-young
Copy link
Contributor Author

@ytmimi Thank you for your review. It seems like I missed some details. I'll take a more careful look at the next PR.
I am wondering to what extent I should modify functions like rewrite_*** in this PR. For example, you recommended modifying rewrite_let_else_block and rewrite_explicit_self, while you suggested changing the signature of combine_str_with_missing_comment later. Should I proceed with modifying the simpler ones for now?

@ytmimi
Copy link
Contributor

ytmimi commented Jun 25, 2024

I'm fairly certain that rewrite_let_else_block and rewrite_explicit_self are only used within these functions so it's likely easier to update their signatures now, while combine_str_with_missing_comment is used throughout the codebase and would require touching a lot of different files.

If you feel like it would be a lot to extend the scope of the current PR then we can always revisit modifying all of these functions in future PRs, but if it's not a heavy lift then we might want to consider doing some of that work in this PR.

src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Thanks for working through all the feedback! Here's my follow up review

src/rewrite.rs Outdated Show resolved Hide resolved
src/rewrite.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
src/items.rs Outdated Show resolved Hide resolved
let pat_shape = shape.offset_left(4)?;
let pat_shape = shape
.offset_left(4)
.max_width_error(shape.width, self.span())?;
Copy link
Contributor

Choose a reason for hiding this comment

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

On thing I've been wondering is whether we should use shap.width or context.config.max_width() for the max_width_error. Would love to get your thoughts on this.

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 believe shape.width provides more specific information, considering that rewrite tries to fit the formatted code into the given shape, while context.config.max_width() is set by the global configuration. Even if we want to expose only max_width to users in error messages (since shape.width might be confusing), in most cases, callers can retrieve context.config.max_width() from its rewrite context so converting RewriteError to ErrorKind would be possible.

However, if there isn't much opportunity to retry formatting based on the returned RewriteError with shape.width and span, it might be pointless to include shape.width, especially if this information is unused.

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 it's fine to leave this as shape.width for now. We can always revisit this decision in the future if it turns out there's something better we should use instead of the width.

@ytmimi ytmimi added pr-waiting-on-author GSoC Google Summer of Code and removed pr-not-reviewed labels Jun 26, 2024
Comment on lines 1918 to 1926
let orig_ty = shape
.offset_left(overhead + spacing.len())
.and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
.and_then(|ty_shape| field.ty.rewrite_result(context, ty_shape).ok());

if let Some(ref ty) = orig_ty {
if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) {
return Some(attr_prefix + &spacing + ty);
return Ok(attr_prefix + &spacing + ty);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we are gonna continue formatting though offset_left returns None, I replaced ty.rewrite with ty.rewrite_result.ok() instead of converting Option into RwResult like below.

let orig_ty = shape
        .offset_left(overhead + spacing.len())
        .max_width(shape.width, field.span())
        .and_then(|ty_shape| field.ty.rewrite_result(context, ty_shape));

    if let Ok(ref ty) = orig_ty {
        if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) {
            return Ok(attr_prefix + &spacing + ty);
        }
    }

Although it seems somewhat pointless to calling rewrite_result.ok() instead of rewrite, I did so since rewrite will return Result after all.
It's pretty minor issue, but I want to hear your suggestion if you have one.

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 calling rewrite_result.ok() is fine. We could also follow your suggestion, but I don't think it makes much of a difference right now.

Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Great work. I took another look and I think we're good to go on this one

@ytmimi
Copy link
Contributor

ytmimi commented Jul 3, 2024

@ding-young when you have a chance can you squash the commits and rebase this PR to bring it up to date

impl rewrite_result for ast::Local, ast::FieldDef, ast::Param, ast::FnRetTy
@ytmimi ytmimi merged commit 21afdb8 into rust-lang:master Jul 4, 2024
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GSoC Google Summer of Code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants