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

adding E0623 for return types - both parameters are anonymous #44124

Closed
wants to merge 8 commits into from

Conversation

gaurikholkar-zz
Copy link

@gaurikholkar-zz gaurikholkar-zz commented Aug 28, 2017

This is a fix for #44018

error[E0621]: explicit lifetime required in the type of `self`
  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
   |
16 |   fn foo<'a>(&self, x: &i32) -> &i32 {
   |                        ----     ----
   |                        |
   |                        this parameter and the return type are
                            declared with different lifetimes...
17 |     x
   |     ^ ...but data from `x` is returned here

error: aborting due to previous error

It also works for the below case where we have self as anonymous

error[E0623]: lifetime mismatch
  --> src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs:17:19
   |
16 |     fn foo<'a>(&self, x: &Foo) -> &Foo {
   |                          ----     ----
   |                          |
   |                          this parameter and the return type are
                            declared with different lifetimes...
17 |         if true { x } else { self }
   |                   ^ ...but data from `x` is returned here

error: aborting due to previous error

r? @nikomatsakis

Currently, I have enabled E0621 where return type and self are anonymous, hence WIP.

@gaurikholkar-zz gaurikholkar-zz changed the title adding E0623 for return types adding E0623 for return types - both parameters are anonymous Aug 28, 2017
@carols10cents carols10cents added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 28, 2017
@@ -0,0 +1,6 @@

Copy link
Contributor

Choose a reason for hiding this comment

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

missing license and newlines in the code

Copy link
Contributor

Choose a reason for hiding this comment

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

also, shouldn't this test go with the other PR?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah. Was a mistake

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.

First round of suggestions.


let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
let (spanfin1, spanfin2, main_label, label) = if let (Some(sup_arg),
Some(sub_arg)) =
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: can we use use the flatter style here too? I really find the if let nesting hard to read. In other words, change the if let (Some(sup_arg), Some(sub_arg)) = (...) { ... } else { false } too:

let sup_arg = or_false!(self.find_arg_with_anonymous_region(sup, sup));
let sub_arg = or_false!(self.find_arg_with_anonymous_region(sub, sub));
...

self.is_return_type_anon(scope_def_id_sub, bregion_sub) {
return false;
}
let (anon_arg_sup, anon_arg_sub) = (sup_arg.arg, sub_arg.arg);
Copy link
Contributor

Choose a reason for hiding this comment

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

If we do the or_false! transformation above, and we don't care about the other field, we could do:

let AnonymousArgInfo { arg: anon_arg_sup, .. } = or_false!(self.find_arg_with_anonymous_region(sup, sup));

Not sure if this is a net win.

Copy link
Author

Choose a reason for hiding this comment

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

I'm a bit confused about what's happening here

format!(" with one lifetime"),
format!(" into the other"))
let (span_1, span_2, span_label) =
if self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup)
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, this logic is sort of complex. First off, let's store self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup) into a variable:

let sup_is_ret_type = self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);

and same for sub. Then I think I would structure the remaining logic something like this:

let sup_is_ret_type = self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
let sub_is_ret_type = self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
let (span_1, span_2, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
    (None, None) =>
        (ty_sup.span, ty_sub.span, format!("this type was declared with multiple lifetimes...")),
    (Some(ret_span), _) =>
        (ty_sub.span, ret_span,  format!("this parameter and the return type are declared with different lifetimes...")),
    (_, Some(ret_span)) =>
        (ty_sup.span, ret_span,  format!("this parameter and the return type are declared with different lifetimes...")),
};

However, this raises the question -- what if both sub and sup appear in the return type? The existing code seems to ignore this case, but it's probably worth adding something like this:

(Some(ret_span1), Some(ret_span2)) =>
    (ret_span1, ret_span2, format!("the return type is declared with different lifetimes...")),

That said, maybe better to wait until we have a test for this case, since I'm not sure off-hand how it can really arise.

@@ -91,19 +118,50 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format!("")
};

let span_label =
format!("these two types are declared with different lifetimes...",);
let (var1_span, var2_span, span_label_1, span_label_2) = if
Copy link
Contributor

Choose a reason for hiding this comment

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

I would restructure this in the same way I as suggested above.

if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() ||
self.is_self_anon(is_first, scope_def_id) {
return false;
} }
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: } on next line

@nikomatsakis nikomatsakis added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 30, 2017
@alexcrichton
Copy link
Member

@gaurikholkar ping just to keep this on your radar!

@gaurikholkar-zz
Copy link
Author

@alexcrichton getting back at it today!

@bors
Copy link
Contributor

bors commented Sep 10, 2017

☔ The latest upstream changes (presumably #44079) made this pull request unmergeable. Please resolve the merge conflicts.

@gaurikholkar-zz gaurikholkar-zz changed the title adding E0623 for return types - both parameters are anonymous adding E0623 for return types - both parameters are anonymous WIP Sep 11, 2017
@gaurikholkar-zz gaurikholkar-zz changed the title adding E0623 for return types - both parameters are anonymous WIP adding E0623 for return types - both parameters are anonymous Sep 12, 2017
@nikomatsakis
Copy link
Contributor

@gaurikholkar so since I had a local checkout of your branch I went ahead and corrected a few nits in the wording of the error messages. However, it looks like now that you've made things better, the example for E0312 isn't working anymore.

I'm a bit torn here --- I feel like most every example we can craft for E0312 is probably just a bug waiting to be fixed (i.e., a case where we can make a better example). But I guess in the interim we can keep shuffling it from bug to bug.

Do you have any instinct for what example would still trigger E0312? Maybe something involving self...?

@gaurikholkar-zz
Copy link
Author

Are you referring to the you tests w.r.t self, return type and impls? Now that they trigger E0623? Also do we want that for impls?

@nikomatsakis
Copy link
Contributor

@gaurikholkar

Are you referring to the you tests w.r.t self, return type and impls? Now that they trigger E0623? Also do we want that for impls?

Sorry, I don't really understand the question. What I am saying is that the example for E0312 found in the extended error message (the one with 'tree and 'human etc) now generates a nice error, instead of E0312. Therefore, to keep the build passing, we have to do one of two things:

  • Replace that example with something that generates E0312. I'm not sure what that should be. The example will have to get somewhat more convoluted, I imagine. This strikes me as overall a good thing, since we think the newer errors are better than E0312, so I am glad that it is hard to make an example that shows E0312.
    • Basically, I think that any example which still shows E0312 can be considered a bug. This implies that we will have to play a game of "whack-a-mole" -- each time we have an example for E0312, we will eventually fix it to display the other error, and then we have to find a new (even more obscure) example for E0312.
  • Remove the extended error message for E0312 (and perhaps the error itself). At some point, when we tire of playing whack-a-mole, we can just remove the extended error message. Even better would be to remove the code that generates E0312 altogether, if we could guarantee it will not run.

Probably we are not yet at that point where it's worth removing the extended error msg for E0312. I imagine we can find some kind of example that still fails.

@arielb1
Copy link
Contributor

arielb1 commented Sep 19, 2017

Hi @gaurikholkar. How it's going with this PR? Is there anything blocking you? Feel free to ping me on IRC.

@arielb1
Copy link
Contributor

arielb1 commented Sep 24, 2017

One small mismatch in a test:

[00:42:51]  error[E0623]: lifetime mismatch
[00:42:51]    --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:11
[00:42:51]     |
[00:42:51]  15 | fn foo(mut x: Ref) {
[00:42:51]     |               ---
[00:42:51]     |               |
[00:42:51] -   |               this type was declared with multiple lifetimes...
[00:42:51] +   |               this type is declared with multiple lifetimes...
[00:42:51]  16 |     x.a = x.b;

is_first,
scope_def_id);
return false;
if let Some(anon_ty) = self.find_anon_type(anon, &br) {
Copy link
Contributor

Choose a reason for hiding this comment

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

style: if let Some((_, fndecl)) = self.find_anon_type(anon, &br)

@arielb1
Copy link
Contributor

arielb1 commented Sep 24, 2017

LGTM modulo nits

@nikomatsakis
Copy link
Contributor

The travis failure is confusing me. I checked out the branch and don't see that file in my copy. Maybe I'm doing something bone-headed...

@gaurikholkar-zz
Copy link
Author

@nikomatsakis yeah even I couldn't find the file :(

@nikomatsakis
Copy link
Contributor

@bors r+

@arielb1
Copy link
Contributor

arielb1 commented Sep 26, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Sep 26, 2017

📌 Commit 73543d5 has been approved by arielb1

@arielb1
Copy link
Contributor

arielb1 commented Sep 26, 2017

@bors rollup

@gaurikholkar-zz
Copy link
Author

When does this get merged?

@gaurikholkar-zz
Copy link
Author

@nikomatsakis

trait Foo {

    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;

}

impl Foo for () {

    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {

        if x > y { x } else { y }

    }

}

I remember discussing that we need not change the message for Impls for the case of E0621, this PR modifies that. Should it be OK?

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this pull request Sep 29, 2017
adding E0623 for return types - both parameters are anonymous

This is a fix for rust-lang#44018
```
error[E0621]: explicit lifetime required in the type of `self`
  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
   |
16 |   fn foo<'a>(&self, x: &i32) -> &i32 {
   |                        ----     ----
   |                        |
   |                        this parameter and the return type are
                            declared with different lifetimes...
17 |     x
   |     ^ ...but data from `x` is returned here

error: aborting due to previous error
```
It also works for the below case where we have self as anonymous

```
error[E0623]: lifetime mismatch
  --> src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs:17:19
   |
16 |     fn foo<'a>(&self, x: &Foo) -> &Foo {
   |                          ----     ----
   |                          |
   |                          this parameter and the return type are
                            declared with different lifetimes...
17 |         if true { x } else { self }
   |                   ^ ...but data from `x` is returned here

error: aborting due to previous error
```
r? @nikomatsakis

Currently, I have enabled E0621 where return type and self are anonymous, hence WIP.
bors added a commit that referenced this pull request Sep 30, 2017
@bors
Copy link
Contributor

bors commented Sep 30, 2017

☔ The latest upstream changes (presumably #44936) made this pull request unmergeable. Please resolve the merge conflicts.

@Mark-Simulacrum
Copy link
Member

Merged in #44936.

estebank added a commit to estebank/rust that referenced this pull request Nov 5, 2017
When there's a lifetime mismatch between an argument with an anonymous
lifetime being returned in a method with a return type that has a named
lifetime, show specialized lifetime error pointing at argument with a
hint to give it an explicit lifetime matching the return type.

```
error[E0621]: explicit lifetime required in the type of `other`
  --> file2.rs:21:21
   |
17 |     fn bar(&self, other: Foo) -> Foo<'a> {
   |                   ----- consider changing the type of `other` to `Foo<'a>`
...
21 |                     other
   |                     ^^^^^ lifetime `'a` required
```

Follow up to rust-lang#44124 and rust-lang#42669.
kennytm added a commit to kennytm/rust that referenced this pull request Nov 7, 2017
Handle anon lifetime arg being returned with named lifetime return type

When there's a lifetime mismatch between an argument with an anonymous
lifetime being returned in a method with a return type that has a named
lifetime, show specialized lifetime error pointing at argument with a
hint to give it an explicit lifetime matching the return type.

```
error[E0621]: explicit lifetime required in the type of `other`
  --> file2.rs:21:21
   |
17 |     fn bar(&self, other: Foo) -> Foo<'a> {
   |                   ----- consider changing the type of `other` to `Foo<'a>`
...
21 |                     other
   |                     ^^^^^ lifetime `'a` required
```

Follow up to rust-lang#44124 and rust-lang#42669. Fix rust-lang#44684.
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