@@ -61,44 +61,9 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
6161 // see:
6262 // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs
6363
64- // handle never
65- // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
6664 if (receiver->get_kind () == TyTy::TypeKind::NEVER)
6765 {
68- // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
69- // type variable, we want `?T` to fallback to `!` if not
70- // otherwise constrained. An example where this arises:
71- //
72- // let _: Option<?T> = Some({ return; });
73- //
74- // here, we would coerce from `!` to `?T`.
75- if (expected->has_substitutions_defined () && !expected->is_concrete ())
76- {
77- location_t locus = mappings.lookup_location (receiver->get_ref ());
78- TyTy::TyVar implicit_var
79- = TyTy::TyVar::get_implicit_infer_var (locus);
80- try_result = CoercionResult{{}, implicit_var.get_tyty ()};
81- }
82- else
83- {
84- bool expected_is_infer_var
85- = expected->get_kind () == TyTy::TypeKind::INFER;
86- bool expected_is_general_infer_var
87- = expected_is_infer_var
88- && (static_cast <TyTy::InferType *> (expected)->get_infer_kind ()
89- == TyTy::InferType::InferTypeKind::GENERAL);
90-
91- // FIXME this 'expected_is_general_infer_var' case needs to eventually
92- // should go away see: compile/never_type_err1.rs
93- //
94- // I think we need inference obligations to say that yes we have a
95- // general inference variable but we add the oligation to the expected
96- // type that it could default to '!'
97- if (expected_is_general_infer_var)
98- try_result = CoercionResult{{}, receiver};
99- else
100- try_result = CoercionResult{{}, expected->clone ()};
101- }
66+ try_result = coerce_never (receiver);
10267 return true ;
10368 }
10469
@@ -169,6 +134,44 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
169134 return !try_result.is_error ();
170135}
171136
137+ TypeCoercionRules::CoercionResult
138+ TypeCoercionRules::coerce_never (TyTy::BaseType *receiver)
139+ {
140+ // handle never
141+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
142+
143+ // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
144+ // type variable, we want `?T` to fallback to `!` if not
145+ // otherwise constrained. An example where this arises:
146+ //
147+ // let _: Option<?T> = Some({ return; });
148+ //
149+ // here, we would coerce from `!` to `?T`.
150+ if (expected->has_substitutions_defined () && !expected->is_concrete ())
151+ {
152+ location_t locus = mappings.lookup_location (receiver->get_ref ());
153+ TyTy::TyVar implicit_var = TyTy::TyVar::get_implicit_infer_var (locus);
154+ return CoercionResult{{}, implicit_var.get_tyty ()};
155+ }
156+
157+ bool expected_is_infer_var = expected->get_kind () == TyTy::TypeKind::INFER;
158+ bool expected_is_general_infer_var
159+ = expected_is_infer_var
160+ && (static_cast <TyTy::InferType *> (expected)->get_infer_kind ()
161+ == TyTy::InferType::InferTypeKind::GENERAL);
162+
163+ // FIXME this 'expected_is_general_infer_var' case needs to eventually
164+ // should go away see: compile/never_type_err1.rs
165+ //
166+ // I think we need inference obligations to say that yes we have a
167+ // general inference variable but we add the oligation to the expected
168+ // type that it could default to '!'
169+ if (expected_is_general_infer_var)
170+ return CoercionResult{{}, receiver};
171+ else
172+ return CoercionResult{{}, expected->clone ()};
173+ }
174+
172175TypeCoercionRules::CoercionResult
173176TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
174177 TyTy::PointerType *expected,
0 commit comments