|
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