Skip to content

Commit 7a8b033

Browse files
committed
Introduce limited support for the never type
1 parent 7ccf2a9 commit 7a8b033

26 files changed

+270
-54
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,11 @@ class TyTyResolveCompile : public TyTy::TyVisitor
503503
translated = compiled_type;
504504
}
505505

506+
void visit (TyTy::NeverType &) override
507+
{
508+
translated = ctx->get_backend ()->void_type ();
509+
}
510+
506511
private:
507512
TyTyResolveCompile (Context *ctx) : ctx (ctx), translated (nullptr) {}
508513

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

+5
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ class TyTyCompile : public TyTy::TyVisitor
222222
= backend->named_type ("str", raw_str, Linemap::predeclared_location ());
223223
}
224224

225+
void visit (TyTy::NeverType &) override
226+
{
227+
translated = backend->void_type ();
228+
}
229+
225230
private:
226231
TyTyCompile (::Backend *backend)
227232
: backend (backend), translated (nullptr),

gcc/rust/backend/rust-compile.cc

+3-5
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ CompileBlock::visit (HIR::BlockExpr &expr)
256256
}
257257
}
258258

259-
if (expr.has_expr () && expr.tail_expr_reachable ())
259+
if (expr.has_expr ())
260260
{
261261
// the previous passes will ensure this is a valid return
262262
// dead code elimination should remove any bad trailing expressions
@@ -410,17 +410,15 @@ HIRCompileBase::compile_function_body (
410410
}
411411
}
412412

413-
if (function_body->has_expr () && function_body->tail_expr_reachable ())
413+
if (function_body->has_expr ())
414414
{
415415
// the previous passes will ensure this is a valid return
416416
// dead code elimination should remove any bad trailing expressions
417417
Bexpression *compiled_expr
418418
= CompileExpr::Compile (function_body->expr.get (), ctx);
419419

420-
if (has_return_type)
420+
if (has_return_type && compiled_expr)
421421
{
422-
rust_assert (compiled_expr != nullptr);
423-
424422
std::vector<Bexpression *> retstmts;
425423
retstmts.push_back (compiled_expr);
426424

gcc/rust/hir/rust-ast-lower.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr)
9090
return true;
9191
});
9292

93-
bool tail_reachable = expr.has_tail_expr () && !block_did_terminate;
93+
bool tail_reachable = !block_did_terminate;
9494
if (expr.has_tail_expr () && block_did_terminate)
9595
{
9696
// warning unreachable tail expressions

gcc/rust/hir/tree/rust-hir-expr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -2511,7 +2511,7 @@ class BlockExpr : public ExprWithBlock
25112511
// Returns whether the block contains an expression
25122512
bool has_expr () const { return expr != nullptr; }
25132513

2514-
bool tail_expr_reachable () const { return tail_reachable; }
2514+
bool is_tail_reachable () const { return tail_reachable; }
25152515

25162516
BlockExpr (Analysis::NodeMapping mappings,
25172517
std::vector<std::unique_ptr<Stmt> > block_statements,

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

+25-13
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,15 @@ class TypeCheckExpr : public TypeCheckBase
145145

146146
void visit (HIR::ReturnExpr &expr) override
147147
{
148-
if (!expr.has_return_expr ())
149-
{
150-
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
151-
return;
152-
}
153-
154148
auto fn_return_tyty = context->peek_return_type ();
155149
rust_assert (fn_return_tyty != nullptr);
156150

157-
auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false);
151+
TyTy::BaseType *expr_ty;
152+
if (expr.has_return_expr ())
153+
expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false);
154+
else
155+
expr_ty = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
156+
158157
if (expr_ty == nullptr)
159158
{
160159
rust_error_at (expr.get_locus (),
@@ -166,6 +165,8 @@ class TypeCheckExpr : public TypeCheckBase
166165
fn_return_tyty->append_reference (expr_ty->get_ref ());
167166
for (auto &ref : infered->get_combined_refs ())
168167
fn_return_tyty->append_reference (ref);
168+
169+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
169170
}
170171

171172
void visit (HIR::CallExpr &expr) override
@@ -624,17 +625,28 @@ class TypeCheckExpr : public TypeCheckBase
624625
auto else_blk_resolved
625626
= TypeCheckExpr::Resolve (expr.get_else_block (), inside_loop);
626627

627-
infered = if_blk_resolved->unify (else_blk_resolved);
628+
if (if_blk_resolved->get_kind () == TyTy::NEVER)
629+
infered = else_blk_resolved;
630+
else if (else_blk_resolved->get_kind () == TyTy::NEVER)
631+
infered = if_blk_resolved;
632+
else
633+
infered = if_blk_resolved->unify (else_blk_resolved);
628634
}
629635

630636
void visit (HIR::IfExprConseqIf &expr) override
631637
{
632638
TypeCheckExpr::Resolve (expr.get_if_condition (), false);
633-
auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop);
634-
auto else_blk
639+
auto if_blk_resolved
640+
= TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop);
641+
auto else_blk_resolved
635642
= TypeCheckExpr::Resolve (expr.get_conseq_if_expr (), inside_loop);
636643

637-
infered = if_blk->unify (else_blk);
644+
if (if_blk_resolved->get_kind () == TyTy::NEVER)
645+
infered = else_blk_resolved;
646+
else if (else_blk_resolved->get_kind () == TyTy::NEVER)
647+
infered = if_blk_resolved;
648+
else
649+
infered = if_blk_resolved->unify (else_blk_resolved);
638650
}
639651

640652
void visit (HIR::BlockExpr &expr) override;
@@ -919,7 +931,7 @@ class TypeCheckExpr : public TypeCheckBase
919931
context->swap_head_loop_context (unified_ty);
920932
}
921933

922-
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
934+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
923935
}
924936

925937
void visit (HIR::ContinueExpr &expr) override
@@ -931,7 +943,7 @@ class TypeCheckExpr : public TypeCheckBase
931943
return;
932944
}
933945

934-
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
946+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
935947
}
936948

937949
void visit (HIR::BorrowExpr &expr) override

gcc/rust/typecheck/rust-hir-type-check-item.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ class TypeCheckItem : public TypeCheckBase
8282

8383
context->pop_return_type ();
8484

85-
expected_ret_tyty->unify (block_expr_ty);
85+
if (block_expr_ty->get_kind () != TyTy::NEVER)
86+
expected_ret_tyty->unify (block_expr_ty);
8687
}
8788

8889
private:

gcc/rust/typecheck/rust-hir-type-check-stmt.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class TypeCheckStmt : public TypeCheckBase
4343
{
4444
infered = TypeCheckExpr::Resolve (stmt.get_expr (), inside_loop);
4545

46-
if (stmt.is_unit_check_needed ())
46+
if (stmt.is_unit_check_needed () && infered->get_kind () != TyTy::NEVER)
4747
{
4848
auto unit = new TyTy::TupleType (stmt.get_mappings ().get_hirid ());
4949
infered = unit->unify (infered);

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

+7-21
Original file line numberDiff line numberDiff line change
@@ -123,39 +123,25 @@ TypeResolution::Resolve (HIR::Crate &crate)
123123
void
124124
TypeCheckExpr::visit (HIR::BlockExpr &expr)
125125
{
126-
TyTy::BaseType *block_tyty
127-
= new TyTy::TupleType (expr.get_mappings ().get_hirid ());
128-
129126
expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
130-
bool is_final_stmt = expr.is_final_stmt (s);
131-
bool has_final_expr = expr.has_expr () && expr.tail_expr_reachable ();
132-
bool stmt_is_final_expr = is_final_stmt && !has_final_expr;
133-
134127
auto resolved = TypeCheckStmt::Resolve (s, inside_loop);
135128
if (resolved == nullptr)
136129
{
137130
rust_error_at (s->get_locus_slow (), "failure to resolve type");
138131
return false;
139132
}
140133

141-
if (stmt_is_final_expr)
142-
{
143-
delete block_tyty;
144-
block_tyty = resolved;
145-
}
146-
147134
return true;
148135
});
149136

150137
if (expr.has_expr ())
151-
{
152-
delete block_tyty;
153-
154-
block_tyty
155-
= TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop);
156-
}
157-
158-
infered = block_tyty->clone ();
138+
infered
139+
= TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop)
140+
->clone ();
141+
else if (expr.is_tail_reachable ())
142+
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
143+
else
144+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
159145
}
160146

161147
// RUST_HIR_TYPE_CHECK_STRUCT_FIELD

gcc/rust/typecheck/rust-substitution-mapper.h

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class SubstMapper : public TyTy::TyVisitor
9999
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
100100
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
101101
void visit (TyTy::StrType &) override { gcc_unreachable (); }
102+
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
102103

103104
private:
104105
SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
@@ -157,6 +158,7 @@ class SubstMapperInternal : public TyTy::TyVisitor
157158
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
158159
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
159160
void visit (TyTy::StrType &) override { gcc_unreachable (); }
161+
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
160162

161163
private:
162164
SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
@@ -211,6 +213,7 @@ class SubstMapperFromExisting : public TyTy::TyVisitor
211213
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
212214
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
213215
void visit (TyTy::StrType &) override { gcc_unreachable (); }
216+
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
214217

215218
private:
216219
SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver)

gcc/rust/typecheck/rust-tycheck-dump.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class TypeResolverDump : public TypeCheckBase
107107
return true;
108108
});
109109

110-
if (expr.has_expr () && expr.tail_expr_reachable ())
110+
if (expr.has_expr ())
111111
{
112112
dump += indent ();
113113
expr.expr->accept_vis (*this);

gcc/rust/typecheck/rust-tyty-call.h

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class TypeCheckCallExpr : private TyVisitor
5353
void visit (ReferenceType &type) override { gcc_unreachable (); }
5454
void visit (ParamType &) override { gcc_unreachable (); }
5555
void visit (StrType &) override { gcc_unreachable (); }
56+
void visit (NeverType &) override { gcc_unreachable (); }
5657

5758
// tuple-structs
5859
void visit (ADTType &type) override;
@@ -100,6 +101,7 @@ class TypeCheckMethodCallExpr : private TyVisitor
100101
void visit (ReferenceType &type) override { gcc_unreachable (); }
101102
void visit (ParamType &) override { gcc_unreachable (); }
102103
void visit (StrType &) override { gcc_unreachable (); }
104+
void visit (NeverType &) override { gcc_unreachable (); }
103105

104106
// FIXME
105107
void visit (FnPtr &type) override { gcc_unreachable (); }

gcc/rust/typecheck/rust-tyty-cmp.h

+17
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class BaseCmp : public TyVisitor
8484

8585
virtual void visit (StrType &) override { ok = false; }
8686

87+
virtual void visit (NeverType &) override { ok = false; }
88+
8789
protected:
8890
BaseCmp (BaseType *base)
8991
: mappings (Analysis::Mappings::get ()),
@@ -806,6 +808,21 @@ class StrCmp : public BaseCmp
806808
StrType *base;
807809
};
808810

811+
class NeverCmp : public BaseCmp
812+
{
813+
using Rust::TyTy::BaseCmp::visit;
814+
815+
public:
816+
NeverCmp (NeverType *base) : BaseCmp (base), base (base) {}
817+
818+
void visit (NeverType &type) override { ok = true; }
819+
820+
private:
821+
BaseType *get_base () override { return base; }
822+
823+
NeverType *base;
824+
};
825+
809826
} // namespace TyTy
810827
} // namespace Rust
811828

gcc/rust/typecheck/rust-tyty-rules.h

+23
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,14 @@ class BaseRules : public TyVisitor
242242
type.as_string ().c_str ());
243243
}
244244

245+
virtual void visit (NeverType &type) override
246+
{
247+
Location ref_locus = mappings->lookup_location (type.get_ref ());
248+
rust_error_at (ref_locus, "expected [%s] got [%s]",
249+
get_base ()->as_string ().c_str (),
250+
type.as_string ().c_str ());
251+
}
252+
245253
protected:
246254
BaseRules (BaseType *base)
247255
: mappings (Analysis::Mappings::get ()),
@@ -1087,6 +1095,21 @@ class StrRules : public BaseRules
10871095
StrType *base;
10881096
};
10891097

1098+
class NeverRules : public BaseRules
1099+
{
1100+
using Rust::TyTy::BaseRules::visit;
1101+
1102+
public:
1103+
NeverRules (NeverType *base) : BaseRules (base), base (base) {}
1104+
1105+
virtual void visit (NeverType &type) override { resolved = type.clone (); }
1106+
1107+
private:
1108+
BaseType *get_base () override { return base; }
1109+
1110+
NeverType *base;
1111+
};
1112+
10901113
} // namespace TyTy
10911114
} // namespace Rust
10921115

gcc/rust/typecheck/rust-tyty-visitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class TyVisitor
4444
virtual void visit (ReferenceType &type) = 0;
4545
virtual void visit (ParamType &type) = 0;
4646
virtual void visit (StrType &type) = 0;
47+
virtual void visit (NeverType &type) = 0;
4748
};
4849

4950
} // namespace TyTy

gcc/rust/typecheck/rust-tyty.cc

+32
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,38 @@ StrType::is_equal (const BaseType &other) const
13041304
return get_kind () == other.get_kind ();
13051305
}
13061306

1307+
void
1308+
NeverType::accept_vis (TyVisitor &vis)
1309+
{
1310+
vis.visit (*this);
1311+
}
1312+
1313+
std::string
1314+
NeverType::as_string () const
1315+
{
1316+
return "!";
1317+
}
1318+
1319+
BaseType *
1320+
NeverType::unify (BaseType *other)
1321+
{
1322+
NeverRules r (this);
1323+
return r.unify (other);
1324+
}
1325+
1326+
bool
1327+
NeverType::can_eq (BaseType *other)
1328+
{
1329+
NeverCmp r (this);
1330+
return r.can_eq (other);
1331+
}
1332+
1333+
BaseType *
1334+
NeverType::clone ()
1335+
{
1336+
return new NeverType (get_ref (), get_ty_ref (), get_combined_refs ());
1337+
}
1338+
13071339
// rust-tyty-call.h
13081340

13091341
void

0 commit comments

Comments
 (0)