Auto merge of #88804 - Mark-Simulacrum:never-algo-v2, r=nikomatsakis,jackh726
Revise never type fallback algorithm This is a rebase of https://github.com/rust-lang/rust/pull/84573, but dropping the stabilization of never type (and the accompanying large test diff). Each commit builds & has tests updated alongside it, and could be reviewed in a more or less standalone fashion. But it may make more sense to review the PR as a whole, I'm not sure. It should be noted that tests being updated isn't really a good indicator of final behavior -- never_type_fallback is not enabled by default in this PR, so we can't really see the full effects of the commits here. This combines the work by Niko, which is [documented in this gist](https://gist.github.com/nikomatsakis/7a07b265dc12f5c3b3bd0422018fa660), with some additional rules largely derived to target specific known patterns that regress with the algorithm solely derived by Niko. We build these from an intuition that: * In general, fallback to `()` is *sound* in all cases * But, in general, we *prefer* fallback to `!` as it accepts more code, particularly that written to intentionally use `!` (e.g., Result's with a Infallible/! variant). When evaluating Niko's proposed algorithm, we find that there are certain cases where fallback to `!` leads to compilation failures in real-world code, and fallback to `()` fixes those errors. In order to allow for stabilization, we need to fix a good portion of these patterns. The final rule set this PR proposes is that, by default, we fallback from `?T` to `!`, with the following exceptions: 1. `?T: Foo` and `Bar::Baz = ?T` and `(): Foo`, then fallback to `()` 2. Per [Niko's algorithm](https://gist.github.com/nikomatsakis/7a07b265dc12f5c3b3bd0422018fa660#proposal-fallback-chooses-between--and--based-on-the-coercion-graph), the "live" `?T` also fallback to `()`. The first rule is necessary to address a fairly common pattern which boils down to something like the snippet below. Without rule 1, we do not see the closure's return type as needing a () fallback, which leads to compilation failure. ```rust #![feature(never_type_fallback)] trait Bar { } impl Bar for () { } impl Bar for u32 { } fn foo<R: Bar>(_: impl Fn() -> R) {} fn main() { foo(|| panic!()); } ``` r? `@jackh726`
This commit is contained in:
commit
900cf5e890
30 changed files with 733 additions and 174 deletions
|
@ -2090,3 +2090,16 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {
|
|||
fmt::Display::fmt(&self.name, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct FoundRelationships {
|
||||
/// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
|
||||
/// obligation, where:
|
||||
///
|
||||
/// * `Foo` is not `Sized`
|
||||
/// * `(): Foo` may be satisfied
|
||||
pub self_in_trait: bool,
|
||||
/// This is true if we identified that this Ty (`?T`) is found in a `<_ as
|
||||
/// _>::AssocType = ?T`
|
||||
pub output: bool,
|
||||
}
|
||||
|
|
|
@ -1672,6 +1672,14 @@ impl<'tcx> TyS<'tcx> {
|
|||
matches!(self.kind(), Infer(TyVar(_)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ty_vid(&self) -> Option<ty::TyVid> {
|
||||
match self.kind() {
|
||||
&Infer(TyVar(vid)) => Some(vid),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_ty_infer(&self) -> bool {
|
||||
matches!(self.kind(), Infer(_))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue