1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Error Reporting Code for the inference engine
13 //! Because of the way inference, and in particular region inference,
14 //! works, it often happens that errors are not detected until far after
15 //! the relevant line of code has been type-checked. Therefore, there is
16 //! an elaborate system to track why a particular constraint in the
17 //! inference graph arose so that we can explain to the user what gave
18 //! rise to a particular error.
20 //! The basis of the system are the "origin" types. An "origin" is the
21 //! reason that a constraint or inference variable arose. There are
22 //! different "origin" enums for different kinds of constraints/variables
23 //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
24 //! a span, but also more information so that we can generate a meaningful
27 //! Having a catalogue of all the different reasons an error can arise is
28 //! also useful for other reasons, like cross-referencing FAQs etc, though
29 //! we are not really taking advantage of this yet.
31 //! # Region Inference
33 //! Region inference is particularly tricky because it always succeeds "in
34 //! the moment" and simply registers a constraint. Then, at the end, we
35 //! can compute the full graph and report errors, so we need to be able to
36 //! store and later report what gave rise to the conflicting constraints.
40 //! Determining whether `T1 <: T2` often involves a number of subtypes and
41 //! subconstraints along the way. A "TypeTrace" is an extended version
42 //! of an origin that traces the types and other values that were being
43 //! compared. It is not necessarily comprehensive (in fact, at the time of
44 //! this writing it only tracks the root values being compared) but I'd
45 //! like to extend it to include significant "waypoints". For example, if
46 //! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
47 //! <: T4` fails, I'd like the trace to include enough information to say
48 //! "in the 2nd element of the tuple". Similarly, failures when comparing
49 //! arguments or return types in fn types should be able to cite the
50 //! specific position, etc.
54 //! Of course, there is still a LOT of code in typeck that has yet to be
55 //! ported to this system, and which relies on string concatenation at the
56 //! time of error detection.
58 use self::FreshOrKept
::*;
62 use super::SubregionOrigin
;
63 use super::RegionVariableOrigin
;
64 use super::ValuePairs
;
65 use super::region_inference
::RegionResolutionError
;
66 use super::region_inference
::ConcreteFailure
;
67 use super::region_inference
::SubSupConflict
;
68 use super::region_inference
::GenericBoundFailure
;
69 use super::region_inference
::GenericKind
;
70 use super::region_inference
::ProcessedErrors
;
71 use super::region_inference
::ProcessedErrorOrigin
;
72 use super::region_inference
::SameRegions
;
74 use std
::collections
::HashSet
;
76 use hir
::map
as ast_map
;
78 use hir
::print
as pprust
;
82 use hir
::def_id
::DefId
;
83 use infer
::{self, TypeOrigin}
;
86 use ty
::{self, TyCtxt, TypeFoldable}
;
87 use ty
::{Region, ReFree}
;
88 use ty
::error
::TypeError
;
90 use std
::cell
::{Cell, RefCell}
;
91 use std
::char::from_u32
;
94 use syntax
::parse
::token
;
96 use syntax_pos
::{self, Pos, Span}
;
97 use errors
::DiagnosticBuilder
;
99 impl<'a
, 'gcx
, 'tcx
> TyCtxt
<'a
, 'gcx
, 'tcx
> {
100 pub fn note_and_explain_region(self,
101 err
: &mut DiagnosticBuilder
,
105 fn item_scope_tag(item
: &hir
::Item
) -> &'
static str {
107 hir
::ItemImpl(..) => "impl",
108 hir
::ItemStruct(..) => "struct",
109 hir
::ItemEnum(..) => "enum",
110 hir
::ItemTrait(..) => "trait",
111 hir
::ItemFn(..) => "function body",
116 fn explain_span
<'a
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
117 heading
: &str, span
: Span
)
118 -> (String
, Option
<Span
>) {
119 let lo
= tcx
.sess
.codemap().lookup_char_pos_adj(span
.lo
);
120 (format
!("the {} at {}:{}", heading
, lo
.line
, lo
.col
.to_usize()),
124 let (description
, span
) = match region
{
125 ty
::ReScope(scope
) => {
127 let unknown_scope
= || {
128 format
!("{}unknown scope: {:?}{}. Please report a bug.",
129 prefix
, scope
, suffix
)
131 let span
= match scope
.span(&self.region_maps
, &self.map
) {
134 err
.note(&unknown_scope());
138 let tag
= match self.map
.find(scope
.node_id(&self.region_maps
)) {
139 Some(ast_map
::NodeBlock(_
)) => "block",
140 Some(ast_map
::NodeExpr(expr
)) => match expr
.node
{
141 hir
::ExprCall(..) => "call",
142 hir
::ExprMethodCall(..) => "method call",
143 hir
::ExprMatch(_
, _
, hir
::MatchSource
::IfLetDesugar { .. }
) => "if let",
144 hir
::ExprMatch(_
, _
, hir
::MatchSource
::WhileLetDesugar
) => "while let",
145 hir
::ExprMatch(_
, _
, hir
::MatchSource
::ForLoopDesugar
) => "for",
146 hir
::ExprMatch(..) => "match",
149 Some(ast_map
::NodeStmt(_
)) => "statement",
150 Some(ast_map
::NodeItem(it
)) => item_scope_tag(&it
),
152 err
.span_note(span
, &unknown_scope());
156 let scope_decorated_tag
= match self.region_maps
.code_extent_data(scope
) {
157 region
::CodeExtentData
::Misc(_
) => tag
,
158 region
::CodeExtentData
::CallSiteScope { .. }
=> {
159 "scope of call-site for function"
161 region
::CodeExtentData
::ParameterScope { .. }
=> {
162 "scope of function body"
164 region
::CodeExtentData
::DestructionScope(_
) => {
165 new_string
= format
!("destruction scope surrounding {}", tag
);
168 region
::CodeExtentData
::Remainder(r
) => {
169 new_string
= format
!("block suffix following statement {}",
170 r
.first_statement_index
);
174 explain_span(self, scope_decorated_tag
, span
)
177 ty
::ReFree(ref fr
) => {
178 let prefix
= match fr
.bound_region
{
180 format
!("the anonymous lifetime #{} defined on", idx
+ 1)
182 ty
::BrFresh(_
) => "an anonymous lifetime defined on".to_owned(),
184 format
!("the lifetime {} as defined on",
189 match self.map
.find(fr
.scope
.node_id(&self.region_maps
)) {
190 Some(ast_map
::NodeBlock(ref blk
)) => {
191 let (msg
, opt_span
) = explain_span(self, "block", blk
.span
);
192 (format
!("{} {}", prefix
, msg
), opt_span
)
194 Some(ast_map
::NodeItem(it
)) => {
195 let tag
= item_scope_tag(&it
);
196 let (msg
, opt_span
) = explain_span(self, tag
, it
.span
);
197 (format
!("{} {}", prefix
, msg
), opt_span
)
200 // this really should not happen, but it does:
202 (format
!("{} unknown free region bounded by scope {:?}",
203 prefix
, fr
.scope
), None
)
208 ty
::ReStatic
=> ("the static lifetime".to_owned(), None
),
210 ty
::ReEmpty
=> ("the empty lifetime".to_owned(), None
),
212 ty
::ReEarlyBound(ref data
) => (data
.name
.to_string(), None
),
214 // FIXME(#13998) ReSkolemized should probably print like
215 // ReFree rather than dumping Debug output on the user.
217 // We shouldn't really be having unification failures with ReVar
218 // and ReLateBound though.
219 ty
::ReSkolemized(..) |
221 ty
::ReLateBound(..) |
223 (format
!("lifetime {:?}", region
), None
)
226 let message
= format
!("{}{}{}", prefix
, description
, suffix
);
227 if let Some(span
) = span
{
228 err
.span_note(span
, &message
);
235 impl<'a
, 'gcx
, 'tcx
> InferCtxt
<'a
, 'gcx
, 'tcx
> {
236 pub fn report_region_errors(&self,
237 errors
: &Vec
<RegionResolutionError
<'tcx
>>) {
238 debug
!("report_region_errors(): {} errors to start", errors
.len());
240 // try to pre-process the errors, which will group some of them
241 // together into a `ProcessedErrors` group:
242 let processed_errors
= self.process_errors(errors
);
243 let errors
= processed_errors
.as_ref().unwrap_or(errors
);
245 debug
!("report_region_errors: {} errors after preprocessing", errors
.len());
247 for error
in errors
{
248 match error
.clone() {
249 ConcreteFailure(origin
, sub
, sup
) => {
250 self.report_concrete_failure(origin
, sub
, sup
).emit();
253 GenericBoundFailure(kind
, param_ty
, sub
) => {
254 self.report_generic_bound_failure(kind
, param_ty
, sub
);
257 SubSupConflict(var_origin
,
259 sup_origin
, sup_r
) => {
260 self.report_sub_sup_conflict(var_origin
,
265 ProcessedErrors(ref origins
,
266 ref same_regions
) => {
267 if !same_regions
.is_empty() {
268 self.report_processed_errors(origins
, same_regions
);
275 // This method goes through all the errors and try to group certain types
276 // of error together, for the purpose of suggesting explicit lifetime
277 // parameters to the user. This is done so that we can have a more
278 // complete view of what lifetimes should be the same.
279 // If the return value is an empty vector, it means that processing
280 // failed (so the return value of this method should not be used).
282 // The method also attempts to weed out messages that seem like
283 // duplicates that will be unhelpful to the end-user. But
284 // obviously it never weeds out ALL errors.
285 fn process_errors(&self, errors
: &Vec
<RegionResolutionError
<'tcx
>>)
286 -> Option
<Vec
<RegionResolutionError
<'tcx
>>> {
287 debug
!("process_errors()");
288 let mut origins
= Vec
::new();
290 // we collect up ConcreteFailures and SubSupConflicts that are
291 // relating free-regions bound on the fn-header and group them
292 // together into this vector
293 let mut same_regions
= Vec
::new();
295 // here we put errors that we will not be able to process nicely
296 let mut other_errors
= Vec
::new();
298 // we collect up GenericBoundFailures in here.
299 let mut bound_failures
= Vec
::new();
301 for error
in errors
{
303 ConcreteFailure(ref origin
, sub
, sup
) => {
304 debug
!("processing ConcreteFailure");
305 match free_regions_from_same_fn(self.tcx
, sub
, sup
) {
306 Some(ref same_frs
) => {
308 ProcessedErrorOrigin
::ConcreteFailure(
312 append_to_same_regions(&mut same_regions
, same_frs
);
315 other_errors
.push(error
.clone());
319 SubSupConflict(ref var_origin
, _
, sub_r
, _
, sup_r
) => {
320 debug
!("processing SubSupConflict sub: {:?} sup: {:?}", sub_r
, sup_r
);
321 match free_regions_from_same_fn(self.tcx
, sub_r
, sup_r
) {
322 Some(ref same_frs
) => {
324 ProcessedErrorOrigin
::VariableFailure(
325 var_origin
.clone()));
326 append_to_same_regions(&mut same_regions
, same_frs
);
329 other_errors
.push(error
.clone());
333 GenericBoundFailure(ref origin
, ref kind
, region
) => {
334 bound_failures
.push((origin
.clone(), kind
.clone(), region
));
336 ProcessedErrors(..) => {
337 bug
!("should not encounter a `ProcessedErrors` yet: {:?}", error
)
342 // ok, let's pull together the errors, sorted in an order that
343 // we think will help user the best
344 let mut processed_errors
= vec
![];
346 // first, put the processed errors, if any
347 if !same_regions
.is_empty() {
348 let common_scope_id
= same_regions
[0].scope_id
;
349 for sr
in &same_regions
{
350 // Since ProcessedErrors is used to reconstruct the function
351 // declaration, we want to make sure that they are, in fact,
352 // from the same scope
353 if sr
.scope_id
!= common_scope_id
{
354 debug
!("returning empty result from process_errors because
355 {} != {}", sr
.scope_id
, common_scope_id
);
359 assert
!(origins
.len() > 0);
360 let pe
= ProcessedErrors(origins
, same_regions
);
361 debug
!("errors processed: {:?}", pe
);
362 processed_errors
.push(pe
);
365 // next, put the other misc errors
366 processed_errors
.extend(other_errors
);
368 // finally, put the `T: 'a` errors, but only if there were no
369 // other errors. otherwise, these have a very high rate of
370 // being unhelpful in practice. This is because they are
371 // basically secondary checks that test the state of the
372 // region graph after the rest of inference is done, and the
373 // other kinds of errors indicate that the region constraint
374 // graph is internally inconsistent, so these test results are
375 // likely to be meaningless.
376 if processed_errors
.is_empty() {
377 for (origin
, kind
, region
) in bound_failures
{
378 processed_errors
.push(GenericBoundFailure(origin
, kind
, region
));
382 // we should always wind up with SOME errors, unless there were no
384 assert
!(if errors
.len() > 0 {processed_errors.len() > 0}
else {true}
);
386 return Some(processed_errors
);
389 struct FreeRegionsFromSameFn
{
390 sub_fr
: ty
::FreeRegion
,
391 sup_fr
: ty
::FreeRegion
,
392 scope_id
: ast
::NodeId
395 impl FreeRegionsFromSameFn
{
396 fn new(sub_fr
: ty
::FreeRegion
,
397 sup_fr
: ty
::FreeRegion
,
398 scope_id
: ast
::NodeId
)
399 -> FreeRegionsFromSameFn
{
400 FreeRegionsFromSameFn
{
408 fn free_regions_from_same_fn
<'a
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
411 -> Option
<FreeRegionsFromSameFn
> {
412 debug
!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub
, sup
);
413 let (scope_id
, fr1
, fr2
) = match (sub
, sup
) {
414 (ReFree(fr1
), ReFree(fr2
)) => {
415 if fr1
.scope
!= fr2
.scope
{
418 assert
!(fr1
.scope
== fr2
.scope
);
419 (fr1
.scope
.node_id(&tcx
.region_maps
), fr1
, fr2
)
423 let parent
= tcx
.map
.get_parent(scope_id
);
424 let parent_node
= tcx
.map
.find(parent
);
426 Some(node
) => match node
{
427 ast_map
::NodeItem(item
) => match item
.node
{
429 Some(FreeRegionsFromSameFn
::new(fr1
, fr2
, scope_id
))
433 ast_map
::NodeImplItem(..) |
434 ast_map
::NodeTraitItem(..) => {
435 Some(FreeRegionsFromSameFn
::new(fr1
, fr2
, scope_id
))
440 debug
!("no parent node of scope_id {}", scope_id
);
446 fn append_to_same_regions(same_regions
: &mut Vec
<SameRegions
>,
447 same_frs
: &FreeRegionsFromSameFn
) {
448 debug
!("append_to_same_regions(same_regions={:?}, same_frs={:?})",
449 same_regions
, same_frs
);
450 let scope_id
= same_frs
.scope_id
;
451 let (sub_fr
, sup_fr
) = (same_frs
.sub_fr
, same_frs
.sup_fr
);
452 for sr
in same_regions
.iter_mut() {
453 if sr
.contains(&sup_fr
.bound_region
) && scope_id
== sr
.scope_id
{
454 sr
.push(sub_fr
.bound_region
);
458 same_regions
.push(SameRegions
{
460 regions
: vec
!(sub_fr
.bound_region
, sup_fr
.bound_region
)
465 /// Adds a note if the types come from similarly named crates
466 fn check_and_note_conflicting_crates(&self,
467 err
: &mut DiagnosticBuilder
,
468 terr
: &TypeError
<'tcx
>,
470 let report_path_match
= |err
: &mut DiagnosticBuilder
, did1
: DefId
, did2
: DefId
| {
471 // Only external crates, if either is from a local
472 // module we could have false positives
473 if !(did1
.is_local() || did2
.is_local()) && did1
.krate
!= did2
.krate
{
474 let exp_path
= self.tcx
.item_path_str(did1
);
475 let found_path
= self.tcx
.item_path_str(did2
);
476 // We compare strings because DefPath can be different
477 // for imported and non-imported crates
478 if exp_path
== found_path
{
479 let crate_name
= self.tcx
.sess
.cstore
.crate_name(did1
.krate
);
480 err
.span_note(sp
, &format
!("Perhaps two different versions \
481 of crate `{}` are being used?",
487 TypeError
::Sorts(ref exp_found
) => {
488 // if they are both "path types", there's a chance of ambiguity
489 // due to different versions of the same crate
490 match (&exp_found
.expected
.sty
, &exp_found
.found
.sty
) {
491 (&ty
::TyEnum(ref exp_adt
, _
), &ty
::TyEnum(ref found_adt
, _
)) |
492 (&ty
::TyStruct(ref exp_adt
, _
), &ty
::TyStruct(ref found_adt
, _
)) |
493 (&ty
::TyEnum(ref exp_adt
, _
), &ty
::TyStruct(ref found_adt
, _
)) |
494 (&ty
::TyStruct(ref exp_adt
, _
), &ty
::TyEnum(ref found_adt
, _
)) => {
495 report_path_match(err
, exp_adt
.did
, found_adt
.did
);
500 TypeError
::Traits(ref exp_found
) => {
501 report_path_match(err
, exp_found
.expected
, exp_found
.found
);
503 _
=> () // FIXME(#22750) handle traits and stuff
507 fn note_error_origin(&self,
508 err
: &mut DiagnosticBuilder
<'tcx
>,
512 &TypeOrigin
::MatchExpressionArm(_
, arm_span
, source
) => match source
{
513 hir
::MatchSource
::IfLetDesugar {..}
=> {
514 err
.span_note(arm_span
, "`if let` arm with an incompatible type");
517 err
.span_note(arm_span
, "match arm with an incompatible type");
524 pub fn note_type_err(&self,
525 diag
: &mut DiagnosticBuilder
<'tcx
>,
527 values
: Option
<ValuePairs
<'tcx
>>,
528 terr
: &TypeError
<'tcx
>)
530 let expected_found
= match values
{
532 Some(values
) => match self.values_str(&values
) {
533 Some((expected
, found
)) => Some((expected
, found
)),
535 // Derived error. Cancel the emitter.
536 self.tcx
.sess
.diagnostic().cancel(diag
);
542 let span
= origin
.span();
544 if let Some((expected
, found
)) = expected_found
{
545 let is_simple_error
= if let &TypeError
::Sorts(ref values
) = terr
{
546 values
.expected
.is_primitive() && values
.found
.is_primitive()
551 if !is_simple_error
{
552 diag
.note_expected_found(&"type", &expected
, &found
);
556 diag
.span_label(span
, &terr
);
558 self.note_error_origin(diag
, &origin
);
559 self.check_and_note_conflicting_crates(diag
, terr
, span
);
560 self.tcx
.note_and_explain_type_err(diag
, terr
, span
);
563 pub fn report_and_explain_type_error(&self,
564 trace
: TypeTrace
<'tcx
>,
565 terr
: &TypeError
<'tcx
>)
566 -> DiagnosticBuilder
<'tcx
>
568 // FIXME: do we want to use a different error code for each origin?
569 let mut diag
= struct_span_err
!(
570 self.tcx
.sess
, trace
.origin
.span(), E0308
,
571 "{}", trace
.origin
.as_failure_str()
573 self.note_type_err(&mut diag
, trace
.origin
, Some(trace
.values
), terr
);
577 /// Returns a string of the form "expected `{}`, found `{}`".
578 fn values_str(&self, values
: &ValuePairs
<'tcx
>) -> Option
<(String
, String
)> {
580 infer
::Types(ref exp_found
) => self.expected_found_str(exp_found
),
581 infer
::TraitRefs(ref exp_found
) => self.expected_found_str(exp_found
),
582 infer
::PolyTraitRefs(ref exp_found
) => self.expected_found_str(exp_found
),
586 fn expected_found_str
<T
: fmt
::Display
+ TypeFoldable
<'tcx
>>(
588 exp_found
: &ty
::error
::ExpectedFound
<T
>)
589 -> Option
<(String
, String
)>
591 let exp_found
= self.resolve_type_vars_if_possible(exp_found
);
592 if exp_found
.references_error() {
596 Some((format
!("{}", exp_found
.expected
), format
!("{}", exp_found
.found
)))
599 fn report_generic_bound_failure(&self,
600 origin
: SubregionOrigin
<'tcx
>,
601 bound_kind
: GenericKind
<'tcx
>,
604 // FIXME: it would be better to report the first error message
605 // with the span of the parameter itself, rather than the span
606 // where the error was detected. But that span is not readily
609 let labeled_user_string
= match bound_kind
{
610 GenericKind
::Param(ref p
) =>
611 format
!("the parameter type `{}`", p
),
612 GenericKind
::Projection(ref p
) =>
613 format
!("the associated type `{}`", p
),
616 let mut err
= match sub
{
617 ty
::ReFree(ty
::FreeRegion {bound_region: ty::BrNamed(..), ..}
) => {
618 // Does the required lifetime have a nice name we can print?
619 let mut err
= struct_span_err
!(self.tcx
.sess
,
622 "{} may not live long enough",
623 labeled_user_string
);
624 err
.help(&format
!("consider adding an explicit lifetime bound `{}: {}`...",
631 // Does the required lifetime have a nice name we can print?
632 let mut err
= struct_span_err
!(self.tcx
.sess
,
635 "{} may not live long enough",
636 labeled_user_string
);
637 err
.help(&format
!("consider adding an explicit lifetime \
638 bound `{}: 'static`...",
644 // If not, be less specific.
645 let mut err
= struct_span_err
!(self.tcx
.sess
,
648 "{} may not live long enough",
649 labeled_user_string
);
650 err
.help(&format
!("consider adding an explicit lifetime bound for `{}`",
652 self.tcx
.note_and_explain_region(
654 &format
!("{} must be valid for ", labeled_user_string
),
661 self.note_region_origin(&mut err
, &origin
);
665 fn report_concrete_failure(&self,
666 origin
: SubregionOrigin
<'tcx
>,
669 -> DiagnosticBuilder
<'tcx
> {
671 infer
::Subtype(trace
) => {
672 let terr
= TypeError
::RegionsDoesNotOutlive(sup
, sub
);
673 self.report_and_explain_type_error(trace
, &terr
)
675 infer
::Reborrow(span
) => {
676 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0312
,
677 "lifetime of reference outlives \
678 lifetime of borrowed content...");
679 self.tcx
.note_and_explain_region(&mut err
,
680 "...the reference is valid for ",
683 self.tcx
.note_and_explain_region(&mut err
,
684 "...but the borrowed content is only valid for ",
689 infer
::ReborrowUpvar(span
, ref upvar_id
) => {
690 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0313
,
691 "lifetime of borrowed pointer outlives \
692 lifetime of captured variable `{}`...",
693 self.tcx
.local_var_name_str(upvar_id
.var_id
));
694 self.tcx
.note_and_explain_region(&mut err
,
695 "...the borrowed pointer is valid for ",
698 self.tcx
.note_and_explain_region(&mut err
,
699 &format
!("...but `{}` is only valid for ",
700 self.tcx
.local_var_name_str(upvar_id
.var_id
)),
705 infer
::InfStackClosure(span
) => {
706 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0314
,
707 "closure outlives stack frame");
708 self.tcx
.note_and_explain_region(&mut err
,
709 "...the closure must be valid for ",
712 self.tcx
.note_and_explain_region(&mut err
,
713 "...but the closure's stack frame is only valid for ",
718 infer
::InvokeClosure(span
) => {
719 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0315
,
720 "cannot invoke closure outside of its lifetime");
721 self.tcx
.note_and_explain_region(&mut err
,
722 "the closure is only valid for ",
727 infer
::DerefPointer(span
) => {
728 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0473
,
729 "dereference of reference outside its lifetime");
730 self.tcx
.note_and_explain_region(&mut err
,
731 "the reference is only valid for ",
736 infer
::FreeVariable(span
, id
) => {
737 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0474
,
738 "captured variable `{}` does not outlive the enclosing closure",
739 self.tcx
.local_var_name_str(id
));
740 self.tcx
.note_and_explain_region(&mut err
,
741 "captured variable is valid for ",
744 self.tcx
.note_and_explain_region(&mut err
,
745 "closure is valid for ",
750 infer
::IndexSlice(span
) => {
751 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0475
,
752 "index of slice outside its lifetime");
753 self.tcx
.note_and_explain_region(&mut err
,
754 "the slice is only valid for ",
759 infer
::RelateObjectBound(span
) => {
760 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0476
,
761 "lifetime of the source pointer does not outlive \
762 lifetime bound of the object type");
763 self.tcx
.note_and_explain_region(&mut err
,
764 "object type is valid for ",
767 self.tcx
.note_and_explain_region(&mut err
,
768 "source pointer is only valid for ",
773 infer
::RelateParamBound(span
, ty
) => {
774 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0477
,
775 "the type `{}` does not fulfill the required lifetime",
776 self.ty_to_string(ty
));
777 self.tcx
.note_and_explain_region(&mut err
,
778 "type must outlive ",
783 infer
::RelateRegionParamBound(span
) => {
784 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0478
,
785 "lifetime bound not satisfied");
786 self.tcx
.note_and_explain_region(&mut err
,
787 "lifetime parameter instantiated with ",
790 self.tcx
.note_and_explain_region(&mut err
,
791 "but lifetime parameter must outlive ",
796 infer
::RelateDefaultParamBound(span
, ty
) => {
797 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0479
,
798 "the type `{}` (provided as the value of \
799 a type parameter) is not valid at this point",
800 self.ty_to_string(ty
));
801 self.tcx
.note_and_explain_region(&mut err
,
802 "type must outlive ",
807 infer
::CallRcvr(span
) => {
808 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0480
,
809 "lifetime of method receiver does not outlive \
811 self.tcx
.note_and_explain_region(&mut err
,
812 "the receiver is only valid for ",
817 infer
::CallArg(span
) => {
818 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0481
,
819 "lifetime of function argument does not outlive \
821 self.tcx
.note_and_explain_region(&mut err
,
822 "the function argument is only valid for ",
827 infer
::CallReturn(span
) => {
828 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0482
,
829 "lifetime of return value does not outlive \
831 self.tcx
.note_and_explain_region(&mut err
,
832 "the return value is only valid for ",
837 infer
::Operand(span
) => {
838 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0483
,
839 "lifetime of operand does not outlive \
841 self.tcx
.note_and_explain_region(&mut err
,
842 "the operand is only valid for ",
847 infer
::AddrOf(span
) => {
848 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0484
,
849 "reference is not valid at the time of borrow");
850 self.tcx
.note_and_explain_region(&mut err
,
851 "the borrow is only valid for ",
856 infer
::AutoBorrow(span
) => {
857 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0485
,
858 "automatically reference is not valid \
859 at the time of borrow");
860 self.tcx
.note_and_explain_region(&mut err
,
861 "the automatic borrow is only valid for ",
866 infer
::ExprTypeIsNotInScope(t
, span
) => {
867 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0486
,
868 "type of expression contains references \
869 that are not valid during the expression: `{}`",
870 self.ty_to_string(t
));
871 self.tcx
.note_and_explain_region(&mut err
,
872 "type is only valid for ",
877 infer
::SafeDestructor(span
) => {
878 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0487
,
879 "unsafe use of destructor: destructor might be called \
880 while references are dead");
881 // FIXME (22171): terms "super/subregion" are suboptimal
882 self.tcx
.note_and_explain_region(&mut err
,
886 self.tcx
.note_and_explain_region(&mut err
,
892 infer
::BindingTypeIsNotValidAtDecl(span
) => {
893 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0488
,
894 "lifetime of variable does not enclose its declaration");
895 self.tcx
.note_and_explain_region(&mut err
,
896 "the variable is only valid for ",
901 infer
::ParameterInScope(_
, span
) => {
902 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0489
,
903 "type/lifetime parameter not in scope here");
904 self.tcx
.note_and_explain_region(&mut err
,
905 "the parameter is only valid for ",
910 infer
::DataBorrowed(ty
, span
) => {
911 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0490
,
912 "a value of type `{}` is borrowed for too long",
913 self.ty_to_string(ty
));
914 self.tcx
.note_and_explain_region(&mut err
, "the type is valid for ", sub
, "");
915 self.tcx
.note_and_explain_region(&mut err
, "but the borrow lasts for ", sup
, "");
918 infer
::ReferenceOutlivesReferent(ty
, span
) => {
919 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0491
,
920 "in type `{}`, reference has a longer lifetime \
921 than the data it references",
922 self.ty_to_string(ty
));
923 self.tcx
.note_and_explain_region(&mut err
,
924 "the pointer is valid for ",
927 self.tcx
.note_and_explain_region(&mut err
,
928 "but the referenced data is only valid for ",
936 fn report_sub_sup_conflict(&self,
937 var_origin
: RegionVariableOrigin
,
938 sub_origin
: SubregionOrigin
<'tcx
>,
940 sup_origin
: SubregionOrigin
<'tcx
>,
941 sup_region
: Region
) {
942 let mut err
= self.report_inference_failure(var_origin
);
944 self.tcx
.note_and_explain_region(&mut err
,
945 "first, the lifetime cannot outlive ",
949 self.note_region_origin(&mut err
, &sup_origin
);
951 self.tcx
.note_and_explain_region(&mut err
,
952 "but, the lifetime must be valid for ",
956 self.note_region_origin(&mut err
, &sub_origin
);
960 fn report_processed_errors(&self,
961 origins
: &[ProcessedErrorOrigin
<'tcx
>],
962 same_regions
: &[SameRegions
]) {
963 for (i
, origin
) in origins
.iter().enumerate() {
964 let mut err
= match *origin
{
965 ProcessedErrorOrigin
::VariableFailure(ref var_origin
) =>
966 self.report_inference_failure(var_origin
.clone()),
967 ProcessedErrorOrigin
::ConcreteFailure(ref sr_origin
, sub
, sup
) =>
968 self.report_concrete_failure(sr_origin
.clone(), sub
, sup
),
971 // attach the suggestion to the last such error
972 if i
== origins
.len() - 1 {
973 self.give_suggestion(&mut err
, same_regions
);
980 fn give_suggestion(&self, err
: &mut DiagnosticBuilder
, same_regions
: &[SameRegions
]) {
981 let scope_id
= same_regions
[0].scope_id
;
982 let parent
= self.tcx
.map
.get_parent(scope_id
);
983 let parent_node
= self.tcx
.map
.find(parent
);
984 let taken
= lifetimes_in_scope(self.tcx
, scope_id
);
985 let life_giver
= LifeGiver
::with_taken(&taken
[..]);
986 let node_inner
= match parent_node
{
987 Some(ref node
) => match *node
{
988 ast_map
::NodeItem(ref item
) => {
990 hir
::ItemFn(ref fn_decl
, unsafety
, constness
, _
, ref gen
, _
) => {
991 Some((fn_decl
, gen
, unsafety
, constness
, item
.name
, item
.span
))
996 ast_map
::NodeImplItem(item
) => {
998 hir
::ImplItemKind
::Method(ref sig
, _
) => {
1009 ast_map
::NodeTraitItem(item
) => {
1011 hir
::MethodTraitItem(ref sig
, Some(_
)) => {
1026 let (fn_decl
, generics
, unsafety
, constness
, name
, span
)
1027 = node_inner
.expect("expect item fn");
1028 let rebuilder
= Rebuilder
::new(self.tcx
, fn_decl
, generics
, same_regions
, &life_giver
);
1029 let (fn_decl
, generics
) = rebuilder
.rebuild();
1030 self.give_expl_lifetime_param(err
, &fn_decl
, unsafety
, constness
, name
, &generics
, span
);
1033 pub fn issue_32330_warnings(&self, span
: Span
, issue32330s
: &[ty
::Issue32330
]) {
1034 for issue32330
in issue32330s
{
1036 ty
::Issue32330
::WontChange
=> { }
1037 ty
::Issue32330
::WillChange { fn_def_id, region_name }
=> {
1038 self.tcx
.sess
.add_lint(
1039 lint
::builtin
::HR_LIFETIME_IN_ASSOC_TYPE
,
1042 format
!("lifetime parameter `{0}` declared on fn `{1}` \
1043 appears only in the return type, \
1044 but here is required to be higher-ranked, \
1045 which means that `{0}` must appear in both \
1046 argument and return types",
1048 self.tcx
.item_path_str(fn_def_id
)));
1055 struct RebuildPathInfo
<'a
> {
1056 path
: &'a hir
::Path
,
1057 // indexes to insert lifetime on path.lifetimes
1059 // number of lifetimes we expect to see on the type referred by `path`
1060 // (e.g., expected=1 for struct Foo<'a>)
1062 anon_nums
: &'a HashSet
<u32>,
1063 region_names
: &'a HashSet
<ast
::Name
>
1066 struct Rebuilder
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
1067 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1068 fn_decl
: &'a hir
::FnDecl
,
1069 generics
: &'a hir
::Generics
,
1070 same_regions
: &'a
[SameRegions
],
1071 life_giver
: &'a LifeGiver
,
1072 cur_anon
: Cell
<u32>,
1073 inserted_anons
: RefCell
<HashSet
<u32>>,
1081 impl<'a
, 'gcx
, 'tcx
> Rebuilder
<'a
, 'gcx
, 'tcx
> {
1082 fn new(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1083 fn_decl
: &'a hir
::FnDecl
,
1084 generics
: &'a hir
::Generics
,
1085 same_regions
: &'a
[SameRegions
],
1086 life_giver
: &'a LifeGiver
)
1087 -> Rebuilder
<'a
, 'gcx
, 'tcx
> {
1092 same_regions
: same_regions
,
1093 life_giver
: life_giver
,
1094 cur_anon
: Cell
::new(0),
1095 inserted_anons
: RefCell
::new(HashSet
::new()),
1099 fn rebuild(&self) -> (hir
::FnDecl
, hir
::Generics
) {
1100 let mut inputs
= self.fn_decl
.inputs
.clone();
1101 let mut output
= self.fn_decl
.output
.clone();
1102 let mut ty_params
= self.generics
.ty_params
.clone();
1103 let where_clause
= self.generics
.where_clause
.clone();
1104 let mut kept_lifetimes
= HashSet
::new();
1105 for sr
in self.same_regions
{
1106 self.cur_anon
.set(0);
1107 self.offset_cur_anon();
1108 let (anon_nums
, region_names
) =
1109 self.extract_anon_nums_and_names(sr
);
1110 let (lifetime
, fresh_or_kept
) = self.pick_lifetime(®ion_names
);
1111 match fresh_or_kept
{
1112 Kept
=> { kept_lifetimes.insert(lifetime.name); }
1115 inputs
= self.rebuild_args_ty(&inputs
[..], lifetime
,
1116 &anon_nums
, ®ion_names
);
1117 output
= self.rebuild_output(&output
, lifetime
, &anon_nums
, ®ion_names
);
1118 ty_params
= self.rebuild_ty_params(ty_params
, lifetime
,
1121 let fresh_lifetimes
= self.life_giver
.get_generated_lifetimes();
1122 let all_region_names
= self.extract_all_region_names();
1123 let generics
= self.rebuild_generics(self.generics
,
1129 let new_fn_decl
= hir
::FnDecl
{
1132 variadic
: self.fn_decl
.variadic
1134 (new_fn_decl
, generics
)
1137 fn pick_lifetime(&self,
1138 region_names
: &HashSet
<ast
::Name
>)
1139 -> (hir
::Lifetime
, FreshOrKept
) {
1140 if !region_names
.is_empty() {
1141 // It's not necessary to convert the set of region names to a
1142 // vector of string and then sort them. However, it makes the
1143 // choice of lifetime name deterministic and thus easier to test.
1144 let mut names
= Vec
::new();
1145 for rn
in region_names
{
1146 let lt_name
= rn
.to_string();
1147 names
.push(lt_name
);
1150 let name
= token
::intern(&names
[0]);
1151 return (name_to_dummy_lifetime(name
), Kept
);
1153 return (self.life_giver
.give_lifetime(), Fresh
);
1156 fn extract_anon_nums_and_names(&self, same_regions
: &SameRegions
)
1157 -> (HashSet
<u32>, HashSet
<ast
::Name
>) {
1158 let mut anon_nums
= HashSet
::new();
1159 let mut region_names
= HashSet
::new();
1160 for br
in &same_regions
.regions
{
1163 anon_nums
.insert(i
);
1165 ty
::BrNamed(_
, name
, _
) => {
1166 region_names
.insert(name
);
1171 (anon_nums
, region_names
)
1174 fn extract_all_region_names(&self) -> HashSet
<ast
::Name
> {
1175 let mut all_region_names
= HashSet
::new();
1176 for sr
in self.same_regions
{
1177 for br
in &sr
.regions
{
1179 ty
::BrNamed(_
, name
, _
) => {
1180 all_region_names
.insert(name
);
1189 fn inc_cur_anon(&self, n
: u32) {
1190 let anon
= self.cur_anon
.get();
1191 self.cur_anon
.set(anon
+n
);
1194 fn offset_cur_anon(&self) {
1195 let mut anon
= self.cur_anon
.get();
1196 while self.inserted_anons
.borrow().contains(&anon
) {
1199 self.cur_anon
.set(anon
);
1202 fn inc_and_offset_cur_anon(&self, n
: u32) {
1203 self.inc_cur_anon(n
);
1204 self.offset_cur_anon();
1207 fn track_anon(&self, anon
: u32) {
1208 self.inserted_anons
.borrow_mut().insert(anon
);
1211 fn rebuild_ty_params(&self,
1212 ty_params
: hir
::HirVec
<hir
::TyParam
>,
1213 lifetime
: hir
::Lifetime
,
1214 region_names
: &HashSet
<ast
::Name
>)
1215 -> hir
::HirVec
<hir
::TyParam
> {
1216 ty_params
.iter().map(|ty_param
| {
1217 let bounds
= self.rebuild_ty_param_bounds(ty_param
.bounds
.clone(),
1221 name
: ty_param
.name
,
1224 default: ty_param
.default.clone(),
1225 span
: ty_param
.span
,
1230 fn rebuild_ty_param_bounds(&self,
1231 ty_param_bounds
: hir
::TyParamBounds
,
1232 lifetime
: hir
::Lifetime
,
1233 region_names
: &HashSet
<ast
::Name
>)
1234 -> hir
::TyParamBounds
{
1235 ty_param_bounds
.iter().map(|tpb
| {
1237 &hir
::RegionTyParamBound(lt
) => {
1238 // FIXME -- it's unclear whether I'm supposed to
1239 // substitute lifetime here. I suspect we need to
1240 // be passing down a map.
1241 hir
::RegionTyParamBound(lt
)
1243 &hir
::TraitTyParamBound(ref poly_tr
, modifier
) => {
1244 let tr
= &poly_tr
.trait_ref
;
1245 let last_seg
= tr
.path
.segments
.last().unwrap();
1246 let mut insert
= Vec
::new();
1247 let lifetimes
= last_seg
.parameters
.lifetimes();
1248 for (i
, lt
) in lifetimes
.iter().enumerate() {
1249 if region_names
.contains(<
.name
) {
1250 insert
.push(i
as u32);
1253 let rebuild_info
= RebuildPathInfo
{
1256 expected
: lifetimes
.len() as u32,
1257 anon_nums
: &HashSet
::new(),
1258 region_names
: region_names
1260 let new_path
= self.rebuild_path(rebuild_info
, lifetime
);
1261 hir
::TraitTyParamBound(hir
::PolyTraitRef
{
1262 bound_lifetimes
: poly_tr
.bound_lifetimes
.clone(),
1263 trait_ref
: hir
::TraitRef
{
1274 fn rebuild_generics(&self,
1275 generics
: &hir
::Generics
,
1276 add
: &Vec
<hir
::Lifetime
>,
1277 keep
: &HashSet
<ast
::Name
>,
1278 remove
: &HashSet
<ast
::Name
>,
1279 ty_params
: hir
::HirVec
<hir
::TyParam
>,
1280 where_clause
: hir
::WhereClause
)
1282 let mut lifetimes
= Vec
::new();
1284 lifetimes
.push(hir
::LifetimeDef
{ lifetime
: *lt
,
1285 bounds
: hir
::HirVec
::new() });
1287 for lt
in &generics
.lifetimes
{
1288 if keep
.contains(<
.lifetime
.name
) ||
1289 !remove
.contains(<
.lifetime
.name
) {
1290 lifetimes
.push((*lt
).clone());
1294 lifetimes
: lifetimes
.into(),
1295 ty_params
: ty_params
,
1296 where_clause
: where_clause
,
1300 fn rebuild_args_ty(&self,
1301 inputs
: &[hir
::Arg
],
1302 lifetime
: hir
::Lifetime
,
1303 anon_nums
: &HashSet
<u32>,
1304 region_names
: &HashSet
<ast
::Name
>)
1305 -> hir
::HirVec
<hir
::Arg
> {
1306 let mut new_inputs
= Vec
::new();
1308 let new_ty
= self.rebuild_arg_ty_or_output(&arg
.ty
, lifetime
,
1309 anon_nums
, region_names
);
1310 let possibly_new_arg
= hir
::Arg
{
1312 pat
: arg
.pat
.clone(),
1315 new_inputs
.push(possibly_new_arg
);
1320 fn rebuild_output(&self, ty
: &hir
::FunctionRetTy
,
1321 lifetime
: hir
::Lifetime
,
1322 anon_nums
: &HashSet
<u32>,
1323 region_names
: &HashSet
<ast
::Name
>) -> hir
::FunctionRetTy
{
1325 hir
::Return(ref ret_ty
) => hir
::Return(
1326 self.rebuild_arg_ty_or_output(&ret_ty
, lifetime
, anon_nums
, region_names
)
1328 hir
::DefaultReturn(span
) => hir
::DefaultReturn(span
),
1332 fn rebuild_arg_ty_or_output(&self,
1334 lifetime
: hir
::Lifetime
,
1335 anon_nums
: &HashSet
<u32>,
1336 region_names
: &HashSet
<ast
::Name
>)
1338 let mut new_ty
= P(ty
.clone());
1339 let mut ty_queue
= vec
!(ty
);
1340 while !ty_queue
.is_empty() {
1341 let cur_ty
= ty_queue
.remove(0);
1343 hir
::TyRptr(lt_opt
, ref mut_ty
) => {
1344 let rebuild
= match lt_opt
{
1345 Some(lt
) => region_names
.contains(<
.name
),
1347 let anon
= self.cur_anon
.get();
1348 let rebuild
= anon_nums
.contains(&anon
);
1350 self.track_anon(anon
);
1352 self.inc_and_offset_cur_anon(1);
1359 node
: hir
::TyRptr(Some(lifetime
), mut_ty
.clone()),
1362 new_ty
= self.rebuild_ty(new_ty
, P(to
));
1364 ty_queue
.push(&mut_ty
.ty
);
1366 hir
::TyPath(ref maybe_qself
, ref path
) => {
1367 match self.tcx
.expect_def(cur_ty
.id
) {
1368 Def
::Enum(did
) | Def
::TyAlias(did
) | Def
::Struct(did
) => {
1369 let generics
= self.tcx
.lookup_item_type(did
).generics
;
1372 generics
.regions
.len(subst
::TypeSpace
) as u32;
1374 path
.segments
.last().unwrap().parameters
.lifetimes();
1375 let mut insert
= Vec
::new();
1376 if lifetimes
.is_empty() {
1377 let anon
= self.cur_anon
.get();
1378 for (i
, a
) in (anon
..anon
+expected
).enumerate() {
1379 if anon_nums
.contains(&a
) {
1380 insert
.push(i
as u32);
1384 self.inc_and_offset_cur_anon(expected
);
1386 for (i
, lt
) in lifetimes
.iter().enumerate() {
1387 if region_names
.contains(<
.name
) {
1388 insert
.push(i
as u32);
1392 let rebuild_info
= RebuildPathInfo
{
1396 anon_nums
: anon_nums
,
1397 region_names
: region_names
1399 let new_path
= self.rebuild_path(rebuild_info
, lifetime
);
1400 let qself
= maybe_qself
.as_ref().map(|qself
| {
1402 ty
: self.rebuild_arg_ty_or_output(&qself
.ty
, lifetime
,
1403 anon_nums
, region_names
),
1404 position
: qself
.position
1409 node
: hir
::TyPath(qself
, new_path
),
1412 new_ty
= self.rebuild_ty(new_ty
, P(to
));
1418 hir
::TyPtr(ref mut_ty
) => {
1419 ty_queue
.push(&mut_ty
.ty
);
1421 hir
::TyVec(ref ty
) |
1422 hir
::TyFixedLengthVec(ref ty
, _
) => {
1425 hir
::TyTup(ref tys
) => ty_queue
.extend(tys
.iter().map(|ty
| &**ty
)),
1432 fn rebuild_ty(&self,
1437 fn build_to(from
: P
<hir
::Ty
>,
1438 to
: &mut Option
<P
<hir
::Ty
>>)
1440 if Some(from
.id
) == to
.as_ref().map(|ty
| ty
.id
) {
1441 return to
.take().expect("`to` type found more than once during rebuild");
1443 from
.map(|hir
::Ty {id, node, span}
| {
1444 let new_node
= match node
{
1445 hir
::TyRptr(lifetime
, mut_ty
) => {
1446 hir
::TyRptr(lifetime
, hir
::MutTy
{
1447 mutbl
: mut_ty
.mutbl
,
1448 ty
: build_to(mut_ty
.ty
, to
),
1451 hir
::TyPtr(mut_ty
) => {
1452 hir
::TyPtr(hir
::MutTy
{
1453 mutbl
: mut_ty
.mutbl
,
1454 ty
: build_to(mut_ty
.ty
, to
),
1457 hir
::TyVec(ty
) => hir
::TyVec(build_to(ty
, to
)),
1458 hir
::TyFixedLengthVec(ty
, e
) => {
1459 hir
::TyFixedLengthVec(build_to(ty
, to
), e
)
1461 hir
::TyTup(tys
) => {
1462 hir
::TyTup(tys
.into_iter().map(|ty
| build_to(ty
, to
)).collect())
1466 hir
::Ty { id: id, node: new_node, span: span }
1470 build_to(from
, &mut Some(to
))
1473 fn rebuild_path(&self,
1474 rebuild_info
: RebuildPathInfo
,
1475 lifetime
: hir
::Lifetime
)
1478 let RebuildPathInfo
{
1486 let last_seg
= path
.segments
.last().unwrap();
1487 let new_parameters
= match last_seg
.parameters
{
1488 hir
::ParenthesizedParameters(..) => {
1489 last_seg
.parameters
.clone()
1492 hir
::AngleBracketedParameters(ref data
) => {
1493 let mut new_lts
= Vec
::new();
1494 if data
.lifetimes
.is_empty() {
1495 // traverse once to see if there's a need to insert lifetime
1496 let need_insert
= (0..expected
).any(|i
| {
1497 indexes
.contains(&i
)
1500 for i
in 0..expected
{
1501 if indexes
.contains(&i
) {
1502 new_lts
.push(lifetime
);
1504 new_lts
.push(self.life_giver
.give_lifetime());
1509 for (i
, lt
) in data
.lifetimes
.iter().enumerate() {
1510 if indexes
.contains(&(i
as u32)) {
1511 new_lts
.push(lifetime
);
1517 let new_types
= data
.types
.iter().map(|t
| {
1518 self.rebuild_arg_ty_or_output(&t
, lifetime
, anon_nums
, region_names
)
1520 let new_bindings
= data
.bindings
.iter().map(|b
| {
1524 ty
: self.rebuild_arg_ty_or_output(&b
.ty
,
1531 hir
::AngleBracketedParameters(hir
::AngleBracketedParameterData
{
1532 lifetimes
: new_lts
.into(),
1534 bindings
: new_bindings
,
1538 let new_seg
= hir
::PathSegment
{
1539 name
: last_seg
.name
,
1540 parameters
: new_parameters
1542 let mut new_segs
= Vec
::new();
1543 new_segs
.extend_from_slice(path
.segments
.split_last().unwrap().1);
1544 new_segs
.push(new_seg
);
1547 global
: path
.global
,
1548 segments
: new_segs
.into()
1553 impl<'a
, 'gcx
, 'tcx
> InferCtxt
<'a
, 'gcx
, 'tcx
> {
1554 fn give_expl_lifetime_param(&self,
1555 err
: &mut DiagnosticBuilder
,
1557 unsafety
: hir
::Unsafety
,
1558 constness
: hir
::Constness
,
1560 generics
: &hir
::Generics
,
1562 let suggested_fn
= pprust
::fun_to_string(decl
, unsafety
, constness
, name
, generics
);
1563 let msg
= format
!("consider using an explicit lifetime \
1564 parameter as shown: {}", suggested_fn
);
1565 err
.span_help(span
, &msg
[..]);
1568 fn report_inference_failure(&self,
1569 var_origin
: RegionVariableOrigin
)
1570 -> DiagnosticBuilder
<'tcx
> {
1571 let br_string
= |br
: ty
::BoundRegion
| {
1572 let mut s
= br
.to_string();
1578 let var_description
= match var_origin
{
1579 infer
::MiscVariable(_
) => "".to_string(),
1580 infer
::PatternRegion(_
) => " for pattern".to_string(),
1581 infer
::AddrOfRegion(_
) => " for borrow expression".to_string(),
1582 infer
::Autoref(_
) => " for autoref".to_string(),
1583 infer
::Coercion(_
) => " for automatic coercion".to_string(),
1584 infer
::LateBoundRegion(_
, br
, infer
::FnCall
) => {
1585 format
!(" for lifetime parameter {}in function call",
1588 infer
::LateBoundRegion(_
, br
, infer
::HigherRankedType
) => {
1589 format
!(" for lifetime parameter {}in generic type", br_string(br
))
1591 infer
::LateBoundRegion(_
, br
, infer
::AssocTypeProjection(type_name
)) => {
1592 format
!(" for lifetime parameter {}in trait containing associated type `{}`",
1593 br_string(br
), type_name
)
1595 infer
::EarlyBoundRegion(_
, name
) => {
1596 format
!(" for lifetime parameter `{}`",
1599 infer
::BoundRegionInCoherence(name
) => {
1600 format
!(" for lifetime parameter `{}` in coherence check",
1603 infer
::UpvarRegion(ref upvar_id
, _
) => {
1604 format
!(" for capture of `{}` by closure",
1605 self.tcx
.local_var_name_str(upvar_id
.var_id
).to_string())
1609 struct_span_err
!(self.tcx
.sess
, var_origin
.span(), E0495
,
1610 "cannot infer an appropriate lifetime{} \
1611 due to conflicting requirements",
1615 fn note_region_origin(&self, err
: &mut DiagnosticBuilder
, origin
: &SubregionOrigin
<'tcx
>) {
1617 infer
::Subtype(ref trace
) => {
1618 if let Some((expected
, found
)) = self.values_str(&trace
.values
) {
1619 // FIXME: do we want a "the" here?
1621 trace
.origin
.span(),
1622 &format
!("...so that {} (expected {}, found {})",
1623 trace
.origin
.as_requirement_str(), expected
, found
));
1625 // FIXME: this really should be handled at some earlier stage. Our
1626 // handling of region checking when type errors are present is
1630 trace
.origin
.span(),
1631 &format
!("...so that {}",
1632 trace
.origin
.as_requirement_str()));
1635 infer
::Reborrow(span
) => {
1638 "...so that reference does not outlive \
1641 infer
::ReborrowUpvar(span
, ref upvar_id
) => {
1645 "...so that closure can access `{}`",
1646 self.tcx
.local_var_name_str(upvar_id
.var_id
)
1649 infer
::InfStackClosure(span
) => {
1652 "...so that closure does not outlive its stack frame");
1654 infer
::InvokeClosure(span
) => {
1657 "...so that closure is not invoked outside its lifetime");
1659 infer
::DerefPointer(span
) => {
1662 "...so that pointer is not dereferenced \
1663 outside its lifetime");
1665 infer
::FreeVariable(span
, id
) => {
1668 &format
!("...so that captured variable `{}` \
1669 does not outlive the enclosing closure",
1670 self.tcx
.local_var_name_str(id
)));
1672 infer
::IndexSlice(span
) => {
1675 "...so that slice is not indexed outside the lifetime");
1677 infer
::RelateObjectBound(span
) => {
1680 "...so that it can be closed over into an object");
1682 infer
::CallRcvr(span
) => {
1685 "...so that method receiver is valid for the method call");
1687 infer
::CallArg(span
) => {
1690 "...so that argument is valid for the call");
1692 infer
::CallReturn(span
) => {
1695 "...so that return value is valid for the call");
1697 infer
::Operand(span
) => {
1700 "...so that operand is valid for operation");
1702 infer
::AddrOf(span
) => {
1705 "...so that reference is valid \
1706 at the time of borrow");
1708 infer
::AutoBorrow(span
) => {
1711 "...so that auto-reference is valid \
1712 at the time of borrow");
1714 infer
::ExprTypeIsNotInScope(t
, span
) => {
1717 &format
!("...so type `{}` of expression is valid during the \
1719 self.ty_to_string(t
)));
1721 infer
::BindingTypeIsNotValidAtDecl(span
) => {
1724 "...so that variable is valid at time of its declaration");
1726 infer
::ParameterInScope(_
, span
) => {
1729 "...so that a type/lifetime parameter is in scope here");
1731 infer
::DataBorrowed(ty
, span
) => {
1734 &format
!("...so that the type `{}` is not borrowed for too long",
1735 self.ty_to_string(ty
)));
1737 infer
::ReferenceOutlivesReferent(ty
, span
) => {
1740 &format
!("...so that the reference type `{}` \
1741 does not outlive the data it points at",
1742 self.ty_to_string(ty
)));
1744 infer
::RelateParamBound(span
, t
) => {
1747 &format
!("...so that the type `{}` \
1748 will meet its required lifetime bounds",
1749 self.ty_to_string(t
)));
1751 infer
::RelateDefaultParamBound(span
, t
) => {
1754 &format
!("...so that type parameter \
1755 instantiated with `{}`, \
1756 will meet its declared lifetime bounds",
1757 self.ty_to_string(t
)));
1759 infer
::RelateRegionParamBound(span
) => {
1762 "...so that the declared lifetime parameter bounds \
1765 infer
::SafeDestructor(span
) => {
1768 "...so that references are valid when the destructor \
1775 fn lifetimes_in_scope
<'a
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1776 scope_id
: ast
::NodeId
)
1777 -> Vec
<hir
::LifetimeDef
> {
1778 let mut taken
= Vec
::new();
1779 let parent
= tcx
.map
.get_parent(scope_id
);
1780 let method_id_opt
= match tcx
.map
.find(parent
) {
1781 Some(node
) => match node
{
1782 ast_map
::NodeItem(item
) => match item
.node
{
1783 hir
::ItemFn(_
, _
, _
, _
, ref gen
, _
) => {
1784 taken
.extend_from_slice(&gen
.lifetimes
);
1789 ast_map
::NodeImplItem(ii
) => {
1791 hir
::ImplItemKind
::Method(ref sig
, _
) => {
1792 taken
.extend_from_slice(&sig
.generics
.lifetimes
);
1802 if let Some(method_id
) = method_id_opt
{
1803 let parent
= tcx
.map
.get_parent(method_id
);
1804 if let Some(node
) = tcx
.map
.find(parent
) {
1806 ast_map
::NodeItem(item
) => match item
.node
{
1807 hir
::ItemImpl(_
, _
, ref gen
, _
, _
, _
) => {
1808 taken
.extend_from_slice(&gen
.lifetimes
);
1819 // LifeGiver is responsible for generating fresh lifetime names
1821 taken
: HashSet
<String
>,
1822 counter
: Cell
<usize>,
1823 generated
: RefCell
<Vec
<hir
::Lifetime
>>,
1827 fn with_taken(taken
: &[hir
::LifetimeDef
]) -> LifeGiver
{
1828 let mut taken_
= HashSet
::new();
1830 let lt_name
= lt
.lifetime
.name
.to_string();
1831 taken_
.insert(lt_name
);
1835 counter
: Cell
::new(0),
1836 generated
: RefCell
::new(Vec
::new()),
1840 fn inc_counter(&self) {
1841 let c
= self.counter
.get();
1842 self.counter
.set(c
+1);
1845 fn give_lifetime(&self) -> hir
::Lifetime
{
1848 let mut s
= String
::from("'");
1849 s
.push_str(&num_to_string(self.counter
.get()));
1850 if !self.taken
.contains(&s
) {
1851 lifetime
= name_to_dummy_lifetime(token
::intern(&s
[..]));
1852 self.generated
.borrow_mut().push(lifetime
);
1860 // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
1861 fn num_to_string(counter
: usize) -> String
{
1862 let mut s
= String
::new();
1863 let (n
, r
) = (counter
/26 + 1, counter
% 26);
1864 let letter
: char = from_u32((r
+97) as u32).unwrap();
1872 fn get_generated_lifetimes(&self) -> Vec
<hir
::Lifetime
> {
1873 self.generated
.borrow().clone()
1877 fn name_to_dummy_lifetime(name
: ast
::Name
) -> hir
::Lifetime
{
1878 hir
::Lifetime
{ id
: ast
::DUMMY_NODE_ID
,
1879 span
: syntax_pos
::DUMMY_SP
,