From: Pierre-Emmanuel Patry <[email protected]>

gcc/rust/ChangeLog:

        * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion):
        Move nevertype coercion from here...
        (TypeCoercionRules::coerce_never): ... to here.
        * typecheck/rust-coercion.h: Add function prototype.

Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
---
 gcc/rust/typecheck/rust-coercion.cc | 75 +++++++++++++++--------------
 gcc/rust/typecheck/rust-coercion.h  |  1 +
 2 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/gcc/rust/typecheck/rust-coercion.cc 
b/gcc/rust/typecheck/rust-coercion.cc
index aa9675afa01..cf285956d16 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -61,44 +61,9 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
   // see:
   // 
https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs
 
-  // handle never
-  // 
https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
   if (receiver->get_kind () == TyTy::TypeKind::NEVER)
     {
-      // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
-      // type variable, we want `?T` to fallback to `!` if not
-      // otherwise constrained. An example where this arises:
-      //
-      //     let _: Option<?T> = Some({ return; });
-      //
-      // here, we would coerce from `!` to `?T`.
-      if (expected->has_substitutions_defined () && !expected->is_concrete ())
-       {
-         location_t locus = mappings.lookup_location (receiver->get_ref ());
-         TyTy::TyVar implicit_var
-           = TyTy::TyVar::get_implicit_infer_var (locus);
-         try_result = CoercionResult{{}, implicit_var.get_tyty ()};
-       }
-      else
-       {
-         bool expected_is_infer_var
-           = expected->get_kind () == TyTy::TypeKind::INFER;
-         bool expected_is_general_infer_var
-           = expected_is_infer_var
-             && (static_cast<TyTy::InferType *> (expected)->get_infer_kind ()
-                 == TyTy::InferType::InferTypeKind::GENERAL);
-
-         // FIXME this 'expected_is_general_infer_var' case needs to eventually
-         // should go away see: compile/never_type_err1.rs
-         //
-         // I think we need inference obligations to say that yes we have a
-         // general inference variable but we add the oligation to the expected
-         // type that it could default to '!'
-         if (expected_is_general_infer_var)
-           try_result = CoercionResult{{}, receiver};
-         else
-           try_result = CoercionResult{{}, expected->clone ()};
-       }
+      try_result = coerce_never (receiver);
       return true;
     }
 
@@ -169,6 +134,44 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
   return !try_result.is_error ();
 }
 
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::coerce_never (TyTy::BaseType *receiver)
+{
+  // handle never
+  // 
https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
+
+  // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
+  // type variable, we want `?T` to fallback to `!` if not
+  // otherwise constrained. An example where this arises:
+  //
+  //     let _: Option<?T> = Some({ return; });
+  //
+  // here, we would coerce from `!` to `?T`.
+  if (expected->has_substitutions_defined () && !expected->is_concrete ())
+    {
+      location_t locus = mappings.lookup_location (receiver->get_ref ());
+      TyTy::TyVar implicit_var = TyTy::TyVar::get_implicit_infer_var (locus);
+      return CoercionResult{{}, implicit_var.get_tyty ()};
+    }
+
+  bool expected_is_infer_var = expected->get_kind () == TyTy::TypeKind::INFER;
+  bool expected_is_general_infer_var
+    = expected_is_infer_var
+      && (static_cast<TyTy::InferType *> (expected)->get_infer_kind ()
+         == TyTy::InferType::InferTypeKind::GENERAL);
+
+  // FIXME this 'expected_is_general_infer_var' case needs to eventually
+  // should go away see: compile/never_type_err1.rs
+  //
+  // I think we need inference obligations to say that yes we have a
+  // general inference variable but we add the oligation to the expected
+  // type that it could default to '!'
+  if (expected_is_general_infer_var)
+    return CoercionResult{{}, receiver};
+  else
+    return CoercionResult{{}, expected->clone ()};
+}
+
 TypeCoercionRules::CoercionResult
 TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
                                      TyTy::PointerType *expected,
diff --git a/gcc/rust/typecheck/rust-coercion.h 
b/gcc/rust/typecheck/rust-coercion.h
index 3a74794c924..864f48ad58b 100644
--- a/gcc/rust/typecheck/rust-coercion.h
+++ b/gcc/rust/typecheck/rust-coercion.h
@@ -58,6 +58,7 @@ public:
                                   bool allow_autoderef,
                                   bool is_cast_site = false);
 
+  CoercionResult coerce_never (TyTy::BaseType *receiver);
   CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver,
                                    TyTy::PointerType *expected,
                                    Mutability mutability);
-- 
2.50.1

Reply via email to