Skip to content

Detect Expressions that evaluate to Unit and warn the user #2016

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

Merged
merged 21 commits into from
Sep 3, 2017

Conversation

zmanian
Copy link
Contributor

@zmanian zmanian commented Sep 3, 2017

Work in progress to resolve #2011

Feedback requested.

}
}
}
fn is_unit_expr(expr: &Expr)->Option<Span>{
Copy link
Member

Choose a reason for hiding this comment

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

probably rustfmt the file

Copy link
Member

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

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

looking good so far. Probably should add a test.

},
ExprKind::If(_, ref then, ref else_)=>{
let check_then = check_last_stmt_in_block(then);
if let Some(ref else_) = *else_{
Copy link
Member

Choose a reason for hiding this comment

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

If there is no else block then it's always going to evaluate to ()

ExprKind::If(_, ref then, ref else_)=>{
let check_then = check_last_stmt_in_block(then);
if let Some(ref else_) = *else_{
let check_else = is_unit_expr(else_.deref());
Copy link
Member

Choose a reason for hiding this comment

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

you shouldn't need to call deref directly. &else_ should work here.

return Some(expr.span.clone());

} else{
return Some(expr.span.clone());
Copy link
Member

Choose a reason for hiding this comment

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

This else block shouldn't be there I think? return None?

if let Some(ref expr_else) = check_else{
return Some(expr_else.clone());
}else{
return Some(expr.span.clone());
Copy link
Member

Choose a reason for hiding this comment

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

return None?

else{
return true;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

nit: newline at EOF

@@ -0,0 +1,14 @@

#![feature(plugin)]
#[plugin(clippy)]
Copy link
Member

Choose a reason for hiding this comment

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

Needs an exclamation mark. The tests didn't run correctly (see the output)

Copy link
Member

@Manishearth Manishearth left a comment

Choose a reason for hiding this comment

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

looking good, needs more tests for the call case and also tests for false positives.

cx,
UNIT_EXPR,
expr.span,
"This expression assigns the Unit type ()",
Copy link
Member

Choose a reason for hiding this comment

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

"assigns" probably isn't the right word to use here for a call

cx,
UNIT_EXPR,
expr.span,
"This expression assigns the Unit type ()",
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Remove "assigns" from the lint
Add false positive tests
@Manishearth
Copy link
Member

Needs rustfmt on the tests, otherwise it's good to go.

It occurs to me that we have chances for false positives on if blocks that diverge via panics too.

Perhaps we should only lint if both the if and else are semicolon'd?

@Manishearth
Copy link
Member

or, well, at worst it will warn about a needless semicolon after a diverging statement. That's fine.

@Manishearth Manishearth closed this Sep 3, 2017
@Manishearth Manishearth reopened this Sep 3, 2017
@Manishearth
Copy link
Member

retriggering travis

@Manishearth Manishearth merged commit 0d9f566 into rust-lang:master Sep 3, 2017
@zmanian zmanian deleted the unit_expr branch September 3, 2017 21:15
@Arnavion
Copy link
Contributor

Arnavion commented Sep 5, 2017

or, well, at worst it will warn about a needless semicolon after a diverging statement. That's fine.

Does "That's fine." mean it's fine for now and that it's planned to be fixed? Or it's by design? I like putting a semi-colon after my continues and breaks and returns :\

@oli-obk
Copy link
Contributor

oli-obk commented Sep 5, 2017

We can detect continue, break and return without troubles. It's foo() where fn foo() -> ! that's problematic.

@oli-obk
Copy link
Contributor

oli-obk commented Sep 5, 2017

retutrn and break actually don't trigger this, just continue, opening an issue

@Arnavion
Copy link
Contributor

Arnavion commented Sep 5, 2017

Ah cool. I did only hit the false positive with continue

@zmanian
Copy link
Contributor Author

zmanian commented Sep 5, 2017

Oh continue is an easy fix.

@oli-obk
Copy link
Contributor

oli-obk commented Sep 5, 2017

Fixed in #2022

@Manishearth
Copy link
Member

Does "That's fine." mean it's fine for now and that it's planned to be fixed?

I meant that it's fine forever.

continue was an omission, that comment was about diverging functions.

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.

Version of let_unit_value that is an early pass
4 participants