aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/ast/rust-item.h11
-rw-r--r--gcc/rust/ast/rust-path.h9
-rw-r--r--gcc/rust/backend/rust-compile-context.h5
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h29
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc56
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h38
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h74
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc53
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h22
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc14
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h30
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h30
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc225
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h74
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc39
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h2
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h45
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h13
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h5
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc106
-rw-r--r--gcc/rust/typecheck/rust-tyty.h61
-rw-r--r--gcc/testsuite/rust/compile/torture/traits12.rs29
-rw-r--r--gcc/testsuite/rust/compile/torture/traits13.rs17
-rw-r--r--gcc/testsuite/rust/compile/torture/traits14.rs23
-rw-r--r--gcc/testsuite/rust/compile/torture/traits15.rs23
30 files changed, 915 insertions, 170 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 9c69b44..64b9247 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -83,6 +83,7 @@ GRS_OBJS = \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
rust/rust-hir-const-fold.o \
+ rust/rust-hir-type-check-type.o \
rust/rust-lint-marklive.o \
rust/rust-hir-type-check-path.o \
$(END)
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index dcfc3d1..0578329 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -3535,7 +3535,16 @@ public:
void insert_implict_self (std::unique_ptr<AST::GenericParam> &&param)
{
- generic_params.push_back (std::move (param));
+ std::vector<std::unique_ptr<GenericParam>> new_list;
+ new_list.reserve (generic_params.size () + 1);
+
+ new_list.push_back (std::move (param));
+ for (auto &p : generic_params)
+ {
+ new_list.push_back (std::move (p));
+ }
+
+ generic_params = std::move (new_list);
}
protected:
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 6ccd3a0..8992993 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -1029,6 +1029,15 @@ public:
}
Location get_locus () const override final { return locus; }
+
+ void iterate_segments (std::function<bool (TypePathSegment *)> cb)
+ {
+ for (auto it = segments.begin (); it != segments.end (); it++)
+ {
+ if (!cb ((*it).get ()))
+ return;
+ }
+ }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 66d037d..bffe97c 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -336,7 +336,10 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &type) override
+ {
+ type.get ()->accept_vis (*this);
+ }
void visit (TyTy::PlaceholderType &type) override
{
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index c16025d..464045a 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -28,6 +28,7 @@ namespace HIR {
class ASTLowerTypePath : public ASTLoweringBase
{
+protected:
using Rust::HIR::ASTLoweringBase::visit;
public:
@@ -88,9 +89,30 @@ public:
mappings->insert_hir_type (crate_num, hirid, translated);
}
+protected:
+ HIR::TypePathSegment *translated_segment;
+
private:
HIR::TypePath *translated;
- HIR::TypePathSegment *translated_segment;
+};
+
+class ASTLowerQualifiedPathInType : public ASTLowerTypePath
+{
+ using ASTLowerTypePath::visit;
+
+public:
+ static HIR::QualifiedPathInType *translate (AST::QualifiedPathInType &type)
+ {
+ ASTLowerQualifiedPathInType resolver;
+ type.accept_vis (resolver);
+ rust_assert (resolver.translated != nullptr);
+ return resolver.translated;
+ }
+
+ void visit (AST::QualifiedPathInType &path) override;
+
+private:
+ HIR::QualifiedPathInType *translated;
};
class ASTLoweringType : public ASTLoweringBase
@@ -187,6 +209,11 @@ public:
translated = ASTLowerTypePath::translate (path);
}
+ void visit (AST::QualifiedPathInType &path) override
+ {
+ translated = ASTLowerQualifiedPathInType::translate (path);
+ }
+
void visit (AST::ArrayType &type) override
{
HIR::Type *translated_type
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index d5138fd..e8784b6 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -450,6 +450,62 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
segment.get_locus ());
}
+void
+ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
+{
+ auto crate_num = mappings->get_current_crate ();
+ auto hirid = mappings->get_next_hir_id (crate_num);
+ Analysis::NodeMapping qual_mappings (
+ crate_num, path.get_qualified_path_type ().get_node_id (), hirid,
+ UNKNOWN_LOCAL_DEFID);
+
+ HIR::Type *qual_type = ASTLoweringType::translate (
+ path.get_qualified_path_type ().get_type ().get ());
+ HIR::TypePath *qual_trait = ASTLowerTypePath::translate (
+ path.get_qualified_path_type ().get_as_type_path ());
+
+ HIR::QualifiedPathType qual_path_type (
+ qual_mappings, std::unique_ptr<HIR::Type> (qual_type),
+ std::unique_ptr<HIR::TypePath> (qual_trait),
+ path.get_qualified_path_type ().get_locus ());
+
+ translated_segment = nullptr;
+ path.get_associated_segment ()->accept_vis (*this);
+ if (translated_segment == nullptr)
+ {
+ rust_fatal_error (path.get_associated_segment ()->get_locus (),
+ "failed to translate AST TypePathSegment");
+ return;
+ }
+ std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment);
+
+ std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments;
+ path.iterate_segments ([&] (AST::TypePathSegment *seg) mutable -> bool {
+ translated_segment = nullptr;
+ seg->accept_vis (*this);
+ if (translated_segment == nullptr)
+ {
+ rust_fatal_error (seg->get_locus (),
+ "failed to translate AST TypePathSegment");
+ return false;
+ }
+
+ translated_segments.push_back (
+ std::unique_ptr<HIR::TypePathSegment> (translated_segment));
+ return true;
+ });
+
+ Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::QualifiedPathInType (std::move (mapping),
+ std::move (qual_path_type),
+ std::move (associated_segment),
+ std::move (translated_segments),
+ path.get_locus ());
+ mappings->insert_hir_type (crate_num, hirid, translated);
+}
+
// rust-ast-lower-base
HIR::Type *
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 0e3c430..13e246f 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -767,6 +767,27 @@ public:
rust_assert (has_as_clause ());
return trait;
}
+
+ bool trait_has_generic_args () const
+ {
+ rust_assert (has_as_clause ());
+ bool is_generic_seg = trait->get_final_segment ()->get_type ()
+ == TypePathSegment::SegmentType::GENERIC;
+ if (!is_generic_seg)
+ return false;
+
+ TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
+ trait->get_final_segment ().get ());
+ return seg->has_generic_args ();
+ }
+
+ GenericArgs &get_trait_generic_args ()
+ {
+ rust_assert (trait_has_generic_args ());
+ TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
+ trait->get_final_segment ().get ());
+ return seg->get_generic_args ();
+ }
};
/* HIR node representing a qualified path-in-expression pattern (path that
@@ -819,6 +840,7 @@ protected:
class QualifiedPathInType : public TypeNoBounds
{
QualifiedPathType path_type;
+ std::unique_ptr<TypePathSegment> associated_segment;
std::vector<std::unique_ptr<TypePathSegment> > segments;
Location locus;
@@ -840,9 +862,11 @@ protected:
public:
QualifiedPathInType (
Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
+ std::unique_ptr<TypePathSegment> associated_segment,
std::vector<std::unique_ptr<TypePathSegment> > path_segments,
Location locus = Location ())
: TypeNoBounds (mappings), path_type (std::move (qual_path_type)),
+ associated_segment (std::move (associated_segment)),
segments (std::move (path_segments)), locus (locus)
{}
@@ -883,6 +907,20 @@ public:
std::string as_string () const override;
void accept_vis (HIRVisitor &vis) override;
+
+ QualifiedPathType &get_path_type () { return path_type; }
+
+ std::unique_ptr<TypePathSegment> &get_associated_segment ()
+ {
+ return associated_segment;
+ }
+
+ std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+ {
+ return segments;
+ }
+
+ Location get_locus () { return locus; }
};
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 97c0311..9ad465a 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -97,6 +97,7 @@ public:
class ResolveTypeToCanonicalPath : public ResolverBase
{
+protected:
using Rust::Resolver::ResolverBase::visit;
public:
@@ -128,7 +129,7 @@ public:
static bool type_resolve_generic_args (AST::GenericArgs &args);
-private:
+protected:
ResolveTypeToCanonicalPath (bool include_generic_args,
bool type_resolve_generic_args)
: ResolverBase (UNKNOWN_NODEID), result (CanonicalPath::create_empty ()),
@@ -182,8 +183,10 @@ public:
}
};
-class ResolveRelativeTypePath
+class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath
{
+ using ResolveTypeToCanonicalPath::visit;
+
public:
static NodeId go (AST::TypePath &path, NodeId parent,
const CanonicalPath &prefix,
@@ -218,6 +221,64 @@ public:
return resolved_node;
}
+
+ static NodeId go (AST::QualifiedPathInType &path, NodeId parent,
+ const CanonicalPath &prefix,
+ bool canonicalize_type_with_generics)
+ {
+ auto &qualified_path = path.get_qualified_path_type ();
+ CanonicalPath result = prefix;
+ if (!resolve_qual_seg (qualified_path, result))
+ return UNKNOWN_NODEID;
+
+ // resolve the associated impl
+ auto resolver = Resolver::get ();
+ NodeId projection_resolved_id = UNKNOWN_NODEID;
+ if (!resolver->get_name_scope ().lookup (result, &projection_resolved_id))
+ {
+ rust_error_at (path.get_locus (),
+ "failed to resolve associated path: %s",
+ result.get ().c_str ());
+
+ return UNKNOWN_NODEID;
+ }
+ // mark the resolution for this
+ resolver->insert_resolved_name (qualified_path.get_node_id (),
+ projection_resolved_id);
+
+ // qualified types are similar to other paths in that we cannot guarantee
+ // that we can resolve the path at name resolution. We must look up
+ // associated types and type information to figure this out properly
+
+ ResolveRelativeTypePath o (result);
+ std::unique_ptr<AST::TypePathSegment> &associated
+ = path.get_associated_segment ();
+
+ associated->accept_vis (o);
+ if (o.failure_flag)
+ return UNKNOWN_NODEID;
+
+ for (auto &seg : path.get_segments ())
+ {
+ seg->accept_vis (o);
+ if (o.failure_flag)
+ return UNKNOWN_NODEID;
+ }
+
+ // we only return the projection id for now since we need the type system to
+ // resolve the associated types in this path
+ return projection_resolved_id;
+ }
+
+private:
+ ResolveRelativeTypePath (CanonicalPath qualified_path)
+ : ResolveTypeToCanonicalPath (true, true)
+ {
+ result = qualified_path;
+ }
+
+ static bool resolve_qual_seg (AST::QualifiedPathType &seg,
+ CanonicalPath &result);
};
class ResolveType : public ResolverBase
@@ -275,6 +336,15 @@ public:
}
}
+ void visit (AST::QualifiedPathInType &path) override
+ {
+ resolved_node
+ = ResolveRelativeTypePath::go (path, parent,
+ CanonicalPath::create_empty (),
+ canonicalize_type_with_generics);
+ ok = resolved_node != UNKNOWN_NODEID;
+ }
+
void visit (AST::ArrayType &type) override;
void visit (AST::ReferenceType &type) override
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 9d79b36..fab70b5 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -243,8 +243,8 @@ Resolver::lookup_resolved_name (NodeId refId, NodeId *defId)
void
Resolver::insert_resolved_type (NodeId refId, NodeId defId)
{
- auto it = resolved_types.find (refId);
- rust_assert (it == resolved_types.end ());
+ // auto it = resolved_types.find (refId);
+ // rust_assert (it == resolved_types.end ());
resolved_types[refId] = defId;
get_type_scope ().append_reference_for_def (refId, defId);
@@ -560,17 +560,15 @@ ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr)
ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (),
canonicalize_type_with_generics);
- bool canonicalize_type_args = true;
bool type_resolve_generic_args = true;
-
CanonicalPath impl_type_seg
= ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (),
- canonicalize_type_args,
+ canonicalize_type_with_generics,
type_resolve_generic_args);
CanonicalPath trait_type_seg
= ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (),
- canonicalize_type_args,
+ canonicalize_type_with_generics,
type_resolve_generic_args);
CanonicalPath root_seg_path
= TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg,
@@ -744,5 +742,48 @@ ResolveItem::resolve_extern_item (AST::ExternalItem *item)
ResolveExternItem::go (item);
}
+// qualified path in type
+
+bool
+ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg,
+ CanonicalPath &result)
+{
+ if (seg.is_error ())
+ {
+ rust_error_at (seg.get_locus (), "segment has error: %s",
+ seg.as_string ().c_str ());
+ return false;
+ }
+ bool include_generic_args_in_path = false;
+
+ NodeId type_resolved_node
+ = ResolveType::go (seg.get_type ().get (), seg.get_node_id ());
+ if (type_resolved_node == UNKNOWN_NODEID)
+ return false;
+
+ CanonicalPath impl_type_seg
+ = ResolveTypeToCanonicalPath::resolve (*seg.get_type ().get (),
+ include_generic_args_in_path);
+ if (!seg.has_as_clause ())
+ {
+ result = result.append (impl_type_seg);
+ return true;
+ }
+
+ NodeId trait_resolved_node
+ = ResolveType::go (&seg.get_as_type_path (), seg.get_node_id ());
+ if (trait_resolved_node == UNKNOWN_NODEID)
+ return false;
+
+ CanonicalPath trait_type_seg
+ = ResolveTypeToCanonicalPath::resolve (seg.get_as_type_path (),
+ include_generic_args_in_path);
+ CanonicalPath projection
+ = TraitImplProjection::resolve (seg.get_node_id (), trait_type_seg,
+ impl_type_seg);
+ result = result.append (projection);
+ return true;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 60cd98a..dd51f83 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -276,6 +276,18 @@ protected:
TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
+ if (impl != nullptr)
+ {
+ HirId impl_block_id = impl->get_mappings ().get_hirid ();
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &lookup_associated);
+ // see testsuite/rust/compile/torture/traits10.rs this can be false
+ if (found_impl_trait)
+ lookup_associated->setup_associated_types ();
+ }
+
// we can substitute the Self with the receiver here
if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
{
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index c86892e..f05ff0c 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -47,26 +47,7 @@ public:
TraitItemReference (TraitItemReference const &other);
- TraitItemReference &operator= (TraitItemReference const &other)
- {
- identifier = other.identifier;
- optional_flag = other.optional_flag;
- type = other.type;
- hir_trait_item = other.hir_trait_item;
- self = other.self;
- locus = other.locus;
- context = other.context;
-
- inherited_substitutions.clear ();
- inherited_substitutions.reserve (other.inherited_substitutions.size ());
- for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
- inherited_substitutions.push_back (other.inherited_substitutions.at (i));
-
- return *this;
- }
-
- TraitItemReference (TraitItemReference &&other) = default;
- TraitItemReference &operator= (TraitItemReference &&other) = default;
+ TraitItemReference &operator= (TraitItemReference const &other);
static TraitItemReference error ()
{
@@ -368,6 +349,7 @@ public:
TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref,
TyTy::BaseType *reciever, HirId ref,
+ HIR::GenericArgs &trait_generics,
Location expr_locus);
private:
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index aeedf7e..be58840 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -58,7 +58,7 @@ ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
resolved = TraitItemReference (identifier, is_optional,
TraitItemReference::TraitItemType::FN, &fn,
- self, substitutions, locus);
+ self, std::move (substitutions), locus);
}
// TraitItemReference items
@@ -196,7 +196,7 @@ TraitItemReference::get_parent_trait_mappings () const
TyTy::BaseType *
AssociatedImplTrait::get_projected_type (
const TraitItemReference *trait_item_ref, TyTy::BaseType *receiver, HirId ref,
- Location expr_locus)
+ HIR::GenericArgs &trait_generics, Location expr_locus)
{
TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ()->clone ();
@@ -219,11 +219,17 @@ AssociatedImplTrait::get_projected_type (
std::vector<TyTy::SubstitutionArg> mappings;
mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
- Location locus; // FIXME
- TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus);
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings),
+ expr_locus);
trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
}
+ if (!trait_generics.is_empty ())
+ {
+ trait_item_tyty
+ = SubstMapper::Resolve (trait_item_tyty, expr_locus, &trait_generics);
+ }
+
return trait_item_tyty;
}
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 0fe2406..365994f 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -37,9 +37,9 @@ public:
Resolve (HIR::TraitItem &item, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions)
{
- ResolveTraitItemToRef resolver (self, substitutions);
+ ResolveTraitItemToRef resolver (self, std::move (substitutions));
item.accept_vis (resolver);
- return resolver.resolved;
+ return std::move (resolver.resolved);
}
void visit (HIR::TraitItemType &type) override;
@@ -51,9 +51,9 @@ public:
private:
ResolveTraitItemToRef (
TyTy::BaseType *self,
- std::vector<TyTy::SubstitutionParamMapping> substitutions)
+ std::vector<TyTy::SubstitutionParamMapping> &&substitutions)
: TypeCheckBase (), resolved (TraitItemReference::error ()), self (self),
- substitutions (substitutions)
+ substitutions (std::move (substitutions))
{}
TraitItemReference resolved;
@@ -146,8 +146,14 @@ private:
std::vector<TraitItemReference> item_refs;
for (auto &item : trait_reference->get_trait_items ())
{
+ // make a copy of the substs
+ std::vector<TyTy::SubstitutionParamMapping> item_subst;
+ for (auto &sub : substitutions)
+ item_subst.push_back (sub.clone ());
+
TraitItemReference trait_item_ref
- = ResolveTraitItemToRef::Resolve (*item.get (), self, substitutions);
+ = ResolveTraitItemToRef::Resolve (*item.get (), self,
+ std::move (item_subst));
item_refs.push_back (std::move (trait_item_ref));
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 3d83523..59ea4ef 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -303,11 +303,12 @@ class TypeCheckImplItemWithTrait : public TypeCheckImplItem
using Rust::Resolver::TypeCheckBase::visit;
public:
- static const TraitItemReference &Resolve (HIR::ImplItem *item,
- TyTy::BaseType *self,
- TraitReference &trait_reference)
+ static const TraitItemReference &
+ Resolve (HIR::ImplItem *item, TyTy::BaseType *self,
+ TraitReference &trait_reference,
+ std::vector<TyTy::SubstitutionParamMapping> substitutions)
{
- TypeCheckImplItemWithTrait resolver (self, trait_reference);
+ TypeCheckImplItemWithTrait resolver (self, trait_reference, substitutions);
item->accept_vis (resolver);
return resolver.resolved_trait_item;
}
@@ -383,7 +384,17 @@ public:
trait_reference.get_name ().c_str ());
}
- resolved_trait_item.associated_type_set (lookup);
+ rust_debug_loc (type.get_locus (), "type-alias within impl block");
+ lookup->debug ();
+
+ // its actually a projection, since we need a way to actually bind the
+ // generic substitutions to the type itself
+ TyTy::ProjectionType *projection = new TyTy::ProjectionType (
+ type.get_mappings ().get_hirid (), lookup, &trait_reference,
+ resolved_trait_item.get_mappings ().get_defid (), substitutions);
+
+ context->insert_type (type.get_mappings (), projection);
+ resolved_trait_item.associated_type_set (projection);
}
void visit (HIR::Function &function) override
@@ -452,10 +463,12 @@ public:
}
private:
- TypeCheckImplItemWithTrait (TyTy::BaseType *self,
- TraitReference &trait_reference)
+ TypeCheckImplItemWithTrait (
+ TyTy::BaseType *self, TraitReference &trait_reference,
+ std::vector<TyTy::SubstitutionParamMapping> substitutions)
: TypeCheckImplItem (self), trait_reference (trait_reference),
- resolved_trait_item (TraitItemReference::error_node ())
+ resolved_trait_item (TraitItemReference::error_node ()),
+ substitutions (substitutions)
{
rust_assert (is_trait_impl_block ());
}
@@ -464,6 +477,7 @@ private:
TraitReference &trait_reference;
TraitItemReference &resolved_trait_item;
+ std::vector<TyTy::SubstitutionParamMapping> substitutions;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index ab32f57..476a961 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -43,6 +43,33 @@ public:
void visit (HIR::ImplBlock &impl_block) override
{
+ std::vector<TyTy::SubstitutionParamMapping> substitutions;
+ if (impl_block.has_generics ())
+ {
+ for (auto &generic_param : impl_block.get_generic_params ())
+ {
+ switch (generic_param.get ()->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ // Skipping Lifetime completely until better handling.
+ break;
+
+ case HIR::GenericParam::GenericKind::TYPE: {
+ TyTy::BaseType *l = nullptr;
+ bool ok = context->lookup_type (
+ generic_param->get_mappings ().get_hirid (), &l);
+ if (ok && l->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ substitutions.push_back (TyTy::SubstitutionParamMapping (
+ static_cast<HIR::TypeParam &> (*generic_param),
+ static_cast<TyTy::ParamType *> (l)));
+ }
+ }
+ break;
+ }
+ }
+ }
+
TraitReference *trait_reference = &TraitReference::error_node ();
if (impl_block.has_trait_ref ())
{
@@ -72,7 +99,8 @@ public:
{
auto &trait_item_ref
= TypeCheckImplItemWithTrait::Resolve (impl_item.get (), self,
- *trait_reference);
+ *trait_reference,
+ substitutions);
trait_item_refs.push_back (trait_item_ref);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 7b0e8ae..8b53e44 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -74,7 +74,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
= context->lookup_associated_trait_impl (impl_block_id, &lookup_associated);
rust_assert (found_impl_trait);
- DefId resolved_item_id = UNKNOWN_DEFID;
HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
const TraitItemReference *trait_item_ref = nullptr;
@@ -85,10 +84,14 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
rust_error_at (item_seg.get_locus (), "unknown associated item");
return;
}
- resolved_item_id = trait_item_ref->get_mappings ().get_defid ();
+ HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args ()
+ ? qual_path_type.get_trait_generic_args ()
+ : HIR::GenericArgs::create_empty ();
+
+ lookup_associated->setup_associated_types ();
infered = lookup_associated->get_projected_type (
- trait_item_ref, root, item_seg.get_mappings ().get_hirid (),
+ trait_item_ref, root, item_seg.get_mappings ().get_hirid (), trait_generics,
item_seg.get_locus ());
// turbo-fish segment path::<ty>
@@ -106,12 +109,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
&item_seg.get_generic_args ());
}
- TyTy::ProjectionType *projection
- = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
- TyTy::TyVar (root->get_ref ()), trait_ref,
- resolved_item_id, lookup_associated);
- context->insert_type (qual_path_type.get_mappings (), projection);
-
// continue on as a path-in-expression
NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
bool fully_resolved = expr.get_segments ().size () <= 1;
@@ -340,6 +337,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
candidates
= PathProbeType::Probe (prev_segment, seg.get_segment (), false,
probe_bounds, ignore_mandatory_trait_items);
+
if (candidates.size () == 0)
{
rust_error_at (
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
new file mode 100644
index 0000000..b54a403
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -0,0 +1,225 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check-type.h"
+#include "rust-hir-trait-resolve.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+TypeCheckType::visit (HIR::TypePath &path)
+{
+ // lookup the Node this resolves to
+ NodeId ref;
+ auto nid = path.get_mappings ().get_nodeid ();
+ if (!resolver->lookup_resolved_type (nid, &ref))
+ {
+ rust_fatal_error (path.get_locus (), "failed to resolve node '%d' to HIR",
+ nid);
+ return;
+ }
+
+ HirId hir_lookup;
+ if (!context->lookup_type_by_node_id (ref, &hir_lookup))
+ {
+ rust_error_at (path.get_locus (), "failed to lookup HIR %d for node '%s'",
+ ref, path.as_string ().c_str ());
+ return;
+ }
+
+ TyTy::BaseType *lookup = nullptr;
+ if (!context->lookup_type (hir_lookup, &lookup))
+ {
+ rust_error_at (path.get_locus (), "failed to lookup HIR TyTy");
+ return;
+ }
+
+ TyTy::BaseType *path_type = lookup->clone ();
+ path_type->set_ref (path.get_mappings ().get_hirid ());
+
+ HIR::TypePathSegment *final_seg = path.get_final_segment ().get ();
+ HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg);
+
+ bool is_big_self = final_seg->is_ident_only ()
+ && (final_seg->as_string ().compare ("Self") == 0);
+
+ if (path_type->needs_generic_substitutions ())
+ {
+ if (is_big_self)
+ {
+ translated = path_type;
+ return;
+ }
+
+ translated = SubstMapper::Resolve (path_type, path.get_locus (), &args);
+ if (translated->get_kind () != TyTy::TypeKind::ERROR
+ && mappings != nullptr)
+ {
+ check_for_unconstrained (args.get_type_args ());
+ }
+ }
+ else if (!args.is_empty ())
+ {
+ rust_error_at (path.get_locus (),
+ "TypePath %s declares generic arguments but "
+ "the type %s does not have any",
+ path.as_string ().c_str (),
+ translated->as_string ().c_str ());
+ }
+ else
+ {
+ translated = path_type;
+ }
+}
+
+void
+TypeCheckType::visit (HIR::QualifiedPathInType &path)
+{
+ HIR::QualifiedPathType qual_path_type = path.get_path_type ();
+ TyTy::BaseType *root
+ = TypeCheckType::Resolve (qual_path_type.get_type ().get ());
+ if (root->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_debug_loc (path.get_locus (), "failed to resolve the root");
+ return;
+ }
+
+ if (!qual_path_type.has_as_clause ())
+ {
+ // then this is just a normal path-in-expression
+ NodeId root_resolved_node_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_type (
+ qual_path_type.get_type ()->get_mappings ().get_nodeid (),
+ &root_resolved_node_id);
+ rust_assert (ok);
+
+ resolve_segments (root_resolved_node_id, path.get_segments (), 0,
+ translated, path.get_mappings (), path.get_locus ());
+ }
+
+ // Resolve the trait now
+ TraitReference *trait_ref
+ = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
+ if (trait_ref->is_error ())
+ return;
+
+ // does this type actually implement this type-bound?
+ if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
+ return;
+
+ // we need resolve to the impl block
+ NodeId impl_resolved_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_name (
+ qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
+ rust_assert (ok);
+
+ HirId impl_block_id;
+ ok = mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (),
+ impl_resolved_id, &impl_block_id);
+ rust_assert (ok);
+
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id, &lookup_associated);
+ rust_assert (found_impl_trait);
+
+ std::unique_ptr<HIR::TypePathSegment> &item_seg
+ = path.get_associated_segment ();
+
+ const TraitItemReference *trait_item_ref = nullptr;
+ ok
+ = trait_ref->lookup_trait_item (item_seg->get_ident_segment ().as_string (),
+ &trait_item_ref);
+ if (!ok)
+ {
+ rust_error_at (item_seg->get_locus (), "unknown associated item");
+ return;
+ }
+
+ // project
+ lookup_associated->setup_associated_types ();
+
+ HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args ()
+ ? qual_path_type.get_trait_generic_args ()
+ : HIR::GenericArgs::create_empty ();
+
+ translated = lookup_associated->get_projected_type (
+ trait_item_ref, root, item_seg->get_mappings ().get_hirid (),
+ trait_generics, item_seg->get_locus ());
+
+ if (translated->get_kind () == TyTy::TypeKind::PLACEHOLDER)
+ {
+ // lets grab the actual projection type
+ TyTy::PlaceholderType *p
+ = static_cast<TyTy::PlaceholderType *> (translated);
+ if (p->can_resolve ())
+ {
+ translated = p->resolve ();
+ }
+ }
+
+ if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
+ {
+ HIR::TypePathSegmentGeneric &generic_seg
+ = static_cast<HIR::TypePathSegmentGeneric &> (*item_seg.get ());
+
+ // turbo-fish segment path::<ty>
+ if (generic_seg.has_generic_args ())
+ {
+ if (!translated->can_substitute ())
+ {
+ rust_error_at (item_seg->get_locus (),
+ "substitutions not supported for %s",
+ translated->as_string ().c_str ());
+ translated
+ = new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ return;
+ }
+ translated = SubstMapper::Resolve (translated, path.get_locus (),
+ &generic_seg.get_generic_args ());
+ }
+ }
+
+ // continue on as a path-in-expression
+ NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
+ bool fully_resolved = path.get_segments ().empty ();
+ if (fully_resolved)
+ {
+ resolver->insert_resolved_name (path.get_mappings ().get_nodeid (),
+ root_resolved_node_id);
+ context->insert_receiver (path.get_mappings ().get_hirid (), root);
+ return;
+ }
+
+ resolve_segments (root_resolved_node_id, path.get_segments (), 0, translated,
+ path.get_mappings (), path.get_locus ());
+}
+
+void
+TypeCheckType::resolve_segments (
+ NodeId root_resolved_node_id,
+ std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset,
+ TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings,
+ Location expr_locus)
+{
+ gcc_unreachable ();
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 15eab25..c02a369 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -1,4 +1,3 @@
-
// Copyright (C) 2020 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -117,72 +116,9 @@ public:
= new TyTy::TupleType (tuple.get_mappings ().get_hirid (), fields);
}
- void visit (HIR::TypePath &path) override
- {
- // lookup the Node this resolves to
- NodeId ref;
- auto nid = path.get_mappings ().get_nodeid ();
- if (!resolver->lookup_resolved_type (nid, &ref))
- {
- rust_fatal_error (path.get_locus (),
- "failed to resolve node '%d' to HIR", nid);
- return;
- }
-
- HirId hir_lookup;
- if (!context->lookup_type_by_node_id (ref, &hir_lookup))
- {
- rust_error_at (path.get_locus (),
- "failed to lookup HIR %d for node '%s'", ref,
- path.as_string ().c_str ());
- return;
- }
-
- TyTy::BaseType *lookup = nullptr;
- if (!context->lookup_type (hir_lookup, &lookup))
- {
- rust_error_at (path.get_locus (), "failed to lookup HIR TyTy");
- return;
- }
-
- TyTy::BaseType *path_type = lookup->clone ();
- path_type->set_ref (path.get_mappings ().get_hirid ());
-
- HIR::TypePathSegment *final_seg = path.get_final_segment ().get ();
- HIR::GenericArgs args
- = TypeCheckResolveGenericArguments::resolve (final_seg);
+ void visit (HIR::TypePath &path) override;
- bool is_big_self = final_seg->is_ident_only ()
- && (final_seg->as_string ().compare ("Self") == 0);
-
- if (path_type->needs_generic_substitutions ())
- {
- if (is_big_self)
- {
- translated = path_type;
- return;
- }
-
- translated = SubstMapper::Resolve (path_type, path.get_locus (), &args);
- if (translated->get_kind () != TyTy::TypeKind::ERROR
- && mappings != nullptr)
- {
- check_for_unconstrained (args.get_type_args ());
- }
- }
- else if (!args.is_empty ())
- {
- rust_error_at (path.get_locus (),
- "TypePath %s declares generic arguments but "
- "the type %s does not have any",
- path.as_string ().c_str (),
- translated->as_string ().c_str ());
- }
- else
- {
- translated = path_type;
- }
- }
+ void visit (HIR::QualifiedPathInType &path) override;
void visit (HIR::ArrayType &type) override;
@@ -246,6 +182,12 @@ private:
}
}
+ void resolve_segments (
+ NodeId root_resolved_node_id,
+ std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset,
+ TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings,
+ Location expr_locus);
+
std::vector<TyTy::SubstitutionParamMapping> *subst_mappings;
TyTy::BaseType *translated;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 7f0e0ff..453f743 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -408,8 +408,9 @@ TraitItemReference::TraitItemReference (
HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
std::vector<TyTy::SubstitutionParamMapping> substitutions, Location locus)
: identifier (identifier), optional_flag (optional), type (type),
- hir_trait_item (hir_trait_item), inherited_substitutions (substitutions),
- locus (locus), self (self), context (TypeCheckContext::get ())
+ hir_trait_item (hir_trait_item),
+ inherited_substitutions (std::move (substitutions)), locus (locus),
+ self (self), context (TypeCheckContext::get ())
{}
TraitItemReference::TraitItemReference (TraitItemReference const &other)
@@ -420,7 +421,28 @@ TraitItemReference::TraitItemReference (TraitItemReference const &other)
inherited_substitutions.clear ();
inherited_substitutions.reserve (other.inherited_substitutions.size ());
for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
- inherited_substitutions.push_back (other.inherited_substitutions.at (i));
+ inherited_substitutions.push_back (
+ other.inherited_substitutions.at (i).clone ());
+}
+
+TraitItemReference &
+TraitItemReference::operator= (TraitItemReference const &other)
+{
+ identifier = other.identifier;
+ optional_flag = other.optional_flag;
+ type = other.type;
+ hir_trait_item = other.hir_trait_item;
+ self = other.self;
+ locus = other.locus;
+ context = other.context;
+
+ inherited_substitutions.clear ();
+ inherited_substitutions.reserve (other.inherited_substitutions.size ());
+ for (size_t i = 0; i < other.inherited_substitutions.size (); i++)
+ inherited_substitutions.push_back (
+ other.inherited_substitutions.at (i).clone ());
+
+ return *this;
}
TyTy::BaseType *
@@ -524,10 +546,13 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
context->insert_type (param.get_mappings (), param_tyty);
}
- return new TyTy::FnType (fn.get_mappings ().get_hirid (),
- fn.get_mappings ().get_defid (),
- function.get_function_name (), function.is_method (),
- std::move (params), ret_type, substitutions);
+ auto resolved
+ = new TyTy::FnType (fn.get_mappings ().get_hirid (),
+ fn.get_mappings ().get_defid (),
+ function.get_function_name (), function.is_method (),
+ std::move (params), ret_type, substitutions);
+ context->insert_type (fn.get_mappings (), resolved);
+ return resolved;
}
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 27b7f12..491de85 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -42,6 +42,8 @@ public:
TyTy::BaseType *type);
bool lookup_type (HirId id, TyTy::BaseType **type);
+ void insert_implicit_type (HirId id, TyTy::BaseType *type);
+
void insert_type_by_node_id (NodeId ref, HirId id);
bool lookup_type_by_node_id (NodeId ref, HirId *id);
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index c7ea029..28cbeb8 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -90,6 +90,36 @@ public:
resolved = concrete;
}
+ void visit (TyTy::PlaceholderType &type) override
+ {
+ rust_assert (type.can_resolve ());
+ resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
+ }
+
+ void visit (TyTy::ProjectionType &type) override
+ {
+ TyTy::ProjectionType *concrete = nullptr;
+ if (!have_generic_args ())
+ {
+ TyTy::BaseType *substs = type.infer_substitions (locus);
+ rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+ concrete = static_cast<TyTy::ProjectionType *> (substs);
+ }
+ else
+ {
+ TyTy::SubstitutionArgumentMappings mappings
+ = type.get_mappings_from_generic_args (*generics);
+ if (mappings.is_error ())
+ return;
+
+ concrete = type.handle_substitions (mappings);
+ }
+
+ if (concrete != nullptr)
+ resolved = concrete;
+ }
+
+ // nothing to do for these
void visit (TyTy::InferType &) override { gcc_unreachable (); }
void visit (TyTy::TupleType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
@@ -107,8 +137,6 @@ public:
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
- void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
- void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
private:
SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
@@ -177,6 +205,17 @@ public:
resolved = type.handle_substitions (mappings);
}
+ void visit (TyTy::PlaceholderType &type) override
+ {
+ rust_assert (type.can_resolve ());
+ resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
+ }
+
+ void visit (TyTy::ProjectionType &type) override
+ {
+ resolved = type.handle_substitions (mappings);
+ }
+
// nothing to do for these
void visit (TyTy::InferType &) override { gcc_unreachable (); }
void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
@@ -191,8 +230,6 @@ public:
void visit (TyTy::CharType &) override { gcc_unreachable (); }
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
- void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
- void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
private:
SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index ff1c627..95a16fa 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -83,6 +83,13 @@ TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
resolved[id] = type;
}
+void
+TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
+{
+ rust_assert (type != nullptr);
+ resolved[id] = type;
+}
+
bool
TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type)
{
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index d30be7f..f12ffb4 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -46,6 +46,19 @@ public:
other = p->resolve ();
}
}
+ else if (other->get_kind () == TypeKind::PLACEHOLDER)
+ {
+ PlaceholderType *p = static_cast<PlaceholderType *> (other);
+ if (p->can_resolve ())
+ {
+ other = p->resolve ();
+ }
+ }
+ else if (other->get_kind () == TypeKind::PROJECTION)
+ {
+ ProjectionType *p = static_cast<ProjectionType *> (other);
+ other = p->get ();
+ }
other->accept_vis (*this);
if (resolved->get_kind () == TyTy::TypeKind::ERROR)
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 4d0b977..db7d8c0 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -76,6 +76,11 @@ public:
other = p->resolve ();
}
}
+ else if (other->get_kind () == TypeKind::PROJECTION)
+ {
+ ProjectionType *p = static_cast<ProjectionType *> (other);
+ other = p->get ();
+ }
other->accept_vis (*this);
if (resolved->get_kind () == TyTy::TypeKind::ERROR)
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index e449b55..7eb717f 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -414,8 +414,6 @@ SubstitutionArgumentMappings
SubstitutionRef::adjust_mappings_for_this (
SubstitutionArgumentMappings &mappings)
{
- Analysis::Mappings *mappings_table = Analysis::Mappings::get ();
-
std::vector<SubstitutionArg> resolved_mappings;
for (size_t i = 0; i < substitutions.size (); i++)
{
@@ -442,20 +440,16 @@ SubstitutionRef::adjust_mappings_for_this (
}
bool ok = !arg.is_error ();
- if (!ok)
+ if (ok)
{
- rust_error_at (mappings_table->lookup_location (
- subst.get_param_ty ()->get_ref ()),
- "failed to find parameter type: %s vs mappings [%s]",
- subst.get_param_ty ()->as_string ().c_str (),
- mappings.as_string ().c_str ());
- return SubstitutionArgumentMappings::error ();
+ SubstitutionArg adjusted (&subst, arg.get_tyty ());
+ resolved_mappings.push_back (std::move (adjusted));
}
-
- SubstitutionArg adjusted (&subst, arg.get_tyty ());
- resolved_mappings.push_back (std::move (adjusted));
}
+ if (resolved_mappings.empty ())
+ return SubstitutionArgumentMappings::error ();
+
return SubstitutionArgumentMappings (resolved_mappings,
mappings.get_locus ());
}
@@ -907,7 +901,9 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok)
- sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ());
+ {
+ sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ());
+ }
}
auto fty = fn->get_return_type ();
@@ -2139,42 +2135,106 @@ ProjectionType::accept_vis (TyConstVisitor &vis) const
std::string
ProjectionType::as_string () const
{
- return "<Projection>";
+ return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">";
}
BaseType *
ProjectionType::unify (BaseType *other)
{
- gcc_unreachable ();
- return nullptr;
+ return base->unify (other);
}
BaseType *
ProjectionType::coerce (BaseType *other)
{
- gcc_unreachable ();
- return nullptr;
+ return base->coerce (other);
}
BaseType *
ProjectionType::cast (BaseType *other)
{
- gcc_unreachable ();
- return nullptr;
+ return base->cast (other);
}
bool
ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
{
- gcc_unreachable ();
- return false;
+ return base->can_eq (other, emit_errors);
}
BaseType *
ProjectionType::clone () const
{
return new ProjectionType (get_ref (), get_ty_ref (), base, trait, item,
- associated, get_combined_refs ());
+ clone_substs (), used_arguments,
+ get_combined_refs ());
+}
+
+ProjectionType *
+ProjectionType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+{
+ ProjectionType *projection = static_cast<ProjectionType *> (clone ());
+ projection->set_ty_ref (mappings->get_next_hir_id ());
+ projection->used_arguments = subst_mappings;
+
+ auto context = Resolver::TypeCheckContext::get ();
+ context->insert_implicit_type (projection->get_ty_ref (), projection);
+
+ for (auto &sub : projection->get_substs ())
+ {
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok
+ = subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
+ if (ok)
+ sub.fill_param_ty (arg.get_tyty (), subst_mappings.get_locus ());
+ }
+
+ auto fty = projection->base;
+ bool is_param_ty = fty->get_kind () == TypeKind::PARAM;
+ if (is_param_ty)
+ {
+ ParamType *p = static_cast<ParamType *> (fty);
+
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool ok = subst_mappings.get_argument_for_symbol (p, &arg);
+ if (ok)
+ {
+ auto argt = arg.get_tyty ();
+ bool arg_is_param = argt->get_kind () == TyTy::TypeKind::PARAM;
+ bool arg_is_concrete = argt->get_kind () != TyTy::TypeKind::INFER;
+
+ if (arg_is_param || arg_is_concrete)
+ {
+ auto new_field = argt->clone ();
+ new_field->set_ref (fty->get_ref ());
+ projection->base = new_field;
+ }
+ else
+ {
+ fty->set_ty_ref (argt->get_ref ());
+ }
+ }
+ }
+ else if (fty->needs_generic_substitutions ()
+ || fty->contains_type_parameters ())
+ {
+ BaseType *concrete
+ = Resolver::SubstMapperInternal::Resolve (fty, subst_mappings);
+
+ if (concrete == nullptr || concrete->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (subst_mappings.get_locus (),
+ "Failed to resolve field substitution type: %s",
+ fty->as_string ().c_str ());
+ return nullptr;
+ }
+
+ auto new_field = concrete->clone ();
+ new_field->set_ref (fty->get_ref ());
+ projection->base = new_field;
+ }
+
+ return projection;
}
// rust-tyty-call.h
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 743874a..0dfae37 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1709,7 +1709,11 @@ public:
std::string get_name () const override final { return as_string (); }
- bool is_unit () const override { return true; }
+ bool is_unit () const override
+ {
+ rust_assert (can_resolve ());
+ return resolve ()->is_unit ();
+ }
std::string get_symbol () const { return symbol; }
@@ -1723,26 +1727,38 @@ public:
bool is_equal (const BaseType &other) const override;
+ bool contains_type_parameters () const override
+ {
+ rust_assert (can_resolve ());
+ return resolve ()->contains_type_parameters ();
+ }
+
private:
std::string symbol;
};
-class ProjectionType : public BaseType
+class ProjectionType : public BaseType, public SubstitutionRef
{
public:
- ProjectionType (HirId ref, TyVar base, Resolver::TraitReference *trait,
- DefId item, Resolver::AssociatedImplTrait *associated,
+ ProjectionType (HirId ref, BaseType *base, Resolver::TraitReference *trait,
+ DefId item, std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments
+ = SubstitutionArgumentMappings::error (),
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PROJECTION, refs), base (base),
- trait (trait), item (item), associated (associated)
+ : BaseType (ref, ref, TypeKind::PROJECTION, refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
{}
- ProjectionType (HirId ref, HirId ty_ref, TyVar base,
+ ProjectionType (HirId ref, HirId ty_ref, BaseType *base,
Resolver::TraitReference *trait, DefId item,
- Resolver::AssociatedImplTrait *associated,
+ std::vector<SubstitutionParamMapping> subst_refs,
+ SubstitutionArgumentMappings generic_arguments
+ = SubstitutionArgumentMappings::error (),
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PROJECTION, refs), base (base),
- trait (trait), item (item), associated (associated)
+ : BaseType (ref, ty_ref, TypeKind::PROJECTION, refs),
+ SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
+ base (base), trait (trait), item (item)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1761,11 +1777,32 @@ public:
bool is_unit () const override { return false; }
+ bool needs_generic_substitutions () const override final
+ {
+ return needs_substitution ();
+ }
+
+ bool supports_substitutions () const override final { return true; }
+
+ bool has_subsititions_defined () const override final
+ {
+ return has_substitutions ();
+ }
+
+ BaseType *get () { return base; }
+
+ bool contains_type_parameters () const override
+ {
+ return base->contains_type_parameters ();
+ }
+
+ ProjectionType *
+ handle_substitions (SubstitutionArgumentMappings mappings) override final;
+
private:
- TyVar base;
+ BaseType *base;
Resolver::TraitReference *trait;
DefId item;
- Resolver::AssociatedImplTrait *associated;
};
} // namespace TyTy
diff --git a/gcc/testsuite/rust/compile/torture/traits12.rs b/gcc/testsuite/rust/compile/torture/traits12.rs
new file mode 100644
index 0000000..a55b965
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits12.rs
@@ -0,0 +1,29 @@
+trait Foo {
+ type A;
+
+ fn test(a: Self::A) -> Self::A {
+ a
+ }
+}
+
+struct Bar(i32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Bar {
+ type A = i32;
+}
+
+struct Baz(f32);
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Foo for Baz {
+ type A = f32;
+}
+
+fn main() {
+ let a: <Baz as Foo>::A;
+ a = 123f32;
+
+ let b;
+ b = <Baz as Foo>::test(a);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits13.rs b/gcc/testsuite/rust/compile/torture/traits13.rs
new file mode 100644
index 0000000..326f039
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits13.rs
@@ -0,0 +1,17 @@
+trait Trait {
+ const FOO: usize;
+ type Target;
+}
+
+struct S;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl Trait for S {
+ const FOO: usize = 0;
+ type Target = usize;
+}
+
+fn main() {
+ let a: <S as Trait>::Target;
+ a = <S as Trait>::FOO;
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits14.rs b/gcc/testsuite/rust/compile/torture/traits14.rs
new file mode 100644
index 0000000..8bca0d5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits14.rs
@@ -0,0 +1,23 @@
+trait Foo<T> {
+ type A;
+
+ fn test(a: T) -> T {
+ a
+ }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<T> {
+ type A = T;
+}
+
+pub fn main() {
+ let a;
+ a = Bar(123);
+
+ let b: <Bar<i32> as Foo<i32>>::A;
+ b = 456;
+
+ let c: <Bar<i32> as Foo<i32>>::A;
+ c = <Bar<i32> as Foo<i32>>::test(a.0);
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits15.rs b/gcc/testsuite/rust/compile/torture/traits15.rs
new file mode 100644
index 0000000..c8c40b7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits15.rs
@@ -0,0 +1,23 @@
+trait Foo<T> {
+ type A;
+
+ fn test(a: T, b: Self::A) -> (T, Self::A) {
+ (a, b)
+ }
+}
+
+struct Bar<T>(T);
+impl<T> Foo<T> for Bar<T> {
+ type A = T;
+}
+
+pub fn main() {
+ let a;
+ a = Bar(123);
+
+ let b: <Bar<i32> as Foo<i32>>::A;
+ b = 456;
+
+ let c;
+ c = <Bar<i32> as Foo<i32>>::test(a.0, 123);
+}