Skip to content

Commit 3aeb9f4

Browse files
committed
Introduce limited support for the never type
1 parent c5fdf8c commit 3aeb9f4

29 files changed

+316
-49
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
@@ -622,17 +623,28 @@ class TypeCheckExpr : public TypeCheckBase
622623
auto else_blk_resolved
623624
= TypeCheckExpr::Resolve (expr.get_else_block (), inside_loop);
624625

625-
infered = if_blk_resolved->unify (else_blk_resolved);
626+
if (if_blk_resolved->get_kind () == TyTy::NEVER)
627+
infered = else_blk_resolved;
628+
else if (else_blk_resolved->get_kind () == TyTy::NEVER)
629+
infered = if_blk_resolved;
630+
else
631+
infered = if_blk_resolved->unify (else_blk_resolved);
626632
}
627633

628634
void visit (HIR::IfExprConseqIf &expr) override
629635
{
630636
TypeCheckExpr::Resolve (expr.get_if_condition (), false);
631-
auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop);
632-
auto else_blk
637+
auto if_blk_resolved
638+
= TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop);
639+
auto else_blk_resolved
633640
= TypeCheckExpr::Resolve (expr.get_conseq_if_expr (), inside_loop);
634641

635-
infered = if_blk->unify (else_blk);
642+
if (if_blk_resolved->get_kind () == TyTy::NEVER)
643+
infered = else_blk_resolved;
644+
else if (else_blk_resolved->get_kind () == TyTy::NEVER)
645+
infered = if_blk_resolved;
646+
else
647+
infered = if_blk_resolved->unify (else_blk_resolved);
636648
}
637649

638650
void visit (HIR::BlockExpr &expr) override;
@@ -929,7 +941,7 @@ class TypeCheckExpr : public TypeCheckBase
929941
context->swap_head_loop_context (unified_ty);
930942
}
931943

932-
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
944+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
933945
}
934946

935947
void visit (HIR::ContinueExpr &expr) override
@@ -941,7 +953,7 @@ class TypeCheckExpr : public TypeCheckBase
941953
return;
942954
}
943955

944-
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
956+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
945957
}
946958

947959
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.cc

+8-21
Original file line numberDiff line numberDiff line change
@@ -123,27 +123,15 @@ 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-
else if (s->is_unit_check_needed () && !resolved->is_unit ())
134+
if (s->is_unit_check_needed () && !resolved->is_unit ())
147135
{
148136
auto unit = new TyTy::TupleType (s->get_mappings ().get_hirid ());
149137
resolved = unit->unify (resolved);
@@ -153,14 +141,13 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
153141
});
154142

155143
if (expr.has_expr ())
156-
{
157-
delete block_tyty;
158-
159-
block_tyty
160-
= TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop);
161-
}
162-
163-
infered = block_tyty->clone ();
144+
infered
145+
= TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop)
146+
->clone ();
147+
else if (expr.is_tail_reachable ())
148+
infered = new TyTy::TupleType (expr.get_mappings ().get_hirid ());
149+
else
150+
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
164151
}
165152

166153
// RUST_HIR_TYPE_CHECK_STRUCT_FIELD

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

+4
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)
@@ -258,6 +261,7 @@ class GetUsedSubstArgs : public TyTy::TyVisitor
258261
void visit (TyTy::ReferenceType &) override { gcc_unreachable (); }
259262
void visit (TyTy::ParamType &) override { gcc_unreachable (); }
260263
void visit (TyTy::StrType &) override { gcc_unreachable (); }
264+
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
261265

262266
private:
263267
GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}

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 ()),
@@ -815,6 +817,21 @@ class StrCmp : public BaseCmp
815817
StrType *base;
816818
};
817819

820+
class NeverCmp : public BaseCmp
821+
{
822+
using Rust::TyTy::BaseCmp::visit;
823+
824+
public:
825+
NeverCmp (NeverType *base) : BaseCmp (base), base (base) {}
826+
827+
void visit (NeverType &type) override { ok = true; }
828+
829+
private:
830+
BaseType *get_base () override { return base; }
831+
832+
NeverType *base;
833+
};
834+
818835
} // namespace TyTy
819836
} // namespace Rust
820837

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

+23
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,14 @@ class BaseRules : public TyVisitor
293293
type.as_string ().c_str ());
294294
}
295295

296+
virtual void visit (NeverType &type) override
297+
{
298+
Location ref_locus = mappings->lookup_location (type.get_ref ());
299+
rust_error_at (ref_locus, "expected [%s] got [%s]",
300+
get_base ()->as_string ().c_str (),
301+
type.as_string ().c_str ());
302+
}
303+
296304
protected:
297305
BaseRules (BaseType *base)
298306
: mappings (Analysis::Mappings::get ()),
@@ -1138,6 +1146,21 @@ class StrRules : public BaseRules
11381146
StrType *base;
11391147
};
11401148

1149+
class NeverRules : public BaseRules
1150+
{
1151+
using Rust::TyTy::BaseRules::visit;
1152+
1153+
public:
1154+
NeverRules (NeverType *base) : BaseRules (base), base (base) {}
1155+
1156+
virtual void visit (NeverType &type) override { resolved = type.clone (); }
1157+
1158+
private:
1159+
BaseType *get_base () override { return base; }
1160+
1161+
NeverType *base;
1162+
};
1163+
11411164
} // namespace TyTy
11421165
} // namespace Rust
11431166

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
@@ -1307,6 +1307,38 @@ StrType::is_equal (const BaseType &other) const
13071307
return get_kind () == other.get_kind ();
13081308
}
13091309

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

13121344
void

0 commit comments

Comments
 (0)