From 9c53eb530a69e92f0ecacce2ff5ae907e16acfc3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 16 Apr 2021 17:06:15 +0100 Subject: Add Check for unconstrained type parameters When we have an impl Foo, the type parameter Y is unconstrained so that we cannot be sure how Y should be substituted later on. Fixes #354 --- gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 3 +- gcc/rust/typecheck/rust-hir-type-check-type.h | 44 ++++++++++++++++++++-- .../xfail_compile/unconstrained_type_param.rs | 12 ++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs (limited to 'gcc') 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 *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 *mappings) + : TypeCheckBase (), mappings (mappings), translated (nullptr) + {} + + void + check_for_unconstrained (std::vector > &type_args) + { + std::map param_location_map; + std::set 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 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 *mappings; TyTy::BaseType *translated; }; diff --git a/gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs b/gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs new file mode 100644 index 0000000..34be7fd --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs @@ -0,0 +1,12 @@ +struct Foo(T, bool); + +impl Foo { + // { dg-error "unconstrained type parameter" "" { target { *-*-* } } .-1 } + fn test() -> Y { + 123 + } +} + +fn main() { + let a = Foo::test(); +} -- cgit v1.1