Skip to content

Commit c0e5ca3

Browse files
committed
Support deref_mut lang item during method resolution
When we have method resolution we need to look at any deref lang items for the receiver. The precise rules need to be tested rigorously to ensure this is right. Fixes #890
1 parent 9023bb8 commit c0e5ca3

10 files changed

+605
-322
lines changed

gcc/rust/Make-lang.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ GRS_OBJS = \
8989
rust/rust-hir-type-check-type.o \
9090
rust/rust-hir-type-check-struct.o \
9191
rust/rust-hir-type-check-pattern.o \
92+
rust/rust-hir-dot-operator.o \
9293
rust/rust-autoderef.o \
9394
rust/rust-substitution-mapper.o \
9495
rust/rust-lint-marklive.o \

gcc/rust/backend/rust-compile-base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class HIRCompileBase : public HIR::HIRFullVisitorBase
6767
tree resolve_deref_adjustment (Resolver::Adjustment &adjustment,
6868
tree expression, Location locus);
6969

70+
tree resolve_indirection_adjustment (Resolver::Adjustment &adjustment,
71+
tree expression, Location locus);
72+
7073
static void setup_attributes_on_fndecl (
7174
tree fndecl, bool is_main_entry_point, bool has_visibility,
7275
const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs);

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,9 +1199,14 @@ HIRCompileBase::resolve_adjustements (
11991199
e = address_expression (e, locus);
12001200
break;
12011201

1202-
case Resolver::Adjustment::AdjustmentType::DEREF_REF:
1202+
case Resolver::Adjustment::AdjustmentType::DEREF:
1203+
case Resolver::Adjustment::AdjustmentType::DEREF_MUT:
12031204
e = resolve_deref_adjustment (adjustment, e, locus);
12041205
break;
1206+
1207+
case Resolver::Adjustment::AdjustmentType::INDIRECTION:
1208+
e = resolve_indirection_adjustment (adjustment, e, locus);
1209+
break;
12051210
}
12061211
}
12071212

@@ -1212,17 +1217,9 @@ tree
12121217
HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
12131218
tree expression, Location locus)
12141219
{
1215-
rust_assert (adjustment.is_deref_adjustment ());
1216-
1217-
tree expected_type
1218-
= TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
1219-
if (!adjustment.has_operator_overload ())
1220-
{
1221-
return ctx->get_backend ()->indirect_expression (expected_type,
1222-
expression,
1223-
true, /* known_valid*/
1224-
locus);
1225-
}
1220+
rust_assert (adjustment.is_deref_adjustment ()
1221+
|| adjustment.is_deref_mut_adjustment ());
1222+
rust_assert (adjustment.has_operator_overload ());
12261223

12271224
TyTy::FnType *lookup = adjustment.get_deref_operator_fn ();
12281225
HIR::ImplItem *resolved_item = adjustment.get_deref_hir_item ();
@@ -1246,13 +1243,19 @@ HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
12461243

12471244
// make the call
12481245
auto fncontext = ctx->peek_fn ();
1249-
tree deref_call
1250-
= ctx->get_backend ()->call_expression (fncontext.fndecl, fn_address,
1251-
{adjusted_argument}, nullptr,
1252-
locus);
1246+
return ctx->get_backend ()->call_expression (fncontext.fndecl, fn_address,
1247+
{adjusted_argument}, nullptr,
1248+
locus);
1249+
}
1250+
1251+
tree
1252+
HIRCompileBase::resolve_indirection_adjustment (
1253+
Resolver::Adjustment &adjustment, tree expression, Location locus)
1254+
{
1255+
tree expected_type
1256+
= TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
12531257

1254-
// do the indirect expression
1255-
return ctx->get_backend ()->indirect_expression (expected_type, deref_call,
1258+
return ctx->get_backend ()->indirect_expression (expected_type, expression,
12561259
true, /* known_valid*/
12571260
locus);
12581261
}

gcc/rust/typecheck/rust-autoderef.cc

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "rust-autoderef.h"
2020
#include "rust-hir-path-probe.h"
2121
#include "rust-hir-dot-operator.h"
22+
#include "rust-hir-trait-resolve.h"
2223

2324
namespace Rust {
2425
namespace Resolver {
@@ -29,26 +30,6 @@ resolve_operator_overload_fn (
2930
TyTy::FnType **resolved_fn, HIR::ImplItem **impl_item,
3031
Adjustment::AdjustmentType *requires_ref_adjustment);
3132

32-
bool
33-
Adjuster::needs_address (const std::vector<Adjustment> &adjustments)
34-
{
35-
for (auto &adjustment : adjustments)
36-
{
37-
switch (adjustment.get_type ())
38-
{
39-
case Adjustment::AdjustmentType::IMM_REF:
40-
case Adjustment::AdjustmentType::MUT_REF:
41-
case Adjustment::AdjustmentType::DEREF_REF:
42-
return true;
43-
44-
default:
45-
break;
46-
}
47-
}
48-
49-
return false;
50-
}
51-
5233
TyTy::BaseType *
5334
Adjuster::adjust_type (const std::vector<Adjustment> &adjustments)
5435
{
@@ -59,36 +40,64 @@ Adjuster::adjust_type (const std::vector<Adjustment> &adjustments)
5940
}
6041

6142
Adjustment
62-
Adjuster::try_deref_type (const TyTy::BaseType *ty)
43+
Adjuster::try_deref_type (const TyTy::BaseType *ty,
44+
Analysis::RustLangItem::ItemType deref_lang_item)
6345
{
64-
// probe for the lang-item
65-
TyTy::BaseType *resolved_base = ty->clone ();
66-
6746
HIR::ImplItem *impl_item = nullptr;
6847
TyTy::FnType *fn = nullptr;
6948
Adjustment::AdjustmentType requires_ref_adjustment
7049
= Adjustment::AdjustmentType::ERROR;
7150
bool operator_overloaded
72-
= resolve_operator_overload_fn (Analysis::RustLangItem::ItemType::DEREF, ty,
73-
&fn, &impl_item, &requires_ref_adjustment);
74-
if (operator_overloaded)
51+
= resolve_operator_overload_fn (deref_lang_item, ty, &fn, &impl_item,
52+
&requires_ref_adjustment);
53+
if (!operator_overloaded)
7554
{
76-
resolved_base = fn->get_return_type ()->clone ();
55+
return Adjustment::get_error ();
7756
}
7857

58+
auto resolved_base = fn->get_return_type ()->clone ();
7959
bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF;
8060
if (!is_valid_type)
8161
return Adjustment::get_error ();
8262

8363
TyTy::ReferenceType *ref_base
8464
= static_cast<TyTy::ReferenceType *> (resolved_base);
8565

86-
auto infered = ref_base->get_base ()->clone ();
66+
Adjustment::AdjustmentType adjustment_type
67+
= Adjustment::AdjustmentType::ERROR;
68+
switch (deref_lang_item)
69+
{
70+
case Analysis::RustLangItem::ItemType::DEREF:
71+
adjustment_type = Adjustment::AdjustmentType::DEREF;
72+
break;
8773

88-
return Adjustment::get_op_overload_deref_adjustment (infered, fn, impl_item,
74+
case Analysis::RustLangItem::ItemType::DEREF_MUT:
75+
adjustment_type = Adjustment::AdjustmentType::DEREF_MUT;
76+
break;
77+
78+
default:
79+
break;
80+
}
81+
82+
return Adjustment::get_op_overload_deref_adjustment (adjustment_type,
83+
ref_base, fn, impl_item,
8984
requires_ref_adjustment);
9085
}
9186

87+
Adjustment
88+
Adjuster::try_raw_deref_type (const TyTy::BaseType *ty)
89+
{
90+
bool is_valid_type = ty->get_kind () == TyTy::TypeKind::REF;
91+
if (!is_valid_type)
92+
return Adjustment::get_error ();
93+
94+
const TyTy::ReferenceType *ref_base
95+
= static_cast<const TyTy::ReferenceType *> (ty);
96+
auto infered = ref_base->get_base ()->clone ();
97+
98+
return Adjustment (Adjustment::AdjustmentType::INDIRECTION, infered);
99+
}
100+
92101
static bool
93102
resolve_operator_overload_fn (
94103
Analysis::RustLangItem::ItemType lang_item_type, const TyTy::BaseType *ty,

gcc/rust/typecheck/rust-autoderef.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class Adjustment
3333

3434
IMM_REF,
3535
MUT_REF,
36-
DEREF_REF
36+
DEREF,
37+
DEREF_MUT,
38+
INDIRECTION,
3739
};
3840

3941
// ctor for all adjustments except derefs
@@ -42,11 +44,12 @@ class Adjustment
4244
{}
4345

4446
static Adjustment get_op_overload_deref_adjustment (
45-
const TyTy::BaseType *expected, TyTy::FnType *fn, HIR::ImplItem *deref_item,
47+
AdjustmentType type, const TyTy::BaseType *expected, TyTy::FnType *fn,
48+
HIR::ImplItem *deref_item,
4649
Adjustment::AdjustmentType requires_ref_adjustment)
4750
{
48-
return Adjustment (Adjustment::DEREF_REF, expected, fn, deref_item,
49-
requires_ref_adjustment);
51+
rust_assert (type == DEREF || type == DEREF_MUT);
52+
return Adjustment (type, expected, fn, deref_item, requires_ref_adjustment);
5053
}
5154

5255
AdjustmentType get_type () const { return type; }
@@ -69,8 +72,12 @@ class Adjustment
6972
return "IMM_REF";
7073
case AdjustmentType::MUT_REF:
7174
return "MUT_REF";
72-
case AdjustmentType::DEREF_REF:
73-
return "DEREF_REF";
75+
case AdjustmentType::DEREF:
76+
return "DEREF";
77+
case AdjustmentType::DEREF_MUT:
78+
return "DEREF_MUT";
79+
case AdjustmentType::INDIRECTION:
80+
return "INDIRECTION";
7481
}
7582
gcc_unreachable ();
7683
return "";
@@ -80,7 +87,9 @@ class Adjustment
8087

8188
bool is_error () const { return type == ERROR; }
8289

83-
bool is_deref_adjustment () const { return type == DEREF_REF; }
90+
bool is_deref_adjustment () const { return type == DEREF; }
91+
92+
bool is_deref_mut_adjustment () const { return type == DEREF_MUT; }
8493

8594
bool has_operator_overload () const { return deref_operator_fn != nullptr; }
8695

@@ -120,9 +129,11 @@ class Adjuster
120129

121130
TyTy::BaseType *adjust_type (const std::vector<Adjustment> &adjustments);
122131

123-
static bool needs_address (const std::vector<Adjustment> &adjustments);
132+
static Adjustment
133+
try_deref_type (const TyTy::BaseType *ty,
134+
Analysis::RustLangItem::ItemType deref_lang_item);
124135

125-
static Adjustment try_deref_type (const TyTy::BaseType *ty);
136+
static Adjustment try_raw_deref_type (const TyTy::BaseType *ty);
126137

127138
private:
128139
const TyTy::BaseType *base;

0 commit comments

Comments
 (0)