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}
;
85 use ty
::{self, TyCtxt, TypeFoldable}
;
86 use ty
::{Region, ReFree}
;
87 use ty
::error
::TypeError
;
89 use std
::cell
::{Cell, RefCell}
;
90 use std
::char::from_u32
;
93 use syntax
::parse
::token
;
95 use syntax_pos
::{self, Pos, Span}
;
96 use errors
::DiagnosticBuilder
;
98 impl<'a
, 'gcx
, 'tcx
> TyCtxt
<'a
, 'gcx
, 'tcx
> {
99 pub fn note_and_explain_region(self,
100 err
: &mut DiagnosticBuilder
,
102 region
: &'tcx ty
::Region
,
104 fn item_scope_tag(item
: &hir
::Item
) -> &'
static str {
106 hir
::ItemImpl(..) => "impl",
107 hir
::ItemStruct(..) => "struct",
108 hir
::ItemUnion(..) => "union",
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
::TyAdt(exp_adt
, _
), &ty
::TyAdt(found_adt
, _
)) => {
492 report_path_match(err
, exp_adt
.did
, found_adt
.did
);
497 TypeError
::Traits(ref exp_found
) => {
498 report_path_match(err
, exp_found
.expected
, exp_found
.found
);
500 _
=> () // FIXME(#22750) handle traits and stuff
504 fn note_error_origin(&self,
505 err
: &mut DiagnosticBuilder
<'tcx
>,
509 &TypeOrigin
::MatchExpressionArm(_
, arm_span
, source
) => match source
{
510 hir
::MatchSource
::IfLetDesugar {..}
=> {
511 err
.span_note(arm_span
, "`if let` arm with an incompatible type");
514 err
.span_note(arm_span
, "match arm with an incompatible type");
521 pub fn note_type_err(&self,
522 diag
: &mut DiagnosticBuilder
<'tcx
>,
524 secondary_span
: Option
<(Span
, String
)>,
525 values
: Option
<ValuePairs
<'tcx
>>,
526 terr
: &TypeError
<'tcx
>)
528 let expected_found
= match values
{
530 Some(values
) => match self.values_str(&values
) {
531 Some((expected
, found
)) => Some((expected
, found
)),
533 // Derived error. Cancel the emitter.
534 self.tcx
.sess
.diagnostic().cancel(diag
);
540 let span
= origin
.span();
542 if let Some((expected
, found
)) = expected_found
{
543 let is_simple_error
= if let &TypeError
::Sorts(ref values
) = terr
{
544 values
.expected
.is_primitive() && values
.found
.is_primitive()
549 if !is_simple_error
{
550 if expected
== found
{
551 if let &TypeError
::Sorts(ref values
) = terr
{
552 diag
.note_expected_found_extra(
553 &"type", &expected
, &found
,
554 &format
!(" ({})", values
.expected
.sort_string(self.tcx
)),
555 &format
!(" ({})", values
.found
.sort_string(self.tcx
)));
557 diag
.note_expected_found(&"type", &expected
, &found
);
560 diag
.note_expected_found(&"type", &expected
, &found
);
565 diag
.span_label(span
, &terr
);
566 if let Some((sp
, msg
)) = secondary_span
{
567 diag
.span_label(sp
, &msg
);
570 self.note_error_origin(diag
, &origin
);
571 self.check_and_note_conflicting_crates(diag
, terr
, span
);
572 self.tcx
.note_and_explain_type_err(diag
, terr
, span
);
575 pub fn report_and_explain_type_error(&self,
576 trace
: TypeTrace
<'tcx
>,
577 terr
: &TypeError
<'tcx
>)
578 -> DiagnosticBuilder
<'tcx
>
580 // FIXME: do we want to use a different error code for each origin?
581 let mut diag
= struct_span_err
!(
582 self.tcx
.sess
, trace
.origin
.span(), E0308
,
583 "{}", trace
.origin
.as_failure_str()
585 self.note_type_err(&mut diag
, trace
.origin
, None
, Some(trace
.values
), terr
);
589 /// Returns a string of the form "expected `{}`, found `{}`".
590 fn values_str(&self, values
: &ValuePairs
<'tcx
>) -> Option
<(String
, String
)> {
592 infer
::Types(ref exp_found
) => self.expected_found_str(exp_found
),
593 infer
::TraitRefs(ref exp_found
) => self.expected_found_str(exp_found
),
594 infer
::PolyTraitRefs(ref exp_found
) => self.expected_found_str(exp_found
),
598 fn expected_found_str
<T
: fmt
::Display
+ TypeFoldable
<'tcx
>>(
600 exp_found
: &ty
::error
::ExpectedFound
<T
>)
601 -> Option
<(String
, String
)>
603 let exp_found
= self.resolve_type_vars_if_possible(exp_found
);
604 if exp_found
.references_error() {
608 Some((format
!("{}", exp_found
.expected
), format
!("{}", exp_found
.found
)))
611 fn report_generic_bound_failure(&self,
612 origin
: SubregionOrigin
<'tcx
>,
613 bound_kind
: GenericKind
<'tcx
>,
616 // FIXME: it would be better to report the first error message
617 // with the span of the parameter itself, rather than the span
618 // where the error was detected. But that span is not readily
621 let labeled_user_string
= match bound_kind
{
622 GenericKind
::Param(ref p
) =>
623 format
!("the parameter type `{}`", p
),
624 GenericKind
::Projection(ref p
) =>
625 format
!("the associated type `{}`", p
),
628 let mut err
= match *sub
{
629 ty
::ReFree(ty
::FreeRegion {bound_region: ty::BrNamed(..), ..}
) => {
630 // Does the required lifetime have a nice name we can print?
631 let mut err
= struct_span_err
!(self.tcx
.sess
,
634 "{} may not live long enough",
635 labeled_user_string
);
636 err
.help(&format
!("consider adding an explicit lifetime bound `{}: {}`...",
643 // Does the required lifetime have a nice name we can print?
644 let mut err
= struct_span_err
!(self.tcx
.sess
,
647 "{} may not live long enough",
648 labeled_user_string
);
649 err
.help(&format
!("consider adding an explicit lifetime \
650 bound `{}: 'static`...",
656 // If not, be less specific.
657 let mut err
= struct_span_err
!(self.tcx
.sess
,
660 "{} may not live long enough",
661 labeled_user_string
);
662 err
.help(&format
!("consider adding an explicit lifetime bound for `{}`",
664 self.tcx
.note_and_explain_region(
666 &format
!("{} must be valid for ", labeled_user_string
),
673 self.note_region_origin(&mut err
, &origin
);
677 fn report_concrete_failure(&self,
678 origin
: SubregionOrigin
<'tcx
>,
681 -> DiagnosticBuilder
<'tcx
> {
683 infer
::Subtype(trace
) => {
684 let terr
= TypeError
::RegionsDoesNotOutlive(sup
, sub
);
685 self.report_and_explain_type_error(trace
, &terr
)
687 infer
::Reborrow(span
) => {
688 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0312
,
689 "lifetime of reference outlives \
690 lifetime of borrowed content...");
691 self.tcx
.note_and_explain_region(&mut err
,
692 "...the reference is valid for ",
695 self.tcx
.note_and_explain_region(&mut err
,
696 "...but the borrowed content is only valid for ",
701 infer
::ReborrowUpvar(span
, ref upvar_id
) => {
702 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0313
,
703 "lifetime of borrowed pointer outlives \
704 lifetime of captured variable `{}`...",
705 self.tcx
.local_var_name_str(upvar_id
.var_id
));
706 self.tcx
.note_and_explain_region(&mut err
,
707 "...the borrowed pointer is valid for ",
710 self.tcx
.note_and_explain_region(&mut err
,
711 &format
!("...but `{}` is only valid for ",
712 self.tcx
.local_var_name_str(upvar_id
.var_id
)),
717 infer
::InfStackClosure(span
) => {
718 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0314
,
719 "closure outlives stack frame");
720 self.tcx
.note_and_explain_region(&mut err
,
721 "...the closure must be valid for ",
724 self.tcx
.note_and_explain_region(&mut err
,
725 "...but the closure's stack frame is only valid for ",
730 infer
::InvokeClosure(span
) => {
731 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0315
,
732 "cannot invoke closure outside of its lifetime");
733 self.tcx
.note_and_explain_region(&mut err
,
734 "the closure is only valid for ",
739 infer
::DerefPointer(span
) => {
740 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0473
,
741 "dereference of reference outside its lifetime");
742 self.tcx
.note_and_explain_region(&mut err
,
743 "the reference is only valid for ",
748 infer
::FreeVariable(span
, id
) => {
749 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0474
,
750 "captured variable `{}` does not outlive the enclosing closure",
751 self.tcx
.local_var_name_str(id
));
752 self.tcx
.note_and_explain_region(&mut err
,
753 "captured variable is valid for ",
756 self.tcx
.note_and_explain_region(&mut err
,
757 "closure is valid for ",
762 infer
::IndexSlice(span
) => {
763 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0475
,
764 "index of slice outside its lifetime");
765 self.tcx
.note_and_explain_region(&mut err
,
766 "the slice is only valid for ",
771 infer
::RelateObjectBound(span
) => {
772 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0476
,
773 "lifetime of the source pointer does not outlive \
774 lifetime bound of the object type");
775 self.tcx
.note_and_explain_region(&mut err
,
776 "object type is valid for ",
779 self.tcx
.note_and_explain_region(&mut err
,
780 "source pointer is only valid for ",
785 infer
::RelateParamBound(span
, ty
) => {
786 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0477
,
787 "the type `{}` does not fulfill the required lifetime",
788 self.ty_to_string(ty
));
789 self.tcx
.note_and_explain_region(&mut err
,
790 "type must outlive ",
795 infer
::RelateRegionParamBound(span
) => {
796 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0478
,
797 "lifetime bound not satisfied");
798 self.tcx
.note_and_explain_region(&mut err
,
799 "lifetime parameter instantiated with ",
802 self.tcx
.note_and_explain_region(&mut err
,
803 "but lifetime parameter must outlive ",
808 infer
::RelateDefaultParamBound(span
, ty
) => {
809 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0479
,
810 "the type `{}` (provided as the value of \
811 a type parameter) is not valid at this point",
812 self.ty_to_string(ty
));
813 self.tcx
.note_and_explain_region(&mut err
,
814 "type must outlive ",
819 infer
::CallRcvr(span
) => {
820 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0480
,
821 "lifetime of method receiver does not outlive \
823 self.tcx
.note_and_explain_region(&mut err
,
824 "the receiver is only valid for ",
829 infer
::CallArg(span
) => {
830 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0481
,
831 "lifetime of function argument does not outlive \
833 self.tcx
.note_and_explain_region(&mut err
,
834 "the function argument is only valid for ",
839 infer
::CallReturn(span
) => {
840 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0482
,
841 "lifetime of return value does not outlive \
843 self.tcx
.note_and_explain_region(&mut err
,
844 "the return value is only valid for ",
849 infer
::Operand(span
) => {
850 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0483
,
851 "lifetime of operand does not outlive \
853 self.tcx
.note_and_explain_region(&mut err
,
854 "the operand is only valid for ",
859 infer
::AddrOf(span
) => {
860 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0484
,
861 "reference is not valid at the time of borrow");
862 self.tcx
.note_and_explain_region(&mut err
,
863 "the borrow is only valid for ",
868 infer
::AutoBorrow(span
) => {
869 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0485
,
870 "automatically reference is not valid \
871 at the time of borrow");
872 self.tcx
.note_and_explain_region(&mut err
,
873 "the automatic borrow is only valid for ",
878 infer
::ExprTypeIsNotInScope(t
, span
) => {
879 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0486
,
880 "type of expression contains references \
881 that are not valid during the expression: `{}`",
882 self.ty_to_string(t
));
883 self.tcx
.note_and_explain_region(&mut err
,
884 "type is only valid for ",
889 infer
::SafeDestructor(span
) => {
890 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0487
,
891 "unsafe use of destructor: destructor might be called \
892 while references are dead");
893 // FIXME (22171): terms "super/subregion" are suboptimal
894 self.tcx
.note_and_explain_region(&mut err
,
898 self.tcx
.note_and_explain_region(&mut err
,
904 infer
::BindingTypeIsNotValidAtDecl(span
) => {
905 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0488
,
906 "lifetime of variable does not enclose its declaration");
907 self.tcx
.note_and_explain_region(&mut err
,
908 "the variable is only valid for ",
913 infer
::ParameterInScope(_
, span
) => {
914 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0489
,
915 "type/lifetime parameter not in scope here");
916 self.tcx
.note_and_explain_region(&mut err
,
917 "the parameter is only valid for ",
922 infer
::DataBorrowed(ty
, span
) => {
923 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0490
,
924 "a value of type `{}` is borrowed for too long",
925 self.ty_to_string(ty
));
926 self.tcx
.note_and_explain_region(&mut err
, "the type is valid for ", sub
, "");
927 self.tcx
.note_and_explain_region(&mut err
, "but the borrow lasts for ", sup
, "");
930 infer
::ReferenceOutlivesReferent(ty
, span
) => {
931 let mut err
= struct_span_err
!(self.tcx
.sess
, span
, E0491
,
932 "in type `{}`, reference has a longer lifetime \
933 than the data it references",
934 self.ty_to_string(ty
));
935 self.tcx
.note_and_explain_region(&mut err
,
936 "the pointer is valid for ",
939 self.tcx
.note_and_explain_region(&mut err
,
940 "but the referenced data is only valid for ",
948 fn report_sub_sup_conflict(&self,
949 var_origin
: RegionVariableOrigin
,
950 sub_origin
: SubregionOrigin
<'tcx
>,
951 sub_region
: &'tcx Region
,
952 sup_origin
: SubregionOrigin
<'tcx
>,
953 sup_region
: &'tcx Region
) {
954 let mut err
= self.report_inference_failure(var_origin
);
956 self.tcx
.note_and_explain_region(&mut err
,
957 "first, the lifetime cannot outlive ",
961 self.note_region_origin(&mut err
, &sup_origin
);
963 self.tcx
.note_and_explain_region(&mut err
,
964 "but, the lifetime must be valid for ",
968 self.note_region_origin(&mut err
, &sub_origin
);
972 fn report_processed_errors(&self,
973 origins
: &[ProcessedErrorOrigin
<'tcx
>],
974 same_regions
: &[SameRegions
]) {
975 for (i
, origin
) in origins
.iter().enumerate() {
976 let mut err
= match *origin
{
977 ProcessedErrorOrigin
::VariableFailure(ref var_origin
) =>
978 self.report_inference_failure(var_origin
.clone()),
979 ProcessedErrorOrigin
::ConcreteFailure(ref sr_origin
, sub
, sup
) =>
980 self.report_concrete_failure(sr_origin
.clone(), sub
, sup
),
983 // attach the suggestion to the last such error
984 if i
== origins
.len() - 1 {
985 self.give_suggestion(&mut err
, same_regions
);
992 fn give_suggestion(&self, err
: &mut DiagnosticBuilder
, same_regions
: &[SameRegions
]) {
993 let scope_id
= same_regions
[0].scope_id
;
994 let parent
= self.tcx
.map
.get_parent(scope_id
);
995 let parent_node
= self.tcx
.map
.find(parent
);
996 let taken
= lifetimes_in_scope(self.tcx
, scope_id
);
997 let life_giver
= LifeGiver
::with_taken(&taken
[..]);
998 let node_inner
= match parent_node
{
999 Some(ref node
) => match *node
{
1000 ast_map
::NodeItem(ref item
) => {
1002 hir
::ItemFn(ref fn_decl
, unsafety
, constness
, _
, ref gen
, _
) => {
1003 Some((fn_decl
, gen
, unsafety
, constness
, item
.name
, item
.span
))
1008 ast_map
::NodeImplItem(item
) => {
1010 hir
::ImplItemKind
::Method(ref sig
, _
) => {
1021 ast_map
::NodeTraitItem(item
) => {
1023 hir
::MethodTraitItem(ref sig
, Some(_
)) => {
1038 let (fn_decl
, generics
, unsafety
, constness
, name
, span
)
1039 = node_inner
.expect("expect item fn");
1040 let rebuilder
= Rebuilder
::new(self.tcx
, fn_decl
, generics
, same_regions
, &life_giver
);
1041 let (fn_decl
, generics
) = rebuilder
.rebuild();
1042 self.give_expl_lifetime_param(
1043 err
, &fn_decl
, unsafety
, constness
, name
, &generics
, span
);
1046 pub fn issue_32330_warnings(&self, span
: Span
, issue32330s
: &[ty
::Issue32330
]) {
1047 for issue32330
in issue32330s
{
1049 ty
::Issue32330
::WontChange
=> { }
1050 ty
::Issue32330
::WillChange { fn_def_id, region_name }
=> {
1051 self.tcx
.sess
.add_lint(
1052 lint
::builtin
::HR_LIFETIME_IN_ASSOC_TYPE
,
1055 format
!("lifetime parameter `{0}` declared on fn `{1}` \
1056 appears only in the return type, \
1057 but here is required to be higher-ranked, \
1058 which means that `{0}` must appear in both \
1059 argument and return types",
1061 self.tcx
.item_path_str(fn_def_id
)));
1068 struct RebuildPathInfo
<'a
> {
1069 path
: &'a hir
::Path
,
1070 // indexes to insert lifetime on path.lifetimes
1072 // number of lifetimes we expect to see on the type referred by `path`
1073 // (e.g., expected=1 for struct Foo<'a>)
1075 anon_nums
: &'a HashSet
<u32>,
1076 region_names
: &'a HashSet
<ast
::Name
>
1079 struct Rebuilder
<'a
, 'gcx
: 'a
+'tcx
, 'tcx
: 'a
> {
1080 tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1081 fn_decl
: &'a hir
::FnDecl
,
1082 generics
: &'a hir
::Generics
,
1083 same_regions
: &'a
[SameRegions
],
1084 life_giver
: &'a LifeGiver
,
1085 cur_anon
: Cell
<u32>,
1086 inserted_anons
: RefCell
<HashSet
<u32>>,
1094 impl<'a
, 'gcx
, 'tcx
> Rebuilder
<'a
, 'gcx
, 'tcx
> {
1095 fn new(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1096 fn_decl
: &'a hir
::FnDecl
,
1097 generics
: &'a hir
::Generics
,
1098 same_regions
: &'a
[SameRegions
],
1099 life_giver
: &'a LifeGiver
)
1100 -> Rebuilder
<'a
, 'gcx
, 'tcx
> {
1105 same_regions
: same_regions
,
1106 life_giver
: life_giver
,
1107 cur_anon
: Cell
::new(0),
1108 inserted_anons
: RefCell
::new(HashSet
::new()),
1112 fn rebuild(&self) -> (hir
::FnDecl
, hir
::Generics
) {
1113 let mut inputs
= self.fn_decl
.inputs
.clone();
1114 let mut output
= self.fn_decl
.output
.clone();
1115 let mut ty_params
= self.generics
.ty_params
.clone();
1116 let where_clause
= self.generics
.where_clause
.clone();
1117 let mut kept_lifetimes
= HashSet
::new();
1118 for sr
in self.same_regions
{
1119 self.cur_anon
.set(0);
1120 self.offset_cur_anon();
1121 let (anon_nums
, region_names
) =
1122 self.extract_anon_nums_and_names(sr
);
1123 let (lifetime
, fresh_or_kept
) = self.pick_lifetime(®ion_names
);
1124 match fresh_or_kept
{
1125 Kept
=> { kept_lifetimes.insert(lifetime.name); }
1128 inputs
= self.rebuild_args_ty(&inputs
[..], lifetime
,
1129 &anon_nums
, ®ion_names
);
1130 output
= self.rebuild_output(&output
, lifetime
, &anon_nums
, ®ion_names
);
1131 ty_params
= self.rebuild_ty_params(ty_params
, lifetime
,
1134 let fresh_lifetimes
= self.life_giver
.get_generated_lifetimes();
1135 let all_region_names
= self.extract_all_region_names();
1136 let generics
= self.rebuild_generics(self.generics
,
1142 let new_fn_decl
= hir
::FnDecl
{
1145 variadic
: self.fn_decl
.variadic
1147 (new_fn_decl
, generics
)
1150 fn pick_lifetime(&self,
1151 region_names
: &HashSet
<ast
::Name
>)
1152 -> (hir
::Lifetime
, FreshOrKept
) {
1153 if !region_names
.is_empty() {
1154 // It's not necessary to convert the set of region names to a
1155 // vector of string and then sort them. However, it makes the
1156 // choice of lifetime name deterministic and thus easier to test.
1157 let mut names
= Vec
::new();
1158 for rn
in region_names
{
1159 let lt_name
= rn
.to_string();
1160 names
.push(lt_name
);
1163 let name
= token
::intern(&names
[0]);
1164 return (name_to_dummy_lifetime(name
), Kept
);
1166 return (self.life_giver
.give_lifetime(), Fresh
);
1169 fn extract_anon_nums_and_names(&self, same_regions
: &SameRegions
)
1170 -> (HashSet
<u32>, HashSet
<ast
::Name
>) {
1171 let mut anon_nums
= HashSet
::new();
1172 let mut region_names
= HashSet
::new();
1173 for br
in &same_regions
.regions
{
1176 anon_nums
.insert(i
);
1178 ty
::BrNamed(_
, name
, _
) => {
1179 region_names
.insert(name
);
1184 (anon_nums
, region_names
)
1187 fn extract_all_region_names(&self) -> HashSet
<ast
::Name
> {
1188 let mut all_region_names
= HashSet
::new();
1189 for sr
in self.same_regions
{
1190 for br
in &sr
.regions
{
1192 ty
::BrNamed(_
, name
, _
) => {
1193 all_region_names
.insert(name
);
1202 fn inc_cur_anon(&self, n
: u32) {
1203 let anon
= self.cur_anon
.get();
1204 self.cur_anon
.set(anon
+n
);
1207 fn offset_cur_anon(&self) {
1208 let mut anon
= self.cur_anon
.get();
1209 while self.inserted_anons
.borrow().contains(&anon
) {
1212 self.cur_anon
.set(anon
);
1215 fn inc_and_offset_cur_anon(&self, n
: u32) {
1216 self.inc_cur_anon(n
);
1217 self.offset_cur_anon();
1220 fn track_anon(&self, anon
: u32) {
1221 self.inserted_anons
.borrow_mut().insert(anon
);
1224 fn rebuild_ty_params(&self,
1225 ty_params
: hir
::HirVec
<hir
::TyParam
>,
1226 lifetime
: hir
::Lifetime
,
1227 region_names
: &HashSet
<ast
::Name
>)
1228 -> hir
::HirVec
<hir
::TyParam
> {
1229 ty_params
.iter().map(|ty_param
| {
1230 let bounds
= self.rebuild_ty_param_bounds(ty_param
.bounds
.clone(),
1234 name
: ty_param
.name
,
1237 default: ty_param
.default.clone(),
1238 span
: ty_param
.span
,
1243 fn rebuild_ty_param_bounds(&self,
1244 ty_param_bounds
: hir
::TyParamBounds
,
1245 lifetime
: hir
::Lifetime
,
1246 region_names
: &HashSet
<ast
::Name
>)
1247 -> hir
::TyParamBounds
{
1248 ty_param_bounds
.iter().map(|tpb
| {
1250 &hir
::RegionTyParamBound(lt
) => {
1251 // FIXME -- it's unclear whether I'm supposed to
1252 // substitute lifetime here. I suspect we need to
1253 // be passing down a map.
1254 hir
::RegionTyParamBound(lt
)
1256 &hir
::TraitTyParamBound(ref poly_tr
, modifier
) => {
1257 let tr
= &poly_tr
.trait_ref
;
1258 let last_seg
= tr
.path
.segments
.last().unwrap();
1259 let mut insert
= Vec
::new();
1260 let lifetimes
= last_seg
.parameters
.lifetimes();
1261 for (i
, lt
) in lifetimes
.iter().enumerate() {
1262 if region_names
.contains(<
.name
) {
1263 insert
.push(i
as u32);
1266 let rebuild_info
= RebuildPathInfo
{
1269 expected
: lifetimes
.len() as u32,
1270 anon_nums
: &HashSet
::new(),
1271 region_names
: region_names
1273 let new_path
= self.rebuild_path(rebuild_info
, lifetime
);
1274 hir
::TraitTyParamBound(hir
::PolyTraitRef
{
1275 bound_lifetimes
: poly_tr
.bound_lifetimes
.clone(),
1276 trait_ref
: hir
::TraitRef
{
1287 fn rebuild_generics(&self,
1288 generics
: &hir
::Generics
,
1289 add
: &Vec
<hir
::Lifetime
>,
1290 keep
: &HashSet
<ast
::Name
>,
1291 remove
: &HashSet
<ast
::Name
>,
1292 ty_params
: hir
::HirVec
<hir
::TyParam
>,
1293 where_clause
: hir
::WhereClause
)
1295 let mut lifetimes
= Vec
::new();
1297 lifetimes
.push(hir
::LifetimeDef
{ lifetime
: *lt
,
1298 bounds
: hir
::HirVec
::new() });
1300 for lt
in &generics
.lifetimes
{
1301 if keep
.contains(<
.lifetime
.name
) ||
1302 !remove
.contains(<
.lifetime
.name
) {
1303 lifetimes
.push((*lt
).clone());
1307 lifetimes
: lifetimes
.into(),
1308 ty_params
: ty_params
,
1309 where_clause
: where_clause
,
1310 span
: generics
.span
,
1314 fn rebuild_args_ty(&self,
1315 inputs
: &[hir
::Arg
],
1316 lifetime
: hir
::Lifetime
,
1317 anon_nums
: &HashSet
<u32>,
1318 region_names
: &HashSet
<ast
::Name
>)
1319 -> hir
::HirVec
<hir
::Arg
> {
1320 let mut new_inputs
= Vec
::new();
1322 let new_ty
= self.rebuild_arg_ty_or_output(&arg
.ty
, lifetime
,
1323 anon_nums
, region_names
);
1324 let possibly_new_arg
= hir
::Arg
{
1326 pat
: arg
.pat
.clone(),
1329 new_inputs
.push(possibly_new_arg
);
1334 fn rebuild_output(&self, ty
: &hir
::FunctionRetTy
,
1335 lifetime
: hir
::Lifetime
,
1336 anon_nums
: &HashSet
<u32>,
1337 region_names
: &HashSet
<ast
::Name
>) -> hir
::FunctionRetTy
{
1339 hir
::Return(ref ret_ty
) => hir
::Return(
1340 self.rebuild_arg_ty_or_output(&ret_ty
, lifetime
, anon_nums
, region_names
)
1342 hir
::DefaultReturn(span
) => hir
::DefaultReturn(span
),
1346 fn rebuild_arg_ty_or_output(&self,
1348 lifetime
: hir
::Lifetime
,
1349 anon_nums
: &HashSet
<u32>,
1350 region_names
: &HashSet
<ast
::Name
>)
1352 let mut new_ty
= P(ty
.clone());
1353 let mut ty_queue
= vec
!(ty
);
1354 while !ty_queue
.is_empty() {
1355 let cur_ty
= ty_queue
.remove(0);
1357 hir
::TyRptr(lt_opt
, ref mut_ty
) => {
1358 let rebuild
= match lt_opt
{
1359 Some(lt
) => region_names
.contains(<
.name
),
1361 let anon
= self.cur_anon
.get();
1362 let rebuild
= anon_nums
.contains(&anon
);
1364 self.track_anon(anon
);
1366 self.inc_and_offset_cur_anon(1);
1373 node
: hir
::TyRptr(Some(lifetime
), mut_ty
.clone()),
1376 new_ty
= self.rebuild_ty(new_ty
, P(to
));
1378 ty_queue
.push(&mut_ty
.ty
);
1380 hir
::TyPath(ref maybe_qself
, ref path
) => {
1381 match self.tcx
.expect_def(cur_ty
.id
) {
1382 Def
::Enum(did
) | Def
::TyAlias(did
) |
1383 Def
::Struct(did
) | Def
::Union(did
) => {
1384 let generics
= self.tcx
.lookup_generics(did
);
1387 generics
.regions
.len() as u32;
1389 path
.segments
.last().unwrap().parameters
.lifetimes();
1390 let mut insert
= Vec
::new();
1391 if lifetimes
.is_empty() {
1392 let anon
= self.cur_anon
.get();
1393 for (i
, a
) in (anon
..anon
+expected
).enumerate() {
1394 if anon_nums
.contains(&a
) {
1395 insert
.push(i
as u32);
1399 self.inc_and_offset_cur_anon(expected
);
1401 for (i
, lt
) in lifetimes
.iter().enumerate() {
1402 if region_names
.contains(<
.name
) {
1403 insert
.push(i
as u32);
1407 let rebuild_info
= RebuildPathInfo
{
1411 anon_nums
: anon_nums
,
1412 region_names
: region_names
1414 let new_path
= self.rebuild_path(rebuild_info
, lifetime
);
1415 let qself
= maybe_qself
.as_ref().map(|qself
| {
1417 ty
: self.rebuild_arg_ty_or_output(&qself
.ty
, lifetime
,
1418 anon_nums
, region_names
),
1419 position
: qself
.position
1424 node
: hir
::TyPath(qself
, new_path
),
1427 new_ty
= self.rebuild_ty(new_ty
, P(to
));
1433 hir
::TyPtr(ref mut_ty
) => {
1434 ty_queue
.push(&mut_ty
.ty
);
1436 hir
::TyVec(ref ty
) |
1437 hir
::TyFixedLengthVec(ref ty
, _
) => {
1440 hir
::TyTup(ref tys
) => ty_queue
.extend(tys
.iter().map(|ty
| &**ty
)),
1447 fn rebuild_ty(&self,
1452 fn build_to(from
: P
<hir
::Ty
>,
1453 to
: &mut Option
<P
<hir
::Ty
>>)
1455 if Some(from
.id
) == to
.as_ref().map(|ty
| ty
.id
) {
1456 return to
.take().expect("`to` type found more than once during rebuild");
1458 from
.map(|hir
::Ty {id, node, span}
| {
1459 let new_node
= match node
{
1460 hir
::TyRptr(lifetime
, mut_ty
) => {
1461 hir
::TyRptr(lifetime
, hir
::MutTy
{
1462 mutbl
: mut_ty
.mutbl
,
1463 ty
: build_to(mut_ty
.ty
, to
),
1466 hir
::TyPtr(mut_ty
) => {
1467 hir
::TyPtr(hir
::MutTy
{
1468 mutbl
: mut_ty
.mutbl
,
1469 ty
: build_to(mut_ty
.ty
, to
),
1472 hir
::TyVec(ty
) => hir
::TyVec(build_to(ty
, to
)),
1473 hir
::TyFixedLengthVec(ty
, e
) => {
1474 hir
::TyFixedLengthVec(build_to(ty
, to
), e
)
1476 hir
::TyTup(tys
) => {
1477 hir
::TyTup(tys
.into_iter().map(|ty
| build_to(ty
, to
)).collect())
1481 hir
::Ty { id: id, node: new_node, span: span }
1485 build_to(from
, &mut Some(to
))
1488 fn rebuild_path(&self,
1489 rebuild_info
: RebuildPathInfo
,
1490 lifetime
: hir
::Lifetime
)
1493 let RebuildPathInfo
{
1501 let last_seg
= path
.segments
.last().unwrap();
1502 let new_parameters
= match last_seg
.parameters
{
1503 hir
::ParenthesizedParameters(..) => {
1504 last_seg
.parameters
.clone()
1507 hir
::AngleBracketedParameters(ref data
) => {
1508 let mut new_lts
= Vec
::new();
1509 if data
.lifetimes
.is_empty() {
1510 // traverse once to see if there's a need to insert lifetime
1511 let need_insert
= (0..expected
).any(|i
| {
1512 indexes
.contains(&i
)
1515 for i
in 0..expected
{
1516 if indexes
.contains(&i
) {
1517 new_lts
.push(lifetime
);
1519 new_lts
.push(self.life_giver
.give_lifetime());
1524 for (i
, lt
) in data
.lifetimes
.iter().enumerate() {
1525 if indexes
.contains(&(i
as u32)) {
1526 new_lts
.push(lifetime
);
1532 let new_types
= data
.types
.iter().map(|t
| {
1533 self.rebuild_arg_ty_or_output(&t
, lifetime
, anon_nums
, region_names
)
1535 let new_bindings
= data
.bindings
.iter().map(|b
| {
1539 ty
: self.rebuild_arg_ty_or_output(&b
.ty
,
1546 hir
::AngleBracketedParameters(hir
::AngleBracketedParameterData
{
1547 lifetimes
: new_lts
.into(),
1549 bindings
: new_bindings
,
1553 let new_seg
= hir
::PathSegment
{
1554 name
: last_seg
.name
,
1555 parameters
: new_parameters
1557 let mut new_segs
= Vec
::new();
1558 new_segs
.extend_from_slice(path
.segments
.split_last().unwrap().1);
1559 new_segs
.push(new_seg
);
1562 global
: path
.global
,
1563 segments
: new_segs
.into()
1568 impl<'a
, 'gcx
, 'tcx
> InferCtxt
<'a
, 'gcx
, 'tcx
> {
1569 fn give_expl_lifetime_param(&self,
1570 err
: &mut DiagnosticBuilder
,
1572 unsafety
: hir
::Unsafety
,
1573 constness
: hir
::Constness
,
1575 generics
: &hir
::Generics
,
1577 let suggested_fn
= pprust
::fun_to_string(decl
, unsafety
, constness
, name
, generics
);
1578 let msg
= format
!("consider using an explicit lifetime \
1579 parameter as shown: {}", suggested_fn
);
1580 err
.span_help(span
, &msg
[..]);
1583 fn report_inference_failure(&self,
1584 var_origin
: RegionVariableOrigin
)
1585 -> DiagnosticBuilder
<'tcx
> {
1586 let br_string
= |br
: ty
::BoundRegion
| {
1587 let mut s
= br
.to_string();
1593 let var_description
= match var_origin
{
1594 infer
::MiscVariable(_
) => "".to_string(),
1595 infer
::PatternRegion(_
) => " for pattern".to_string(),
1596 infer
::AddrOfRegion(_
) => " for borrow expression".to_string(),
1597 infer
::Autoref(_
) => " for autoref".to_string(),
1598 infer
::Coercion(_
) => " for automatic coercion".to_string(),
1599 infer
::LateBoundRegion(_
, br
, infer
::FnCall
) => {
1600 format
!(" for lifetime parameter {}in function call",
1603 infer
::LateBoundRegion(_
, br
, infer
::HigherRankedType
) => {
1604 format
!(" for lifetime parameter {}in generic type", br_string(br
))
1606 infer
::LateBoundRegion(_
, br
, infer
::AssocTypeProjection(type_name
)) => {
1607 format
!(" for lifetime parameter {}in trait containing associated type `{}`",
1608 br_string(br
), type_name
)
1610 infer
::EarlyBoundRegion(_
, name
) => {
1611 format
!(" for lifetime parameter `{}`",
1614 infer
::BoundRegionInCoherence(name
) => {
1615 format
!(" for lifetime parameter `{}` in coherence check",
1618 infer
::UpvarRegion(ref upvar_id
, _
) => {
1619 format
!(" for capture of `{}` by closure",
1620 self.tcx
.local_var_name_str(upvar_id
.var_id
).to_string())
1624 struct_span_err
!(self.tcx
.sess
, var_origin
.span(), E0495
,
1625 "cannot infer an appropriate lifetime{} \
1626 due to conflicting requirements",
1630 fn note_region_origin(&self, err
: &mut DiagnosticBuilder
, origin
: &SubregionOrigin
<'tcx
>) {
1632 infer
::Subtype(ref trace
) => {
1633 if let Some((expected
, found
)) = self.values_str(&trace
.values
) {
1634 // FIXME: do we want a "the" here?
1636 trace
.origin
.span(),
1637 &format
!("...so that {} (expected {}, found {})",
1638 trace
.origin
.as_requirement_str(), expected
, found
));
1640 // FIXME: this really should be handled at some earlier stage. Our
1641 // handling of region checking when type errors are present is
1645 trace
.origin
.span(),
1646 &format
!("...so that {}",
1647 trace
.origin
.as_requirement_str()));
1650 infer
::Reborrow(span
) => {
1653 "...so that reference does not outlive \
1656 infer
::ReborrowUpvar(span
, ref upvar_id
) => {
1660 "...so that closure can access `{}`",
1661 self.tcx
.local_var_name_str(upvar_id
.var_id
)
1664 infer
::InfStackClosure(span
) => {
1667 "...so that closure does not outlive its stack frame");
1669 infer
::InvokeClosure(span
) => {
1672 "...so that closure is not invoked outside its lifetime");
1674 infer
::DerefPointer(span
) => {
1677 "...so that pointer is not dereferenced \
1678 outside its lifetime");
1680 infer
::FreeVariable(span
, id
) => {
1683 &format
!("...so that captured variable `{}` \
1684 does not outlive the enclosing closure",
1685 self.tcx
.local_var_name_str(id
)));
1687 infer
::IndexSlice(span
) => {
1690 "...so that slice is not indexed outside the lifetime");
1692 infer
::RelateObjectBound(span
) => {
1695 "...so that it can be closed over into an object");
1697 infer
::CallRcvr(span
) => {
1700 "...so that method receiver is valid for the method call");
1702 infer
::CallArg(span
) => {
1705 "...so that argument is valid for the call");
1707 infer
::CallReturn(span
) => {
1710 "...so that return value is valid for the call");
1712 infer
::Operand(span
) => {
1715 "...so that operand is valid for operation");
1717 infer
::AddrOf(span
) => {
1720 "...so that reference is valid \
1721 at the time of borrow");
1723 infer
::AutoBorrow(span
) => {
1726 "...so that auto-reference is valid \
1727 at the time of borrow");
1729 infer
::ExprTypeIsNotInScope(t
, span
) => {
1732 &format
!("...so type `{}` of expression is valid during the \
1734 self.ty_to_string(t
)));
1736 infer
::BindingTypeIsNotValidAtDecl(span
) => {
1739 "...so that variable is valid at time of its declaration");
1741 infer
::ParameterInScope(_
, span
) => {
1744 "...so that a type/lifetime parameter is in scope here");
1746 infer
::DataBorrowed(ty
, span
) => {
1749 &format
!("...so that the type `{}` is not borrowed for too long",
1750 self.ty_to_string(ty
)));
1752 infer
::ReferenceOutlivesReferent(ty
, span
) => {
1755 &format
!("...so that the reference type `{}` \
1756 does not outlive the data it points at",
1757 self.ty_to_string(ty
)));
1759 infer
::RelateParamBound(span
, t
) => {
1762 &format
!("...so that the type `{}` \
1763 will meet its required lifetime bounds",
1764 self.ty_to_string(t
)));
1766 infer
::RelateDefaultParamBound(span
, t
) => {
1769 &format
!("...so that type parameter \
1770 instantiated with `{}`, \
1771 will meet its declared lifetime bounds",
1772 self.ty_to_string(t
)));
1774 infer
::RelateRegionParamBound(span
) => {
1777 "...so that the declared lifetime parameter bounds \
1780 infer
::SafeDestructor(span
) => {
1783 "...so that references are valid when the destructor \
1790 fn lifetimes_in_scope
<'a
, 'gcx
, 'tcx
>(tcx
: TyCtxt
<'a
, 'gcx
, 'tcx
>,
1791 scope_id
: ast
::NodeId
)
1792 -> Vec
<hir
::LifetimeDef
> {
1793 let mut taken
= Vec
::new();
1794 let parent
= tcx
.map
.get_parent(scope_id
);
1795 let method_id_opt
= match tcx
.map
.find(parent
) {
1796 Some(node
) => match node
{
1797 ast_map
::NodeItem(item
) => match item
.node
{
1798 hir
::ItemFn(.., ref gen
, _
) => {
1799 taken
.extend_from_slice(&gen
.lifetimes
);
1804 ast_map
::NodeImplItem(ii
) => {
1806 hir
::ImplItemKind
::Method(ref sig
, _
) => {
1807 taken
.extend_from_slice(&sig
.generics
.lifetimes
);
1817 if let Some(method_id
) = method_id_opt
{
1818 let parent
= tcx
.map
.get_parent(method_id
);
1819 if let Some(node
) = tcx
.map
.find(parent
) {
1821 ast_map
::NodeItem(item
) => match item
.node
{
1822 hir
::ItemImpl(_
, _
, ref gen
, ..) => {
1823 taken
.extend_from_slice(&gen
.lifetimes
);
1834 // LifeGiver is responsible for generating fresh lifetime names
1836 taken
: HashSet
<String
>,
1837 counter
: Cell
<usize>,
1838 generated
: RefCell
<Vec
<hir
::Lifetime
>>,
1842 fn with_taken(taken
: &[hir
::LifetimeDef
]) -> LifeGiver
{
1843 let mut taken_
= HashSet
::new();
1845 let lt_name
= lt
.lifetime
.name
.to_string();
1846 taken_
.insert(lt_name
);
1850 counter
: Cell
::new(0),
1851 generated
: RefCell
::new(Vec
::new()),
1855 fn inc_counter(&self) {
1856 let c
= self.counter
.get();
1857 self.counter
.set(c
+1);
1860 fn give_lifetime(&self) -> hir
::Lifetime
{
1863 let mut s
= String
::from("'");
1864 s
.push_str(&num_to_string(self.counter
.get()));
1865 if !self.taken
.contains(&s
) {
1866 lifetime
= name_to_dummy_lifetime(token
::intern(&s
[..]));
1867 self.generated
.borrow_mut().push(lifetime
);
1875 // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
1876 fn num_to_string(counter
: usize) -> String
{
1877 let mut s
= String
::new();
1878 let (n
, r
) = (counter
/26 + 1, counter
% 26);
1879 let letter
: char = from_u32((r
+97) as u32).unwrap();
1887 fn get_generated_lifetimes(&self) -> Vec
<hir
::Lifetime
> {
1888 self.generated
.borrow().clone()
1892 fn name_to_dummy_lifetime(name
: ast
::Name
) -> hir
::Lifetime
{
1893 hir
::Lifetime
{ id
: ast
::DUMMY_NODE_ID
,
1894 span
: syntax_pos
::DUMMY_SP
,