aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-17 14:42:02 +0000
committerGitHub <noreply@github.com>2021-04-17 14:42:02 +0000
commitf958d1717745ad66a19c346c0e4b0bba1c813e7b (patch)
treec0744f0944f6236bc4e9082bf7d9602ae361d3da
parent3ee4bf774c517b25baaec0863550ab6c52f4b120 (diff)
parent9c53eb530a69e92f0ecacce2ff5ae907e16acfc3 (diff)
downloadgcc-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.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h44
-rw-r--r--gcc/testsuite/rust.test/xfail_compile/unconstrained_type_param.rs12
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();
+}