use crate::infer::error_reporting::note_and_explain_region; use crate::infer::{self, InferCtxt, SubregionOrigin}; use crate::middle::region; use crate::ty::error::TypeError; use crate::ty::{self, Region}; use errors::{struct_span_err, 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); note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "..."); note_and_explain_region( self.tcx, 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..." ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "...the reference is valid for ", sub, "...", ); note_and_explain_region( self.tcx, 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 ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "...the borrowed pointer is valid for ", sub, "...", ); note_and_explain_region( self.tcx, 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"); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "...the closure must be valid for ", sub, "...", ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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) ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "captured variable is valid for ", sup, "", ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "object type is valid for ", sub, "", ); note_and_explain_region( self.tcx, 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 => note_and_explain_region( self.tcx, region_scope_tree, &mut err, "type must satisfy ", sub, "", ), _ => note_and_explain_region( self.tcx, 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"); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "lifetime parameter instantiated with ", sup, "", ); note_and_explain_region( self.tcx, 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) ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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) ); note_and_explain_region( self.tcx, 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 note_and_explain_region( self.tcx, region_scope_tree, &mut err, "superregion: ", sup, "", ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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" ); note_and_explain_region( self.tcx, 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) ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "the type is valid for ", sub, "", ); note_and_explain_region( self.tcx, 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) ); note_and_explain_region( self.tcx, region_scope_tree, &mut err, "the pointer is valid for ", sub, "", ); note_and_explain_region( self.tcx, 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), } } }