diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-16 17:06:15 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-16 17:07:56 +0100 |
commit | 9c53eb530a69e92f0ecacce2ff5ae907e16acfc3 (patch) | |
tree | 47a88bcce0341aa28c4104531c3d8c8bd920ca06 /gcc/rust | |
parent | ce593f09f410e1ab0cfe44a680299bc47ab7885f (diff) | |
download | gcc-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.h | 3 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.h | 44 |
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; }; |