| use crate::infer::{self, InferCtxt, SubregionOrigin}; |
| use crate::middle::region; |
| use crate::ty::error::TypeError; |
| use crate::ty::{self, Region}; |
| use errors::DiagnosticBuilder; |
| |
| use rustc_error_codes::*; |
| |
| impl<'a, 'tcx> InferCtxt<'a, 'tcx> { |
| pub(super) fn note_region_origin( |
| &self, |
| err: &mut DiagnosticBuilder<'_>, |
| origin: &SubregionOrigin<'tcx>, |
| ) { |
| match *origin { |
| infer::Subtype(ref trace) => { |
| if let Some((expected, found)) = self.values_str(&trace.values) { |
| err.span_note( |
| trace.cause.span, |
| &format!("...so that the {}", trace.cause.as_requirement_str()), |
| ); |
| |
| err.note_expected_found(&"", expected, &"", found); |
| } else { |
| // FIXME: this really should be handled at some earlier stage. Our |
| // handling of region checking when type errors are present is |
| // *terrible*. |
| |
| err.span_note( |
| trace.cause.span, |
| &format!("...so that {}", trace.cause.as_requirement_str()), |
| ); |
| } |
| } |
| infer::Reborrow(span) => { |
| err.span_note(span, "...so that reference does not outlive borrowed content"); |
| } |
| infer::ReborrowUpvar(span, ref upvar_id) => { |
| let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
| err.span_note(span, &format!("...so that closure can access `{}`", var_name)); |
| } |
| infer::InfStackClosure(span) => { |
| err.span_note(span, "...so that closure does not outlive its stack frame"); |
| } |
| infer::InvokeClosure(span) => { |
| err.span_note(span, "...so that closure is not invoked outside its lifetime"); |
| } |
| infer::DerefPointer(span) => { |
| err.span_note(span, "...so that pointer is not dereferenced outside its lifetime"); |
| } |
| infer::ClosureCapture(span, id) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so that captured variable `{}` does not outlive the \ |
| enclosing closure", |
| self.tcx.hir().name(id) |
| ), |
| ); |
| } |
| infer::IndexSlice(span) => { |
| err.span_note(span, "...so that slice is not indexed outside the lifetime"); |
| } |
| infer::RelateObjectBound(span) => { |
| err.span_note(span, "...so that it can be closed over into an object"); |
| } |
| infer::CallRcvr(span) => { |
| err.span_note(span, "...so that method receiver is valid for the method call"); |
| } |
| infer::CallArg(span) => { |
| err.span_note(span, "...so that argument is valid for the call"); |
| } |
| infer::CallReturn(span) => { |
| err.span_note(span, "...so that return value is valid for the call"); |
| } |
| infer::Operand(span) => { |
| err.span_note(span, "...so that operand is valid for operation"); |
| } |
| infer::AddrOf(span) => { |
| err.span_note(span, "...so that reference is valid at the time of borrow"); |
| } |
| infer::AutoBorrow(span) => { |
| err.span_note(span, "...so that auto-reference is valid at the time of borrow"); |
| } |
| infer::ExprTypeIsNotInScope(t, span) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so type `{}` of expression is valid during the \ |
| expression", |
| self.ty_to_string(t) |
| ), |
| ); |
| } |
| infer::BindingTypeIsNotValidAtDecl(span) => { |
| err.span_note(span, "...so that variable is valid at time of its declaration"); |
| } |
| infer::ParameterInScope(_, span) => { |
| err.span_note(span, "...so that a type/lifetime parameter is in scope here"); |
| } |
| infer::DataBorrowed(ty, span) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so that the type `{}` is not borrowed for too long", |
| self.ty_to_string(ty) |
| ), |
| ); |
| } |
| infer::ReferenceOutlivesReferent(ty, span) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so that the reference type `{}` does not outlive the \ |
| data it points at", |
| self.ty_to_string(ty) |
| ), |
| ); |
| } |
| infer::RelateParamBound(span, t) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so that the type `{}` will meet its required \ |
| lifetime bounds", |
| self.ty_to_string(t) |
| ), |
| ); |
| } |
| infer::RelateDefaultParamBound(span, t) => { |
| err.span_note( |
| span, |
| &format!( |
| "...so that type parameter instantiated with `{}`, will \ |
| meet its declared lifetime bounds", |
| self.ty_to_string(t) |
| ), |
| ); |
| } |
| infer::RelateRegionParamBound(span) => { |
| err.span_note( |
| span, |
| "...so that the declared lifetime parameter bounds are satisfied", |
| ); |
| } |
| infer::SafeDestructor(span) => { |
| err.span_note(span, "...so that references are valid when the destructor runs"); |
| } |
| infer::CompareImplMethodObligation { span, .. } => { |
| err.span_note( |
| span, |
| "...so that the definition in impl matches the definition from the \ |
| trait", |
| ); |
| } |
| } |
| } |
| |
| pub(super) fn report_concrete_failure( |
| &self, |
| region_scope_tree: ®ion::ScopeTree, |
| origin: SubregionOrigin<'tcx>, |
| sub: Region<'tcx>, |
| sup: Region<'tcx>, |
| ) -> DiagnosticBuilder<'tcx> { |
| match origin { |
| infer::Subtype(box trace) => { |
| let terr = TypeError::RegionsDoesNotOutlive(sup, sub); |
| let mut err = self.report_and_explain_type_error(trace, &terr); |
| self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "..."); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...does not necessarily outlive ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::Reborrow(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0312, |
| "lifetime of reference outlives lifetime of \ |
| borrowed content..." |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...the reference is valid for ", |
| sub, |
| "...", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...but the borrowed content is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::ReborrowUpvar(span, ref upvar_id) => { |
| let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0313, |
| "lifetime of borrowed pointer outlives lifetime \ |
| of captured variable `{}`...", |
| var_name |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...the borrowed pointer is valid for ", |
| sub, |
| "...", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| &format!("...but `{}` is only valid for ", var_name), |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::InfStackClosure(span) => { |
| let mut err = |
| struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...the closure must be valid for ", |
| sub, |
| "...", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "...but the closure's stack frame is only valid \ |
| for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::InvokeClosure(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0315, |
| "cannot invoke closure outside of its lifetime" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the closure is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::DerefPointer(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0473, |
| "dereference of reference outside its lifetime" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the reference is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::ClosureCapture(span, id) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0474, |
| "captured variable `{}` does not outlive the \ |
| enclosing closure", |
| self.tcx.hir().name(id) |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "captured variable is valid for ", |
| sup, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "closure is valid for ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::IndexSlice(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0475, |
| "index of slice outside its lifetime" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the slice is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::RelateObjectBound(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0476, |
| "lifetime of the source pointer does not outlive \ |
| lifetime bound of the object type" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "object type is valid for ", |
| sub, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "source pointer is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::RelateParamBound(span, ty) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0477, |
| "the type `{}` does not fulfill the required \ |
| lifetime", |
| self.ty_to_string(ty) |
| ); |
| match *sub { |
| ty::ReStatic => self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "type must satisfy ", |
| sub, |
| "", |
| ), |
| _ => self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "type must outlive ", |
| sub, |
| "", |
| ), |
| } |
| err |
| } |
| infer::RelateRegionParamBound(span) => { |
| let mut err = |
| struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "lifetime parameter instantiated with ", |
| sup, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "but lifetime parameter must outlive ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::RelateDefaultParamBound(span, ty) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0479, |
| "the type `{}` (provided as the value of a type \ |
| parameter) is not valid at this point", |
| self.ty_to_string(ty) |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "type must outlive ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::CallRcvr(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0480, |
| "lifetime of method receiver does not outlive the \ |
| method call" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the receiver is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::CallArg(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0481, |
| "lifetime of function argument does not outlive \ |
| the function call" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the function argument is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::CallReturn(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0482, |
| "lifetime of return value does not outlive the \ |
| function call" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the return value is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::Operand(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0483, |
| "lifetime of operand does not outlive the \ |
| operation" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the operand is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::AddrOf(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0484, |
| "reference is not valid at the time of borrow" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the borrow is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::AutoBorrow(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0485, |
| "automatically reference is not valid at the time \ |
| of borrow" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the automatic borrow is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::ExprTypeIsNotInScope(t, span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0486, |
| "type of expression contains references that are \ |
| not valid during the expression: `{}`", |
| self.ty_to_string(t) |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "type is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::SafeDestructor(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0487, |
| "unsafe use of destructor: destructor might be \ |
| called while references are dead" |
| ); |
| // FIXME (22171): terms "super/subregion" are suboptimal |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "superregion: ", |
| sup, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "subregion: ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::BindingTypeIsNotValidAtDecl(span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0488, |
| "lifetime of variable does not enclose its \ |
| declaration" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the variable is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::ParameterInScope(_, span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0489, |
| "type/lifetime parameter not in scope here" |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the parameter is only valid for ", |
| sub, |
| "", |
| ); |
| err |
| } |
| infer::DataBorrowed(ty, span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0490, |
| "a value of type `{}` is borrowed for too long", |
| self.ty_to_string(ty) |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the type is valid for ", |
| sub, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "but the borrow lasts for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::ReferenceOutlivesReferent(ty, span) => { |
| let mut err = struct_span_err!( |
| self.tcx.sess, |
| span, |
| E0491, |
| "in type `{}`, reference has a longer lifetime \ |
| than the data it references", |
| self.ty_to_string(ty) |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "the pointer is valid for ", |
| sub, |
| "", |
| ); |
| self.tcx.note_and_explain_region( |
| region_scope_tree, |
| &mut err, |
| "but the referenced data is only valid for ", |
| sup, |
| "", |
| ); |
| err |
| } |
| infer::CompareImplMethodObligation { |
| span, |
| item_name, |
| impl_item_def_id, |
| trait_item_def_id, |
| } => self.report_extra_impl_obligation( |
| span, |
| item_name, |
| impl_item_def_id, |
| trait_item_def_id, |
| &format!("`{}: {}`", sup, sub), |
| ), |
| } |
| } |
| |
| pub(super) fn report_placeholder_failure( |
| &self, |
| region_scope_tree: ®ion::ScopeTree, |
| placeholder_origin: SubregionOrigin<'tcx>, |
| sub: Region<'tcx>, |
| sup: Region<'tcx>, |
| ) -> DiagnosticBuilder<'tcx> { |
| // I can't think how to do better than this right now. -nikomatsakis |
| match placeholder_origin { |
| infer::Subtype(box trace) => { |
| let terr = TypeError::RegionsPlaceholderMismatch; |
| self.report_and_explain_type_error(trace, &terr) |
| } |
| |
| _ => self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup), |
| } |
| } |
| } |