@@ -31,26 +31,21 @@ mod var_name;
3131enum ConstraintCategory {
3232 Cast ,
3333 Assignment ,
34- AssignmentToUpvar ,
3534 Return ,
36- CallArgumentToUpvar ,
3735 CallArgument ,
3836 Other ,
3937 Boring ,
4038}
4139
4240impl fmt:: Display for ConstraintCategory {
4341 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
42+ // Must end with a space. Allows for empty names to be provided.
4443 match self {
45- ConstraintCategory :: Assignment | ConstraintCategory :: AssignmentToUpvar => {
46- write ! ( f, "assignment" )
47- }
48- ConstraintCategory :: Return => write ! ( f, "return" ) ,
49- ConstraintCategory :: Cast => write ! ( f, "cast" ) ,
50- ConstraintCategory :: CallArgument | ConstraintCategory :: CallArgumentToUpvar => {
51- write ! ( f, "argument" )
52- }
53- _ => write ! ( f, "free region" ) ,
44+ ConstraintCategory :: Assignment => write ! ( f, "assignment " ) ,
45+ ConstraintCategory :: Return => write ! ( f, "return " ) ,
46+ ConstraintCategory :: Cast => write ! ( f, "cast " ) ,
47+ ConstraintCategory :: CallArgument => write ! ( f, "argument " ) ,
48+ _ => write ! ( f, "" ) ,
5449 }
5550 }
5651}
@@ -224,10 +219,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
224219 "constraint_is_interesting: locations={:?} constraint={:?}" ,
225220 constraint. locations, constraint
226221 ) ;
227- if let Locations :: Interesting ( _ ) = constraint . locations {
228- true
229- } else {
230- false
222+
223+ match constraint . locations {
224+ Locations :: Interesting ( _ ) | Locations :: All => true ,
225+ _ => false ,
231226 }
232227 }
233228
@@ -320,45 +315,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
320315 }
321316 }
322317
323- let category = match (
324- category,
318+ let ( fr_is_local, outlived_fr_is_local) : ( bool , bool ) = (
325319 self . universal_regions . is_local_free_region ( fr) ,
326320 self . universal_regions . is_local_free_region ( outlived_fr) ,
327- ) {
328- ( ConstraintCategory :: Assignment , true , false ) => ConstraintCategory :: AssignmentToUpvar ,
329- ( ConstraintCategory :: CallArgument , true , false ) => {
330- ConstraintCategory :: CallArgumentToUpvar
331- }
332- ( category, _, _) => category,
321+ ) ;
322+ debug ! ( "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}" ,
323+ fr_is_local, outlived_fr_is_local, category) ;
324+
325+ match ( category, fr_is_local, outlived_fr_is_local) {
326+ ( ConstraintCategory :: Assignment , true , false ) |
327+ ( ConstraintCategory :: CallArgument , true , false ) =>
328+ self . report_escaping_data_error ( mir, infcx, mir_def_id, fr, outlived_fr,
329+ category, span, errors_buffer) ,
330+ _ =>
331+ self . report_general_error ( mir, infcx, mir_def_id, fr, fr_is_local,
332+ outlived_fr, outlived_fr_is_local,
333+ category, span, errors_buffer) ,
333334 } ;
334-
335- debug ! ( "report_error: category={:?}" , category) ;
336- match category {
337- ConstraintCategory :: AssignmentToUpvar | ConstraintCategory :: CallArgumentToUpvar => self
338- . report_closure_error (
339- mir,
340- infcx,
341- mir_def_id,
342- fr,
343- outlived_fr,
344- category,
345- span,
346- errors_buffer,
347- ) ,
348- _ => self . report_general_error (
349- mir,
350- infcx,
351- mir_def_id,
352- fr,
353- outlived_fr,
354- category,
355- span,
356- errors_buffer,
357- ) ,
358- }
359335 }
360336
361- fn report_closure_error (
337+ fn report_escaping_data_error (
362338 & self ,
363339 mir : & Mir < ' tcx > ,
364340 infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
@@ -373,29 +349,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
373349 let outlived_fr_name_and_span =
374350 self . get_var_name_and_span_for_region ( infcx. tcx , mir, outlived_fr) ;
375351
352+ let escapes_from = if infcx. tcx . is_closure ( mir_def_id) { "closure" } else { "function" } ;
353+
376354 if fr_name_and_span. is_none ( ) && outlived_fr_name_and_span. is_none ( ) {
377- return self . report_general_error (
378- mir,
379- infcx,
380- mir_def_id,
381- fr,
382- outlived_fr,
383- category,
384- span,
385- errors_buffer,
386- ) ;
355+ return self . report_general_error ( mir, infcx, mir_def_id,
356+ fr, true , outlived_fr, false ,
357+ category, span, errors_buffer) ;
387358 }
388359
389- let mut diag = infcx
390- . tcx
391- . sess
392- . struct_span_err ( span, & format ! ( "borrowed data escapes outside of closure" ) ) ;
360+ let mut diag = infcx. tcx . sess . struct_span_err (
361+ span, & format ! ( "borrowed data escapes outside of {}" , escapes_from) ,
362+ ) ;
393363
394364 if let Some ( ( outlived_fr_name, outlived_fr_span) ) = outlived_fr_name_and_span {
395365 if let Some ( name) = outlived_fr_name {
396366 diag. span_label (
397367 outlived_fr_span,
398- format ! ( "`{}` is declared here, outside of the closure body" , name) ,
368+ format ! ( "`{}` is declared here, outside of the {} body" , name, escapes_from ) ,
399369 ) ;
400370 }
401371 }
@@ -404,13 +374,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
404374 if let Some ( name) = fr_name {
405375 diag. span_label (
406376 fr_span,
407- format ! (
408- "`{}` is a reference that is only valid in the closure body" ,
409- name
410- ) ,
377+ format ! ( "`{}` is a reference that is only valid in the {} body" ,
378+ name, escapes_from) ,
411379 ) ;
412380
413- diag. span_label ( span, format ! ( "`{}` escapes the closure body here" , name) ) ;
381+ diag. span_label ( span, format ! ( "`{}` escapes the {} body here" ,
382+ name, escapes_from) ) ;
414383 }
415384 }
416385
@@ -423,7 +392,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
423392 infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
424393 mir_def_id : DefId ,
425394 fr : RegionVid ,
395+ fr_is_local : bool ,
426396 outlived_fr : RegionVid ,
397+ outlived_fr_is_local : bool ,
427398 category : ConstraintCategory ,
428399 span : Span ,
429400 errors_buffer : & mut Vec < Diagnostic > ,
@@ -434,17 +405,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
434405 ) ;
435406
436407 let counter = & mut 1 ;
437- let fr_name = self . give_region_a_name ( infcx. tcx , mir, mir_def_id, fr, counter, & mut diag) ;
438- let outlived_fr_name =
439- self . give_region_a_name ( infcx. tcx , mir, mir_def_id, outlived_fr, counter, & mut diag) ;
440-
441- diag. span_label (
442- span,
443- format ! (
444- "{} requires that `{}` must outlive `{}`" ,
445- category, fr_name, outlived_fr_name,
446- ) ,
447- ) ;
408+ let fr_name = self . give_region_a_name (
409+ infcx, mir, mir_def_id, fr, counter, & mut diag) ;
410+ let outlived_fr_name = self . give_region_a_name (
411+ infcx, mir, mir_def_id, outlived_fr, counter, & mut diag) ;
412+
413+ let mir_def_name = if infcx. tcx . is_closure ( mir_def_id) { "closure" } else { "function" } ;
414+
415+ match ( category, outlived_fr_is_local, fr_is_local) {
416+ ( ConstraintCategory :: Return , true , _) => {
417+ diag. span_label ( span, format ! (
418+ "{} was supposed to return data with lifetime `{}` but it is returning \
419+ data with lifetime `{}`",
420+ mir_def_name, fr_name, outlived_fr_name,
421+ ) ) ;
422+ } ,
423+ _ => {
424+ diag. span_label ( span, format ! (
425+ "{}requires that `{}` must outlive `{}`" ,
426+ category, fr_name, outlived_fr_name,
427+ ) ) ;
428+ } ,
429+ }
448430
449431 diag. buffer ( errors_buffer) ;
450432 }
0 commit comments