Skip to content

Commit be158fc

Browse files
committed
Complete refactor of generic traits handling
From PR #1086 I introduced a new setup_associated_types2 interface which is used to ensure we handle the complex associated types in libcore slices but this interface was inconsistant as well as the get_projected_type. This path refactors the code base to get rid of the old setup_associated_types interface in favour of this new one. It also removes the get_projected_type interface which was not going to work either. Fixes #1105
1 parent 712ae2f commit be158fc

9 files changed

+67
-197
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
5252

5353
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
5454
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (concrete);
55+
fntype->monomorphize ();
5556

5657
// items can be forward compiled which means we may not need to invoke this
5758
// code. We might also have already compiled this generic function as well.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ CompileItem::visit (HIR::Function &function)
127127
{
128128
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
129129
fntype = static_cast<TyTy::FnType *> (concrete);
130+
fntype->monomorphize ();
130131
}
131132
}
132133

gcc/rust/backend/rust-compile-resolve-path.cc

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -251,21 +251,6 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
251251
rust_assert (ok); // found
252252
rust_assert (trait_item_ref->is_optional ()); // has definition
253253

254-
Analysis::NodeMapping trait_mappings
255-
= trait_item_ref->get_parent_trait_mappings ();
256-
257-
HirId associated_impl_id;
258-
ok = ctx->get_tyctx ()->lookup_associated_impl_mapping_for_self (
259-
trait_mappings.get_hirid (), receiver, &associated_impl_id);
260-
rust_assert (ok);
261-
262-
Resolver::AssociatedImplTrait *associated = nullptr;
263-
bool found_associated_trait_impl
264-
= ctx->get_tyctx ()->lookup_associated_trait_impl (
265-
associated_impl_id, &associated);
266-
rust_assert (found_associated_trait_impl);
267-
associated->setup_associated_types ();
268-
269254
return CompileTraitItem::Compile (
270255
trait_item_ref->get_hir_trait_item (), ctx, lookup, true,
271256
expr_locus);

gcc/rust/typecheck/rust-hir-path-probe.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -326,18 +326,6 @@ class PathProbeType : public TypeCheckBase
326326
}
327327

328328
TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
329-
if (impl != nullptr && !is_reciever_generic ())
330-
331-
{
332-
HirId impl_block_id = impl->get_mappings ().get_hirid ();
333-
AssociatedImplTrait *lookup_associated = nullptr;
334-
bool found_impl_trait
335-
= context->lookup_associated_trait_impl (impl_block_id,
336-
&lookup_associated);
337-
// see testsuite/rust/compile/torture/traits10.rs this can be false
338-
if (found_impl_trait)
339-
lookup_associated->setup_associated_types ();
340-
}
341329

342330
// we can substitute the Self with the receiver here
343331
if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)

gcc/rust/typecheck/rust-hir-trait-ref.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -454,18 +454,11 @@ class AssociatedImplTrait
454454

455455
TyTy::BaseType *get_self () { return self; }
456456

457-
void setup_associated_types ();
458-
459-
void setup_associated_types2 (const TyTy::BaseType *self,
460-
const TyTy::TypeBoundPredicate &bound);
457+
void setup_associated_types (const TyTy::BaseType *self,
458+
const TyTy::TypeBoundPredicate &bound);
461459

462460
void reset_associated_types ();
463461

464-
TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref,
465-
TyTy::BaseType *reciever, HirId ref,
466-
HIR::GenericArgs &trait_generics,
467-
Location expr_locus);
468-
469462
private:
470463
TraitReference *trait;
471464
HIR::ImplBlock *impl;

gcc/rust/typecheck/rust-hir-trait-resolve.cc

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -154,29 +154,7 @@ TraitItemReference::associated_type_reset () const
154154
}
155155

156156
void
157-
AssociatedImplTrait::setup_associated_types ()
158-
{
159-
ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) {
160-
TraitItemReference *resolved_trait_item = nullptr;
161-
bool ok = trait->lookup_trait_item (type.get_new_type_name (),
162-
&resolved_trait_item);
163-
if (!ok)
164-
return;
165-
if (resolved_trait_item->get_trait_item_type ()
166-
!= TraitItemReference::TraitItemType::TYPE)
167-
return;
168-
169-
TyTy::BaseType *lookup;
170-
if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
171-
return;
172-
173-
resolved_trait_item->associated_type_set (lookup);
174-
});
175-
iter.go ();
176-
}
177-
178-
void
179-
AssociatedImplTrait::setup_associated_types2 (
157+
AssociatedImplTrait::setup_associated_types (
180158
const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound)
181159
{
182160
// compute the constrained impl block generic arguments based on self and the
@@ -390,46 +368,6 @@ TraitItemReference::is_object_safe () const
390368
return false;
391369
}
392370

393-
TyTy::BaseType *
394-
AssociatedImplTrait::get_projected_type (
395-
const TraitItemReference *trait_item_ref, TyTy::BaseType *receiver, HirId ref,
396-
HIR::GenericArgs &trait_generics, Location expr_locus)
397-
{
398-
TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ()->clone ();
399-
400-
// we can substitute the Self with the receiver here
401-
if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
402-
{
403-
TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
404-
TyTy::SubstitutionParamMapping *param = nullptr;
405-
for (auto &param_mapping : fn->get_substs ())
406-
{
407-
const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
408-
if (type_param.get_type_representation ().compare ("Self") == 0)
409-
{
410-
param = &param_mapping;
411-
break;
412-
}
413-
}
414-
rust_assert (param != nullptr);
415-
416-
std::vector<TyTy::SubstitutionArg> mappings;
417-
mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
418-
419-
TyTy::SubstitutionArgumentMappings args (std::move (mappings),
420-
expr_locus);
421-
trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
422-
}
423-
424-
if (!trait_generics.is_empty ())
425-
{
426-
trait_item_tyty
427-
= SubstMapper::Resolve (trait_item_tyty, expr_locus, &trait_generics);
428-
}
429-
430-
return trait_item_tyty;
431-
}
432-
433371
// rust-hir-path-probe.h
434372

435373
void

gcc/rust/typecheck/rust-hir-type-check-path.cc

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -67,41 +67,41 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
6767
// inherit the bound
6868
root->inherit_bounds ({specified_bound});
6969

70-
// we need resolve to the impl block
71-
NodeId impl_resolved_id = UNKNOWN_NODEID;
72-
bool ok = resolver->lookup_resolved_name (
73-
qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
74-
rust_assert (ok);
75-
76-
HirId impl_block_id;
77-
ok = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
78-
impl_resolved_id, &impl_block_id);
79-
rust_assert (ok);
80-
81-
AssociatedImplTrait *lookup_associated = nullptr;
82-
bool found_impl_trait
83-
= context->lookup_associated_trait_impl (impl_block_id, &lookup_associated);
84-
rust_assert (found_impl_trait);
85-
70+
// lookup the associated item from the specified bound
8671
HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
87-
88-
const TraitItemReference *trait_item_ref = nullptr;
89-
ok = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
90-
&trait_item_ref);
91-
if (!ok)
72+
HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
73+
TyTy::TypeBoundPredicateItem item
74+
= specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
75+
if (item.is_error ())
9276
{
9377
rust_error_at (item_seg.get_locus (), "unknown associated item");
9478
return;
9579
}
9680

97-
HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args ()
98-
? qual_path_type.get_trait_generic_args ()
99-
: HIR::GenericArgs::create_empty ();
81+
// infer the root type
82+
infered = item.get_tyty_for_receiver (root);
10083

101-
lookup_associated->setup_associated_types ();
102-
infered = lookup_associated->get_projected_type (
103-
trait_item_ref, root, item_seg.get_mappings ().get_hirid (), trait_generics,
104-
item_seg.get_locus ());
84+
// we need resolve to the impl block
85+
NodeId impl_resolved_id = UNKNOWN_NODEID;
86+
bool have_associated_impl = resolver->lookup_resolved_name (
87+
qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
88+
AssociatedImplTrait *lookup_associated = nullptr;
89+
if (have_associated_impl)
90+
{
91+
HirId impl_block_id;
92+
bool ok
93+
= mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
94+
impl_resolved_id, &impl_block_id);
95+
rust_assert (ok);
96+
97+
bool found_impl_trait
98+
= context->lookup_associated_trait_impl (impl_block_id,
99+
&lookup_associated);
100+
if (found_impl_trait)
101+
{
102+
lookup_associated->setup_associated_types (root, specified_bound);
103+
}
104+
}
105105

106106
// turbo-fish segment path::<ty>
107107
if (item_seg.has_generic_args ())
@@ -119,6 +119,7 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
119119
}
120120

121121
// continue on as a path-in-expression
122+
const TraitItemReference *trait_item_ref = item.get_raw_item ();
122123
NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
123124
bool fully_resolved = expr.get_segments ().size () <= 1;
124125

@@ -348,20 +349,6 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
348349
HIR::ImplBlock *impl = candidate.item.trait.impl;
349350
if (impl != nullptr)
350351
{
351-
AssociatedImplTrait *lookup_associated = nullptr;
352-
bool found_impl_trait = context->lookup_associated_trait_impl (
353-
impl->get_mappings ().get_hirid (), &lookup_associated);
354-
355-
// setup associated mappings if possible we might be resolving a
356-
// path within a default implementation of a trait function
357-
// see: testsuite/rust/compile/torture/traits16.rs
358-
if (found_impl_trait)
359-
lookup_associated->setup_associated_types ();
360-
361-
// we need a new ty_ref_id for this trait item
362-
tyseg = tyseg->clone ();
363-
tyseg->set_ty_ref (mappings->get_next_hir_id ());
364-
365352
// get the associated impl block
366353
associated_impl_block = impl;
367354
}

gcc/rust/typecheck/rust-hir-type-check-type.cc

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -142,31 +142,35 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
142142
return;
143143
}
144144

145+
// get the predicate for the bound
146+
auto specified_bound
147+
= get_predicate_from_bound (*qual_path_type.get_trait ().get ());
148+
if (specified_bound.is_error ())
149+
return;
150+
151+
// inherit the bound
152+
root->inherit_bounds ({specified_bound});
153+
154+
// lookup the associated item from the specified bound
145155
std::unique_ptr<HIR::TypePathSegment> &item_seg
146156
= path.get_associated_segment ();
147-
const TraitItemReference *trait_item_ref = nullptr;
148-
bool ok
149-
= trait_ref->lookup_trait_item (item_seg->get_ident_segment ().as_string (),
150-
&trait_item_ref);
151-
if (!ok)
157+
HIR::PathIdentSegment item_seg_identifier = item_seg->get_ident_segment ();
158+
TyTy::TypeBoundPredicateItem item
159+
= specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
160+
if (item.is_error ())
152161
{
153162
rust_error_at (item_seg->get_locus (), "unknown associated item");
154163
return;
155164
}
156165

157-
// this will be the placeholder from the trait but we may be able to project
158-
// it based on the impl block
159-
translated = trait_item_ref->get_tyty ();
160-
161-
// this is the associated generics we need to potentially apply
162-
HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args ()
163-
? qual_path_type.get_trait_generic_args ()
164-
: HIR::GenericArgs::create_empty ();
166+
// infer the root type
167+
translated = item.get_tyty_for_receiver (root);
165168

166169
// we need resolve to the impl block
167170
NodeId impl_resolved_id = UNKNOWN_NODEID;
168171
bool have_associated_impl = resolver->lookup_resolved_name (
169172
qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
173+
AssociatedImplTrait *lookup_associated = nullptr;
170174
if (have_associated_impl)
171175
{
172176
HirId impl_block_id;
@@ -175,30 +179,16 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
175179
impl_resolved_id, &impl_block_id);
176180
rust_assert (ok);
177181

178-
AssociatedImplTrait *lookup_associated = nullptr;
179182
bool found_impl_trait
180183
= context->lookup_associated_trait_impl (impl_block_id,
181184
&lookup_associated);
182-
rust_assert (found_impl_trait);
183-
184-
// project
185-
lookup_associated->setup_associated_types ();
186-
translated = lookup_associated->get_projected_type (
187-
trait_item_ref, root, item_seg->get_mappings ().get_hirid (),
188-
trait_generics, item_seg->get_locus ());
189-
}
190-
191-
if (translated->get_kind () == TyTy::TypeKind::PLACEHOLDER)
192-
{
193-
// lets grab the actual projection type
194-
TyTy::PlaceholderType *p
195-
= static_cast<TyTy::PlaceholderType *> (translated);
196-
if (p->can_resolve ())
185+
if (found_impl_trait)
197186
{
198-
translated = p->resolve ();
187+
lookup_associated->setup_associated_types (root, specified_bound);
199188
}
200189
}
201190

191+
// turbo-fish segment path::<ty>
202192
if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
203193
{
204194
HIR::TypePathSegmentGeneric &generic_seg
@@ -222,6 +212,7 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
222212
}
223213

224214
// continue on as a path-in-expression
215+
const TraitItemReference *trait_item_ref = item.get_raw_item ();
225216
NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
226217
bool fully_resolved = path.get_segments ().empty ();
227218
if (fully_resolved)
@@ -448,22 +439,6 @@ TypeCheckType::resolve_segments (
448439
{
449440
resolved_node_id
450441
= candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
451-
452-
// lookup the associated-impl-trait
453-
HIR::ImplBlock *impl = candidate.item.trait.impl;
454-
if (impl != nullptr && !reciever_is_generic)
455-
{
456-
AssociatedImplTrait *lookup_associated = nullptr;
457-
bool found_impl_trait = context->lookup_associated_trait_impl (
458-
impl->get_mappings ().get_hirid (), &lookup_associated);
459-
rust_assert (found_impl_trait);
460-
461-
lookup_associated->setup_associated_types ();
462-
463-
// we need a new ty_ref_id for this trait item
464-
tyseg = tyseg->clone ();
465-
tyseg->set_ty_ref (mappings->get_next_hir_id ());
466-
}
467442
}
468443

469444
if (seg->is_generic_segment ())

0 commit comments

Comments
 (0)