aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <herron.philip@googlemail.com>2025-04-16 20:38:17 +0100
committerPhilip Herron <philip.herron@embecosm.com>2025-04-17 09:28:24 +0000
commitbb01719f0e1665a777b2b475e5feaafd01aa3ac8 (patch)
tree7ae758403f8689e8f0935541d1f9fb4ced8bc8ae
parent50a90f12af84ba2d203a0510bbeb41a383981303 (diff)
downloadgcc-bb01719f0e1665a777b2b475e5feaafd01aa3ac8.zip
gcc-bb01719f0e1665a777b2b475e5feaafd01aa3ac8.tar.gz
gcc-bb01719f0e1665a777b2b475e5feaafd01aa3ac8.tar.bz2
gccrs: Add check for placeholder (infer) type in return position
It is not allowed to have a declared inference variable in the return position of a function as this may never get infered you need good points of truth. Ideally if we get a student for GSoC 25 we will get the Default Hir Visitor so that we can grab the HIR::InferredType locus instead of using the ref location lookups. Fixes Rust-GCC#402 gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): add diagnostic * typecheck/rust-tyty.cc (BaseType::contains_infer): new helper to grab first infer var * typecheck/rust-tyty.h: prototype gcc/testsuite/ChangeLog: * rust/compile/issue-402.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc32
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc85
-rw-r--r--gcc/rust/typecheck/rust-tyty.h3
-rw-r--r--gcc/testsuite/rust/compile/issue-402.rs14
4 files changed, 134 insertions, 0 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index a29f043..e388994 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -649,6 +649,38 @@ TypeCheckItem::visit (HIR::Function &function)
context->switch_to_fn_body ();
auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
+ // emit check for
+ // error[E0121]: the type placeholder `_` is not allowed within types on item
+ const auto placeholder = ret_type->contains_infer ();
+ if (placeholder != nullptr && function.has_return_type ())
+ {
+ // FIXME
+ // this will be a great place for the Default Hir Visitor we want to
+ // grab the locations of the placeholders (HIR::InferredType) their
+ // location, for now maybe we can use their hirid to lookup the location
+ location_t placeholder_locus
+ = mappings.lookup_location (placeholder->get_ref ());
+ location_t type_locus = function.get_return_type ().get_locus ();
+ rich_location r (line_table, placeholder_locus);
+
+ bool have_expected_type
+ = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
+ if (!have_expected_type)
+ {
+ r.add_range (type_locus);
+ }
+ else
+ {
+ std::string fixit
+ = "replace with the correct type " + block_expr_ty->get_name ();
+ r.add_fixit_replace (type_locus, fixit.c_str ());
+ }
+
+ rust_error_at (r, ErrorCode::E0121,
+ "the type placeholder %<_%> is not allowed within types "
+ "on item signatures");
+ }
+
location_t fn_return_locus = function.has_function_return_type ()
? function.get_return_type ().get_locus ()
: function.get_locus ();
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 28c99a9..4da51ff 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -682,6 +682,91 @@ BaseType::debug () const
debug_str ().c_str ());
}
+const TyTy::BaseType *
+BaseType::contains_infer () const
+{
+ const TyTy::BaseType *x = destructure ();
+
+ if (auto fn = x->try_as<const FnType> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_type ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto fn = x->try_as<const FnPtr> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_tyty ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto adt = x->try_as<const ADTType> ())
+ {
+ for (auto &variant : adt->get_variants ())
+ {
+ bool is_num_variant
+ = variant->get_variant_type () == VariantDef::VariantType::NUM;
+ if (is_num_variant)
+ continue;
+
+ for (auto &field : variant->get_fields ())
+ {
+ const BaseType *field_type = field->get_field_type ();
+ auto infer = (field_type->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ }
+ return nullptr;
+ }
+ else if (auto arr = x->try_as<const ArrayType> ())
+ {
+ return arr->get_element_type ()->contains_infer ();
+ }
+ else if (auto slice = x->try_as<const SliceType> ())
+ {
+ return slice->get_element_type ()->contains_infer ();
+ }
+ else if (auto ptr = x->try_as<const PointerType> ())
+ {
+ return ptr->get_base ()->contains_infer ();
+ }
+ else if (auto ref = x->try_as<const ReferenceType> ())
+ {
+ return ref->get_base ()->contains_infer ();
+ }
+ else if (auto tuple = x->try_as<const TupleType> ())
+ {
+ for (size_t i = 0; i < tuple->num_fields (); i++)
+ {
+ auto infer = (tuple->get_field (i)->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ return nullptr;
+ }
+ else if (auto closure = x->try_as<const ClosureType> ())
+ {
+ auto infer = (closure->get_parameters ().contains_infer ());
+ if (infer)
+ return infer;
+ return closure->get_result_type ().contains_infer ();
+ }
+ else if (x->is<InferType> ())
+ {
+ return x;
+ }
+
+ return nullptr;
+}
+
bool
BaseType::is_concrete () const
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index e1370e0..b14e9f25 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -137,6 +137,9 @@ public:
void inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ // contains_infer checks if there is an inference variable inside the type
+ const TyTy::BaseType *contains_infer () const;
+
// is_unit returns whether this is just a unit-struct
bool is_unit () const;
diff --git a/gcc/testsuite/rust/compile/issue-402.rs b/gcc/testsuite/rust/compile/issue-402.rs
new file mode 100644
index 0000000..2c99fc8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-402.rs
@@ -0,0 +1,14 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+struct GenericStruct<T>(T, usize);
+
+pub fn test() -> GenericStruct<_> {
+ // { dg-error "the type placeholder ._. is not allowed within types on item signatures .E0121." "" { target *-*-* } .-1 }
+ GenericStruct(1, 2)
+}
+
+fn square(num: i32) -> _ {
+ // { dg-error "the type placeholder ._. is not allowed within types on item signatures .E0121." "" { target *-*-* } .-1 }
+ num * num
+}