Skip to content

Commit b71cc52

Browse files
bors[bot]philberty
andauthored
Merge #920
920: Support deref_mut lang item during method resolution r=philberty a=philberty This adds in the lookups for the DEREF_MUT lang item for operator overloading this needs more testing to ensure the behaviour is correct and is the same as rustc. Fixes #890 Co-authored-by: Philip Herron <[email protected]>
2 parents 9023bb8 + c0e5ca3 commit b71cc52

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)