|
9 | 9 | // except according to those terms. |
10 | 10 |
|
11 | 11 | use syntax_pos::Span; |
| 12 | +use rustc::middle::region::ScopeTree; |
12 | 13 | use rustc::mir::{BorrowKind, Field, Local, Location, Operand}; |
13 | 14 | use rustc::mir::{Place, ProjectionElem, Rvalue, StatementKind}; |
14 | 15 | use rustc::ty::{self, RegionKind}; |
15 | 16 | use rustc_data_structures::indexed_vec::Idx; |
16 | 17 |
|
| 18 | +use std::rc::Rc; |
| 19 | + |
17 | 20 | use super::{MirBorrowckCtxt, Context}; |
18 | 21 | use super::{InitializationRequiringAction, PrefixSet}; |
19 | 22 | use dataflow::{BorrowData, Borrows, FlowAtLocation, MovingOutStatements}; |
@@ -354,64 +357,100 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { |
354 | 357 | _ => drop_span, |
355 | 358 | }; |
356 | 359 |
|
357 | | - match &self.describe_place(&borrow.place) { |
358 | | - Some(description) => { |
359 | | - match borrow.region { |
360 | | - RegionKind::ReScope(_) => { |
361 | | - let mut err = self.tcx.path_does_not_live_long_enough( |
362 | | - drop_span, &format!("`{}`", description), Origin::Mir); |
363 | | - err.span_label(borrow_span, "borrow occurs here"); |
364 | | - err.span_label(drop_span, |
365 | | - format!("`{}` dropped here while still borrowed", |
366 | | - description)); |
367 | | - if let Some(end) = end_span { |
368 | | - err.span_label(end, "borrowed value needs to live until here"); |
369 | | - } |
370 | | - err.emit(); |
371 | | - }, |
372 | | - _ => { |
373 | | - let mut err = self.tcx.path_does_not_live_long_enough( |
374 | | - borrow_span, &format!("`{}`", description), Origin::Mir); |
375 | | - err.span_label(borrow_span, "does not live long enough"); |
376 | | - err.span_label(drop_span, "borrowed value only lives until here"); |
377 | | - self.tcx.note_and_explain_region(scope_tree, &mut err, |
378 | | - "borrowed value must be valid for ", |
379 | | - borrow.region, "..."); |
380 | | - err.emit(); |
381 | | - } |
382 | | - } |
| 360 | + match (borrow.region, &self.describe_place(&borrow.place)) { |
| 361 | + (RegionKind::ReScope(_), Some(name)) => { |
| 362 | + self.report_scoped_local_value_does_not_live_long_enough( |
| 363 | + name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); |
383 | 364 | }, |
384 | | - None => { |
385 | | - match borrow.region { |
386 | | - RegionKind::ReEarlyBound(_) | RegionKind::ReFree(_) => { |
387 | | - let mut err = self.tcx.path_does_not_live_long_enough(proper_span, |
388 | | - "borrowed value", |
389 | | - Origin::Mir); |
390 | | - err.span_label(proper_span, "does not live long enough"); |
391 | | - err.span_label(drop_span, "temporary value only lives until here"); |
392 | | - self.tcx.note_and_explain_region(scope_tree, &mut err, |
393 | | - "borrowed value must be valid for ", |
394 | | - borrow.region, "..."); |
395 | | - err.emit(); |
396 | | - }, |
397 | | - _ => { |
398 | | - let mut err = self.tcx.path_does_not_live_long_enough(drop_span, |
399 | | - "borrowed value", |
400 | | - Origin::Mir); |
401 | | - err.span_label(proper_span, "temporary value created here"); |
402 | | - err.span_label(drop_span, |
403 | | - "temporary value dropped here while still borrowed"); |
404 | | - err.note("consider using a `let` binding to increase its lifetime"); |
405 | | - if let Some(end) = end_span { |
406 | | - err.span_label(end, "temporary value needs to live until here"); |
407 | | - } |
408 | | - err.emit(); |
409 | | - }, |
410 | | - } |
| 365 | + (RegionKind::ReScope(_), None) => { |
| 366 | + self.report_scoped_temporary_value_does_not_live_long_enough( |
| 367 | + &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); |
| 368 | + }, |
| 369 | + (RegionKind::ReEarlyBound(_), Some(name)) | |
| 370 | + (RegionKind::ReFree(_), Some(name)) | |
| 371 | + (RegionKind::ReStatic, Some(name)) | |
| 372 | + (RegionKind::ReEmpty, Some(name)) | |
| 373 | + (RegionKind::ReVar(_), Some(name)) => { |
| 374 | + self.report_unscoped_local_value_does_not_live_long_enough( |
| 375 | + name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); |
| 376 | + }, |
| 377 | + (RegionKind::ReEarlyBound(_), None) | |
| 378 | + (RegionKind::ReFree(_), None) | |
| 379 | + (RegionKind::ReStatic, None) | |
| 380 | + (RegionKind::ReEmpty, None) | |
| 381 | + (RegionKind::ReVar(_), None) => { |
| 382 | + self.report_unscoped_temporary_value_does_not_live_long_enough( |
| 383 | + &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); |
| 384 | + }, |
| 385 | + (RegionKind::ReLateBound(_, _), _) | |
| 386 | + (RegionKind::ReSkolemized(_, _), _) | |
| 387 | + (RegionKind::ReErased, _) => { |
| 388 | + span_bug!(drop_span, "region does not make sense in this context"); |
411 | 389 | }, |
412 | 390 | } |
413 | 391 | } |
414 | 392 |
|
| 393 | + fn report_scoped_local_value_does_not_live_long_enough( |
| 394 | + &mut self, name: &String, _scope_tree: &Rc<ScopeTree>, _borrow: &BorrowData<'tcx>, |
| 395 | + drop_span: Span, borrow_span: Span, _proper_span: Span, end_span: Option<Span> |
| 396 | + ) { |
| 397 | + let mut err = self.tcx.path_does_not_live_long_enough(drop_span, |
| 398 | + &format!("`{}`", name), |
| 399 | + Origin::Mir); |
| 400 | + err.span_label(borrow_span, "borrow occurs here"); |
| 401 | + err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); |
| 402 | + if let Some(end) = end_span { |
| 403 | + err.span_label(end, "borrowed value needs to live until here"); |
| 404 | + } |
| 405 | + err.emit(); |
| 406 | + } |
| 407 | + |
| 408 | + fn report_scoped_temporary_value_does_not_live_long_enough( |
| 409 | + &mut self, _scope_tree: &Rc<ScopeTree>, _borrow: &BorrowData<'tcx>, |
| 410 | + drop_span: Span, borrow_span: Span, proper_span: Span, end_span: Option<Span> |
| 411 | + ) { |
| 412 | + let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, |
| 413 | + "borrowed value", |
| 414 | + Origin::Mir); |
| 415 | + err.span_label(proper_span, "temporary value created here"); |
| 416 | + err.span_label(drop_span, "temporary value dropped here while still borrowed"); |
| 417 | + err.note("consider using a `let` binding to increase its lifetime"); |
| 418 | + if let Some(end) = end_span { |
| 419 | + err.span_label(end, "temporary value needs to live until here"); |
| 420 | + } |
| 421 | + err.emit(); |
| 422 | + } |
| 423 | + |
| 424 | + fn report_unscoped_local_value_does_not_live_long_enough( |
| 425 | + &mut self, name: &String, scope_tree: &Rc<ScopeTree>, borrow: &BorrowData<'tcx>, |
| 426 | + drop_span: Span, borrow_span: Span, _proper_span: Span, _end_span: Option<Span> |
| 427 | + ) { |
| 428 | + let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, |
| 429 | + &format!("`{}`", name), |
| 430 | + Origin::Mir); |
| 431 | + err.span_label(borrow_span, "does not live long enough"); |
| 432 | + err.span_label(drop_span, "borrowed value only lives until here"); |
| 433 | + self.tcx.note_and_explain_region(scope_tree, &mut err, |
| 434 | + "borrowed value must be valid for ", |
| 435 | + borrow.region, "..."); |
| 436 | + err.emit(); |
| 437 | + } |
| 438 | + |
| 439 | + fn report_unscoped_temporary_value_does_not_live_long_enough( |
| 440 | + &mut self, scope_tree: &Rc<ScopeTree>, borrow: &BorrowData<'tcx>, |
| 441 | + drop_span: Span, _borrow_span: Span, proper_span: Span, _end_span: Option<Span> |
| 442 | + ) { |
| 443 | + let mut err = self.tcx.path_does_not_live_long_enough(proper_span, |
| 444 | + "borrowed value", |
| 445 | + Origin::Mir); |
| 446 | + err.span_label(proper_span, "does not live long enough"); |
| 447 | + err.span_label(drop_span, "temporary value only lives until here"); |
| 448 | + self.tcx.note_and_explain_region(scope_tree, &mut err, |
| 449 | + "borrowed value must be valid for ", |
| 450 | + borrow.region, "..."); |
| 451 | + err.emit(); |
| 452 | + } |
| 453 | + |
415 | 454 | pub(super) fn report_illegal_mutation_of_borrowed( |
416 | 455 | &mut self, |
417 | 456 | _: Context, |
|
0 commit comments