diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-17 14:42:02 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-17 14:42:02 +0000 |
commit | f958d1717745ad66a19c346c0e4b0bba1c813e7b (patch) | |
tree | c0744f0944f6236bc4e9082bf7d9602ae361d3da | |
parent | 3ee4bf774c517b25baaec0863550ab6c52f4b120 (diff) | |
parent | 9c53eb530a69e92f0ecacce2ff5ae907e16acfc3 (diff) | |
download | gcc-f958d1717745ad66a19c346c0e4b0bba1c813e7b.zip gcc-f958d1717745ad66a19c346c0e4b0bba1c813e7b.tar.gz gcc-f958d1717745ad66a19c346c0e4b0bba1c813e7b.tar.bz2 |
Merge #378
378: Add Check for unconstrained type parameters r=philberty a=philberty
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
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-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 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs | 12 |
3 files changed, 55 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 04fffd7..6556947 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; }; 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>(T, bool); + +impl<X, Y> Foo<X> { + // { dg-error "unconstrained type parameter" "" { target { *-*-* } } .-1 } + fn test() -> Y { + 123 + } +} + +fn main() { + let a = Foo::test(); +} |