aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-04-15 17:41:40 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-04-16 16:08:55 +0100
commitee247029acfaee991660ff14c85f7146b9040511 (patch)
treeb025ed32a121c3774f9c83803e18d6ec0fffeed0 /gcc/rust
parentce593f09f410e1ab0cfe44a680299bc47ab7885f (diff)
downloadgcc-ee247029acfaee991660ff14c85f7146b9040511.zip
gcc-ee247029acfaee991660ff14c85f7146b9040511.tar.gz
gcc-ee247029acfaee991660ff14c85f7146b9040511.tar.bz2
Fix crash when mapping of Generic argument changes.
When we have a struct Foo <T>(T) but the fntype in impl block is different fn <X> Bar(a:X) -> Foo<X>(X) { } we must take advantage of the adjustment code in the substitution mapper. This affects MethodCallExpr and PathInExpressions where it used to resolve the root segment and leave the arguments as inference variables when we lack a segement with generic arguments. This also fixes a bug in name resolution where the Self keyword resolved to the struct/type the impl block resolves to but it needed to resolve to the impl block type explicitly which ensures the parameter mappings reflect what the parent impl block is. Fixes: #376
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h42
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h4
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h42
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h17
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty.h9
7 files changed, 102 insertions, 28 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 9c19ce6..27f5305 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -186,14 +186,15 @@ public:
if (resolved_node == UNKNOWN_NODEID)
return;
- auto Self = CanonicalPath::get_big_self ();
resolver->get_type_scope ().insert (
- Self, resolved_node, impl_block.get_type ()->get_locus_slow ());
+ CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id (),
+ impl_block.get_type ()->get_locus_slow ());
for (auto &impl_item : impl_block.get_impl_items ())
impl_item->accept_vis (*this);
- resolver->get_type_scope ().peek ()->clear_name (Self, resolved_node);
+ resolver->get_type_scope ().peek ()->clear_name (
+ CanonicalPath::get_big_self (), impl_block.get_type ()->get_node_id ());
resolver->get_type_scope ().pop ();
}
@@ -208,7 +209,7 @@ public:
resolver->push_new_name_rib (resolver->get_name_scope ().peek ());
resolver->push_new_type_rib (resolver->get_type_scope ().peek ());
- // self turns into self: Self as a function param
+ // self turns into (self: Self) as a function param
AST::SelfParam &self_param = method.get_self_param ();
AST::IdentifierPattern self_pattern (
self_param.get_node_id (), "self", self_param.get_locus (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index cb2f250..bdc6df3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -251,8 +251,10 @@ public:
if (adt->has_substitutions () && fn->needs_substitution ())
{
rust_assert (adt->was_substituted ());
+ auto used_args_in_prev_segment = GetUsedSubstArgs::From (adt);
lookup
- = fn->handle_substitions (adt->get_substitution_arguments ());
+ = SubstMapperInternal::Resolve (fn,
+ used_args_in_prev_segment);
}
}
}
@@ -767,10 +769,15 @@ public:
return;
else if (expr.get_num_segments () == 1)
{
+ Location locus = expr.get_segments ().back ().get_locus ();
+ if (tyseg->needs_generic_substitutions ())
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
+
infered = tyseg;
return;
}
+ TyTy::BaseType *prev_segment = tyseg;
NodeId resolved_node_id = UNKNOWN_NODEID;
for (size_t i = 1; i < expr.get_num_segments (); i++)
{
@@ -792,11 +799,11 @@ public:
}
auto candidate = candidates.at (0);
+ prev_segment = tyseg;
tyseg = candidate.ty;
resolved_node_id
= candidate.impl_item->get_impl_mappings ().get_nodeid ();
- bool did_substitute = false;
if (seg.has_generic_args ())
{
if (!tyseg->can_substitute ())
@@ -807,23 +814,30 @@ public:
return;
}
- did_substitute = true;
tyseg = SubstMapper::Resolve (tyseg, expr.get_locus (),
&seg.get_generic_args ());
-
if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
return;
}
+ }
+
+ if (tyseg->needs_generic_substitutions ())
+ {
+ Location locus = expr.get_segments ().back ().get_locus ();
+ if (!prev_segment->needs_generic_substitutions ())
+ {
+ auto used_args_in_prev_segment
+ = GetUsedSubstArgs::From (prev_segment);
+ tyseg
+ = SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment);
+ }
else
{
- if (tyseg->needs_generic_substitutions ())
- {
- did_substitute = true;
- tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ());
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
}
+
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
}
rust_assert (resolved_node_id != UNKNOWN_NODEID);
@@ -1027,10 +1041,6 @@ private:
lookup = SubstMapper::Resolve (lookup, expr.get_locus (),
&root.get_generic_args ());
}
- else if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
- }
return lookup;
}
@@ -1089,7 +1099,7 @@ private:
TyTy::BaseType *infered_array_elems;
bool inside_loop;
-};
+}; // namespace Resolver
} // 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 173294b..04fffd7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -195,14 +195,14 @@ public:
"the type %s does not have any",
path.as_string ().c_str (),
translated->as_string ().c_str ());
- return;
}
}
else if (translated->has_subsititions_defined ())
{
translated
- = SubstMapper::Resolve (translated, path.get_locus ());
+ = SubstMapper::InferSubst (translated, path.get_locus ());
}
+
return;
}
}
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index db43cbd..bc20e4b 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -223,6 +223,48 @@ private:
TyTy::BaseType *resolved;
};
+class GetUsedSubstArgs : public TyTy::TyVisitor
+{
+public:
+ static TyTy::SubstitutionArgumentMappings From (TyTy::BaseType *from)
+ {
+ GetUsedSubstArgs mapper;
+ from->accept_vis (mapper);
+ return mapper.args;
+ }
+
+ void visit (TyTy::FnType &type) override
+ {
+ args = type.get_substitution_arguments ();
+ }
+
+ void visit (TyTy::ADTType &type) override
+ {
+ args = type.get_substitution_arguments ();
+ }
+
+ void visit (TyTy::InferType &) override { gcc_unreachable (); }
+ void visit (TyTy::TupleType &) override { gcc_unreachable (); }
+ void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
+ void visit (TyTy::ArrayType &) override { gcc_unreachable (); }
+ void visit (TyTy::BoolType &) override { gcc_unreachable (); }
+ void visit (TyTy::IntType &) override { gcc_unreachable (); }
+ void visit (TyTy::UintType &) override { gcc_unreachable (); }
+ void visit (TyTy::FloatType &) override { gcc_unreachable (); }
+ void visit (TyTy::USizeType &) override { gcc_unreachable (); }
+ void visit (TyTy::ISizeType &) override { gcc_unreachable (); }
+ void visit (TyTy::ErrorType &) override { gcc_unreachable (); }
+ void visit (TyTy::CharType &) override { gcc_unreachable (); }
+ void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
+ void visit (TyTy::ParamType &) override { gcc_unreachable (); }
+ void visit (TyTy::StrType &) override { gcc_unreachable (); }
+
+private:
+ GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
+
+ TyTy::SubstitutionArgumentMappings args;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index e2e0d08..b195e5c 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -776,13 +776,22 @@ public:
bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
rust_assert (ok);
+ if (lookup->get_kind () == TypeKind::PARAM)
+ {
+ InferType infer (UNKNOWN_HIRID, InferType::InferTypeKind::GENERAL);
+ return infer.can_eq (other);
+ }
+
return lookup->can_eq (other);
}
- void visit (ParamType &type) override
- {
- ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
- }
+ // imagine the case where we have:
+ // struct Foo<T>(T);
+ // Then we declare a generic impl block
+ // impl <X>Foo<X> { ... }
+ // both of these types are compatible so we mostly care about the number of
+ // generic arguments
+ void visit (ParamType &type) override { ok = true; }
private:
BaseType *get_base () override { return base; }
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 8f2faec..8378cf2 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -251,10 +251,12 @@ SubstitutionRef::adjust_mappings_for_this (
Analysis::Mappings *mappings_table = Analysis::Mappings::get ();
std::vector<SubstitutionArg> resolved_mappings;
- for (auto &subst : substitutions)
+ for (size_t i = 0; i < substitutions.size (); i++)
{
+ auto &subst = substitutions.at (i);
+
SubstitutionArg arg = SubstitutionArg::error ();
- bool ok = mappings.get_argument_for_symbol (subst.get_param_ty (), &arg);
+ bool ok = mappings.get_argument_at (0, &arg);
if (!ok)
{
rust_error_at (mappings_table->lookup_location (
@@ -613,6 +615,7 @@ FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
for (auto &sub : fn->get_substs ())
{
SubstitutionArg arg = SubstitutionArg::error ();
+
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
rust_assert (ok);
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index c428c4c..2f343c1 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -495,6 +495,15 @@ public:
return false;
}
+ bool get_argument_at (size_t index, SubstitutionArg *argument)
+ {
+ if (index > mappings.size ())
+ return false;
+
+ *argument = mappings.at (index);
+ return true;
+ }
+
// is_concrete means if the used args is non error, ie: non empty this will
// verify if actual real types have been put in place of are they still
// ParamTy