]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_hir_typeck/src/fallback.rs
Rollup merge of #105641 - Amanieu:btree_cursor, r=m-ou-se
[rust.git] / compiler / rustc_hir_typeck / src / fallback.rs
1 use crate::FnCtxt;
2 use rustc_data_structures::{
3     fx::{FxHashMap, FxHashSet},
4     graph::WithSuccessors,
5     graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
6 };
7 use rustc_middle::ty::{self, Ty};
8
9 impl<'tcx> FnCtxt<'_, 'tcx> {
10     /// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
11     /// if fallback has occurred.
12     pub(super) fn type_inference_fallback(&self) {
13         debug!(
14             "type-inference-fallback start obligations: {:#?}",
15             self.fulfillment_cx.borrow_mut().pending_obligations()
16         );
17
18         // All type checking constraints were added, try to fallback unsolved variables.
19         self.select_obligations_where_possible(|_| {});
20
21         debug!(
22             "type-inference-fallback post selection obligations: {:#?}",
23             self.fulfillment_cx.borrow_mut().pending_obligations()
24         );
25
26         // Check if we have any unsolved variables. If not, no need for fallback.
27         let unsolved_variables = self.unsolved_variables();
28         if unsolved_variables.is_empty() {
29             return;
30         }
31
32         let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
33
34         // We do fallback in two passes, to try to generate
35         // better error messages.
36         // The first time, we do *not* replace opaque types.
37         for ty in unsolved_variables {
38             debug!("unsolved_variable = {:?}", ty);
39             self.fallback_if_possible(ty, &diverging_fallback);
40         }
41
42         // We now see if we can make progress. This might cause us to
43         // unify inference variables for opaque types, since we may
44         // have unified some other type variables during the first
45         // phase of fallback. This means that we only replace
46         // inference variables with their underlying opaque types as a
47         // last resort.
48         //
49         // In code like this:
50         //
51         // ```rust
52         // type MyType = impl Copy;
53         // fn produce() -> MyType { true }
54         // fn bad_produce() -> MyType { panic!() }
55         // ```
56         //
57         // we want to unify the opaque inference variable in `bad_produce`
58         // with the diverging fallback for `panic!` (e.g. `()` or `!`).
59         // This will produce a nice error message about conflicting concrete
60         // types for `MyType`.
61         //
62         // If we had tried to fallback the opaque inference variable to `MyType`,
63         // we will generate a confusing type-check error that does not explicitly
64         // refer to opaque types.
65         self.select_obligations_where_possible(|_| {});
66     }
67
68     // Tries to apply a fallback to `ty` if it is an unsolved variable.
69     //
70     // - Unconstrained ints are replaced with `i32`.
71     //
72     // - Unconstrained floats are replaced with `f64`.
73     //
74     // - Non-numerics may get replaced with `()` or `!`, depending on
75     //   how they were categorized by `calculate_diverging_fallback`
76     //   (and the setting of `#![feature(never_type_fallback)]`).
77     //
78     // Fallback becomes very dubious if we have encountered
79     // type-checking errors. In that case, fallback to Error.
80     //
81     // Sets `FnCtxt::fallback_has_occurred` if fallback is performed
82     // during this call.
83     fn fallback_if_possible(
84         &self,
85         ty: Ty<'tcx>,
86         diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
87     ) {
88         // Careful: we do NOT shallow-resolve `ty`. We know that `ty`
89         // is an unsolved variable, and we determine its fallback
90         // based solely on how it was created, not what other type
91         // variables it may have been unified with since then.
92         //
93         // The reason this matters is that other attempts at fallback
94         // may (in principle) conflict with this fallback, and we wish
95         // to generate a type error in that case. (However, this
96         // actually isn't true right now, because we're only using the
97         // builtin fallback rules. This would be true if we were using
98         // user-supplied fallbacks. But it's still useful to write the
99         // code to detect bugs.)
100         //
101         // (Note though that if we have a general type variable `?T`
102         // that is then unified with an integer type variable `?I`
103         // that ultimately never gets resolved to a special integral
104         // type, `?T` is not considered unsolved, but `?I` is. The
105         // same is true for float variables.)
106         let fallback = match ty.kind() {
107             _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
108             ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
109             ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
110             _ => match diverging_fallback.get(&ty) {
111                 Some(&fallback_ty) => fallback_ty,
112                 None => return,
113             },
114         };
115         debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
116
117         let span = self
118             .infcx
119             .type_var_origin(ty)
120             .map(|origin| origin.span)
121             .unwrap_or(rustc_span::DUMMY_SP);
122         self.demand_eqtype(span, ty, fallback);
123         self.fallback_has_occurred.set(true);
124     }
125
126     /// The "diverging fallback" system is rather complicated. This is
127     /// a result of our need to balance 'do the right thing' with
128     /// backwards compatibility.
129     ///
130     /// "Diverging" type variables are variables created when we
131     /// coerce a `!` type into an unbound type variable `?X`. If they
132     /// never wind up being constrained, the "right and natural" thing
133     /// is that `?X` should "fallback" to `!`. This means that e.g. an
134     /// expression like `Some(return)` will ultimately wind up with a
135     /// type like `Option<!>` (presuming it is not assigned or
136     /// constrained to have some other type).
137     ///
138     /// However, the fallback used to be `()` (before the `!` type was
139     /// added). Moreover, there are cases where the `!` type 'leaks
140     /// out' from dead code into type variables that affect live
141     /// code. The most common case is something like this:
142     ///
143     /// ```rust
144     /// # fn foo() -> i32 { 4 }
145     /// match foo() {
146     ///     22 => Default::default(), // call this type `?D`
147     ///     _ => return, // return has type `!`
148     /// } // call the type of this match `?M`
149     /// ```
150     ///
151     /// Here, coercing the type `!` into `?M` will create a diverging
152     /// type variable `?X` where `?X <: ?M`. We also have that `?D <:
153     /// ?M`. If `?M` winds up unconstrained, then `?X` will
154     /// fallback. If it falls back to `!`, then all the type variables
155     /// will wind up equal to `!` -- this includes the type `?D`
156     /// (since `!` doesn't implement `Default`, we wind up a "trait
157     /// not implemented" error in code like this). But since the
158     /// original fallback was `()`, this code used to compile with `?D
159     /// = ()`. This is somewhat surprising, since `Default::default()`
160     /// on its own would give an error because the types are
161     /// insufficiently constrained.
162     ///
163     /// Our solution to this dilemma is to modify diverging variables
164     /// so that they can *either* fallback to `!` (the default) or to
165     /// `()` (the backwards compatibility case). We decide which
166     /// fallback to use based on whether there is a coercion pattern
167     /// like this:
168     ///
169     /// ```ignore (not-rust)
170     /// ?Diverging -> ?V
171     /// ?NonDiverging -> ?V
172     /// ?V != ?NonDiverging
173     /// ```
174     ///
175     /// Here `?Diverging` represents some diverging type variable and
176     /// `?NonDiverging` represents some non-diverging type
177     /// variable. `?V` can be any type variable (diverging or not), so
178     /// long as it is not equal to `?NonDiverging`.
179     ///
180     /// Intuitively, what we are looking for is a case where a
181     /// "non-diverging" type variable (like `?M` in our example above)
182     /// is coerced *into* some variable `?V` that would otherwise
183     /// fallback to `!`. In that case, we make `?V` fallback to `!`,
184     /// along with anything that would flow into `?V`.
185     ///
186     /// The algorithm we use:
187     /// * Identify all variables that are coerced *into* by a
188     ///   diverging variable. Do this by iterating over each
189     ///   diverging, unsolved variable and finding all variables
190     ///   reachable from there. Call that set `D`.
191     /// * Walk over all unsolved, non-diverging variables, and find
192     ///   any variable that has an edge into `D`.
193     fn calculate_diverging_fallback(
194         &self,
195         unsolved_variables: &[Ty<'tcx>],
196     ) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
197         debug!("calculate_diverging_fallback({:?})", unsolved_variables);
198
199         // Construct a coercion graph where an edge `A -> B` indicates
200         // a type variable is that is coerced
201         let coercion_graph = self.create_coercion_graph();
202
203         // Extract the unsolved type inference variable vids; note that some
204         // unsolved variables are integer/float variables and are excluded.
205         let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
206
207         // Compute the diverging root vids D -- that is, the root vid of
208         // those type variables that (a) are the target of a coercion from
209         // a `!` type and (b) have not yet been solved.
210         //
211         // These variables are the ones that are targets for fallback to
212         // either `!` or `()`.
213         let diverging_roots: FxHashSet<ty::TyVid> = self
214             .diverging_type_vars
215             .borrow()
216             .iter()
217             .map(|&ty| self.shallow_resolve(ty))
218             .filter_map(|ty| ty.ty_vid())
219             .map(|vid| self.root_var(vid))
220             .collect();
221         debug!(
222             "calculate_diverging_fallback: diverging_type_vars={:?}",
223             self.diverging_type_vars.borrow()
224         );
225         debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
226
227         // Find all type variables that are reachable from a diverging
228         // type variable. These will typically default to `!`, unless
229         // we find later that they are *also* reachable from some
230         // other type variable outside this set.
231         let mut roots_reachable_from_diverging = DepthFirstSearch::new(&coercion_graph);
232         let mut diverging_vids = vec![];
233         let mut non_diverging_vids = vec![];
234         for unsolved_vid in unsolved_vids {
235             let root_vid = self.root_var(unsolved_vid);
236             debug!(
237                 "calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
238                 unsolved_vid,
239                 root_vid,
240                 diverging_roots.contains(&root_vid),
241             );
242             if diverging_roots.contains(&root_vid) {
243                 diverging_vids.push(unsolved_vid);
244                 roots_reachable_from_diverging.push_start_node(root_vid);
245
246                 debug!(
247                     "calculate_diverging_fallback: root_vid={:?} reaches {:?}",
248                     root_vid,
249                     coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
250                 );
251
252                 // drain the iterator to visit all nodes reachable from this node
253                 roots_reachable_from_diverging.complete_search();
254             } else {
255                 non_diverging_vids.push(unsolved_vid);
256             }
257         }
258
259         debug!(
260             "calculate_diverging_fallback: roots_reachable_from_diverging={:?}",
261             roots_reachable_from_diverging,
262         );
263
264         // Find all type variables N0 that are not reachable from a
265         // diverging variable, and then compute the set reachable from
266         // N0, which we call N. These are the *non-diverging* type
267         // variables. (Note that this set consists of "root variables".)
268         let mut roots_reachable_from_non_diverging = DepthFirstSearch::new(&coercion_graph);
269         for &non_diverging_vid in &non_diverging_vids {
270             let root_vid = self.root_var(non_diverging_vid);
271             if roots_reachable_from_diverging.visited(root_vid) {
272                 continue;
273             }
274             roots_reachable_from_non_diverging.push_start_node(root_vid);
275             roots_reachable_from_non_diverging.complete_search();
276         }
277         debug!(
278             "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}",
279             roots_reachable_from_non_diverging,
280         );
281
282         debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations());
283
284         // For each diverging variable, figure out whether it can
285         // reach a member of N. If so, it falls back to `()`. Else
286         // `!`.
287         let mut diverging_fallback = FxHashMap::default();
288         diverging_fallback.reserve(diverging_vids.len());
289         for &diverging_vid in &diverging_vids {
290             let diverging_ty = self.tcx.mk_ty_var(diverging_vid);
291             let root_vid = self.root_var(diverging_vid);
292             let can_reach_non_diverging = coercion_graph
293                 .depth_first_search(root_vid)
294                 .any(|n| roots_reachable_from_non_diverging.visited(n));
295
296             let mut found_infer_var_info = ty::InferVarInfo { self_in_trait: false, output: false };
297
298             for (vid, info) in self.inh.infer_var_info.borrow().iter() {
299                 if self.infcx.root_var(*vid) == root_vid {
300                     found_infer_var_info.self_in_trait |= info.self_in_trait;
301                     found_infer_var_info.output |= info.output;
302                 }
303             }
304
305             if found_infer_var_info.self_in_trait && found_infer_var_info.output {
306                 // This case falls back to () to ensure that the code pattern in
307                 // tests/ui/never_type/fallback-closure-ret.rs continues to
308                 // compile when never_type_fallback is enabled.
309                 //
310                 // This rule is not readily explainable from first principles,
311                 // but is rather intended as a patchwork fix to ensure code
312                 // which compiles before the stabilization of never type
313                 // fallback continues to work.
314                 //
315                 // Typically this pattern is encountered in a function taking a
316                 // closure as a parameter, where the return type of that closure
317                 // (checked by `relationship.output`) is expected to implement
318                 // some trait (checked by `relationship.self_in_trait`). This
319                 // can come up in non-closure cases too, so we do not limit this
320                 // rule to specifically `FnOnce`.
321                 //
322                 // When the closure's body is something like `panic!()`, the
323                 // return type would normally be inferred to `!`. However, it
324                 // needs to fall back to `()` in order to still compile, as the
325                 // trait is specifically implemented for `()` but not `!`.
326                 //
327                 // For details on the requirements for these relationships to be
328                 // set, see the relationship finding module in
329                 // compiler/rustc_trait_selection/src/traits/relationships.rs.
330                 debug!("fallback to () - found trait and projection: {:?}", diverging_vid);
331                 diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
332             } else if can_reach_non_diverging {
333                 debug!("fallback to () - reached non-diverging: {:?}", diverging_vid);
334                 diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
335             } else {
336                 debug!("fallback to ! - all diverging: {:?}", diverging_vid);
337                 diverging_fallback.insert(diverging_ty, self.tcx.mk_diverging_default());
338             }
339         }
340
341         diverging_fallback
342     }
343
344     /// Returns a graph whose nodes are (unresolved) inference variables and where
345     /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
346     fn create_coercion_graph(&self) -> VecGraph<ty::TyVid> {
347         let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations();
348         debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations);
349         let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations
350             .into_iter()
351             .filter_map(|obligation| {
352                 // The predicates we are looking for look like `Coerce(?A -> ?B)`.
353                 // They will have no bound variables.
354                 obligation.predicate.kind().no_bound_vars()
355             })
356             .filter_map(|atom| {
357                 // We consider both subtyping and coercion to imply 'flow' from
358                 // some position in the code `a` to a different position `b`.
359                 // This is then used to determine which variables interact with
360                 // live code, and as such must fall back to `()` to preserve
361                 // soundness.
362                 //
363                 // In practice currently the two ways that this happens is
364                 // coercion and subtyping.
365                 let (a, b) = if let ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) = atom {
366                     (a, b)
367                 } else if let ty::PredicateKind::Subtype(ty::SubtypePredicate {
368                     a_is_expected: _,
369                     a,
370                     b,
371                 }) = atom
372                 {
373                     (a, b)
374                 } else {
375                     return None;
376                 };
377
378                 let a_vid = self.root_vid(a)?;
379                 let b_vid = self.root_vid(b)?;
380                 Some((a_vid, b_vid))
381             })
382             .collect();
383         debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges);
384         let num_ty_vars = self.num_ty_vars();
385         VecGraph::new(num_ty_vars, coercion_edges)
386     }
387
388     /// If `ty` is an unresolved type variable, returns its root vid.
389     fn root_vid(&self, ty: Ty<'tcx>) -> Option<ty::TyVid> {
390         Some(self.root_var(self.shallow_resolve(ty).ty_vid()?))
391     }
392 }