[gccrs COMMIT] gccrs: Add flag to unify of expect never
gerris.rs@gmail.com
gerris.rs@gmail.com
Fri Sep 18 19:26:19 GMT 2026
From: Philip Herron <herron.philip@googlemail.com>
Fixes Rust-GCC/gccrs#4918
gcc/rust/ChangeLog:
* typecheck/rust-coercion.cc (TypeCoercionRules::TryCoerce): add flag
(TypeCoercionRules::TypeCoercionRules): Likewise.
(TypeCoercionRules::do_coercion): Likewise.
(TypeCoercionRules::coerce_unsafe_ptr): Likewise.
(TypeCoercionRules::coerce_borrowed_pointer): Likewise.
(TypeCoercionRules::select): Likewise.
* typecheck/rust-coercion.h: Likewise.
* typecheck/rust-hir-dot-operator.cc (MethodResolver::try_select_predicate_candidates):
Likewise.
* typecheck/rust-type-util.cc (unify_site_and): Likewise.
* typecheck/rust-type-util.h (unify_site_and): Likewise.
* typecheck/rust-unify.cc (UnifyRules::UnifyRules): Likewise.
(UnifyRules::Resolve): Likewise.
(UnifyRules::resolve_subtype): Likewise.
(UnifyRules::expect_never): Likewise.
* typecheck/rust-unify.h: Likewise.
gcc/testsuite/ChangeLog:
* rust/compile/issues/4918.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github: https://github.com/Rust-GCC/gccrs/commit/215416773ce7d0dcd27a9593d05563facc5c7e56
The commit has been mentioned in the following issue(s):
- Rust-GCC/gccrs#4918: https://github.com/Rust-GCC/gccrs/issues/4918
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4919
gcc/rust/typecheck/rust-coercion.cc | 23 +++++++++-----
gcc/rust/typecheck/rust-coercion.h | 6 ++--
gcc/rust/typecheck/rust-hir-dot-operator.cc | 12 ++++++--
gcc/rust/typecheck/rust-type-util.cc | 5 ++--
gcc/rust/typecheck/rust-type-util.h | 3 +-
gcc/rust/typecheck/rust-unify.cc | 24 ++++++++++-----
gcc/rust/typecheck/rust-unify.h | 6 ++--
gcc/testsuite/rust/compile/issues/4918.rs | 33 +++++++++++++++++++++
8 files changed, 86 insertions(+), 26 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issues/4918.rs
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index 4df9934d8..9d4de57db 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -37,10 +37,11 @@ TypeCoercionRules::Coerce (TyTy::BaseType *receiver, TyTy::BaseType *expected,
TypeCoercionRules::CoercionResult
TypeCoercionRules::TryCoerce (TyTy::BaseType *receiver,
TyTy::BaseType *expected, location_t locus,
- bool allow_autoderef, bool is_cast_site)
+ bool allow_autoderef, bool is_cast_site,
+ bool allow_never_coercion)
{
TypeCoercionRules resolver (expected, locus, false, allow_autoderef, true,
- is_cast_site);
+ is_cast_site, allow_never_coercion);
bool ok = resolver.do_coercion (receiver);
return ok ? resolver.try_result : CoercionResult::get_error ();
}
@@ -48,11 +49,13 @@ TypeCoercionRules::TryCoerce (TyTy::BaseType *receiver,
TypeCoercionRules::TypeCoercionRules (TyTy::BaseType *expected,
location_t locus, bool emit_errors,
bool allow_autoderef, bool try_flag,
- bool is_cast_site)
+ bool is_cast_site,
+ bool allow_never_coercion)
: AutoderefCycle (!allow_autoderef), mappings (Analysis::Mappings::get ()),
context (TypeCheckContext::get ()), expected (expected), locus (locus),
try_result (CoercionResult::get_error ()), emit_errors (emit_errors),
- try_flag (try_flag), is_cast_site (is_cast_site)
+ try_flag (try_flag), is_cast_site (is_cast_site),
+ allow_never_coercion (allow_never_coercion)
{}
bool
@@ -121,7 +124,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
TyTy::TyWithLocation (receiver),
locus /*unify_locus*/, false /*emit_errors*/,
!try_flag /*commit_if_ok*/, try_flag /*infer*/,
- try_flag /*cleanup on error*/);
+ try_flag /*cleanup on error*/,
+ true /*check_bounds*/, allow_never_coercion);
if (result->get_kind () != TyTy::TypeKind::ERROR)
{
try_result = CoercionResult{{}, result};
@@ -248,7 +252,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
locus /*unify_locus*/, !try_flag /*emit_errors*/,
!try_flag /*commit_if_ok*/,
try_flag && !is_cast_site /*infer*/,
- try_flag /*cleanup on error*/);
+ try_flag /*cleanup on error*/, true /*check_bounds*/,
+ allow_never_coercion);
bool unsafe_ptr_coerceion_ok = result->get_kind () != TyTy::TypeKind::ERROR;
if (unsafe_ptr_coerceion_ok)
return CoercionResult{{}, result};
@@ -284,7 +289,8 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
TyTy::TyWithLocation (expected), locus,
false /*emit_errors*/, !try_flag /*commit_if_ok*/,
try_flag /* infer */,
- try_flag /*cleanup_on_failure*/);
+ try_flag /*cleanup_on_failure*/,
+ true /*check_bounds*/, allow_never_coercion);
bool default_coerceion_ok
= result->get_kind () != TyTy::TypeKind::ERROR;
if (default_coerceion_ok)
@@ -625,7 +631,8 @@ TypeCoercionRules::select (TyTy::BaseType &autoderefed)
TyTy::TyWithLocation (&autoderefed),
UNDEF_LOCATION /* locus */, false /*emit_errors*/,
!try_flag /*commit_if_ok*/, try_flag /*infer*/,
- try_flag /*cleanup*/);
+ try_flag /*cleanup*/, true /*check_bounds*/,
+ allow_never_coercion);
bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
if (!ok)
return false;
diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h
index 0674cf5df..be5daf39f 100644
--- a/gcc/rust/typecheck/rust-coercion.h
+++ b/gcc/rust/typecheck/rust-coercion.h
@@ -56,7 +56,8 @@ public:
static CoercionResult TryCoerce (TyTy::BaseType *receiver,
TyTy::BaseType *expected, location_t locus,
bool allow_autoderef,
- bool is_cast_site = false);
+ bool is_cast_site = false,
+ bool allow_never_coercion = true);
CoercionResult coerce_never (TyTy::BaseType *receiver);
CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver,
@@ -82,7 +83,7 @@ public:
protected:
TypeCoercionRules (TyTy::BaseType *expected, location_t locus,
bool emit_errors, bool allow_autoderef, bool try_flag,
- bool is_cast_site);
+ bool is_cast_site, bool allow_never_coercion = true);
bool select (TyTy::BaseType &autoderefed) override;
@@ -124,6 +125,7 @@ private:
bool emit_errors;
bool try_flag;
bool is_cast_site;
+ bool allow_never_coercion;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 06d9aa88e..24b8b8ccc 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -364,7 +364,9 @@ MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
auto res
= TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
- false /*allow-autoderef*/);
+ false /*allow-autoderef*/,
+ false /*is_cast_site*/,
+ false /*allow_never_coercion*/);
bool ok = !res.is_error ();
if (ok)
{
@@ -415,7 +417,9 @@ MethodResolver::try_select_inherent_impl_candidates (
auto res
= TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
- false /*allow-autoderef*/);
+ false /*allow-autoderef*/,
+ false /*is_cast_site*/,
+ false /*allow_never_coercion*/);
bool ok = !res.is_error ();
if (ok)
{
@@ -451,7 +455,9 @@ MethodResolver::try_select_trait_impl_candidates (
auto res
= TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
- false /*allow-autoderef*/);
+ false /*allow-autoderef*/,
+ false /*is_cast_site*/,
+ false /*allow_never_coercion*/);
bool ok = !res.is_error ();
if (ok)
{
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index 2234f89e0..7df36f0d3 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -281,7 +281,8 @@ unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
TyTy::BaseType *
unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
location_t unify_locus, bool emit_errors, bool commit_if_ok,
- bool implicit_infer_vars, bool cleanup, bool check_bounds)
+ bool implicit_infer_vars, bool cleanup, bool check_bounds,
+ bool allow_never_coercion)
{
TypeCheckContext &context = *TypeCheckContext::get ();
@@ -301,7 +302,7 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
TyTy::BaseType *result
= UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/,
emit_errors, check_bounds, implicit_infer_vars,
- commits, infers);
+ commits, infers, nullptr, allow_never_coercion);
bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
rust_debug_loc (unify_locus,
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
index 860f23cfc..89687d9f2 100644
--- a/gcc/rust/typecheck/rust-type-util.h
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -38,7 +38,8 @@ TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs,
TyTy::TyWithLocation rhs,
location_t unify_locus, bool emit_errors,
bool commit_if_ok, bool implicit_infer_vars,
- bool cleanup, bool check_bounds = true);
+ bool cleanup, bool check_bounds = true,
+ bool allow_never_coercion = true);
TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs,
TyTy::TyWithLocation rhs,
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 417804b44..db6dabcf8 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -39,12 +39,13 @@ UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
bool check_bounds, bool infer,
std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers,
- ActiveADTs &active_adts)
+ ActiveADTs &active_adts, bool allow_never_coercion)
: lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
emit_error (emit_error), infer_flag (infer),
- check_bounds_flag (check_bounds), commits (commits), infers (infers),
- active_adts (active_adts), mappings (Analysis::Mappings::get ()),
- context (*TypeCheckContext::get ())
+ check_bounds_flag (check_bounds),
+ allow_never_coercion (allow_never_coercion), commits (commits),
+ infers (infers), active_adts (active_adts),
+ mappings (Analysis::Mappings::get ()), context (*TypeCheckContext::get ())
{}
TyTy::BaseType *
@@ -53,14 +54,14 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
bool check_bounds, bool infer,
std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers,
- ActiveADTs *active_adts)
+ ActiveADTs *active_adts, bool allow_never_coercion)
{
ActiveADTs root_active_adts;
if (active_adts == nullptr)
active_adts = &root_active_adts;
UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, check_bounds, infer,
- commits, infers, *active_adts);
+ commits, infers, *active_adts, allow_never_coercion);
TyTy::BaseType *result = r.go ();
bool failed = result->get_kind () == TyTy::TypeKind::ERROR;
@@ -84,7 +85,7 @@ UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs)
TyTy::BaseType *result
= UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error,
check_bounds_flag, infer_flag, commits, infers,
- &active_adts);
+ &active_adts, allow_never_coercion);
// If the recursive call resulted in an error and would have emitted an error
// message, disable error emission for the current level to avoid duplicate
@@ -1835,8 +1836,15 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
}
break;
+ case TyTy::NEVER:
+ return ltype;
+
default:
- return rtype;
+ {
+ if (allow_never_coercion)
+ return rtype;
+ }
+ break;
}
return unify_error_type_node ();
}
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 2091bd1b1..29938cfff 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -90,7 +90,7 @@ public:
Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus,
bool commit_flag, bool emit_error, bool check_bounds, bool infer,
std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers,
- ActiveADTs *active_adts = nullptr);
+ ActiveADTs *active_adts = nullptr, bool allow_never_coercion = true);
static void commit (TyTy::BaseType *base, TyTy::BaseType *other,
TyTy::BaseType *resolved);
@@ -135,7 +135,8 @@ private:
UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
location_t locus, bool commit_flag, bool emit_error, bool infer,
bool check_bounds, std::vector<CommitSite> &commits,
- std::vector<InferenceSite> &infers, ActiveADTs &active_adts);
+ std::vector<InferenceSite> &infers, ActiveADTs &active_adts,
+ bool allow_never_coercion);
TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs,
TyTy::TyWithLocation rhs);
@@ -156,6 +157,7 @@ private:
bool emit_error;
bool infer_flag;
bool check_bounds_flag;
+ bool allow_never_coercion;
std::vector<CommitSite> &commits;
std::vector<InferenceSite> &infers;
diff --git a/gcc/testsuite/rust/compile/issues/4918.rs b/gcc/testsuite/rust/compile/issues/4918.rs
new file mode 100644
index 000000000..b378d1b35
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issues/4918.rs
@@ -0,0 +1,33 @@
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub enum Ordering {
+ Less,
+ Equal,
+ Greater,
+}
+
+pub trait Ord {
+ fn cmp(&self, other: &Self) -> Ordering;
+}
+
+impl Ord for i32 {
+ fn cmp(&self, _other: &i32) -> Ordering {
+ Ordering::Equal
+ }
+}
+
+impl Ord for ! {
+ fn cmp(&self, _other: &!) -> Ordering {
+ Ordering::Equal
+ }
+}
+
+fn main() {
+ let left: i32 = 1;
+ let right: i32 = 2;
+ let _ = left.cmp(&right);
+}
base-commit: 5870b08eac1603169553d896c128fd886523f6af
--
2.55.0
More information about the Gcc-rust
mailing list