Skip to content

Commit ac09b68

Browse files
committed
gccrs: check for invalid const calls during code-gen
Closure calls are not const so this is invalid. This patch fixes two bugs 1. Make the look at the parent context optional for generics 2. Ensure we look for non const calls during call expr code-gen Fixes #3551 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where possible * backend/rust-compile-item.h: update header * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional gcc/testsuite/ChangeLog: * rust/compile/issue-3551.rs: New test. Signed-off-by: Philip Herron <herron.philip@googlemail.com>
1 parent baa4c42 commit ac09b68

5 files changed

Lines changed: 115 additions & 12 deletions

File tree

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,28 @@ CompileExpr::visit (HIR::CallExpr &expr)
13381338
};
13391339

13401340
auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
1341+
if (ctx->const_context_p ())
1342+
{
1343+
if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address)))
1344+
{
1345+
rust_error_at (expr.get_locus (),
1346+
"calls in constants are limited to constant "
1347+
"functions, tuple structs and tuple variants");
1348+
return;
1349+
}
1350+
1351+
if (TREE_CODE (fn_address) == ADDR_EXPR)
1352+
{
1353+
tree fndecl = TREE_OPERAND (fn_address, 0);
1354+
if (!DECL_DECLARED_CONSTEXPR_P (fndecl))
1355+
{
1356+
rust_error_at (expr.get_locus (),
1357+
"calls in constants are limited to constant "
1358+
"functions, tuple structs and tuple variants");
1359+
return;
1360+
}
1361+
}
1362+
}
13411363

13421364
// is this a closure call?
13431365
bool possible_trait_call

gcc/rust/backend/rust-compile-item.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,5 +297,65 @@ CompileItem::visit (HIR::Module &module)
297297
CompileItem::compile (item.get (), ctx);
298298
}
299299

300+
void
301+
CompileItem::visit (HIR::TupleStruct &tuple_struct_decl)
302+
{
303+
TyTy::BaseType *lookup = nullptr;
304+
if (!ctx->get_tyctx ()->lookup_type (
305+
tuple_struct_decl.get_mappings ().get_hirid (), &lookup))
306+
{
307+
rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type");
308+
return;
309+
}
310+
311+
if (lookup->is_concrete ())
312+
TyTyResolveCompile::compile (ctx, lookup);
313+
}
314+
315+
void
316+
CompileItem::visit (HIR::Enum &enum_decl)
317+
{
318+
TyTy::BaseType *lookup = nullptr;
319+
if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (),
320+
&lookup))
321+
{
322+
rust_error_at (enum_decl.get_locus (), "failed to resolve type");
323+
return;
324+
}
325+
326+
if (lookup->is_concrete ())
327+
TyTyResolveCompile::compile (ctx, lookup);
328+
}
329+
330+
void
331+
CompileItem::visit (HIR::Union &union_decl)
332+
{
333+
TyTy::BaseType *lookup = nullptr;
334+
if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (),
335+
&lookup))
336+
{
337+
rust_error_at (union_decl.get_locus (), "failed to resolve type");
338+
return;
339+
}
340+
341+
if (lookup->is_concrete ())
342+
TyTyResolveCompile::compile (ctx, lookup);
343+
}
344+
345+
void
346+
CompileItem::visit (HIR::StructStruct &struct_decl)
347+
{
348+
TyTy::BaseType *lookup = nullptr;
349+
if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (),
350+
&lookup))
351+
{
352+
rust_error_at (struct_decl.get_locus (), "failed to resolve type");
353+
return;
354+
}
355+
356+
if (lookup->is_concrete ())
357+
TyTyResolveCompile::compile (ctx, lookup);
358+
}
359+
300360
} // namespace Compile
301361
} // namespace Rust

gcc/rust/backend/rust-compile-item.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
4444
void visit (HIR::ImplBlock &impl_block) override;
4545
void visit (HIR::ExternBlock &extern_block) override;
4646
void visit (HIR::Module &module) override;
47+
void visit (HIR::TupleStruct &tuple_struct) override;
48+
void visit (HIR::Enum &enum_decl) override;
49+
void visit (HIR::Union &union_decl) override;
50+
void visit (HIR::StructStruct &struct_decl) override;
4751

4852
// Empty visit for unused Stmt HIR nodes.
49-
void visit (HIR::TupleStruct &) override {}
5053
void visit (HIR::EnumItem &) override {}
5154
void visit (HIR::EnumItemTuple &) override {}
5255
void visit (HIR::EnumItemStruct &) override {}
@@ -57,9 +60,6 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
5760
void visit (HIR::ExternCrate &) override {}
5861
void visit (HIR::UseDeclaration &) override {}
5962
void visit (HIR::TypeAlias &) override {}
60-
void visit (HIR::StructStruct &) override {}
61-
void visit (HIR::Enum &) override {}
62-
void visit (HIR::Union &) override {}
6363
void visit (HIR::Trait &) override {}
6464
void visit (HIR::EmptyStmt &) override {}
6565
void visit (HIR::LetStmt &) override {}

gcc/rust/typecheck/rust-hir-type-check-expr.cc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,16 +1726,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
17261726
void
17271727
TypeCheckExpr::visit (HIR::ClosureExpr &expr)
17281728
{
1729-
TypeCheckContextItem current_context = context->peek_context ();
1730-
TyTy::FnType *current_context_fndecl = current_context.get_context_type ();
1731-
1729+
std::vector<TyTy::SubstitutionParamMapping> subst_refs;
17321730
HirId ref = expr.get_mappings ().get_hirid ();
17331731
DefId id = expr.get_mappings ().get_defid ();
1734-
RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()};
1732+
RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()};
1733+
1734+
if (context->have_function_context ())
1735+
{
1736+
TypeCheckContextItem current_context = context->peek_context ();
1737+
TyTy::FnType *current_context_fndecl
1738+
= current_context.get_context_type ();
1739+
1740+
ident = RustIdent{current_context_fndecl->get_ident ().path,
1741+
expr.get_locus ()};
17351742

1736-
// get from parent context
1737-
std::vector<TyTy::SubstitutionParamMapping> subst_refs
1738-
= current_context_fndecl->clone_substs ();
1743+
subst_refs = current_context_fndecl->clone_substs ();
1744+
}
17391745

17401746
std::vector<TyTy::TyVar> parameter_types;
17411747
for (auto &p : expr.get_params ())
@@ -1769,7 +1775,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
17691775
TyTy::TyVar result_type
17701776
= expr.has_return_type ()
17711777
? TyTy::TyVar (
1772-
TypeCheckType::Resolve (expr.get_return_type ())->get_ref ())
1778+
TypeCheckType::Resolve (expr.get_return_type ())->get_ref ())
17731779
: TyTy::TyVar::get_implicit_infer_var (expr.get_locus ());
17741780

17751781
// resolve the block
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#[lang = "sized"]
2+
pub trait Sized {}
3+
4+
#[lang = "fn_once"]
5+
pub trait FnOnce<Args> {
6+
#[lang = "fn_once_output"]
7+
type Output;
8+
9+
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
10+
}
11+
12+
struct Bug {
13+
a: [(); (|| 0)()],
14+
// { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" "" { target *-*-* } .-1 }
15+
}

0 commit comments

Comments
 (0)