@@ -50,29 +50,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
5050 let fallback_occurred = self . fallback_types ( ) ;
5151
5252 if fallback_occurred {
53- // We now see if we can make progress. This might cause us to
54- // unify inference variables for opaque types, since we may
55- // have unified some other type variables during the first
56- // phase of fallback. This means that we only replace
57- // inference variables with their underlying opaque types as a
58- // last resort.
59- //
60- // In code like this:
61- //
62- // ```rust
63- // type MyType = impl Copy;
64- // fn produce() -> MyType { true }
65- // fn bad_produce() -> MyType { panic!() }
66- // ```
67- //
68- // we want to unify the opaque inference variable in `bad_produce`
69- // with the diverging fallback for `panic!` (e.g. `()` or `!`).
70- // This will produce a nice error message about conflicting concrete
71- // types for `MyType`.
72- //
73- // If we had tried to fallback the opaque inference variable to `MyType`,
74- // we will generate a confusing type-check error that does not explicitly
75- // refer to opaque types.
53+ // if fallback occurred, previously stalled goals may make progress again
7654 self . select_obligations_where_possible ( |_| { } ) ;
7755 }
7856 }
@@ -157,73 +135,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
157135 true
158136 }
159137
160- /// The "diverging fallback" system is rather complicated. This is
161- /// a result of our need to balance 'do the right thing' with
162- /// backwards compatibility.
163- ///
164- /// "Diverging" type variables are variables created when we
165- /// coerce a `!` type into an unbound type variable `?X`. If they
166- /// never wind up being constrained, the "right and natural" thing
167- /// is that `?X` should "fallback" to `!`. This means that e.g. an
168- /// expression like `Some(return)` will ultimately wind up with a
169- /// type like `Option<!>` (presuming it is not assigned or
170- /// constrained to have some other type).
171- ///
172- /// However, the fallback used to be `()` (before the `!` type was
173- /// added). Moreover, there are cases where the `!` type 'leaks
174- /// out' from dead code into type variables that affect live
175- /// code. The most common case is something like this:
176- ///
177- /// ```rust
178- /// # fn foo() -> i32 { 4 }
179- /// match foo() {
180- /// 22 => Default::default(), // call this type `?D`
181- /// _ => return, // return has type `!`
182- /// } // call the type of this match `?M`
183- /// ```
184- ///
185- /// Here, coercing the type `!` into `?M` will create a diverging
186- /// type variable `?X` where `?X <: ?M`. We also have that `?D <:
187- /// ?M`. If `?M` winds up unconstrained, then `?X` will
188- /// fallback. If it falls back to `!`, then all the type variables
189- /// will wind up equal to `!` -- this includes the type `?D`
190- /// (since `!` doesn't implement `Default`, we wind up a "trait
191- /// not implemented" error in code like this). But since the
192- /// original fallback was `()`, this code used to compile with `?D
193- /// = ()`. This is somewhat surprising, since `Default::default()`
194- /// on its own would give an error because the types are
195- /// insufficiently constrained.
196- ///
197- /// Our solution to this dilemma is to modify diverging variables
198- /// so that they can *either* fallback to `!` (the default) or to
199- /// `()` (the backwards compatibility case). We decide which
200- /// fallback to use based on whether there is a coercion pattern
201- /// like this:
202- ///
203- /// ```ignore (not-rust)
204- /// ?Diverging -> ?V
205- /// ?NonDiverging -> ?V
206- /// ?V != ?NonDiverging
207- /// ```
208- ///
209- /// Here `?Diverging` represents some diverging type variable and
210- /// `?NonDiverging` represents some non-diverging type
211- /// variable. `?V` can be any type variable (diverging or not), so
212- /// long as it is not equal to `?NonDiverging`.
213- ///
214- /// Intuitively, what we are looking for is a case where a
215- /// "non-diverging" type variable (like `?M` in our example above)
216- /// is coerced *into* some variable `?V` that would otherwise
217- /// fallback to `!`. In that case, we make `?V` fallback to `!`,
218- /// along with anything that would flow into `?V`.
219- ///
220- /// The algorithm we use:
221- /// * Identify all variables that are coerced *into* by a
222- /// diverging variable. Do this by iterating over each
223- /// diverging, unsolved variable and finding all variables
224- /// reachable from there. Call that set `D`.
225- /// * Walk over all unsolved, non-diverging variables, and find
226- /// any variable that has an edge into `D`.
227138 fn calculate_diverging_fallback (
228139 & self ,
229140 unresolved_variables : & [ Ty < ' tcx > ] ,
0 commit comments