@@ -451,7 +451,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
451451 // expects the types within the function to be consistent.
452452 err_count_on_creation : usize ,
453453
454- ret_ty : Ty < ' tcx > ,
454+ ret_ty : Option < Ty < ' tcx > > ,
455455
456456 ps : RefCell < UnsafetyState > ,
457457
@@ -785,12 +785,14 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
785785
786786 // Create the function context. This is either derived from scratch or,
787787 // 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, None , body. id ) ;
789+ let ret_ty = fn_sig. output ( ) ;
789790 * fcx. ps . borrow_mut ( ) = UnsafetyState :: function ( unsafety, unsafety_id) ;
790791
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 ) ;
793- fn_sig = fcx. tcx . mk_fn_sig ( fn_sig. inputs ( ) . iter ( ) . cloned ( ) , & fcx. ret_ty , fn_sig. variadic ) ;
792+ fcx. require_type_is_sized ( ret_ty, decl. output . span ( ) , traits:: ReturnType ) ;
793+ fcx. ret_ty = fcx. instantiate_anon_types ( & Some ( ret_ty) ) ;
794+ fn_sig = fcx. tcx . mk_fn_sig ( fn_sig. inputs ( ) . iter ( ) . cloned ( ) , & fcx. ret_ty . unwrap ( ) ,
795+ fn_sig. variadic ) ;
794796
795797 {
796798 let mut visit = GatherLocalsVisitor { fcx : & fcx, } ;
@@ -821,7 +823,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
821823
822824 inherited. tables . borrow_mut ( ) . liberated_fn_sigs . insert ( fn_id, fn_sig) ;
823825
824- fcx. check_expr_coercable_to_type ( body, fcx. ret_ty ) ;
826+ fcx. check_expr_coercable_to_type ( body, fcx. ret_ty . unwrap ( ) ) ;
825827
826828 fcx
827829}
@@ -1245,7 +1247,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
12451247 expected_type : Ty < ' tcx > ,
12461248 id : ast:: NodeId ) {
12471249 ccx. inherited ( id) . enter ( |inh| {
1248- let fcx = FnCtxt :: new ( & inh, expected_type , expr. id ) ;
1250+ let fcx = FnCtxt :: new ( & inh, None , expr. id ) ;
12491251 fcx. require_type_is_sized ( expected_type, expr. span , traits:: ConstSized ) ;
12501252
12511253 // Gather locals in statics (because of block expressions).
@@ -1530,7 +1532,7 @@ enum TupleArgumentsFlag {
15301532
15311533impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
15321534 pub fn new ( inh : & ' a Inherited < ' a , ' gcx , ' tcx > ,
1533- rty : Ty < ' tcx > ,
1535+ rty : Option < Ty < ' tcx > > ,
15341536 body_id : ast:: NodeId )
15351537 -> FnCtxt < ' a , ' gcx , ' tcx > {
15361538 FnCtxt {
@@ -3705,14 +3707,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
37053707 }
37063708 hir:: ExprAgain ( _) => { tcx. types . never }
37073709 hir:: ExprRet ( ref expr_opt) => {
3708- if let Some ( ref e) = * expr_opt {
3709- self . check_expr_coercable_to_type ( & e, self . ret_ty ) ;
3710+ if self . ret_ty . is_none ( ) {
3711+ struct_span_err ! ( self . tcx. sess, expr. span, E0572 ,
3712+ "return statement outside of function body" ) . emit ( ) ;
3713+ } else if let Some ( ref e) = * expr_opt {
3714+ self . check_expr_coercable_to_type ( & e, self . ret_ty . unwrap ( ) ) ;
37103715 } else {
37113716 match self . eq_types ( false ,
37123717 & self . misc ( expr. span ) ,
3713- self . ret_ty ,
3714- tcx. mk_nil ( ) )
3715- {
3718+ self . ret_ty . unwrap ( ) ,
3719+ tcx. mk_nil ( ) ) {
37163720 Ok ( ok) => self . register_infer_ok_obligations ( ok) ,
37173721 Err ( _) => {
37183722 struct_span_err ! ( tcx. sess, expr. span, E0069 ,
0 commit comments