Now that associated types are fully implemented the iterator adaptors only need
type parameters which are associated with actual storage. All other type
parameters can either be derived from these (e.g. they are an associated type)
or can be bare on the `impl` block itself.
This is a breaking change due to the removal of type parameters on these
iterator adaptors, but code can fairly easily migrate by just deleting the
relevant type parameters for each adaptor. Other behavior should not be
affected.
Closes#21839
[breaking-change]
trans: When coercing to `Box<Trait>` or `Box<[T]>`, leave datum in it's original L-/R-value state.
This fixes a subtle issue where temporaries were being allocated (but not necessarily initialized) to the (parent) terminating scope of a match expression; in particular, the code to zero out the temporary emitted by `datum.store_to` is only attached to the particular match-arm for that temporary, but when going down other arms of the match expression, the temporary may falsely appear to have been initialized, depending on what the stack held at that location, and thus may have its destructor erroneously run at the end of the terminating scope.
FIx#20055.
(There may be a latent bug still remaining in `fn into_fat_ptr`, but I am so annoyed by the test/run-pass/coerce_match.rs failures that I want to land this now.)
Note: Do not merge until we get a newer snapshot that includes #21374
There was some type inference fallout (see 4th commit) because type inference with `a..b` is not as good as with `range(a, b)` (see #21672).
r? @alexcrichton
This fixes a subtle issue where temporaries were being allocated (but
not necessarily initialized) to the (parent) terminating scope of a
match expression; in particular, the code to zero out the temporary
emitted by `datum.store_to` is only attached to the particular
match-arm for that temporary, but when going down other arms of the
match expression, the temporary may falsely appear to have been
initialized, depending on what the stack held at that location, and
thus may have its destructor erroneously run at the end of the
terminating scope.
Test cases to appear in a follow-up commit.
Fix#20055
Two minor improvements that have been on my TODO list for a while:
* Clang uses a size of `-1` for arrays of unknown size and we should do that too as it will tell LLVM to omit the size information in debuginfo.
* There was no LLDB test case for handling the optimized enum representation introduced by @luqmana. This PR finally adds one.
E.g. `fn foo() { foo() }`, or, more subtlely
impl Foo for Box<Foo+'static> {
fn bar(&self) {
self.bar();
}
}
The compiler will warn and point out the points where recursion occurs,
if it determines that the function cannot return without calling itself.
Closes#17899.
---
This is highly non-perfect, in particular, my wording above is quite precise, and I have some unresolved questions: This currently will warn about
```rust
fn foo() {
if bar { loop {} }
foo()
}
```
even though `foo` may never be called (i.e. our apparent "unconditional" recursion is actually conditional). I don't know if we should handle this case, and ones like it with `panic!()` instead of `loop` (or anything else that "returns" `!`).
However, strictly speaking, it seems to me that changing the above to not warn will require changing
```rust
fn foo() {
while bar {}
foo()
}
```
to also not warn since it could be that the `while` is an infinite loop and doesn't ever hit the `foo`.
I'm inclined to think we let these cases warn since true edge cases like the first one seem rare, and if they do occur they seem like they would usually be typos in the function call. (I could imagine someone accidentally having code like `fn foo() { assert!(bar()); foo() /* meant to be boo() */ }` which won't warn if the `loop` case is "fixed".)
(Part of the reason this is unresolved is wanting feedback, part of the reason is I couldn't devise a strategy that worked in all cases.)
---
The name `unconditional_self_calls` is kinda clunky; and this reconstructs the CFG for each function that is linted which may or may not be very expensive, I don't know.
This allows one to look at an `ExprMethodCall` `foo.bar()` where `bar`
is a method in some trait and (sometimes) extract the `impl` that `bar`
is defined in, e.g.
trait Foo {
fn bar(&self);
}
impl Foo for uint { // <A>
fn bar(&self) {}
}
fn main() {
1u.bar(); // impl_def_id == Some(<A>)
}
This definitely doesn't handle all cases, but is correct when it is
known, meaning it should only be used for certain linting/heuristic
purposes; no safety analysis.
This should fix issue #20797 (but I don't want to close it automatically).
As the actual fix is very small this would be a perfect candidate for a rollup.