Skip to content

Commit 43a9278

Browse files
committed
gccrs: Fix method resolution to use TryCoerce
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.
1 parent a204260 commit 43a9278

File tree

6 files changed

+240
-58
lines changed

6 files changed

+240
-58
lines changed

gcc/rust/typecheck/rust-coercion.cc

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ TypeCoercionRules::CoercionResult
2727
TypeCoercionRules::Coerce (TyTy::BaseType *receiver, TyTy::BaseType *expected,
2828
Location locus, bool allow_autoderef)
2929
{
30-
TypeCoercionRules resolver (expected, locus, true, allow_autoderef);
30+
TypeCoercionRules resolver (expected, locus, true, allow_autoderef, false);
3131
bool ok = resolver.do_coercion (receiver);
3232
return ok ? resolver.try_result : CoercionResult::get_error ();
3333
}
@@ -37,16 +37,18 @@ TypeCoercionRules::TryCoerce (TyTy::BaseType *receiver,
3737
TyTy::BaseType *expected, Location locus,
3838
bool allow_autoderef)
3939
{
40-
TypeCoercionRules resolver (expected, locus, false, allow_autoderef);
40+
TypeCoercionRules resolver (expected, locus, false, allow_autoderef, true);
4141
bool ok = resolver.do_coercion (receiver);
4242
return ok ? resolver.try_result : CoercionResult::get_error ();
4343
}
4444

4545
TypeCoercionRules::TypeCoercionRules (TyTy::BaseType *expected, Location locus,
46-
bool emit_errors, bool allow_autoderef)
46+
bool emit_errors, bool allow_autoderef,
47+
bool try_flag)
4748
: AutoderefCycle (!allow_autoderef), mappings (Analysis::Mappings::get ()),
4849
context (TypeCheckContext::get ()), expected (expected), locus (locus),
49-
try_result (CoercionResult::get_error ()), emit_errors (emit_errors)
50+
try_result (CoercionResult::get_error ()), emit_errors (emit_errors),
51+
try_flag (try_flag)
5052
{}
5153

5254
bool
@@ -139,6 +141,31 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
139141
break;
140142
}
141143

144+
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210
145+
switch (receiver->get_kind ())
146+
{
147+
default: {
148+
rust_debug (
149+
"do_coercion default unify and infer expected: %s receiver %s",
150+
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
151+
TyTy::BaseType *result
152+
= unify_site_and (receiver->get_ref (),
153+
TyTy::TyWithLocation (expected),
154+
TyTy::TyWithLocation (receiver),
155+
locus /*unify_locus*/, false /*emit_errors*/,
156+
!try_flag /*commit_if_ok*/, true /*infer*/,
157+
try_flag /*cleanup on error*/);
158+
rust_debug ("result");
159+
result->debug ();
160+
if (result->get_kind () != TyTy::TypeKind::ERROR)
161+
{
162+
try_result = CoercionResult{{}, result};
163+
return true;
164+
}
165+
}
166+
break;
167+
}
168+
142169
return !try_result.is_error ();
143170
}
144171

@@ -170,13 +197,21 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
170197
break;
171198

172199
default: {
200+
// FIXME this can probably turn into a unify_and
173201
if (receiver->can_eq (expected, false))
174202
return CoercionResult{{}, expected->clone ()};
175203

176204
return CoercionResult::get_error ();
177205
}
178206
}
179207

208+
bool receiver_is_non_ptr = receiver->get_kind () != TyTy::TypeKind::POINTER;
209+
if (autoderef_flag && receiver_is_non_ptr)
210+
{
211+
// it is unsafe to autoderef to raw pointers
212+
return CoercionResult::get_error ();
213+
}
214+
180215
if (!coerceable_mutability (from_mutbl, to_mutbl))
181216
{
182217
Location lhs = mappings->lookup_location (receiver->get_ref ());
@@ -192,9 +227,9 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
192227
TyTy::BaseType *result
193228
= unify_site_and (receiver->get_ref (), TyTy::TyWithLocation (expected),
194229
TyTy::TyWithLocation (coerced_mutability),
195-
Location () /*unify_locus*/, false /*emit_errors*/,
196-
true /*commit_if_ok*/, true /*infer*/,
197-
true /*cleanup on error*/);
230+
locus /*unify_locus*/, false /*emit_errors*/,
231+
!try_flag /*commit_if_ok*/, true /*infer*/,
232+
try_flag /*cleanup on error*/);
198233
bool unsafe_ptr_coerceion_ok = result->get_kind () != TyTy::TypeKind::ERROR;
199234
if (unsafe_ptr_coerceion_ok)
200235
return CoercionResult{{}, result};
@@ -229,8 +264,12 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
229264
// back to a final unity anyway
230265
rust_debug ("coerce_borrowed_pointer -- unify");
231266
TyTy::BaseType *result
232-
= unify_site (receiver->get_ref (), TyTy::TyWithLocation (receiver),
233-
TyTy::TyWithLocation (expected), locus);
267+
= unify_site_and (receiver->get_ref (),
268+
TyTy::TyWithLocation (receiver),
269+
TyTy::TyWithLocation (expected), locus,
270+
false /*emit_errors*/, true /*commit_if_ok*/,
271+
false /* FIXME infer do we want to allow this?? */,
272+
true /*cleanup_on_failure*/);
234273
return CoercionResult{{}, result};
235274
}
236275
}

gcc/rust/typecheck/rust-coercion.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class TypeCoercionRules : protected AutoderefCycle
6969

7070
protected:
7171
TypeCoercionRules (TyTy::BaseType *expected, Location locus, bool emit_errors,
72-
bool allow_autoderef);
72+
bool allow_autoderef, bool try_flag);
7373

7474
bool select (TyTy::BaseType &autoderefed) override;
7575

@@ -87,6 +87,7 @@ class TypeCoercionRules : protected AutoderefCycle
8787
// mutable fields
8888
CoercionResult try_result;
8989
bool emit_errors;
90+
bool try_flag;
9091
};
9192

9293
} // namespace Resolver

0 commit comments

Comments
 (0)