Skip to content

Commit 7ae95e5

Browse files
committed
Auto merge of #40224 - nikomatsakis:issue-39808, r=eddyb
change the strategy for diverging types The new strategy is as follows. First, the `!` type is assigned in two cases: - a block with a diverging statement and no tail expression (e.g., `{return;}`); - any expression with the type `!` is considered diverging. Second, we track when we are in a diverging state, and we permit a value of any type to be coerced **into** `!` if the expression that produced it is diverging. This means that `fn foo() -> ! { panic!(); 22 }` type-checks, even though the block has a type of `usize`. Finally, coercions **from** the `!` type to any other are always permitted. Fixes #39808. Fixes #39984.
2 parents fe15119 + 2414222 commit 7ae95e5

File tree

146 files changed

+2433
-2592
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

146 files changed

+2433
-2592
lines changed

src/librustc/cfg/construct.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7474

7575
impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
7676
fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
77-
if let Some(break_to_expr_id) = blk.break_to_expr_id {
77+
if blk.targeted_by_break {
7878
let expr_exit = self.add_ast_node(blk.id, &[]);
7979

8080
self.breakable_block_scopes.push(BlockScope {
81-
block_expr_id: break_to_expr_id,
81+
block_expr_id: blk.id,
8282
break_index: expr_exit,
8383
});
8484

@@ -195,7 +195,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
195195
// [..expr..]
196196
//
197197
let cond_exit = self.expr(&cond, pred); // 1
198-
let then_exit = self.block(&then, cond_exit); // 2
198+
let then_exit = self.expr(&then, cond_exit); // 2
199199
self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4
200200
}
201201

@@ -215,7 +215,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
215215
// [..expr..]
216216
//
217217
let cond_exit = self.expr(&cond, pred); // 1
218-
let then_exit = self.block(&then, cond_exit); // 2
218+
let then_exit = self.expr(&then, cond_exit); // 2
219219
let else_exit = self.expr(&otherwise, cond_exit); // 3
220220
self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5
221221
}

src/librustc/hir/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
960960
}
961961
ExprIf(ref head_expression, ref if_block, ref optional_else) => {
962962
visitor.visit_expr(head_expression);
963-
visitor.visit_block(if_block);
963+
visitor.visit_expr(if_block);
964964
walk_list!(visitor, visit_expr, optional_else);
965965
}
966966
ExprWhile(ref subexpression, ref block, ref opt_sp_name) => {

src/librustc/hir/lowering.rs

+21-18
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ impl<'a> LoweringContext<'a> {
11561156
bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
11571157
}
11581158

1159-
fn lower_block(&mut self, b: &Block, break_to: Option<NodeId>) -> P<hir::Block> {
1159+
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
11601160
let mut expr = None;
11611161

11621162
let mut stmts = vec![];
@@ -1179,7 +1179,7 @@ impl<'a> LoweringContext<'a> {
11791179
expr: expr,
11801180
rules: self.lower_block_check_mode(&b.rules),
11811181
span: b.span,
1182-
break_to_expr_id: break_to,
1182+
targeted_by_break: targeted_by_break,
11831183
})
11841184
}
11851185

@@ -1274,7 +1274,7 @@ impl<'a> LoweringContext<'a> {
12741274
}
12751275
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
12761276
self.with_new_scopes(|this| {
1277-
let body = this.lower_block(body, None);
1277+
let body = this.lower_block(body, false);
12781278
let body = this.expr_block(body, ThinVec::new());
12791279
let body_id = this.record_body(body, Some(decl));
12801280
hir::ItemFn(this.lower_fn_decl(decl),
@@ -1368,7 +1368,7 @@ impl<'a> LoweringContext<'a> {
13681368
hir::TraitMethod::Required(names))
13691369
}
13701370
TraitItemKind::Method(ref sig, Some(ref body)) => {
1371-
let body = this.lower_block(body, None);
1371+
let body = this.lower_block(body, false);
13721372
let expr = this.expr_block(body, ThinVec::new());
13731373
let body_id = this.record_body(expr, Some(&sig.decl));
13741374
hir::TraitItemKind::Method(this.lower_method_sig(sig),
@@ -1424,7 +1424,7 @@ impl<'a> LoweringContext<'a> {
14241424
hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
14251425
}
14261426
ImplItemKind::Method(ref sig, ref body) => {
1427-
let body = this.lower_block(body, None);
1427+
let body = this.lower_block(body, false);
14281428
let expr = this.expr_block(body, ThinVec::new());
14291429
let body_id = this.record_body(expr, Some(&sig.decl));
14301430
hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
@@ -1848,32 +1848,35 @@ impl<'a> LoweringContext<'a> {
18481848
id: id,
18491849
rules: hir::DefaultBlock,
18501850
span: span,
1851-
break_to_expr_id: None,
1851+
targeted_by_break: false,
18521852
});
18531853
P(self.expr_block(blk, ThinVec::new()))
18541854
}
18551855
_ => P(self.lower_expr(els)),
18561856
}
18571857
});
18581858

1859-
hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk, None), else_opt)
1859+
let then_blk = self.lower_block(blk, false);
1860+
let then_expr = self.expr_block(then_blk, ThinVec::new());
1861+
1862+
hir::ExprIf(P(self.lower_expr(cond)), P(then_expr), else_opt)
18601863
}
18611864
ExprKind::While(ref cond, ref body, opt_ident) => {
18621865
self.with_loop_scope(e.id, |this|
18631866
hir::ExprWhile(
18641867
this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
1865-
this.lower_block(body, None),
1868+
this.lower_block(body, false),
18661869
this.lower_opt_sp_ident(opt_ident)))
18671870
}
18681871
ExprKind::Loop(ref body, opt_ident) => {
18691872
self.with_loop_scope(e.id, |this|
1870-
hir::ExprLoop(this.lower_block(body, None),
1873+
hir::ExprLoop(this.lower_block(body, false),
18711874
this.lower_opt_sp_ident(opt_ident),
18721875
hir::LoopSource::Loop))
18731876
}
18741877
ExprKind::Catch(ref body) => {
1875-
self.with_catch_scope(e.id, |this|
1876-
hir::ExprBlock(this.lower_block(body, Some(e.id))))
1878+
self.with_catch_scope(body.id, |this|
1879+
hir::ExprBlock(this.lower_block(body, true)))
18771880
}
18781881
ExprKind::Match(ref expr, ref arms) => {
18791882
hir::ExprMatch(P(self.lower_expr(expr)),
@@ -1891,7 +1894,7 @@ impl<'a> LoweringContext<'a> {
18911894
})
18921895
})
18931896
}
1894-
ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk, None)),
1897+
ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk, false)),
18951898
ExprKind::Assign(ref el, ref er) => {
18961899
hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
18971900
}
@@ -2037,7 +2040,7 @@ impl<'a> LoweringContext<'a> {
20372040

20382041
// `<pat> => <body>`
20392042
{
2040-
let body = self.lower_block(body, None);
2043+
let body = self.lower_block(body, false);
20412044
let body_expr = P(self.expr_block(body, ThinVec::new()));
20422045
let pat = self.lower_pat(pat);
20432046
arms.push(self.arm(hir_vec![pat], body_expr));
@@ -2109,7 +2112,7 @@ impl<'a> LoweringContext<'a> {
21092112
let (guard, body) = if let ExprKind::If(ref cond,
21102113
ref then,
21112114
_) = else_expr.node {
2112-
let then = self.lower_block(then, None);
2115+
let then = self.lower_block(then, false);
21132116
(Some(cond),
21142117
self.expr_block(then, ThinVec::new()))
21152118
} else {
@@ -2159,7 +2162,7 @@ impl<'a> LoweringContext<'a> {
21592162
// Note that the block AND the condition are evaluated in the loop scope.
21602163
// This is done to allow `break` from inside the condition of the loop.
21612164
let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| (
2162-
this.lower_block(body, None),
2165+
this.lower_block(body, false),
21632166
this.expr_break(e.span, ThinVec::new()),
21642167
this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
21652168
));
@@ -2220,7 +2223,7 @@ impl<'a> LoweringContext<'a> {
22202223
// `::std::option::Option::Some(<pat>) => <body>`
22212224
let pat_arm = {
22222225
let body_block = self.with_loop_scope(e.id,
2223-
|this| this.lower_block(body, None));
2226+
|this| this.lower_block(body, false));
22242227
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
22252228
let pat = self.lower_pat(pat);
22262229
let some_pat = self.pat_some(e.span, pat);
@@ -2652,7 +2655,7 @@ impl<'a> LoweringContext<'a> {
26522655
id: self.next_id(),
26532656
rules: hir::DefaultBlock,
26542657
span: span,
2655-
break_to_expr_id: None,
2658+
targeted_by_break: false,
26562659
}
26572660
}
26582661

@@ -2760,7 +2763,7 @@ impl<'a> LoweringContext<'a> {
27602763
id: id,
27612764
stmts: stmts,
27622765
expr: Some(expr),
2763-
break_to_expr_id: None,
2766+
targeted_by_break: false,
27642767
});
27652768
self.expr_block(block, attrs)
27662769
}

src/librustc/hir/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,11 @@ pub struct Block {
549549
/// Distinguishes between `unsafe { ... }` and `{ ... }`
550550
pub rules: BlockCheckMode,
551551
pub span: Span,
552-
/// The id of the expression that `break` breaks to if the block can be broken out of.
553-
/// Currently only `Some(_)` for `catch {}` blocks
554-
pub break_to_expr_id: Option<NodeId>,
552+
/// If true, then there may exist `break 'a` values that aim to
553+
/// break out of this block early. As of this writing, this is not
554+
/// currently permitted in Rust itself, but it is generated as
555+
/// part of `catch` statements.
556+
pub targeted_by_break: bool,
555557
}
556558

557559
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
@@ -993,8 +995,8 @@ pub enum Expr_ {
993995
ExprType(P<Expr>, P<Ty>),
994996
/// An `if` block, with an optional else block
995997
///
996-
/// `if expr { block } else { expr }`
997-
ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
998+
/// `if expr { expr } else { expr }`
999+
ExprIf(P<Expr>, P<Expr>, Option<P<Expr>>),
9981000
/// A while loop, with an optional label
9991001
///
10001002
/// `'label: while expr { block }`

src/librustc/hir/print.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,7 @@ impl<'a> State<'a> {
10361036
word(&mut self.s, " else if ")?;
10371037
self.print_expr(&i)?;
10381038
space(&mut self.s)?;
1039-
self.print_block(&then)?;
1039+
self.print_expr(&then)?;
10401040
self.print_else(e.as_ref().map(|e| &**e))
10411041
}
10421042
// "final else"
@@ -1058,13 +1058,13 @@ impl<'a> State<'a> {
10581058

10591059
pub fn print_if(&mut self,
10601060
test: &hir::Expr,
1061-
blk: &hir::Block,
1061+
blk: &hir::Expr,
10621062
elseopt: Option<&hir::Expr>)
10631063
-> io::Result<()> {
10641064
self.head("if")?;
10651065
self.print_expr(test)?;
10661066
space(&mut self.s)?;
1067-
self.print_block(blk)?;
1067+
self.print_expr(blk)?;
10681068
self.print_else(elseopt)
10691069
}
10701070

src/librustc/infer/type_variable.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct TypeVariableTable<'tcx> {
3030
}
3131

3232
/// Reasons to create a type inference variable
33+
#[derive(Debug)]
3334
pub enum TypeVariableOrigin {
3435
MiscVariable(Span),
3536
NormalizeProjectionType(Span),
@@ -41,6 +42,7 @@ pub enum TypeVariableOrigin {
4142
AdjustmentType(Span),
4243
DivergingStmt(Span),
4344
DivergingBlockExpr(Span),
45+
DivergingFn(Span),
4446
LatticeVariable(Span),
4547
}
4648

@@ -196,14 +198,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
196198
diverging: bool,
197199
origin: TypeVariableOrigin,
198200
default: Option<Default<'tcx>>,) -> ty::TyVid {
201+
debug!("new_var(diverging={:?}, origin={:?})", diverging, origin);
199202
self.eq_relations.new_key(());
200203
let index = self.values.push(TypeVariableData {
201204
value: Bounded { relations: vec![], default: default },
202205
origin: origin,
203206
diverging: diverging
204207
});
205208
let v = ty::TyVid { index: index as u32 };
206-
debug!("new_var() -> {:?}", v);
209+
debug!("new_var: diverging={:?} index={:?}", diverging, v);
207210
v
208211
}
209212

src/librustc/middle/expr_use_visitor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
414414
self.consume_exprs(exprs);
415415
}
416416

417-
hir::ExprIf(ref cond_expr, ref then_blk, ref opt_else_expr) => {
417+
hir::ExprIf(ref cond_expr, ref then_expr, ref opt_else_expr) => {
418418
self.consume_expr(&cond_expr);
419-
self.walk_block(&then_blk);
419+
self.walk_expr(&then_expr);
420420
if let Some(ref else_expr) = *opt_else_expr {
421421
self.consume_expr(&else_expr);
422422
}

src/librustc/middle/liveness.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
821821

822822
fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
823823
-> LiveNode {
824-
if let Some(break_to_expr_id) = blk.break_to_expr_id {
825-
self.breakable_block_ln.insert(break_to_expr_id, succ);
824+
if blk.targeted_by_break {
825+
self.breakable_block_ln.insert(blk.id, succ);
826826
}
827827
let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
828828
blk.stmts.iter().rev().fold(succ, |succ, stmt| {
@@ -951,7 +951,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
951951
// ( succ )
952952
//
953953
let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ);
954-
let then_ln = self.propagate_through_block(&then, succ);
954+
let then_ln = self.propagate_through_expr(&then, succ);
955955
let ln = self.live_node(expr.id, expr.span);
956956
self.init_from_succ(ln, else_ln);
957957
self.merge_from_succ(ln, then_ln, false);

src/librustc/traits/error_reporting.rs

+1
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
904904
ObligationCauseCode::StartFunctionType |
905905
ObligationCauseCode::IntrinsicType |
906906
ObligationCauseCode::MethodReceiver |
907+
ObligationCauseCode::ReturnNoExpression |
907908
ObligationCauseCode::MiscObligation => {
908909
}
909910
ObligationCauseCode::SliceOrArrayElem => {

src/librustc/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ pub enum ObligationCauseCode<'tcx> {
173173

174174
// method receiver
175175
MethodReceiver,
176+
177+
// `return` with no expression
178+
ReturnNoExpression,
176179
}
177180

178181
#[derive(Clone, Debug, PartialEq, Eq)]

src/librustc/traits/structural_impls.rs

+3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
167167
type Lifted = traits::ObligationCauseCode<'tcx>;
168168
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
169169
match *self {
170+
super::ReturnNoExpression => Some(super::ReturnNoExpression),
170171
super::MiscObligation => Some(super::MiscObligation),
171172
super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
172173
super::TupleElem => Some(super::TupleElem),
@@ -489,6 +490,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
489490
super::StructInitializerSized |
490491
super::VariableType(_) |
491492
super::ReturnType |
493+
super::ReturnNoExpression |
492494
super::RepeatVec |
493495
super::FieldSized |
494496
super::ConstSized |
@@ -533,6 +535,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
533535
super::StructInitializerSized |
534536
super::VariableType(_) |
535537
super::ReturnType |
538+
super::ReturnNoExpression |
536539
super::RepeatVec |
537540
super::FieldSized |
538541
super::ConstSized |

0 commit comments

Comments
 (0)