error_reporting.rs 70.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

S
Steve Klabnik 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
//! Error Reporting Code for the inference engine
//!
//! Because of the way inference, and in particular region inference,
//! works, it often happens that errors are not detected until far after
//! the relevant line of code has been type-checked. Therefore, there is
//! an elaborate system to track why a particular constraint in the
//! inference graph arose so that we can explain to the user what gave
//! rise to a particular error.
//!
//! The basis of the system are the "origin" types. An "origin" is the
//! reason that a constraint or inference variable arose. There are
//! different "origin" enums for different kinds of constraints/variables
//! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
//! a span, but also more information so that we can generate a meaningful
//! error message.
//!
//! Having a catalogue of all the different reasons an error can arise is
//! also useful for other reasons, like cross-referencing FAQs etc, though
//! we are not really taking advantage of this yet.
//!
//! # Region Inference
//!
//! Region inference is particularly tricky because it always succeeds "in
//! the moment" and simply registers a constraint. Then, at the end, we
//! can compute the full graph and report errors, so we need to be able to
//! store and later report what gave rise to the conflicting constraints.
//!
//! # Subtype Trace
//!
//! Determing whether `T1 <: T2` often involves a number of subtypes and
//! subconstraints along the way. A "TypeTrace" is an extended version
//! of an origin that traces the types and other values that were being
//! compared. It is not necessarily comprehensive (in fact, at the time of
//! this writing it only tracks the root values being compared) but I'd
//! like to extend it to include significant "waypoints". For example, if
//! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
//! <: T4` fails, I'd like the trace to include enough information to say
//! "in the 2nd element of the tuple". Similarly, failures when comparing
//! arguments or return types in fn types should be able to cite the
//! specific position, etc.
//!
//! # Reality vs plan
//!
//! Of course, there is still a LOT of code in typeck that has yet to be
//! ported to this system, and which relies on string concatenation at the
//! time of error detection.

S
Steven Fackler 已提交
58
use self::FreshOrKept::*;
59

60 61 62 63 64 65 66 67 68 69 70 71 72
use super::InferCtxt;
use super::TypeTrace;
use super::SubregionOrigin;
use super::RegionVariableOrigin;
use super::ValuePairs;
use super::region_inference::RegionResolutionError;
use super::region_inference::ConcreteFailure;
use super::region_inference::SubSupConflict;
use super::region_inference::SupSupConflict;
use super::region_inference::ParamBoundFailure;
use super::region_inference::ProcessedErrors;
use super::region_inference::SameRegions;

73
use std::collections::HashSet;
74
use middle::def;
75
use middle::infer;
76
use middle::subst;
77
use middle::ty::{mod, Ty};
78 79 80
use middle::ty::{Region, ReFree};
use std::cell::{Cell, RefCell};
use std::char::from_u32;
E
Eduard Burtescu 已提交
81
use std::rc::Rc;
82
use std::string::String;
83 84
use syntax::ast;
use syntax::ast_map;
85
use syntax::ast_util::{name_to_dummy_lifetime, PostExpansionMethod};
86
use syntax::owned_slice::OwnedSlice;
87
use syntax::codemap;
88
use syntax::parse::token;
89
use syntax::print::pprust;
90
use syntax::ptr::P;
91
use util::ppaux::bound_region_to_string;
92 93
use util::ppaux::note_and_explain_region;

94 95 96 97
// Note: only import UserString, not Repr, since user-facing error
// messages shouldn't include debug serializations.
use util::ppaux::UserString;

98
pub trait ErrorReporting<'tcx> {
E
Eduard Burtescu 已提交
99
    fn report_region_errors(&self,
100
                            errors: &Vec<RegionResolutionError<'tcx>>);
101

102 103
    fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
                      -> Vec<RegionResolutionError<'tcx>>;
104

105
    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>);
106

E
Eduard Burtescu 已提交
107
    fn report_and_explain_type_error(&self,
108 109
                                     trace: TypeTrace<'tcx>,
                                     terr: &ty::type_err<'tcx>);
110

111
    fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
112

113
    fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
E
Eduard Burtescu 已提交
114
        &self,
115
        exp_found: &ty::expected_found<T>)
116
        -> Option<String>;
117

E
Eduard Burtescu 已提交
118
    fn report_concrete_failure(&self,
119
                               origin: SubregionOrigin<'tcx>,
120 121 122
                               sub: Region,
                               sup: Region);

123
    fn report_param_bound_failure(&self,
124
                                  origin: SubregionOrigin<'tcx>,
125 126 127 128
                                  param_ty: ty::ParamTy,
                                  sub: Region,
                                  sups: Vec<Region>);

E
Eduard Burtescu 已提交
129
    fn report_sub_sup_conflict(&self,
130
                               var_origin: RegionVariableOrigin,
131
                               sub_origin: SubregionOrigin<'tcx>,
132
                               sub_region: Region,
133
                               sup_origin: SubregionOrigin<'tcx>,
134 135
                               sup_region: Region);

E
Eduard Burtescu 已提交
136
    fn report_sup_sup_conflict(&self,
137
                               var_origin: RegionVariableOrigin,
138
                               origin1: SubregionOrigin<'tcx>,
139
                               region1: Region,
140
                               origin2: SubregionOrigin<'tcx>,
141
                               region2: Region);
142 143 144

    fn report_processed_errors(&self,
                               var_origin: &[RegionVariableOrigin],
145
                               trace_origin: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
146 147 148
                               same_regions: &[SameRegions]);

    fn give_suggestion(&self, same_regions: &[SameRegions]);
149 150
}

151
trait ErrorReportingHelpers<'tcx> {
E
Eduard Burtescu 已提交
152
    fn report_inference_failure(&self,
153 154
                                var_origin: RegionVariableOrigin);

E
Eduard Burtescu 已提交
155
    fn note_region_origin(&self,
156
                          origin: &SubregionOrigin<'tcx>);
157 158

    fn give_expl_lifetime_param(&self,
159 160 161
                                decl: &ast::FnDecl,
                                fn_style: ast::FnStyle,
                                ident: ast::Ident,
162
                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
163 164
                                generics: &ast::Generics,
                                span: codemap::Span);
165
}
166

167
impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
E
Eduard Burtescu 已提交
168
    fn report_region_errors(&self,
169
                            errors: &Vec<RegionResolutionError<'tcx>>) {
170 171
        let p_errors = self.process_errors(errors);
        let errors = if p_errors.is_empty() { errors } else { &p_errors };
D
Daniel Micay 已提交
172
        for error in errors.iter() {
E
Eduard Burtescu 已提交
173
            match error.clone() {
174 175 176 177
                ConcreteFailure(origin, sub, sup) => {
                    self.report_concrete_failure(origin, sub, sup);
                }

178 179 180 181
                ParamBoundFailure(origin, param_ty, sub, sups) => {
                    self.report_param_bound_failure(origin, param_ty, sub, sups);
                }

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
                SubSupConflict(var_origin,
                               sub_origin, sub_r,
                               sup_origin, sup_r) => {
                    self.report_sub_sup_conflict(var_origin,
                                                 sub_origin, sub_r,
                                                 sup_origin, sup_r);
                }

                SupSupConflict(var_origin,
                               origin1, r1,
                               origin2, r2) => {
                    self.report_sup_sup_conflict(var_origin,
                                                 origin1, r1,
                                                 origin2, r2);
                }
197 198 199 200 201 202 203 204 205 206

                ProcessedErrors(ref var_origins,
                                ref trace_origins,
                                ref same_regions) => {
                    if !same_regions.is_empty() {
                        self.report_processed_errors(var_origins.as_slice(),
                                                     trace_origins.as_slice(),
                                                     same_regions.as_slice());
                    }
                }
207 208 209 210
            }
        }
    }

211 212 213 214 215 216
    // This method goes through all the errors and try to group certain types
    // of error together, for the purpose of suggesting explicit lifetime
    // parameters to the user. This is done so that we can have a more
    // complete view of what lifetimes should be the same.
    // If the return value is an empty vector, it means that processing
    // failed (so the return value of this method should not be used)
217 218
    fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
                      -> Vec<RegionResolutionError<'tcx>> {
219
        debug!("process_errors()");
220 221 222
        let mut var_origins = Vec::new();
        let mut trace_origins = Vec::new();
        let mut same_regions = Vec::new();
H
Huon Wilson 已提交
223
        let mut processed_errors = Vec::new();
224
        for error in errors.iter() {
E
Eduard Burtescu 已提交
225
            match error.clone() {
226
                ConcreteFailure(origin, sub, sup) => {
227
                    debug!("processing ConcreteFailure")
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
                    let trace = match origin {
                        infer::Subtype(trace) => Some(trace),
                        _ => None,
                    };
                    match free_regions_from_same_fn(self.tcx, sub, sup) {
                        Some(ref same_frs) if trace.is_some() => {
                            let trace = trace.unwrap();
                            let terr = ty::terr_regions_does_not_outlive(sup,
                                                                         sub);
                            trace_origins.push((trace, terr));
                            append_to_same_regions(&mut same_regions, same_frs);
                        }
                        _ => processed_errors.push((*error).clone()),
                    }
                }
                SubSupConflict(var_origin, _, sub_r, _, sup_r) => {
244
                    debug!("processing SubSupConflict")
245 246 247 248 249 250 251 252 253 254 255 256 257
                    match free_regions_from_same_fn(self.tcx, sub_r, sup_r) {
                        Some(ref same_frs) => {
                            var_origins.push(var_origin);
                            append_to_same_regions(&mut same_regions, same_frs);
                        }
                        None => processed_errors.push((*error).clone()),
                    }
                }
                SupSupConflict(..) => processed_errors.push((*error).clone()),
                _ => ()  // This shouldn't happen
            }
        }
        if !same_regions.is_empty() {
258
            let common_scope_id = same_regions[0].scope_id;
259 260 261 262 263
            for sr in same_regions.iter() {
                // Since ProcessedErrors is used to reconstruct the function
                // declaration, we want to make sure that they are, in fact,
                // from the same scope
                if sr.scope_id != common_scope_id {
264 265
                    debug!("returning empty result from process_errors because
                            {} != {}", sr.scope_id, common_scope_id);
H
Huon Wilson 已提交
266
                    return vec!();
267 268 269
                }
            }
            let pe = ProcessedErrors(var_origins, trace_origins, same_regions);
L
Luqman Aden 已提交
270
            debug!("errors processed: {}", pe);
271 272 273 274 275 276 277 278 279 280 281
            processed_errors.push(pe);
        }
        return processed_errors;


        struct FreeRegionsFromSameFn {
            sub_fr: ty::FreeRegion,
            sup_fr: ty::FreeRegion,
            scope_id: ast::NodeId
        }

282 283 284 285 286 287 288 289 290 291 292 293 294
        impl FreeRegionsFromSameFn {
            fn new(sub_fr: ty::FreeRegion,
                   sup_fr: ty::FreeRegion,
                   scope_id: ast::NodeId)
                   -> FreeRegionsFromSameFn {
                FreeRegionsFromSameFn {
                    sub_fr: sub_fr,
                    sup_fr: sup_fr,
                    scope_id: scope_id
                }
            }
        }

E
Eduard Burtescu 已提交
295
        fn free_regions_from_same_fn(tcx: &ty::ctxt,
296 297 298
                                     sub: Region,
                                     sup: Region)
                                     -> Option<FreeRegionsFromSameFn> {
L
Luqman Aden 已提交
299
            debug!("free_regions_from_same_fn(sub={}, sup={})", sub, sup);
300 301
            let (scope_id, fr1, fr2) = match (sub, sup) {
                (ReFree(fr1), ReFree(fr2)) => {
302
                    if fr1.scope != fr2.scope {
303 304
                        return None
                    }
305 306
                    assert!(fr1.scope == fr2.scope);
                    (fr1.scope.node_id(), fr1, fr2)
307 308 309 310 311 312 313 314 315
                },
                _ => return None
            };
            let parent = tcx.map.get_parent(scope_id);
            let parent_node = tcx.map.find(parent);
            match parent_node {
                Some(node) => match node {
                    ast_map::NodeItem(item) => match item.node {
                        ast::ItemFn(..) => {
316
                            Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
317 318 319
                        },
                        _ => None
                    },
320 321
                    ast_map::NodeImplItem(..) |
                    ast_map::NodeTraitItem(..) => {
322 323
                        Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
                    },
324 325
                    _ => None
                },
326 327 328 329
                None => {
                    debug!("no parent node of scope_id {}", scope_id)
                    None
                }
330 331 332 333 334 335 336
            }
        }

        fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
                                  same_frs: &FreeRegionsFromSameFn) {
            let scope_id = same_frs.scope_id;
            let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr);
A
Aaron Turon 已提交
337
            for sr in same_regions.iter_mut() {
338 339 340 341 342 343 344 345 346 347 348 349 350
                if sr.contains(&sup_fr.bound_region)
                   && scope_id == sr.scope_id {
                    sr.push(sub_fr.bound_region);
                    return
                }
            }
            same_regions.push(SameRegions {
                scope_id: scope_id,
                regions: vec!(sub_fr.bound_region, sup_fr.bound_region)
            })
        }
    }

351
    fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>) {
352 353 354 355 356 357 358 359 360 361 362 363
        let expected_found_str = match self.values_str(&trace.values) {
            Some(v) => v,
            None => {
                return; /* derived error */
            }
        };

        let message_root_str = match trace.origin {
            infer::Misc(_) => "mismatched types",
            infer::MethodCompatCheck(_) => "method not compatible with trait",
            infer::ExprAssignable(_) => "mismatched types",
            infer::RelateTraitRefs(_) => "mismatched traits",
364
            infer::RelateSelfType(_) => "mismatched types",
365
            infer::RelateOutputImplTypes(_) => "mismatched types",
366
            infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
367
            infer::IfExpression(_) => "if and else have incompatible types",
368
            infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
369 370 371 372
        };

        self.tcx.sess.span_err(
            trace.origin.span(),
A
Alex Crichton 已提交
373
            format!("{}: {} ({})",
374 375
                 message_root_str,
                 expected_found_str,
376
                 ty::type_err_to_str(self.tcx, terr)).as_slice());
377 378 379 380 381 382

        match trace.origin {
            infer::MatchExpressionArm(_, arm_span) =>
                self.tcx.sess.span_note(arm_span, "match arm with an incompatible type"),
            _ => ()
        }
383
    }
384

385
    fn report_and_explain_type_error(&self,
386 387
                                     trace: TypeTrace<'tcx>,
                                     terr: &ty::type_err<'tcx>) {
388
        self.report_type_error(trace, terr);
389 390 391
        ty::note_and_explain_type_err(self.tcx, terr);
    }

S
Steve Klabnik 已提交
392 393
    /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
    /// error.
394
    fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
395
        match *values {
396 397
            infer::Types(ref exp_found) => self.expected_found_str(exp_found),
            infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found)
398 399 400
        }
    }

401
    fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
E
Eduard Burtescu 已提交
402
        &self,
403
        exp_found: &ty::expected_found<T>)
404
        -> Option<String>
405 406 407 408 409 410 411 412 413 414 415
    {
        let expected = exp_found.expected.resolve(self);
        if expected.contains_error() {
            return None;
        }

        let found = exp_found.found.resolve(self);
        if found.contains_error() {
            return None;
        }

416
        Some(format!("expected `{}`, found `{}`",
417 418
                     expected.user_string(self.tcx),
                     found.user_string(self.tcx)))
419 420
    }

421
    fn report_param_bound_failure(&self,
422
                                  origin: SubregionOrigin<'tcx>,
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
                                  param_ty: ty::ParamTy,
                                  sub: Region,
                                  _sups: Vec<Region>) {

        // FIXME: it would be better to report the first error message
        // with the span of the parameter itself, rather than the span
        // where the error was detected. But that span is not readily
        // accessible.

        match sub {
            ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
                // Does the required lifetime have a nice name we can print?
                self.tcx.sess.span_err(
                    origin.span(),
                    format!(
P
P1start 已提交
438 439 440 441 442 443
                        "the parameter type `{}` may not live long enough",
                        param_ty.user_string(self.tcx)).as_slice());
                self.tcx.sess.span_help(
                    origin.span(),
                    format!(
                        "consider adding an explicit lifetime bound `{}: {}`...",
444 445 446 447 448 449 450 451 452
                        param_ty.user_string(self.tcx),
                        sub.user_string(self.tcx)).as_slice());
            }

            ty::ReStatic => {
                // Does the required lifetime have a nice name we can print?
                self.tcx.sess.span_err(
                    origin.span(),
                    format!(
P
P1start 已提交
453 454 455 456 457 458
                        "the parameter type `{}` may not live long enough",
                        param_ty.user_string(self.tcx)).as_slice());
                self.tcx.sess.span_help(
                    origin.span(),
                    format!(
                        "consider adding an explicit lifetime bound `{}: 'static`...",
459 460 461 462 463 464 465 466
                        param_ty.user_string(self.tcx)).as_slice());
            }

            _ => {
                // If not, be less specific.
                self.tcx.sess.span_err(
                    origin.span(),
                    format!(
P
P1start 已提交
467 468 469 470 471 472
                        "the parameter type `{}` may not live long enough",
                        param_ty.user_string(self.tcx)).as_slice());
                self.tcx.sess.span_help(
                    origin.span(),
                    format!(
                        "consider adding an explicit lifetime bound to `{}`",
473 474 475 476 477 478 479 480 481 482 483 484 485
                        param_ty.user_string(self.tcx)).as_slice());
                note_and_explain_region(
                    self.tcx,
                    format!("the parameter type `{}` must be valid for ",
                            param_ty.user_string(self.tcx)).as_slice(),
                    sub,
                    "...");
            }
        }

        self.note_region_origin(&origin);
    }

E
Eduard Burtescu 已提交
486
    fn report_concrete_failure(&self,
487
                               origin: SubregionOrigin<'tcx>,
488 489 490 491
                               sub: Region,
                               sup: Region) {
        match origin {
            infer::Subtype(trace) => {
492
                let terr = ty::terr_regions_does_not_outlive(sup, sub);
493 494 495 496 497
                self.report_and_explain_type_error(trace, &terr);
            }
            infer::Reborrow(span) => {
                self.tcx.sess.span_err(
                    span,
498
                    "lifetime of reference outlines \
499 500 501
                     lifetime of borrowed content...");
                note_and_explain_region(
                    self.tcx,
502
                    "...the reference is valid for ",
503 504 505 506 507 508 509 510
                    sub,
                    "...");
                note_and_explain_region(
                    self.tcx,
                    "...but the borrowed content is only valid for ",
                    sup,
                    "");
            }
511 512 513 514 515
            infer::ReborrowUpvar(span, ref upvar_id) => {
                self.tcx.sess.span_err(
                    span,
                    format!("lifetime of borrowed pointer outlives \
                            lifetime of captured variable `{}`...",
516 517 518
                            ty::local_var_name_str(self.tcx,
                                                   upvar_id.var_id)
                                .get()
519
                                .to_string()).as_slice());
520 521 522 523 524 525 526 527
                note_and_explain_region(
                    self.tcx,
                    "...the borrowed pointer is valid for ",
                    sub,
                    "...");
                note_and_explain_region(
                    self.tcx,
                    format!("...but `{}` is only valid for ",
528 529 530
                            ty::local_var_name_str(self.tcx,
                                                   upvar_id.var_id)
                                .get()
531
                                .to_string()).as_slice(),
532 533 534
                    sup,
                    "");
            }
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
            infer::InfStackClosure(span) => {
                self.tcx.sess.span_err(
                    span,
                    "closure outlives stack frame");
                note_and_explain_region(
                    self.tcx,
                    "...the closure must be valid for ",
                    sub,
                    "...");
                note_and_explain_region(
                    self.tcx,
                    "...but the closure's stack frame is only valid for ",
                    sup,
                    "");
            }
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
            infer::InvokeClosure(span) => {
                self.tcx.sess.span_err(
                    span,
                    "cannot invoke closure outside of its lifetime");
                note_and_explain_region(
                    self.tcx,
                    "the closure is only valid for ",
                    sup,
                    "");
            }
            infer::DerefPointer(span) => {
                self.tcx.sess.span_err(
                    span,
                    "dereference of reference outside its lifetime");
                note_and_explain_region(
                    self.tcx,
                    "the reference is only valid for ",
                    sup,
                    "");
            }
570
            infer::FreeVariable(span, id) => {
571 572
                self.tcx.sess.span_err(
                    span,
573 574
                    format!("captured variable `{}` does not \
                            outlive the enclosing closure",
575 576
                            ty::local_var_name_str(self.tcx,
                                                   id).get()
577
                                                      .to_string()).as_slice());
578 579 580 581 582 583 584 585 586 587 588
                note_and_explain_region(
                    self.tcx,
                    "captured variable is valid for ",
                    sup,
                    "");
                note_and_explain_region(
                    self.tcx,
                    "closure is valid for ",
                    sub,
                    "");
            }
589 590 591 592 593 594 595 596 597 598 599 600 601
            infer::ProcCapture(span, id) => {
                self.tcx.sess.span_err(
                    span,
                    format!("captured variable `{}` must be 'static \
                             to be captured in a proc",
                            ty::local_var_name_str(self.tcx, id).get())
                        .as_slice());
                note_and_explain_region(
                    self.tcx,
                    "captured variable is only valid for ",
                    sup,
                    "");
            }
602
            infer::IndexSlice(span) => {
603 604
                self.tcx.sess.span_err(span,
                                       "index of slice outside its lifetime");
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
                note_and_explain_region(
                    self.tcx,
                    "the slice is only valid for ",
                    sup,
                    "");
            }
            infer::RelateObjectBound(span) => {
                self.tcx.sess.span_err(
                    span,
                    "lifetime of the source pointer does not outlive \
                     lifetime bound of the object type");
                note_and_explain_region(
                    self.tcx,
                    "object type is valid for ",
                    sub,
                    "");
                note_and_explain_region(
                    self.tcx,
                    "source pointer is only valid for ",
                    sup,
                    "");
            }
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
            infer::RelateProcBound(span, var_node_id, ty) => {
                self.tcx.sess.span_err(
                    span,
                    format!(
                        "the type `{}` of captured variable `{}` \
                         outlives the `proc()` it \
                         is captured in",
                        self.ty_to_string(ty),
                        ty::local_var_name_str(self.tcx,
                                               var_node_id)).as_slice());
                note_and_explain_region(
                    self.tcx,
                    "`proc()` is valid for ",
                    sub,
                    "");
                note_and_explain_region(
                    self.tcx,
                    format!("the type `{}` is only valid for ",
                            self.ty_to_string(ty)).as_slice(),
                    sup,
                    "");
            }
649
            infer::RelateParamBound(span, ty) => {
650 651
                self.tcx.sess.span_err(
                    span,
652
                    format!("the type `{}` does not fulfill the \
653
                             required lifetime",
654
                            self.ty_to_string(ty)).as_slice());
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
                note_and_explain_region(self.tcx,
                                        "type must outlive ",
                                        sub,
                                        "");
            }
            infer::RelateRegionParamBound(span) => {
                self.tcx.sess.span_err(
                    span,
                    "declared lifetime bound not satisfied");
                note_and_explain_region(
                    self.tcx,
                    "lifetime parameter instantiated with ",
                    sup,
                    "");
                note_and_explain_region(
                    self.tcx,
                    "but lifetime parameter must outlive ",
                    sub,
                    "");
            }
            infer::RelateDefaultParamBound(span, ty) => {
                self.tcx.sess.span_err(
                    span,
                    format!("the type `{}` (provided as the value of \
                             a type parameter) is not valid at this point",
                            self.ty_to_string(ty)).as_slice());
                note_and_explain_region(self.tcx,
                                        "type must outlive ",
                                        sub,
                                        "");
            }
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
            infer::CallRcvr(span) => {
                self.tcx.sess.span_err(
                    span,
                    "lifetime of method receiver does not outlive \
                     the method call");
                note_and_explain_region(
                    self.tcx,
                    "the receiver is only valid for ",
                    sup,
                    "");
            }
            infer::CallArg(span) => {
                self.tcx.sess.span_err(
                    span,
                    "lifetime of function argument does not outlive \
                     the function call");
                note_and_explain_region(
                    self.tcx,
                    "the function argument is only valid for ",
                    sup,
                    "");
            }
            infer::CallReturn(span) => {
                self.tcx.sess.span_err(
                    span,
                    "lifetime of return value does not outlive \
                     the function call");
                note_and_explain_region(
                    self.tcx,
                    "the return value is only valid for ",
                    sup,
                    "");
            }
            infer::AddrOf(span) => {
                self.tcx.sess.span_err(
                    span,
722
                    "reference is not valid \
723 724 725 726 727 728 729 730 731 732
                     at the time of borrow");
                note_and_explain_region(
                    self.tcx,
                    "the borrow is only valid for ",
                    sup,
                    "");
            }
            infer::AutoBorrow(span) => {
                self.tcx.sess.span_err(
                    span,
733
                    "automatically reference is not valid \
734 735 736 737 738 739 740
                     at the time of borrow");
                note_and_explain_region(
                    self.tcx,
                    "the automatic borrow is only valid for ",
                    sup,
                    "");
            }
741 742 743 744 745 746 747 748 749 750 751 752
            infer::ExprTypeIsNotInScope(t, span) => {
                self.tcx.sess.span_err(
                    span,
                    format!("type of expression contains references \
                             that are not valid during the expression: `{}`",
                            self.ty_to_string(t)).as_slice());
                note_and_explain_region(
                    self.tcx,
                    "type is only valid for ",
                    sup,
                    "");
            }
753 754 755 756 757 758 759 760 761 762
            infer::BindingTypeIsNotValidAtDecl(span) => {
                self.tcx.sess.span_err(
                    span,
                    "lifetime of variable does not enclose its declaration");
                note_and_explain_region(
                    self.tcx,
                    "the variable is only valid for ",
                    sup,
                    "");
            }
N
Niko Matsakis 已提交
763
            infer::ReferenceOutlivesReferent(ty, span) => {
764
                self.tcx.sess.span_err(
N
Niko Matsakis 已提交
765
                    span,
766 767 768
                    format!("in type `{}`, reference has a longer lifetime \
                             than the data it references",
                            self.ty_to_string(ty)).as_slice());
769 770 771 772 773 774 775 776 777 778 779 780 781 782
                note_and_explain_region(
                    self.tcx,
                    "the pointer is valid for ",
                    sub,
                    "");
                note_and_explain_region(
                    self.tcx,
                    "but the referenced data is only valid for ",
                    sup,
                    "");
            }
        }
    }

E
Eduard Burtescu 已提交
783
    fn report_sub_sup_conflict(&self,
784
                               var_origin: RegionVariableOrigin,
785
                               sub_origin: SubregionOrigin<'tcx>,
786
                               sub_region: Region,
787
                               sup_origin: SubregionOrigin<'tcx>,
788
                               sup_region: Region) {
789
        self.report_inference_failure(var_origin);
790 791 792 793 794 795 796

        note_and_explain_region(
            self.tcx,
            "first, the lifetime cannot outlive ",
            sup_region,
            "...");

797
        self.note_region_origin(&sup_origin);
798 799 800 801 802 803 804

        note_and_explain_region(
            self.tcx,
            "but, the lifetime must be valid for ",
            sub_region,
            "...");

805
        self.note_region_origin(&sub_origin);
806 807
    }

E
Eduard Burtescu 已提交
808
    fn report_sup_sup_conflict(&self,
809
                               var_origin: RegionVariableOrigin,
810
                               origin1: SubregionOrigin<'tcx>,
811
                               region1: Region,
812
                               origin2: SubregionOrigin<'tcx>,
813
                               region2: Region) {
814
        self.report_inference_failure(var_origin);
815 816 817 818 819 820 821

        note_and_explain_region(
            self.tcx,
            "first, the lifetime must be contained by ",
            region1,
            "...");

822
        self.note_region_origin(&origin1);
823 824 825 826 827 828 829

        note_and_explain_region(
            self.tcx,
            "but, the lifetime must also be contained by ",
            region2,
            "...");

830
        self.note_region_origin(&origin2);
831
    }
832 833 834

    fn report_processed_errors(&self,
                               var_origins: &[RegionVariableOrigin],
835
                               trace_origins: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
836 837
                               same_regions: &[SameRegions]) {
        for vo in var_origins.iter() {
E
Eduard Burtescu 已提交
838
            self.report_inference_failure(vo.clone());
839
        }
840
        self.give_suggestion(same_regions);
E
Eduard Burtescu 已提交
841 842
        for &(ref trace, terr) in trace_origins.iter() {
            self.report_type_error(trace.clone(), &terr);
843 844 845 846 847 848 849 850
        }
    }

    fn give_suggestion(&self, same_regions: &[SameRegions]) {
        let scope_id = same_regions[0].scope_id;
        let parent = self.tcx.map.get_parent(scope_id);
        let parent_node = self.tcx.map.find(parent);
        let node_inner = match parent_node {
F
Flavio Percoco 已提交
851 852 853
            Some(ref node) => match *node {
                ast_map::NodeItem(ref item) => {
                    match item.node {
854 855
                        ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => {
                            Some((&**fn_decl, gen, pur, item.ident, None, item.span))
F
Flavio Percoco 已提交
856 857 858 859
                        },
                        _ => None
                    }
                }
860 861 862 863 864 865 866
                ast_map::NodeImplItem(ref item) => {
                    match **item {
                        ast::MethodImplItem(ref m) => {
                            Some((m.pe_fn_decl(),
                                  m.pe_generics(),
                                  m.pe_fn_style(),
                                  m.pe_ident(),
867
                                  Some(&m.pe_explicit_self().node),
868 869
                                  m.span))
                        }
870
                        ast::TypeImplItem(_) => None,
871
                    }
872
                },
873 874 875 876 877 878 879 880 881 882 883 884 885
                ast_map::NodeTraitItem(ref item) => {
                    match **item {
                        ast::ProvidedMethod(ref m) => {
                            Some((m.pe_fn_decl(),
                                  m.pe_generics(),
                                  m.pe_fn_style(),
                                  m.pe_ident(),
                                  Some(&m.pe_explicit_self().node),
                                  m.span))
                        }
                        _ => None
                    }
                }
886 887 888 889
                _ => None
            },
            None => None
        };
890 891 892 893
        let (fn_decl, generics, fn_style, ident, expl_self, span)
                                    = node_inner.expect("expect item fn");
        let taken = lifetimes_in_scope(self.tcx, scope_id);
        let life_giver = LifeGiver::with_taken(taken.as_slice());
894
        let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
895 896 897
                                       generics, same_regions, &life_giver);
        let (fn_decl, expl_self, generics) = rebuilder.rebuild();
        self.give_expl_lifetime_param(&fn_decl, fn_style, ident,
898
                                      expl_self.as_ref(), &generics, span);
899 900 901
    }
}

902 903 904 905 906 907 908 909 910 911 912
struct RebuildPathInfo<'a> {
    path: &'a ast::Path,
    // indexes to insert lifetime on path.lifetimes
    indexes: Vec<uint>,
    // number of lifetimes we expect to see on the type referred by `path`
    // (e.g., expected=1 for struct Foo<'a>)
    expected: uint,
    anon_nums: &'a HashSet<uint>,
    region_names: &'a HashSet<ast::Name>
}

913 914
struct Rebuilder<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
915 916
    fn_decl: &'a ast::FnDecl,
    expl_self_opt: Option<&'a ast::ExplicitSelf_>,
917 918
    generics: &'a ast::Generics,
    same_regions: &'a [SameRegions],
919
    life_giver: &'a LifeGiver,
920 921 922 923
    cur_anon: Cell<uint>,
    inserted_anons: RefCell<HashSet<uint>>,
}

924 925 926 927 928
enum FreshOrKept {
    Fresh,
    Kept
}

929 930
impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
    fn new(tcx: &'a ty::ctxt<'tcx>,
931 932
           fn_decl: &'a ast::FnDecl,
           expl_self_opt: Option<&'a ast::ExplicitSelf_>,
933
           generics: &'a ast::Generics,
934 935
           same_regions: &'a [SameRegions],
           life_giver: &'a LifeGiver)
936
           -> Rebuilder<'a, 'tcx> {
937 938 939
        Rebuilder {
            tcx: tcx,
            fn_decl: fn_decl,
940
            expl_self_opt: expl_self_opt,
941 942
            generics: generics,
            same_regions: same_regions,
943
            life_giver: life_giver,
944 945 946 947 948
            cur_anon: Cell::new(0),
            inserted_anons: RefCell::new(HashSet::new()),
        }
    }

949 950
    fn rebuild(&self)
               -> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
951
        let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
952
        let mut inputs = self.fn_decl.inputs.clone();
953
        let mut output = self.fn_decl.output.clone();
954
        let mut ty_params = self.generics.ty_params.clone();
955
        let where_clause = self.generics.where_clause.clone();
956
        let mut kept_lifetimes = HashSet::new();
957 958 959 960 961
        for sr in self.same_regions.iter() {
            self.cur_anon.set(0);
            self.offset_cur_anon();
            let (anon_nums, region_names) =
                                self.extract_anon_nums_and_names(sr);
962 963 964 965 966 967 968
            let (lifetime, fresh_or_kept) = self.pick_lifetime(&region_names);
            match fresh_or_kept {
                Kept => { kept_lifetimes.insert(lifetime.name); }
                _ => ()
            }
            expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime,
                                                   &anon_nums, &region_names);
969 970
            inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime,
                                          &anon_nums, &region_names);
971
            output = self.rebuild_output(&output, lifetime, &anon_nums, &region_names);
972 973
            ty_params = self.rebuild_ty_params(ty_params, lifetime,
                                               &region_names);
974
        }
975
        let fresh_lifetimes = self.life_giver.get_generated_lifetimes();
976 977
        let all_region_names = self.extract_all_region_names();
        let generics = self.rebuild_generics(self.generics,
978 979 980
                                             &fresh_lifetimes,
                                             &kept_lifetimes,
                                             &all_region_names,
981 982
                                             ty_params,
                                             where_clause);
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
        let new_fn_decl = ast::FnDecl {
            inputs: inputs,
            output: output,
            variadic: self.fn_decl.variadic
        };
        (new_fn_decl, expl_self_opt, generics)
    }

    fn pick_lifetime(&self,
                     region_names: &HashSet<ast::Name>)
                     -> (ast::Lifetime, FreshOrKept) {
        if region_names.len() > 0 {
            // It's not necessary to convert the set of region names to a
            // vector of string and then sort them. However, it makes the
            // choice of lifetime name deterministic and thus easier to test.
            let mut names = Vec::new();
            for rn in region_names.iter() {
R
Richo Healey 已提交
1000
                let lt_name = token::get_name(*rn).get().to_string();
1001 1002 1003
                names.push(lt_name);
            }
            names.sort();
1004
            let name = token::str_to_ident(names[0].as_slice()).name;
1005 1006 1007
            return (name_to_dummy_lifetime(name), Kept);
        }
        return (self.life_giver.give_lifetime(), Fresh);
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
    }

    fn extract_anon_nums_and_names(&self, same_regions: &SameRegions)
                                   -> (HashSet<uint>, HashSet<ast::Name>) {
        let mut anon_nums = HashSet::new();
        let mut region_names = HashSet::new();
        for br in same_regions.regions.iter() {
            match *br {
                ty::BrAnon(i) => {
                    anon_nums.insert(i);
                }
                ty::BrNamed(_, name) => {
                    region_names.insert(name);
                }
                _ => ()
            }
        }
        (anon_nums, region_names)
    }

    fn extract_all_region_names(&self) -> HashSet<ast::Name> {
        let mut all_region_names = HashSet::new();
        for sr in self.same_regions.iter() {
            for br in sr.regions.iter() {
                match *br {
                    ty::BrNamed(_, name) => {
                        all_region_names.insert(name);
                    }
                    _ => ()
                }
            }
        }
        all_region_names
    }

    fn inc_cur_anon(&self, n: uint) {
        let anon = self.cur_anon.get();
        self.cur_anon.set(anon+n);
    }

    fn offset_cur_anon(&self) {
        let mut anon = self.cur_anon.get();
1050
        while self.inserted_anons.borrow().contains(&anon) {
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
            anon += 1;
        }
        self.cur_anon.set(anon);
    }

    fn inc_and_offset_cur_anon(&self, n: uint) {
        self.inc_cur_anon(n);
        self.offset_cur_anon();
    }

    fn track_anon(&self, anon: uint) {
1062
        self.inserted_anons.borrow_mut().insert(anon);
1063 1064
    }

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
    fn rebuild_ty_params(&self,
                         ty_params: OwnedSlice<ast::TyParam>,
                         lifetime: ast::Lifetime,
                         region_names: &HashSet<ast::Name>)
                         -> OwnedSlice<ast::TyParam> {
        ty_params.map(|ty_param| {
            let bounds = self.rebuild_ty_param_bounds(ty_param.bounds.clone(),
                                                      lifetime,
                                                      region_names);
            ast::TyParam {
                ident: ty_param.ident,
                id: ty_param.id,
                bounds: bounds,
N
Nick Cameron 已提交
1078
                unbound: ty_param.unbound.clone(),
1079
                default: ty_param.default.clone(),
1080
                span: ty_param.span,
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
            }
        })
    }

    fn rebuild_ty_param_bounds(&self,
                               ty_param_bounds: OwnedSlice<ast::TyParamBound>,
                               lifetime: ast::Lifetime,
                               region_names: &HashSet<ast::Name>)
                               -> OwnedSlice<ast::TyParamBound> {
        ty_param_bounds.map(|tpb| {
            match tpb {
1092 1093 1094 1095 1096 1097
                &ast::RegionTyParamBound(lt) => {
                    // FIXME -- it's unclear whether I'm supposed to
                    // substitute lifetime here. I suspect we need to
                    // be passing down a map.
                    ast::RegionTyParamBound(lt)
                }
N
Niko Matsakis 已提交
1098 1099
                &ast::TraitTyParamBound(ref poly_tr) => {
                    let tr = &poly_tr.trait_ref;
1100 1101
                    let last_seg = tr.path.segments.last().unwrap();
                    let mut insert = Vec::new();
1102 1103
                    let lifetimes = last_seg.parameters.lifetimes();
                    for (i, lt) in lifetimes.iter().enumerate() {
1104 1105 1106 1107 1108 1109 1110
                        if region_names.contains(&lt.name) {
                            insert.push(i);
                        }
                    }
                    let rebuild_info = RebuildPathInfo {
                        path: &tr.path,
                        indexes: insert,
1111
                        expected: lifetimes.len(),
1112 1113 1114 1115
                        anon_nums: &HashSet::new(),
                        region_names: region_names
                    };
                    let new_path = self.rebuild_path(rebuild_info, lifetime);
N
Niko Matsakis 已提交
1116 1117 1118 1119 1120 1121
                    ast::TraitTyParamBound(ast::PolyTraitRef {
                        bound_lifetimes: poly_tr.bound_lifetimes.clone(),
                        trait_ref: ast::TraitRef {
                            path: new_path,
                            ref_id: tr.ref_id,
                        }
1122 1123 1124 1125 1126 1127
                    })
                }
            }
        })
    }

1128 1129 1130 1131 1132 1133 1134
    fn rebuild_expl_self(&self,
                         expl_self_opt: Option<ast::ExplicitSelf_>,
                         lifetime: ast::Lifetime,
                         anon_nums: &HashSet<uint>,
                         region_names: &HashSet<ast::Name>)
                         -> Option<ast::ExplicitSelf_> {
        match expl_self_opt {
1135
            Some(ref expl_self) => match *expl_self {
1136
                ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
1137
                    Some(lt) => if region_names.contains(&lt.name) {
1138
                        return Some(ast::SelfRegion(Some(lifetime), muta, id));
1139 1140 1141 1142 1143 1144
                    },
                    None => {
                        let anon = self.cur_anon.get();
                        self.inc_and_offset_cur_anon(1);
                        if anon_nums.contains(&anon) {
                            self.track_anon(anon);
1145
                            return Some(ast::SelfRegion(Some(lifetime), muta, id));
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
                        }
                    }
                },
                _ => ()
            },
            None => ()
        }
        expl_self_opt
    }

1156 1157
    fn rebuild_generics(&self,
                        generics: &ast::Generics,
1158 1159
                        add: &Vec<ast::Lifetime>,
                        keep: &HashSet<ast::Name>,
1160
                        remove: &HashSet<ast::Name>,
1161 1162
                        ty_params: OwnedSlice<ast::TyParam>,
                        where_clause: ast::WhereClause)
1163 1164 1165
                        -> ast::Generics {
        let mut lifetimes = Vec::new();
        for lt in add.iter() {
1166 1167
            lifetimes.push(ast::LifetimeDef { lifetime: *lt,
                                              bounds: Vec::new() });
1168 1169
        }
        for lt in generics.lifetimes.iter() {
1170
            if keep.contains(&lt.lifetime.name) ||
1171
                !remove.contains(&lt.lifetime.name) {
1172 1173 1174 1175 1176
                lifetimes.push((*lt).clone());
            }
        }
        ast::Generics {
            lifetimes: lifetimes,
1177 1178
            ty_params: ty_params,
            where_clause: where_clause,
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
        }
    }

    fn rebuild_args_ty(&self,
                       inputs: &[ast::Arg],
                       lifetime: ast::Lifetime,
                       anon_nums: &HashSet<uint>,
                       region_names: &HashSet<ast::Name>)
                       -> Vec<ast::Arg> {
        let mut new_inputs = Vec::new();
        for arg in inputs.iter() {
1190
            let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime,
1191 1192 1193
                                                       anon_nums, region_names);
            let possibly_new_arg = ast::Arg {
                ty: new_ty,
1194
                pat: arg.pat.clone(),
1195 1196 1197 1198 1199 1200 1201
                id: arg.id
            };
            new_inputs.push(possibly_new_arg);
        }
        new_inputs
    }

1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    fn rebuild_output(&self, ty: &ast::FunctionRetTy,
                      lifetime: ast::Lifetime,
                      anon_nums: &HashSet<uint>,
                      region_names: &HashSet<ast::Name>) -> ast::FunctionRetTy {
        match *ty {
            ast::Return(ref ret_ty) => ast::Return(
                self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
            ),
            ast::NoReturn(span) => ast::NoReturn(span)
        }
    }

1214
    fn rebuild_arg_ty_or_output(&self,
1215
                                ty: &ast::Ty,
1216 1217 1218
                                lifetime: ast::Lifetime,
                                anon_nums: &HashSet<uint>,
                                region_names: &HashSet<ast::Name>)
1219 1220
                                -> P<ast::Ty> {
        let mut new_ty = P(ty.clone());
1221 1222
        let mut ty_queue = vec!(ty);
        while !ty_queue.is_empty() {
1223
            let cur_ty = ty_queue.remove(0).unwrap();
1224
            match cur_ty.node {
1225 1226 1227
                ast::TyRptr(lt_opt, ref mut_ty) => {
                    let rebuild = match lt_opt {
                        Some(lt) => region_names.contains(&lt.name),
1228 1229
                        None => {
                            let anon = self.cur_anon.get();
1230 1231
                            let rebuild = anon_nums.contains(&anon);
                            if rebuild {
1232 1233 1234
                                self.track_anon(anon);
                            }
                            self.inc_and_offset_cur_anon(1);
1235
                            rebuild
1236
                        }
1237 1238 1239 1240 1241 1242 1243 1244
                    };
                    if rebuild {
                        let to = ast::Ty {
                            id: cur_ty.id,
                            node: ast::TyRptr(Some(lifetime), mut_ty.clone()),
                            span: cur_ty.span
                        };
                        new_ty = self.rebuild_ty(new_ty, P(to));
1245
                    }
1246
                    ty_queue.push(&*mut_ty.ty);
1247
                }
1248
                ast::TyPath(ref path, id) => {
1249
                    let a_def = match self.tcx.def_map.borrow().get(&id) {
1250 1251 1252 1253 1254
                        None => {
                            self.tcx
                                .sess
                                .fatal(format!(
                                        "unbound path {}",
1255
                                        pprust::path_to_string(path)).as_slice())
1256
                        }
1257 1258 1259
                        Some(&d) => d
                    };
                    match a_def {
1260
                        def::DefTy(did, _) | def::DefStruct(did) => {
1261
                            let generics = ty::lookup_item_type(self.tcx, did).generics;
1262

1263 1264 1265
                            let expected =
                                generics.regions.len(subst::TypeSpace);
                            let lifetimes =
1266
                                path.segments.last().unwrap().parameters.lifetimes();
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
                            let mut insert = Vec::new();
                            if lifetimes.len() == 0 {
                                let anon = self.cur_anon.get();
                                for (i, a) in range(anon,
                                                    anon+expected).enumerate() {
                                    if anon_nums.contains(&a) {
                                        insert.push(i);
                                    }
                                    self.track_anon(a);
                                }
                                self.inc_and_offset_cur_anon(expected);
                            } else {
                                for (i, lt) in lifetimes.iter().enumerate() {
                                    if region_names.contains(&lt.name) {
                                        insert.push(i);
                                    }
                                }
                            }
1285 1286 1287 1288 1289 1290 1291
                            let rebuild_info = RebuildPathInfo {
                                path: path,
                                indexes: insert,
                                expected: expected,
                                anon_nums: anon_nums,
                                region_names: region_names
                            };
1292 1293 1294
                            let new_path = self.rebuild_path(rebuild_info, lifetime);
                            let to = ast::Ty {
                                id: cur_ty.id,
1295
                                node: ast::TyPath(new_path, id),
1296 1297 1298
                                span: cur_ty.span
                            };
                            new_ty = self.rebuild_ty(new_ty, P(to));
1299 1300 1301 1302 1303
                        }
                        _ => ()
                    }

                }
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313

                ast::TyPtr(ref mut_ty) => {
                    ty_queue.push(&*mut_ty.ty);
                }
                ast::TyVec(ref ty) |
                ast::TyFixedLengthVec(ref ty, _) => {
                    ty_queue.push(&**ty);
                }
                ast::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
                _ => {}
1314 1315 1316 1317 1318 1319
            }
        }
        new_ty
    }

    fn rebuild_ty(&self,
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
                  from: P<ast::Ty>,
                  to: P<ast::Ty>)
                  -> P<ast::Ty> {

        fn build_to(from: P<ast::Ty>,
                    to: &mut Option<P<ast::Ty>>)
                    -> P<ast::Ty> {
            if Some(from.id) == to.as_ref().map(|ty| ty.id) {
                return to.take().expect("`to` type found more than once during rebuild");
            }
            from.map(|ast::Ty {id, node, span}| {
                let new_node = match node {
                    ast::TyRptr(lifetime, mut_ty) => {
                        ast::TyRptr(lifetime, ast::MutTy {
                            mutbl: mut_ty.mutbl,
                            ty: build_to(mut_ty.ty, to),
                        })
1337
                    }
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
                    ast::TyPtr(mut_ty) => {
                        ast::TyPtr(ast::MutTy {
                            mutbl: mut_ty.mutbl,
                            ty: build_to(mut_ty.ty, to),
                        })
                    }
                    ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
                    ast::TyFixedLengthVec(ty, e) => {
                        ast::TyFixedLengthVec(build_to(ty, to), e)
                    }
                    ast::TyTup(tys) => {
A
Aaron Turon 已提交
1349
                        ast::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
1350 1351 1352 1353 1354 1355
                    }
                    ast::TyParen(typ) => ast::TyParen(build_to(typ, to)),
                    other => other
                };
                ast::Ty { id: id, node: new_node, span: span }
            })
1356 1357
        }

1358
        build_to(from, &mut Some(to))
1359 1360 1361
    }

    fn rebuild_path(&self,
1362
                    rebuild_info: RebuildPathInfo,
1363
                    lifetime: ast::Lifetime)
1364 1365
                    -> ast::Path
    {
1366
        let RebuildPathInfo {
1367 1368 1369 1370 1371
            path,
            indexes,
            expected,
            anon_nums,
            region_names,
1372 1373
        } = rebuild_info;

1374
        let last_seg = path.segments.last().unwrap();
1375 1376 1377
        let new_parameters = match last_seg.parameters {
            ast::ParenthesizedParameters(..) => {
                last_seg.parameters.clone()
1378
            }
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395

            ast::AngleBracketedParameters(ref data) => {
                let mut new_lts = Vec::new();
                if data.lifetimes.len() == 0 {
                    // traverse once to see if there's a need to insert lifetime
                    let need_insert = range(0, expected).any(|i| {
                        indexes.contains(&i)
                    });
                    if need_insert {
                        for i in range(0, expected) {
                            if indexes.contains(&i) {
                                new_lts.push(lifetime);
                            } else {
                                new_lts.push(self.life_giver.give_lifetime());
                            }
                        }
                    }
1396
                } else {
1397 1398 1399 1400 1401 1402 1403
                    for (i, lt) in data.lifetimes.iter().enumerate() {
                        if indexes.contains(&i) {
                            new_lts.push(lifetime);
                        } else {
                            new_lts.push(*lt);
                        }
                    }
1404
                }
1405 1406 1407 1408 1409 1410 1411
                let new_types = data.types.map(|t| {
                    self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
                });
                ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
                    lifetimes: new_lts,
                    types: new_types
                })
1412
            }
1413
        };
1414 1415
        let new_seg = ast::PathSegment {
            identifier: last_seg.identifier,
1416
            parameters: new_parameters
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
        };
        let mut new_segs = Vec::new();
        new_segs.push_all(path.segments.init());
        new_segs.push(new_seg);
        ast::Path {
            span: path.span,
            global: path.global,
            segments: new_segs
        }
    }
1427 1428
}

1429
impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
1430
    fn give_expl_lifetime_param(&self,
1431 1432 1433
                                decl: &ast::FnDecl,
                                fn_style: ast::FnStyle,
                                ident: ast::Ident,
1434
                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
1435 1436
                                generics: &ast::Generics,
                                span: codemap::Span) {
1437
        let suggested_fn = pprust::fun_to_string(decl, fn_style, ident,
1438
                                              opt_explicit_self, generics);
1439 1440
        let msg = format!("consider using an explicit lifetime \
                           parameter as shown: {}", suggested_fn);
P
P1start 已提交
1441
        self.tcx.sess.span_help(span, msg.as_slice());
1442 1443
    }

E
Eduard Burtescu 已提交
1444
    fn report_inference_failure(&self,
1445 1446
                                var_origin: RegionVariableOrigin) {
        let var_description = match var_origin {
1447 1448 1449 1450 1451 1452
            infer::MiscVariable(_) => "".to_string(),
            infer::PatternRegion(_) => " for pattern".to_string(),
            infer::AddrOfRegion(_) => " for borrow expression".to_string(),
            infer::AddrOfSlice(_) => " for slice expression".to_string(),
            infer::Autoref(_) => " for autoref".to_string(),
            infer::Coercion(_) => " for automatic coercion".to_string(),
1453
            infer::LateBoundRegion(_, br, infer::FnCall) => {
1454
                format!(" for {}in function call",
1455
                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
1456
            }
1457 1458
            infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
                format!(" for {}in generic type",
1459
                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
1460
            }
1461
            infer::EarlyBoundRegion(_, name) => {
1462
                format!(" for lifetime parameter `{}`",
1463
                        token::get_name(name).get())
1464
            }
1465
            infer::BoundRegionInCoherence(name) => {
1466
                format!(" for lifetime parameter `{}` in coherence check",
1467
                        token::get_name(name).get())
1468
            }
1469 1470
            infer::UpvarRegion(ref upvar_id, _) => {
                format!(" for capture of `{}` by closure",
1471
                        ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_string())
1472
            }
1473 1474 1475 1476 1477 1478
        };

        self.tcx.sess.span_err(
            var_origin.span(),
            format!("cannot infer an appropriate lifetime{} \
                    due to conflicting requirements",
1479
                    var_description).as_slice());
1480 1481
    }

1482
    fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
1483
        match *origin {
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
            infer::Subtype(ref trace) => {
                let desc = match trace.origin {
                    infer::Misc(_) => {
                        format!("types are compatible")
                    }
                    infer::MethodCompatCheck(_) => {
                        format!("method type is compatible with trait")
                    }
                    infer::ExprAssignable(_) => {
                        format!("expression is assignable")
                    }
                    infer::RelateTraitRefs(_) => {
                        format!("traits are compatible")
                    }
                    infer::RelateSelfType(_) => {
1499 1500 1501 1502 1503
                        format!("self type matches impl self type")
                    }
                    infer::RelateOutputImplTypes(_) => {
                        format!("trait type parameters matches those \
                                 specified on the impl")
1504
                    }
1505
                    infer::MatchExpressionArm(_, _) => {
1506 1507 1508 1509 1510
                        format!("match arms have compatible types")
                    }
                    infer::IfExpression(_) => {
                        format!("if and else have compatible types")
                    }
1511 1512 1513
                    infer::IfExpressionWithNoElse(_) => {
                        format!("if may be missing an else clause")
                    }
1514 1515 1516 1517 1518 1519 1520
                };

                match self.values_str(&trace.values) {
                    Some(values_str) => {
                        self.tcx.sess.span_note(
                            trace.origin.span(),
                            format!("...so that {} ({})",
1521
                                    desc, values_str).as_slice());
1522 1523 1524 1525 1526 1527 1528 1529
                    }
                    None => {
                        // Really should avoid printing this error at
                        // all, since it is derived, but that would
                        // require more refactoring than I feel like
                        // doing right now. - nmatsakis
                        self.tcx.sess.span_note(
                            trace.origin.span(),
1530
                            format!("...so that {}", desc).as_slice());
1531 1532 1533 1534 1535 1536
                    }
                }
            }
            infer::Reborrow(span) => {
                self.tcx.sess.span_note(
                    span,
1537
                    "...so that reference does not outlive \
1538 1539
                    borrowed content");
            }
1540 1541 1542
            infer::ReborrowUpvar(span, ref upvar_id) => {
                self.tcx.sess.span_note(
                    span,
1543 1544 1545 1546
                    format!(
                        "...so that closure can access `{}`",
                        ty::local_var_name_str(self.tcx, upvar_id.var_id)
                            .get()
1547
                            .to_string()).as_slice())
1548
            }
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
            infer::InfStackClosure(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that closure does not outlive its stack frame");
            }
            infer::InvokeClosure(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that closure is not invoked outside its lifetime");
            }
            infer::DerefPointer(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that pointer is not dereferenced \
                    outside its lifetime");
            }
1565
            infer::FreeVariable(span, id) => {
1566 1567
                self.tcx.sess.span_note(
                    span,
1568 1569
                    format!("...so that captured variable `{}` \
                            does not outlive the enclosing closure",
1570 1571
                            ty::local_var_name_str(
                                self.tcx,
1572
                                id).get().to_string()).as_slice());
1573
            }
1574 1575 1576 1577 1578 1579 1580 1581 1582
            infer::ProcCapture(span, id) => {
                self.tcx.sess.span_note(
                    span,
                    format!("...so that captured variable `{}` \
                            is 'static",
                            ty::local_var_name_str(
                                self.tcx,
                                id).get()).as_slice());
            }
1583 1584 1585 1586 1587 1588 1589 1590
            infer::IndexSlice(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that slice is not indexed outside the lifetime");
            }
            infer::RelateObjectBound(span) => {
                self.tcx.sess.span_note(
                    span,
1591 1592 1593
                    "...so that it can be closed over into an object");
            }
            infer::RelateProcBound(span, var_node_id, _ty) => {
1594
                self.tcx.sess.span_note(
1595 1596 1597 1598 1599 1600
                    span,
                    format!(
                        "...so that the variable `{}` can be captured \
                         into a proc",
                        ty::local_var_name_str(self.tcx,
                                               var_node_id)).as_slice());
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
            }
            infer::CallRcvr(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that method receiver is valid for the method call");
            }
            infer::CallArg(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that argument is valid for the call");
            }
            infer::CallReturn(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that return value is valid for the call");
            }
            infer::AddrOf(span) => {
                self.tcx.sess.span_note(
                    span,
1620
                    "...so that reference is valid \
1621 1622 1623 1624 1625
                     at the time of borrow");
            }
            infer::AutoBorrow(span) => {
                self.tcx.sess.span_note(
                    span,
1626 1627
                    "...so that auto-reference is valid \
                     at the time of borrow");
1628
            }
1629 1630 1631 1632 1633 1634 1635
            infer::ExprTypeIsNotInScope(t, span) => {
                self.tcx.sess.span_note(
                    span,
                    format!("...so type `{}` of expression is valid during the \
                             expression",
                            self.ty_to_string(t)).as_slice());
            }
1636 1637 1638 1639 1640
            infer::BindingTypeIsNotValidAtDecl(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that variable is valid at time of its declaration");
            }
1641 1642 1643 1644 1645 1646 1647
            infer::ReferenceOutlivesReferent(ty, span) => {
                self.tcx.sess.span_note(
                    span,
                    format!("...so that the reference type `{}` \
                             does not outlive the data it points at",
                            self.ty_to_string(ty)).as_slice());
            }
1648
            infer::RelateParamBound(span, t) => {
1649 1650
                self.tcx.sess.span_note(
                    span,
1651
                    format!("...so that the type `{}` \
1652
                             will meet the declared lifetime bounds",
1653 1654 1655 1656 1657 1658 1659
                            self.ty_to_string(t)).as_slice());
            }
            infer::RelateDefaultParamBound(span, t) => {
                self.tcx.sess.span_note(
                    span,
                    format!("...so that type parameter \
                             instantiated with `{}`, \
1660
                             will meet its declared lifetime bounds",
1661 1662 1663
                            self.ty_to_string(t)).as_slice());
            }
            infer::RelateRegionParamBound(span) => {
1664 1665
                self.tcx.sess.span_note(
                    span,
1666 1667
                    format!("...so that the declared lifetime parameter bounds \
                                are satisfied").as_slice());
1668 1669
            }
        }
1670 1671 1672
    }
}

1673 1674
pub trait Resolvable<'tcx> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Self;
1675
    fn contains_error(&self) -> bool;
J
Jakub Bukaj 已提交
1676 1677
}

1678 1679
impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Ty<'tcx> {
J
Jakub Bukaj 已提交
1680 1681 1682 1683 1684 1685 1686
        infcx.resolve_type_vars_if_possible(*self)
    }
    fn contains_error(&self) -> bool {
        ty::type_is_error(*self)
    }
}

1687 1688 1689
impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
                   -> Rc<ty::TraitRef<'tcx>> {
E
Eduard Burtescu 已提交
1690
        Rc::new(infcx.resolve_type_vars_in_trait_ref_if_possible(&**self))
1691 1692
    }
    fn contains_error(&self) -> bool {
E
Eduard Burtescu 已提交
1693
        ty::trait_ref_contains_error(&**self)
1694 1695 1696
    }
}

1697 1698
fn lifetimes_in_scope(tcx: &ty::ctxt,
                      scope_id: ast::NodeId)
1699
                      -> Vec<ast::LifetimeDef> {
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
    let mut taken = Vec::new();
    let parent = tcx.map.get_parent(scope_id);
    let method_id_opt = match tcx.map.find(parent) {
        Some(node) => match node {
            ast_map::NodeItem(item) => match item.node {
                ast::ItemFn(_, _, _, ref gen, _) => {
                    taken.push_all(gen.lifetimes.as_slice());
                    None
                },
                _ => None
            },
1711 1712
            ast_map::NodeImplItem(ii) => {
                match *ii {
1713
                    ast::MethodImplItem(ref m) => {
1714 1715 1716
                        taken.push_all(m.pe_generics().lifetimes.as_slice());
                        Some(m.id)
                    }
1717
                    ast::TypeImplItem(_) => None,
1718 1719
                }
            }
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742
            _ => None
        },
        None => None
    };
    if method_id_opt.is_some() {
        let method_id = method_id_opt.unwrap();
        let parent = tcx.map.get_parent(method_id);
        match tcx.map.find(parent) {
            Some(node) => match node {
                ast_map::NodeItem(item) => match item.node {
                    ast::ItemImpl(ref gen, _, _, _) => {
                        taken.push_all(gen.lifetimes.as_slice());
                    }
                    _ => ()
                },
                _ => ()
            },
            None => ()
        }
    }
    return taken;
}

1743 1744
// LifeGiver is responsible for generating fresh lifetime names
struct LifeGiver {
1745
    taken: HashSet<String>,
1746 1747 1748 1749 1750
    counter: Cell<uint>,
    generated: RefCell<Vec<ast::Lifetime>>,
}

impl LifeGiver {
1751
    fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
1752 1753
        let mut taken_ = HashSet::new();
        for lt in taken.iter() {
1754
            let lt_name = token::get_name(lt.lifetime.name).get().to_string();
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
            taken_.insert(lt_name);
        }
        LifeGiver {
            taken: taken_,
            counter: Cell::new(0),
            generated: RefCell::new(Vec::new()),
        }
    }

    fn inc_counter(&self) {
        let c = self.counter.get();
        self.counter.set(c+1);
    }

    fn give_lifetime(&self) -> ast::Lifetime {
        let mut lifetime;
        loop {
1772
            let mut s = String::from_str("'");
1773
            s.push_str(num_to_string(self.counter.get()).as_slice());
1774 1775 1776
            if !self.taken.contains(&s) {
                lifetime = name_to_dummy_lifetime(
                                    token::str_to_ident(s.as_slice()).name);
1777
                self.generated.borrow_mut().push(lifetime);
1778 1779 1780 1781 1782 1783 1784 1785
                break;
            }
            self.inc_counter();
        }
        self.inc_counter();
        return lifetime;

        // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
1786
        fn num_to_string(counter: uint) -> String {
1787
            let mut s = String::new();
1788 1789 1790
            let (n, r) = (counter/26 + 1, counter % 26);
            let letter: char = from_u32((r+97) as u32).unwrap();
            for _ in range(0, n) {
1791
                s.push(letter);
1792
            }
1793
            s
1794 1795 1796 1797
        }
    }

    fn get_generated_lifetimes(&self) -> Vec<ast::Lifetime> {
E
Erick Tryzelaar 已提交
1798
        self.generated.borrow().clone()
1799 1800
    }
}