aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-04-16 17:06:15 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-04-16 17:07:56 +0100
commit9c53eb530a69e92f0ecacce2ff5ae907e16acfc3 (patch)
tree47a88bcce0341aa28c4104531c3d8c8bd920ca06 /gcc/rust
parentce593f09f410e1ab0cfe44a680299bc47ab7885f (diff)
downloadgcc-9c53eb530a69e92f0ecacce2ff5ae907e16acfc3.zip
gcc-9c53eb530a69e92f0ecacce2ff5ae907e16acfc3.tar.gz
gcc-9c53eb530a69e92f0ecacce2ff5ae907e16acfc3.tar.bz2
Add Check for unconstrained type parameters
When we have an impl<X,Y> Foo<X>, the type parameter Y is unconstrained so that we cannot be sure how Y should be substituted later on. Fixes #354
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h44
2 files changed, 43 insertions, 4 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 0131555..356faa6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -211,7 +211,8 @@ public:
}
}
- auto self = TypeCheckType::Resolve (impl_block.get_type ().get ());
+ auto self
+ = TypeCheckType::Resolve (impl_block.get_type ().get (), &substitutions);
if (self == nullptr || self->get_kind () == TyTy::TypeKind::ERROR)
{
rust_error_at (impl_block.get_locus (), "failed to resolve impl type");
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 173294b..1bd7757 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -95,9 +95,11 @@ class TypeCheckType : public TypeCheckBase
using Rust::Resolver::TypeCheckBase::visit;
public:
- static TyTy::BaseType *Resolve (HIR::Type *type)
+ static TyTy::BaseType *
+ Resolve (HIR::Type *type,
+ std::vector<TyTy::SubstitutionParamMapping> *mappings = nullptr)
{
- TypeCheckType resolver;
+ TypeCheckType resolver (mappings);
type->accept_vis (resolver);
if (resolver.translated == nullptr)
@@ -186,6 +188,11 @@ public:
translated
= SubstMapper::Resolve (translated, path.get_locus (),
&args);
+ if (translated->get_kind () != TyTy::TypeKind::ERROR
+ && mappings != nullptr)
+ {
+ check_for_unconstrained (args.get_type_args ());
+ }
}
else
{
@@ -241,8 +248,39 @@ public:
}
private:
- TypeCheckType () : TypeCheckBase (), translated (nullptr) {}
+ TypeCheckType (std::vector<TyTy::SubstitutionParamMapping> *mappings)
+ : TypeCheckBase (), mappings (mappings), translated (nullptr)
+ {}
+
+ void
+ check_for_unconstrained (std::vector<std::unique_ptr<HIR::Type> > &type_args)
+ {
+ std::map<std::string, Location> param_location_map;
+ std::set<std::string> param_tys;
+ for (auto &mapping : *mappings)
+ {
+ std::string sym = mapping.get_param_ty ()->get_symbol ();
+ param_tys.insert (sym);
+ param_location_map[sym]
+ = mapping.get_generic_param ()->get_locus_slow ();
+ }
+
+ std::set<std::string> args;
+ for (auto &arg : type_args)
+ args.insert (arg->as_string ());
+
+ for (auto &exp : param_tys)
+ {
+ bool used = args.find (exp) != args.end ();
+ if (!used)
+ {
+ Location locus = param_location_map.at (exp);
+ rust_error_at (locus, "unconstrained type parameter");
+ }
+ }
+ }
+ std::vector<TyTy::SubstitutionParamMapping> *mappings;
TyTy::BaseType *translated;
};