This new way is **slightly** less expressive (I would be shocked if it
affects any code, though) when it comes to higher-ranked bounds or a
few other weird tricks. But we don't handle those consistently
regardless, and the new way does not require normalization and is just
wildly simpler.
check::method - unify receivers before normalizing method signatures
Normalizing method signatures can unify inference variables, which can
cause receiver unification to fail. Unify the receivers first to avoid
that.
Fixes#36701.
Fixes#45801.
Fixes#45855.
r? @eddyb
beta-nominating because #43880 made this ICE happen in more cases (the code in that issue ICEs post-#43880 only, but the unit test here ICEs on all versions).
Implement arbitrary_self_types
r? @arielb1
cc @nikomatsakis
Partial implementation of #44874. Supports trait and struct methods with arbitrary self types, as long as the type derefs (transitively) to `Self`. Doesn't support raw-pointer `self` yet.
Methods with non-standard self types (i.e. anything other than `&self, &mut self, and Box<Self>`) are not object safe, because dynamic dispatch hasn't been implemented for them yet.
I believe this is also a (partial) fix for #27941.
Fix checking of auto trait bounds in trait objects.
Any auto trait is allowed in trait object bounds. Fix duplicate check of type and lifetime parameter count, which we were [emitting twice](https://play.rust-lang.org/?gist=37dbbdbbec62dec423bb8f6d92f137cc&version=stable).
Note: This was the last use of `Send` in the compiler, meaning after a new `stage0` we could remove the `send` lang item.
Normalizing method signatures can unify inference variables, which can
cause receiver unification to fail. Unify the receivers first to avoid
that.
Fixes#36701.
Fixes#45801.
Fixes#45855.
I doubt this changes anything, I was just trying to fix an issue with
error messages and ended up doing this along with other things.
Committing it separately so I can undo it easily.
- added some old code that used ExplicitSelf::determine to check for eqtype with the expected self type in the simple cases
- this fixes problems with error messages being worse in those cases, which caused some compile-fail tests to fail
Rewrote ExplicitSelf, adding a new `Other` variant for arbitrary self
types. It’s a bit more sophisticated now, and checks for type equality,
so you have to pass the type context and param env as arguments.
There’s a borrow-checker error here that I have to fix
Rewrote check_method_receiver, so it acts as if arbitrary self types
are allowed, and then checks for ExplicitSelf::Other at the end and
disallows it unless the feature is present.
If the feature is enabled, allow method `self` types to be any type
that auto-derefs to `self`.
- Currently, this supports inherent methods as well as trait methods.
The plan AFAIK is to only allow this for trait methods, so I guess it
won’t stay this way
- Dynamic dispatch isn’t implemented yet, so the compiler will ICE if
you define a trait method that takes `self: Rc<Self>` and try to call
it on an `Rc<Trait>`. I will probably just make those methods
non-object-safe initially.
new rules for merging expected and supplied types in closure signatures
As uncovered in #38714, we currently have some pretty bogus code for combining the "expected signature" of a closure with the "supplied signature". To set the scene, consider a case like this:
```rust
fn foo<F>(f: F)
where
F: for<'a> FnOnce(&'a u32) -> &'a u32
// ^ *expected* signature comes from this where-clause
{
...
}
fn main() {
foo(|x: &u32| -> &u32 { .. }
// ^^^^^^^^^^^^^^^^^ supplied signature
// comes from here
}
```
In this case, the supplied signature (a) includes all the parts and (b) is the same as the expected signature, modulo the names used for the regions. But often people supply only *some* parts of the signature. For example, one might write `foo(|x| ..)`, leaving *everything* to be inferred, or perhaps `foo(|x: &u32| ...)`, which leaves the return type to be inferred.
In the current code, we use the expected type to supply the types that are not given, but otherwise use the type the user gave, except for one case: if the user writes `fn foo(|x: _| ..)` (i.e., an underscore at the outermost level), then we will take the expected type (rather than instantiating a fresh type variable). This can result in nonsensical situations, particularly with bound regions that link the types of parameters to one another or to the return type. Consider `foo(|x: &u32| ...)` -- if we *literally* splice the expected return type of `&'a u32` together with what the user gave, we wind up with a signature like `for<'a> fn(&u32) -> &'a u32`. This is not even permitted as a type, because bound regions like `'a` must appear also in the arguments somewhere, which is why #38714 leads to an ICE.
This PR institutes some new rules. These are not meant to be the *final* set of rules, but they are a kind of "lower bar" for what kind of code we accept (i.e., we can extend these rules in the future to be smarter in some cases, but -- as we will see -- these rules do accept some things that we then would not be able to back off from).
These rules are derived from a few premises:
- First and foremost, anonymous regions in closure annotation are mostly requests for the code to "figure out the right lifetime" and shouldn't be read too closely. So for example when people write a closure signature like `|x: &u32|`, they are really intended for us to "figure out" the right region for `x`.
- In contrast, the current code treats this supplied type as being more definitive. In particular, writing `|x: &u32|` would always result in the region of `x` being bound in the closure type. In other words, the signature would be something like `for<'a> fn(&'a u32)` -- this is derived from the fact that `fn(&u32)` expands to a type where the region is bound in the fn type.
- This PR takes a different approach. The "binding level" for reference types appearing in closure signatures can be informed in some cases by the expected signature. So, for example, if the expected signature is something like `(&'f u32)`, where the region of the first argument appears free, then for `|x: &u32|`, the new code would infer `x` to also have the free region `'f`.
- This inference has some limits. We don't do this for bindings that appear within the selected types themselves. So e.g. `|x: fn(&u32)|`, when combined with an expected type of `fn(fn(&'f u32))`, would still result in a closure that expects `for<'a> fn(&'a u32)`. Such an annotation will ultimately result in an error, as it happens, since `foo` is supplying a `fn(&'f u32)` to the closure, but the closure signature demands a `for<'a> fn(&'a u32)`. But still we choose to trust it and have the user change it.
- I wanted to preserve the rough intuition that one can copy-and-paste a type out of the fn signature and into the fn body without dramatically changing its meaning. Interestingly, if one has `|x: &u32|`, then regardless of whether the region of `x` is bound or free in the closure signature, it is also free in the region body, and that is also true when one writes `let x: &u32`, so that intuition holds here. But the same would not be true for `fn(&u32)`, hence the different behavior.
- Second, we must take either **all** the references to bound regions from the expected type or **none**. The current code, as we saw, will happily take a bound region in the return type but drop the other place where it is used, in the parameters. Since bound regions are all about linking multiple things together, I think it's important not to do that. (That said, we could conceivably be a bit less strict here, since the subtyping rules will get our back, but we definitely don't want any bound regions that appear only in the return type.)
- Finally, we cannot take the bound region names from the supplied types and "intermix" them with the names from the expected types.
- We *could* potentially do some alpha renaming, but I didn't do that.
- Ultimately, if the types the user supplied do not match expectations in some way that we cannot recover from, we fallback to deriving the closure signature solely from those expected types.
- For example, if the expected type is `u32` but the user wrote `i32`.
- Or, more subtle, if the user wrote e.g. `&'x u32` for some named lifetime `'x`, but the expected type includes a bound lifetime (`for<'a> (&'a u32)`). In that case, preferring the type that the user explicitly wrote would hide an appearance of a bound name from the expected type, and we try to never do that.
The detailed rules that I came up with are found in the code, but for ease of reading I've also [excerpted them into a gist](https://gist.github.com/nikomatsakis/e69252a2b57e6d97d044c2f254c177f1). I am not convinced they are correct and would welcome feedback for alternative approaches.
(As an aside, the way I think I would ultimately *prefer* to think about this is that the conversion from HIR types to internal types could be parameterized by an "expected type" that it uses to guide itself. However, since that would be a pain, I opted *in the code* to first instantiate the supplied types as `Ty<'tcx>` and then "merge" those types with the `Ty<'tcx>` from the expected signature.)
I think we should probably FCP this before landing.
cc @rust-lang/lang
r? @arielb1
Copy all `AsciiExt` methods to the primitive types directly in order to deprecate it later
**EDIT:** [this PR is ready now](https://github.com/rust-lang/rust/pull/44042#issuecomment-333883548). I edited this post to reflect the current status of discussion, which is (apart from code review) pretty much settled.
---
This is my current progress in order to prepare stabilization of #39658. As discussed there (and in #39659), the idea is to deprecated `AsciiExt` and copy all methods to the type directly. Apparently there isn't really a reason to have those methods in an extension trait¹.
~~This is **work in progress**: copy&pasting code while slightly modifying the documentation isn't the most exciting thing to do. Therefore I wanted to already open this WIP PR after doing basically 1/4 of the job (copying methods to `&[u8]`, `char` and `&str` is still missing) to get some feedback before I continue. Some questions possibly worth discussing:~~
1. ~~Does everyone agree that deprecating `AsciiExt` is a good idea? Does everyone agree with the goal of this PR?~~ => apparently yes
2. ~~Are my changes OK so far? Did I do something wrong?~~
3. ~~The issue of the unstable-attribute is currently set to 0. I would wait until you say "Ok" to the whole thing, then create a tracking issue and then insert the correct issue id. Is that ok?~~
4. ~~I tweaked `eq_ignore_ascii_case()`: it now takes the argument `other: u8` instead of `other: &u8`. The latter was enforced by the trait. Since we're not bound to a trait anymore, we can drop the reference, ok?~~ => I reverted this, because the interface has to match the `AsciiExt` interface exactly.
¹ ~~Could it be that we can't write `impl [u8] {}`? This might be the reason for `AsciiExt`. If that is the case: is there a good reason we can't write such an impl block? What can we do instead?~~ => we couldn't at the time this PR was opened, but Simon made it possible.
/cc @SimonSapin @zackw
RFC 2008: Future-proofing enums/structs with #[non_exhaustive] attribute
This work-in-progress pull request contains my changes to implement [RFC 2008](https://github.com/rust-lang/rfcs/pull/2008). The related tracking issue is #44109.
As of writing, enum-related functionality is not included and there are some issues related to tuple/unit structs. Enum related tests are currently ignored.
WIP PR requested by @nikomatsakis [in Gitter](https://gitter.im/rust-impl-period/WG-compiler-middle?at=59e90e6297cedeb0482ade3e).
[Syntax] Implement auto trait syntax
Implements `auto trait Send {}` as a substitute for `trait Send {} impl Send for .. {}`.
See the [internals thread](https://internals.rust-lang.org/t/pre-rfc-renaming-oibits-and-changing-their-declaration-syntax/3086) for motivation. Part of #13231.
The first commit is just a rename moving from "default trait" to "auto trait". The rest is parser->AST->HIR work and making it the same as the current syntax for everything below HIR. It's under the `optin_builtin_traits` feature gate.
When can we remove the old syntax? Do we need to wait for a new `stage0`? We also need to formally decide for the new form (even if the keyword is not settled yet).
Observations:
- If you `auto trait Auto {}` and then `impl Auto for .. {}` that's accepted even if it's redundant.
- The new syntax is simpler internally which will allow for a net removal of code, for example well-formedness checks are effectively moved to the parser.
- Rustfmt and clippy are broken, need to fix those.
- Rustdoc just ignores it for now.
ping @petrochenkov @nikomatsakis
DefaultImpl is a highly confusing name for what we now call auto impls,
as in `impl Send for ..`. The name auto impl is not formally decided
but for sanity anything is better than `DefaultImpl` which refers
neither to `default impl` nor to `impl Default`.