-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic pointers coerceable #1931
Conversation
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-tyty.cc (ADTType::is_concrete): need to consider if is a num_variant * typecheck/rust-tyty.h: refactor to cc file
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::Resolve): refactor (UnifyRules::commit): refactor * typecheck/rust-unify.h: likewise
This is a complex type-system change where it begins out journey to get rid of our can_eq interface. Rust allows: let x:*mut T let y = x as *mut u8; Which requires us to consider find a way to infer what T should be so as to keep unify happy. This means we need to introduce a new unify_and interface where we can optionally inject inference variables as well as only commit the inference variable joins when they are sucsessful. So for this case we can then inject an implicit inference variables for T that can unify against u8 to make this a valid type-resolution. Fixes #1930 Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::resolve_method_address): update to new inteface * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsafe_ptr): likewise (TypeCoercionRules::coerce_borrowed_pointer): likewise * typecheck/rust-hir-type-check.h: likewise * typecheck/rust-type-util.cc (unify_site_and): new interface to allow for infer and commit * typecheck/rust-type-util.h (unify_site_and): likewise * typecheck/rust-typecheck-context.cc (TypeCheckContext::clear_type): new interface * typecheck/rust-unify.cc (UnifyRules::UnifyRules): update (UnifyRules::Resolve): new optional flags for commit and infer (UnifyRules::go): likewise (UnifyRules::expect_adt): refactor to use new interface (UnifyRules::expect_reference): likewise (UnifyRules::expect_pointer): likewise (UnifyRules::expect_array): likewise (UnifyRules::expect_slice): likewise (UnifyRules::expect_fndef): likewise (UnifyRules::expect_fnptr): likewise (UnifyRules::expect_tuple): likewise (UnifyRules::expect_closure): likewise * typecheck/rust-unify.h: refactor interface gcc/testsuite/ChangeLog: * rust/compile/issue-1930.rs: New test.
We should allow implicit inference on the expected side too not just the receiver. Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::go): allow lhs infer vars
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-casts.cc (TypeCastRules::check): update to new interface * typecheck/rust-coercion.cc (TypeCoercionRules::Coerce): likewise (TypeCoercionRules::TryCoerce): likewise (TypeCoercionRules::TypeCoercionRules): likewise * typecheck/rust-coercion.h: likewise * typecheck/rust-type-util.cc (coercion_site): likewise
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::go): respect the emit_errors flag
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * backend/rust-compile-base.h: unconsify * backend/rust-compile.cc (HIRCompileBase::coercion_site): likewise (HIRCompileBase::coercion_site1): likewise * typecheck/rust-autoderef.cc (Adjuster::try_deref_type): likewise (Adjuster::try_raw_deref_type): likewise (Adjuster::try_unsize_type): likewise (AutoderefCycle::cycle): likewise (AutoderefCycle::try_autoderefed): likewise * typecheck/rust-autoderef.h: likewise * typecheck/rust-coercion.cc (TypeCoercionRules::select): likewise * typecheck/rust-coercion.h: likewise * typecheck/rust-hir-dot-operator.cc (MethodResolver::Probe): likewise (MethodResolver::select): likewise * typecheck/rust-hir-dot-operator.h: likewise
When generating implicit inference variables we can miss cases where the other side might be another inference variable too but it runs the risk of generating unending inference cycles needing more info but if they other side is a non general inference variables like <integer> or <float> this is safe to do so and allows us to infer mroe cases. Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-unify.cc (UnifyRules::go): fix inference check
Rust allows us to call generic pointer methods on pointers so in non generic contexts the old code using the bad can_eq interface couldn't handle this case. So taking advantage of our new unify_and interface to try and infer when required we can start using our TryCoerce interface to reuse existing code to assemble possible candidates more acurately using the existing coercion rules. Fixes #1901 #878 Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-coercion.cc (TypeCoercionRules::Coerce): Add new try_flag (TypeCoercionRules::TypeCoercionRules): set new try flag (TypeCoercionRules::do_coercion): default to a final unify_and in the else case (TypeCoercionRules::coerce_unsafe_ptr): cannot coerce to a ptr from ref during autoderef (TypeCoercionRules::coerce_borrowed_pointer): respect coerceable mutability * typecheck/rust-coercion.h: update header * typecheck/rust-hir-dot-operator.cc (MethodResolver::select): use new TryCoerce interface (MethodResolver::append_adjustments): ensure we maintain adjustment mappings * typecheck/rust-hir-dot-operator.h: add new method append_adjustments * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): extra logging gcc/testsuite/ChangeLog: * rust/compile/issue-1901.rs: New test.
Signed-off-by: Philip Herron <[email protected]> gcc/rust/ChangeLog: * typecheck/rust-tyty-cmp.h: remove * typecheck/rust-tyty.cc (set_cmp_autoderef_mode): likewise (reset_cmp_autoderef_mode): likewise * typecheck/rust-tyty.h (set_cmp_autoderef_mode): likewise (reset_cmp_autoderef_mode): likewise
if (autoderef_flag && receiver_is_non_ptr) | ||
{ | ||
// it is unsafe to autoderef to raw pointers | ||
return CoercionResult::get_error (); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unsafe as in "this is allowed in unsafe contexts"? Or is it always forbidden?
else if (receiver_is_ref && impl_self_is_ref) | ||
{ | ||
const TyTy::ReferenceType &sptr | ||
= *static_cast<const TyTy::ReferenceType *> (impl_self); | ||
const TyTy::ReferenceType &ptr | ||
= *static_cast<const TyTy::ReferenceType *> (raw); | ||
|
||
// we could do this via lang-item assemblies if we refactor this | ||
bool mut_match = sptr.mutability () == ptr.mutability (); | ||
if (!mut_match) | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So having ambiguous implementations for *mut T
and *const T
is allowed as you pointed out in zulip, but is it also allowed for &mut T
and &T
? Or am I misunderstanding this bit of code?
In order to fix the following issues we need to begin the journey to get rid of
the can_eq interface as well as the autoderef_flag hack inside it. In non-generic
contexts in order to call const pointer lang item methods the can_eq interface
was not possible to infer that these types are valid. This patch set adds a new
unify_and interface so that we can optionally inject inference variables and only
commit them when everything is ok and on failure cleanup. So during method
resolution and picking we can now pick using our TryCoerce interface instead
of the bad can_eq one.
Fixes #1903 #1901 #878
Addresses #1895