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

Detect missing ; on methods with return type () #42850

Merged
merged 6 commits into from
Jun 28, 2017

Conversation

estebank
Copy link
Contributor

  • Point out the origin of a type requirement when it is the return type
    of a method
  • Point out possibly missing semicolon when the return type is () and
    the implicit return makes sense as a statement
  • Suggest changing the return type of methods with default return type
  • Don't suggest changing the return type on fn main()
  • Don't suggest changing the return type on impl fn
  • Suggest removal of semicolon (instead of being help)

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@estebank
Copy link
Contributor Author

estebank commented Jun 23, 2017

Previous discussion: #39231, #36409. Re #42823.

Copy link
Member

@Mark-Simulacrum Mark-Simulacrum left a comment

Choose a reason for hiding this comment

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

Could you move the compile-fail tests to UI tests before the actual changes are implemented, in a separate commit so we can see the differences this PR introduces?

@shepmaster shepmaster added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 23, 2017
|
11 | fn main() {
| - expected `()` because of this default return type
12 | while true {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the main function spanned on this? while etc. can't return a value via tail expression

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code now walks up until it finds a fn block for success or a while or for block for failure, avoiding this.

name, node: hir::ItemFn(ref decl, ..), ..
}) = parent {
decl.clone().and_then(|decl| {
Some((decl, name == Symbol::intern("main")))
Copy link
Contributor

Choose a reason for hiding this comment

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

that's rather unrobust: this compiles and runs:

fn main() {
    println!("{}", foo::main());
}

mod foo {
    pub fn main() -> u32 { 4 }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seemed good enough at the time, given that the failure mode is not suggesting a return type when it could, but point taken. Is there a way to figure out wether the current method is the main method during typeck?

--> $DIR/block-must-not-have-result-do.rs:13:9
|
11 | fn main() {
| - expected `()` because of this default return type
Copy link
Contributor

@arielb1 arielb1 Jun 23, 2017

Choose a reason for hiding this comment

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

Why is the main function spanned on this? loop, while etc. can't return a value via tail expression.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as the previous one.

"default "
} else {
""
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do resolve_type_vars_if_possible here or somewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

- Point out the origin of a type requirement when it is the return type
  of a method
- Point out possibly missing semicolon when the return type is () and
  the implicit return makes sense as a statement
- Suggest changing the return type of methods with default return type
- Don't suggest changing the return type on fn main()
- Don't suggest changing the return type on impl fn
@estebank
Copy link
Contributor Author

@Mark-Simulacrum moved the ui tests on a commit on its own, and separated the changes onto two other commits.

Don't specify a suggested return type for `TyAnon`, `TyFnDef`,
`TyFnPtr`, `TyDynamic`, `TyClosure` and `TyProjection`.
@@ -1,6 +1,9 @@
error[E0308]: mismatched types
--> $DIR/equality.rs:25:5
|
21 | fn two(x: bool) -> impl Foo {
| -------- expected `i32` because of this return type
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't seem right. It's the return 1_i32; which is causing this error and ideally that's what would be pointed to.

@@ -34,8 +34,13 @@ error[E0425]: cannot find function `is_directory` in this scope
error[E0308]: mismatched types
--> $DIR/token-error-correct-3.rs:25:13
|
20 | -> io::Result<bool> {
| ---------------- expected `()` because of this return type
Copy link
Member

Choose a reason for hiding this comment

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

This is clearly not right.

@@ -0,0 +1,4 @@
error[E0601]: main function not found
Copy link
Contributor

Choose a reason for hiding this comment

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

is this really testing what we expect it to test?

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

Left a few nits, but this looks pretty good to me.

@@ -594,8 +594,12 @@ impl<'hir> Map<'hir> {
/// last good node id we found. Note that reaching the crate root (id == 0),
/// is not an error, since items in the crate module have the crate root as
/// parent.
fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
where F: Fn(&Node<'hir>) -> bool
fn walk_parent_nodes<F, F2>(&self,
Copy link
Contributor

Choose a reason for hiding this comment

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

Meh. This is fine for now, but it'd be nice to make this an iterator, I think.

@@ -626,6 +632,34 @@ impl<'hir> Map<'hir> {
}
}

pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment explaining what this function does would be good. Ideally with an example.

@@ -4210,6 +4214,130 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty
}

/// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and wether it is
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: s/wether/whether/

@nikomatsakis
Copy link
Contributor

r=me with nits addressed (not the iterator thing, though if you want to, that's good too)

- Fix typo
- Add docstring
- Remove spurious test output file
@estebank
Copy link
Contributor Author

@bors r=nikomatsakis

@bors
Copy link
Contributor

bors commented Jun 27, 2017

📌 Commit 7dad295 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Jun 28, 2017

⌛ Testing commit 7dad295 with merge 962840a15d3468f254a66d49aa1ff469ed611c41...

@bors
Copy link
Contributor

bors commented Jun 28, 2017

💔 Test failed - status-travis

@Mark-Simulacrum
Copy link
Member

Timed out while building Cargo.

@bors retry

@bors
Copy link
Contributor

bors commented Jun 28, 2017

⌛ Testing commit 7dad295 with merge 69c65d2...

bors added a commit that referenced this pull request Jun 28, 2017
Detect missing `;` on methods with return type `()`

 - Point out the origin of a type requirement when it is the return type
   of a method
 - Point out possibly missing semicolon when the return type is `()` and
   the implicit return makes sense as a statement
 - Suggest changing the return type of methods with default return type
 - Don't suggest changing the return type on `fn main()`
 - Don't suggest changing the return type on impl fn
 - Suggest removal of semicolon (instead of being help)
@bors
Copy link
Contributor

bors commented Jun 28, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 69c65d2 to master...

@bors bors merged commit 7dad295 into rust-lang:master Jun 28, 2017
estebank added a commit to estebank/rust that referenced this pull request Jul 26, 2017
Before this, the diagnostic errors would only point at the return type
when changing it would be a possible solution to a type error. Add a
label to the return type without a suggestion to change in order to make
the source of the expected type obvious.

Follow up to rust-lang#42850, fixes rust-lang#25133, fixes rust-lang#41897.
bors added a commit that referenced this pull request Aug 9, 2017
Point at return type always when type mismatch against it

Before this, the diagnostic errors would only point at the return type
when changing it would be a possible solution to a type error. Add a
label to the return type without a suggestion to change in order to make
the source of the expected type obvious.

Follow up to #42850, fixes #25133, fixes #41897.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants