aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-09-05 00:14:00 +0000
committerGitHub <noreply@github.com>2021-09-05 00:14:00 +0000
commit50623899998de5a8ffe47227a351c2b3dd29aa0a (patch)
tree4fac02e7fc1b271b1bf50d8812e150ab8ee30db9 /gcc
parentc33c6f3676dfca1a6bd7984cebf5028c015ea182 (diff)
parent0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759 (diff)
downloadgcc-50623899998de5a8ffe47227a351c2b3dd29aa0a.zip
gcc-50623899998de5a8ffe47227a351c2b3dd29aa0a.tar.gz
gcc-50623899998de5a8ffe47227a351c2b3dd29aa0a.tar.bz2
Merge #655
655: Generic Qualified Paths r=philberty a=philberty This fixes how we handle associated types in relation to generic traits. Generic traits are interesting because, a TypePath usually resolves to a normal TyTy type which can be substituted using the mapper classes, but a trait is a definition of behaviour which is made up of types, constants or functions. In order to handle generic traits we must add substitution support to the associated types which are represented by projections see this commit for detail on the changes 0798add3d3c1bf4b20ecc1b4fa1047ba4ba19759 Also see https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/struct.ProjectionTy.html Fixes #434 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
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);
+}