@@ -24,6 +24,7 @@ use std::fmt;
2424use syntax:: ast;
2525use syntax_pos:: { Span , DUMMY_SP } ;
2626
27+ use rustc_data_structures:: fx:: FxHashSet ;
2728use rustc_data_structures:: indexed_vec:: Idx ;
2829
2930fn mirbug ( tcx : TyCtxt , span : Span , msg : & str ) {
@@ -87,6 +88,11 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
8788 self . sanitize_type ( rvalue, rval_ty) ;
8889 }
8990
91+ fn visit_local_decl ( & mut self , local_decl : & LocalDecl < ' tcx > ) {
92+ self . super_local_decl ( local_decl) ;
93+ self . sanitize_type ( local_decl, local_decl. ty ) ;
94+ }
95+
9096 fn visit_mir ( & mut self , mir : & Mir < ' tcx > ) {
9197 self . sanitize_type ( & "return type" , mir. return_ty ) ;
9298 for local_decl in & mir. local_decls {
@@ -317,6 +323,7 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
317323 fulfillment_cx : traits:: FulfillmentContext < ' tcx > ,
318324 last_span : Span ,
319325 body_id : ast:: NodeId ,
326+ reported_errors : FxHashSet < ( Ty < ' tcx > , Span ) > ,
320327}
321328
322329impl < ' a , ' gcx , ' tcx > TypeChecker < ' a , ' gcx , ' tcx > {
@@ -326,6 +333,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
326333 fulfillment_cx : traits:: FulfillmentContext :: new ( ) ,
327334 last_span : DUMMY_SP ,
328335 body_id : body_id,
336+ reported_errors : FxHashSet ( ) ,
329337 }
330338 }
331339
@@ -641,9 +649,39 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
641649 }
642650 }
643651
644- fn typeck_mir ( & mut self , mir : & Mir < ' tcx > ) {
652+ fn check_local ( & mut self , mir : & Mir < ' gcx > , local : Local , local_decl : & LocalDecl < ' gcx > ) {
653+ match mir. local_kind ( local) {
654+ LocalKind :: ReturnPointer | LocalKind :: Arg => {
655+ // return values of normal functions are required to be
656+ // sized by typeck, but return values of ADT constructors are
657+ // not because we don't include a `Self: Sized` bounds on them.
658+ //
659+ // Unbound parts of arguments were never required to be Sized
660+ // - maybe we should make that a warning.
661+ return
662+ }
663+ LocalKind :: Var | LocalKind :: Temp => { }
664+ }
665+
666+ let span = local_decl. source_info . span ;
667+ let ty = local_decl. ty ;
668+ if !ty. is_sized ( self . tcx ( ) . global_tcx ( ) , self . infcx . param_env ( ) , span) {
669+ if let None = self . reported_errors . replace ( ( ty, span) ) {
670+ span_err ! ( self . tcx( ) . sess, span, E0161 ,
671+ "cannot move a value of type {0}: the size of {0} \
672+ cannot be statically determined", ty) ;
673+ }
674+ }
675+ }
676+
677+ fn typeck_mir ( & mut self , mir : & Mir < ' gcx > ) {
645678 self . last_span = mir. span ;
646679 debug ! ( "run_on_mir: {:?}" , mir. span) ;
680+
681+ for ( local, local_decl) in mir. local_decls . iter_enumerated ( ) {
682+ self . check_local ( mir, local, local_decl) ;
683+ }
684+
647685 for block in mir. basic_blocks ( ) {
648686 for stmt in & block. statements {
649687 if stmt. source_info . span != DUMMY_SP {
@@ -698,16 +736,18 @@ impl TypeckMir {
698736impl < ' tcx > MirPass < ' tcx > for TypeckMir {
699737 fn run_pass < ' a > ( & mut self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
700738 src : MirSource , mir : & mut Mir < ' tcx > ) {
701- debug ! ( "run_pass: {}" , tcx. node_path_str( src. item_id( ) ) ) ;
739+ let item_id = src. item_id ( ) ;
740+ let def_id = tcx. hir . local_def_id ( item_id) ;
741+ debug ! ( "run_pass: {}" , tcx. item_path_str( def_id) ) ;
702742
703743 if tcx. sess . err_count ( ) > 0 {
704744 // compiling a broken program can obviously result in a
705745 // broken MIR, so try not to report duplicate errors.
706746 return ;
707747 }
708- let param_env = ty:: ParameterEnvironment :: for_item ( tcx, src . item_id ( ) ) ;
748+ let param_env = ty:: ParameterEnvironment :: for_item ( tcx, item_id) ;
709749 tcx. infer_ctxt ( param_env, Reveal :: UserFacing ) . enter ( |infcx| {
710- let mut checker = TypeChecker :: new ( & infcx, src . item_id ( ) ) ;
750+ let mut checker = TypeChecker :: new ( & infcx, item_id) ;
711751 {
712752 let mut verifier = TypeVerifier :: new ( & mut checker, mir) ;
713753 verifier. visit_mir ( mir) ;
0 commit comments