@@ -451,7 +451,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
451
451
// expects the types within the function to be consistent.
452
452
err_count_on_creation : usize ,
453
453
454
- ret_ty : Ty < ' tcx > ,
454
+ ret_ty : Option < Ty < ' tcx > > ,
455
455
456
456
ps : RefCell < UnsafetyState > ,
457
457
@@ -785,11 +785,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
785
785
786
786
// Create the function context. This is either derived from scratch or,
787
787
// in the case of function expressions, based on the outer context.
788
- let mut fcx = FnCtxt :: new ( inherited, fn_sig. output ( ) , body. id ) ;
788
+ let mut fcx = FnCtxt :: new ( inherited, body. id ) ;
789
+ let ret_ty = fn_sig. output ( ) ;
789
790
* fcx. ps . borrow_mut ( ) = UnsafetyState :: function ( unsafety, unsafety_id) ;
790
791
791
- fcx. require_type_is_sized ( fcx . ret_ty , decl. output . span ( ) , traits:: ReturnType ) ;
792
- fcx. ret_ty = fcx. instantiate_anon_types ( & fcx . ret_ty ) ;
792
+ fcx. require_type_is_sized ( ret_ty, decl. output . span ( ) , traits:: ReturnType ) ;
793
+ fcx. ret_ty = fcx. instantiate_anon_types ( & ret_ty) ;
793
794
fn_sig = fcx. tcx . mk_fn_sig ( fn_sig. inputs ( ) . iter ( ) . cloned ( ) , & fcx. ret_ty , fn_sig. variadic ) ;
794
795
795
796
{
@@ -821,7 +822,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
821
822
822
823
inherited. tables . borrow_mut ( ) . liberated_fn_sigs . insert ( fn_id, fn_sig) ;
823
824
824
- fcx. check_expr_coercable_to_type ( body, fcx. ret_ty ) ;
825
+ fcx. check_expr_coercable_to_type ( body, fcx. ret_ty . unwrap ( ) ) ;
825
826
826
827
fcx
827
828
}
@@ -1245,7 +1246,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
1245
1246
expected_type : Ty < ' tcx > ,
1246
1247
id : ast:: NodeId ) {
1247
1248
ccx. inherited ( id) . enter ( |inh| {
1248
- let fcx = FnCtxt :: new ( & inh, expected_type , expr. id ) ;
1249
+ let fcx = FnCtxt :: new ( & inh, expr. id ) ;
1249
1250
fcx. require_type_is_sized ( expected_type, expr. span , traits:: ConstSized ) ;
1250
1251
1251
1252
// Gather locals in statics (because of block expressions).
@@ -1530,15 +1531,14 @@ enum TupleArgumentsFlag {
1530
1531
1531
1532
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
1532
1533
pub fn new ( inh : & ' a Inherited < ' a , ' gcx , ' tcx > ,
1533
- rty : Ty < ' tcx > ,
1534
1534
body_id : ast:: NodeId )
1535
1535
-> FnCtxt < ' a , ' gcx , ' tcx > {
1536
1536
FnCtxt {
1537
1537
ast_ty_to_ty_cache : RefCell :: new ( NodeMap ( ) ) ,
1538
1538
body_id : body_id,
1539
1539
writeback_errors : Cell :: new ( false ) ,
1540
1540
err_count_on_creation : inh. tcx . sess . err_count ( ) ,
1541
- ret_ty : rty ,
1541
+ ret_ty : None ,
1542
1542
ps : RefCell :: new ( UnsafetyState :: function ( hir:: Unsafety :: Normal ,
1543
1543
ast:: CRATE_NODE_ID ) ) ,
1544
1544
diverges : Cell :: new ( Diverges :: Maybe ) ,
@@ -3705,14 +3705,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3705
3705
}
3706
3706
hir:: ExprAgain ( _) => { tcx. types . never }
3707
3707
hir:: ExprRet ( ref expr_opt) => {
3708
- if let Some ( ref e) = * expr_opt {
3709
- self . check_expr_coercable_to_type ( & e, self . ret_ty ) ;
3708
+ if self . ret_ty . is_none ( ) {
3709
+ struct_span_err ! ( self . tcx. sess, expr. span, E0571 ,
3710
+ "return statement cannot be out of a function scope" ) . emit ( ) ;
3711
+ } else if let Some ( ref e) = * expr_opt {
3712
+ self . check_expr_coercable_to_type ( & e, self . ret_ty . unwrap ( ) ) ;
3710
3713
} else {
3711
3714
match self . eq_types ( false ,
3712
3715
& self . misc ( expr. span ) ,
3713
- self . ret_ty ,
3714
- tcx. mk_nil ( ) )
3715
- {
3716
+ self . ret_ty . unwrap ( ) ,
3717
+ tcx. mk_nil ( ) ) {
3716
3718
Ok ( ok) => self . register_infer_ok_obligations ( ok) ,
3717
3719
Err ( _) => {
3718
3720
struct_span_err ! ( tcx. sess, expr. span, E0069 ,
0 commit comments