]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_typeck/src/check/mod.rs
Auto merge of #88266 - nikomatsakis:issue-87879, r=jackh726
[rust.git] / compiler / rustc_typeck / src / check / mod.rs
index d1e583ed1845a991ba32a964f69898228fa3e089..a88b1c7af5a96640f49b498fd536d0524ea57834 100644 (file)
@@ -75,6 +75,7 @@
 pub mod dropck;
 mod expectation;
 mod expr;
+mod fallback;
 mod fn_ctxt;
 mod gather_locals;
 mod generator_interior;
@@ -391,7 +392,7 @@ fn typeck_with_fallback<'tcx>(
                 fn_sig,
             );
 
-            let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
+            let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0;
             fcx
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
@@ -445,54 +446,12 @@ fn typeck_with_fallback<'tcx>(
             fcx
         };
 
-        // All type checking constraints were added, try to fallback unsolved variables.
-        fcx.select_obligations_where_possible(false, |_| {});
-        let mut fallback_has_occurred = false;
-
-        // We do fallback in two passes, to try to generate
-        // better error messages.
-        // The first time, we do *not* replace opaque types.
-        for ty in &fcx.unsolved_variables() {
-            fallback_has_occurred |= fcx.fallback_if_possible(ty, FallbackMode::NoOpaque);
-        }
-        // We now see if we can make progress. This might
-        // cause us to unify inference variables for opaque types,
-        // since we may have unified some other type variables
-        // during the first phase of fallback.
-        // This means that we only replace inference variables with their underlying
-        // opaque types as a last resort.
-        //
-        // In code like this:
-        //
-        // ```rust
-        // type MyType = impl Copy;
-        // fn produce() -> MyType { true }
-        // fn bad_produce() -> MyType { panic!() }
-        // ```
-        //
-        // we want to unify the opaque inference variable in `bad_produce`
-        // with the diverging fallback for `panic!` (e.g. `()` or `!`).
-        // This will produce a nice error message about conflicting concrete
-        // types for `MyType`.
-        //
-        // If we had tried to fallback the opaque inference variable to `MyType`,
-        // we will generate a confusing type-check error that does not explicitly
-        // refer to opaque types.
-        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
-
-        // We now run fallback again, but this time we allow it to replace
-        // unconstrained opaque type variables, in addition to performing
-        // other kinds of fallback.
-        for ty in &fcx.unsolved_variables() {
-            fallback_has_occurred |= fcx.fallback_if_possible(ty, FallbackMode::All);
-        }
-
-        // See if we can make any more progress.
-        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
+        let fallback_has_occurred = fcx.type_inference_fallback();
 
         // Even though coercion casts provide type hints, we check casts after fallback for
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
         fcx.check_casts();
+        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
 
         // Closure and generator analysis may run after fallback
         // because they don't constrain other type variables.
@@ -914,16 +873,6 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-/// Controls how we perform fallback for unconstrained
-/// type variables.
-enum FallbackMode {
-    /// Do not fallback type variables to opaque types.
-    NoOpaque,
-    /// Perform all possible kinds of fallback, including
-    /// turning type variables to opaque types.
-    All,
-}
-
 /// A wrapper for `InferCtxt`'s `in_progress_typeck_results` field.
 #[derive(Copy, Clone)]
 struct MaybeInProgressTables<'a, 'tcx> {