error_reporting.rs 69.6 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
                                decl: &ast::FnDecl,
N
Niko Matsakis 已提交
160
                                unsafety: ast::Unsafety,
161
                                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
                None => {
327
                    debug!("no parent node of scope_id {}", scope_id);
328 329
                    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
            infer::EquatePredicate(_) => "equality predicate not satisfied",
370 371 372 373
        };

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

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

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

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

403
    fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
E
Eduard Burtescu 已提交
404
        &self,
405
        exp_found: &ty::expected_found<T>)
406
        -> Option<String>
407 408 409 410 411 412 413 414 415 416 417
    {
        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;
        }

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

423
    fn report_param_bound_failure(&self,
424
                                  origin: SubregionOrigin<'tcx>,
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
                                  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 已提交
440 441 442 443 444 445
                        "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 `{}: {}`...",
446 447 448 449 450 451 452 453 454
                        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 已提交
455 456 457 458 459 460
                        "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`...",
461 462 463 464 465 466 467 468
                        param_ty.user_string(self.tcx)).as_slice());
            }

            _ => {
                // If not, be less specific.
                self.tcx.sess.span_err(
                    origin.span(),
                    format!(
P
P1start 已提交
469 470 471 472 473 474
                        "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 `{}`",
475 476 477 478 479 480 481 482 483 484 485 486 487
                        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 已提交
488
    fn report_concrete_failure(&self,
489
                               origin: SubregionOrigin<'tcx>,
490 491 492 493
                               sub: Region,
                               sup: Region) {
        match origin {
            infer::Subtype(trace) => {
494
                let terr = ty::terr_regions_does_not_outlive(sup, sub);
495 496 497 498 499
                self.report_and_explain_type_error(trace, &terr);
            }
            infer::Reborrow(span) => {
                self.tcx.sess.span_err(
                    span,
500
                    "lifetime of reference outlines \
501 502 503
                     lifetime of borrowed content...");
                note_and_explain_region(
                    self.tcx,
504
                    "...the reference is valid for ",
505 506 507 508 509 510 511 512
                    sub,
                    "...");
                note_and_explain_region(
                    self.tcx,
                    "...but the borrowed content is only valid for ",
                    sup,
                    "");
            }
513 514 515 516 517
            infer::ReborrowUpvar(span, ref upvar_id) => {
                self.tcx.sess.span_err(
                    span,
                    format!("lifetime of borrowed pointer outlives \
                            lifetime of captured variable `{}`...",
518 519 520
                            ty::local_var_name_str(self.tcx,
                                                   upvar_id.var_id)
                                .get()
521
                                .to_string()).as_slice());
522 523 524 525 526 527 528 529
                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 ",
530 531 532
                            ty::local_var_name_str(self.tcx,
                                                   upvar_id.var_id)
                                .get()
533
                                .to_string()).as_slice(),
534 535 536
                    sup,
                    "");
            }
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
            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,
                    "");
            }
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
            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,
                    "");
            }
572
            infer::FreeVariable(span, id) => {
573 574
                self.tcx.sess.span_err(
                    span,
575 576
                    format!("captured variable `{}` does not \
                            outlive the enclosing closure",
577 578
                            ty::local_var_name_str(self.tcx,
                                                   id).get()
579
                                                      .to_string()).as_slice());
580 581 582 583 584 585 586 587 588 589 590 591
                note_and_explain_region(
                    self.tcx,
                    "captured variable is valid for ",
                    sup,
                    "");
                note_and_explain_region(
                    self.tcx,
                    "closure is valid for ",
                    sub,
                    "");
            }
            infer::IndexSlice(span) => {
592 593
                self.tcx.sess.span_err(span,
                                       "index of slice outside its lifetime");
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
                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,
                    "");
            }
616
            infer::RelateParamBound(span, ty) => {
617 618
                self.tcx.sess.span_err(
                    span,
619
                    format!("the type `{}` does not fulfill the \
620
                             required lifetime",
621
                            self.ty_to_string(ty)).as_slice());
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
                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,
                                        "");
            }
653 654 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 686 687 688
            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,
689
                    "reference is not valid \
690 691 692 693 694 695 696 697 698 699
                     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,
700
                    "automatically reference is not valid \
701 702 703 704 705 706 707
                     at the time of borrow");
                note_and_explain_region(
                    self.tcx,
                    "the automatic borrow is only valid for ",
                    sup,
                    "");
            }
708 709 710 711 712 713 714 715 716 717 718 719
            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,
                    "");
            }
720 721 722 723 724 725 726 727 728 729
            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 已提交
730
            infer::ReferenceOutlivesReferent(ty, span) => {
731
                self.tcx.sess.span_err(
N
Niko Matsakis 已提交
732
                    span,
733 734 735
                    format!("in type `{}`, reference has a longer lifetime \
                             than the data it references",
                            self.ty_to_string(ty)).as_slice());
736 737 738 739 740 741 742 743 744 745 746 747 748 749
                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 已提交
750
    fn report_sub_sup_conflict(&self,
751
                               var_origin: RegionVariableOrigin,
752
                               sub_origin: SubregionOrigin<'tcx>,
753
                               sub_region: Region,
754
                               sup_origin: SubregionOrigin<'tcx>,
755
                               sup_region: Region) {
756
        self.report_inference_failure(var_origin);
757 758 759 760 761 762 763

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

764
        self.note_region_origin(&sup_origin);
765 766 767 768 769 770 771

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

772
        self.note_region_origin(&sub_origin);
773 774
    }

E
Eduard Burtescu 已提交
775
    fn report_sup_sup_conflict(&self,
776
                               var_origin: RegionVariableOrigin,
777
                               origin1: SubregionOrigin<'tcx>,
778
                               region1: Region,
779
                               origin2: SubregionOrigin<'tcx>,
780
                               region2: Region) {
781
        self.report_inference_failure(var_origin);
782 783 784 785 786 787 788

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

789
        self.note_region_origin(&origin1);
790 791 792 793 794 795 796

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

797
        self.note_region_origin(&origin2);
798
    }
799 800 801

    fn report_processed_errors(&self,
                               var_origins: &[RegionVariableOrigin],
802
                               trace_origins: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
803 804
                               same_regions: &[SameRegions]) {
        for vo in var_origins.iter() {
E
Eduard Burtescu 已提交
805
            self.report_inference_failure(vo.clone());
806
        }
807
        self.give_suggestion(same_regions);
E
Eduard Burtescu 已提交
808 809
        for &(ref trace, terr) in trace_origins.iter() {
            self.report_type_error(trace.clone(), &terr);
810 811 812 813 814 815 816 817
        }
    }

    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 已提交
818 819 820
            Some(ref node) => match *node {
                ast_map::NodeItem(ref item) => {
                    match item.node {
821 822
                        ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => {
                            Some((&**fn_decl, gen, pur, item.ident, None, item.span))
F
Flavio Percoco 已提交
823 824 825 826
                        },
                        _ => None
                    }
                }
827 828 829 830 831
                ast_map::NodeImplItem(ref item) => {
                    match **item {
                        ast::MethodImplItem(ref m) => {
                            Some((m.pe_fn_decl(),
                                  m.pe_generics(),
N
Niko Matsakis 已提交
832
                                  m.pe_unsafety(),
833
                                  m.pe_ident(),
834
                                  Some(&m.pe_explicit_self().node),
835 836
                                  m.span))
                        }
837
                        ast::TypeImplItem(_) => None,
838
                    }
839
                },
840 841 842 843 844
                ast_map::NodeTraitItem(ref item) => {
                    match **item {
                        ast::ProvidedMethod(ref m) => {
                            Some((m.pe_fn_decl(),
                                  m.pe_generics(),
N
Niko Matsakis 已提交
845
                                  m.pe_unsafety(),
846 847 848 849 850 851 852
                                  m.pe_ident(),
                                  Some(&m.pe_explicit_self().node),
                                  m.span))
                        }
                        _ => None
                    }
                }
853 854 855 856
                _ => None
            },
            None => None
        };
N
Niko Matsakis 已提交
857
        let (fn_decl, generics, unsafety, ident, expl_self, span)
858 859 860
                                    = node_inner.expect("expect item fn");
        let taken = lifetimes_in_scope(self.tcx, scope_id);
        let life_giver = LifeGiver::with_taken(taken.as_slice());
861
        let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
862 863
                                       generics, same_regions, &life_giver);
        let (fn_decl, expl_self, generics) = rebuilder.rebuild();
N
Niko Matsakis 已提交
864
        self.give_expl_lifetime_param(&fn_decl, unsafety, ident,
865
                                      expl_self.as_ref(), &generics, span);
866 867 868
    }
}

869 870 871 872 873 874 875 876 877 878 879
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>
}

880 881
struct Rebuilder<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
882 883
    fn_decl: &'a ast::FnDecl,
    expl_self_opt: Option<&'a ast::ExplicitSelf_>,
884 885
    generics: &'a ast::Generics,
    same_regions: &'a [SameRegions],
886
    life_giver: &'a LifeGiver,
887 888 889 890
    cur_anon: Cell<uint>,
    inserted_anons: RefCell<HashSet<uint>>,
}

891 892 893 894 895
enum FreshOrKept {
    Fresh,
    Kept
}

896 897
impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
    fn new(tcx: &'a ty::ctxt<'tcx>,
898 899
           fn_decl: &'a ast::FnDecl,
           expl_self_opt: Option<&'a ast::ExplicitSelf_>,
900
           generics: &'a ast::Generics,
901 902
           same_regions: &'a [SameRegions],
           life_giver: &'a LifeGiver)
903
           -> Rebuilder<'a, 'tcx> {
904 905 906
        Rebuilder {
            tcx: tcx,
            fn_decl: fn_decl,
907
            expl_self_opt: expl_self_opt,
908 909
            generics: generics,
            same_regions: same_regions,
910
            life_giver: life_giver,
911 912 913 914 915
            cur_anon: Cell::new(0),
            inserted_anons: RefCell::new(HashSet::new()),
        }
    }

916 917
    fn rebuild(&self)
               -> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
918
        let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
919
        let mut inputs = self.fn_decl.inputs.clone();
920
        let mut output = self.fn_decl.output.clone();
921
        let mut ty_params = self.generics.ty_params.clone();
922
        let where_clause = self.generics.where_clause.clone();
923
        let mut kept_lifetimes = HashSet::new();
924 925 926 927 928
        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);
929 930 931 932 933 934 935
            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);
936 937
            inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime,
                                          &anon_nums, &region_names);
938
            output = self.rebuild_output(&output, lifetime, &anon_nums, &region_names);
939 940
            ty_params = self.rebuild_ty_params(ty_params, lifetime,
                                               &region_names);
941
        }
942
        let fresh_lifetimes = self.life_giver.get_generated_lifetimes();
943 944
        let all_region_names = self.extract_all_region_names();
        let generics = self.rebuild_generics(self.generics,
945 946 947
                                             &fresh_lifetimes,
                                             &kept_lifetimes,
                                             &all_region_names,
948 949
                                             ty_params,
                                             where_clause);
950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
        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 已提交
967
                let lt_name = token::get_name(*rn).get().to_string();
968 969 970
                names.push(lt_name);
            }
            names.sort();
971
            let name = token::str_to_ident(names[0].as_slice()).name;
972 973 974
            return (name_to_dummy_lifetime(name), Kept);
        }
        return (self.life_giver.give_lifetime(), Fresh);
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
    }

    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();
1017
        while self.inserted_anons.borrow().contains(&anon) {
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
            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) {
1029
        self.inserted_anons.borrow_mut().insert(anon);
1030 1031
    }

1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
    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 已提交
1045
                unbound: ty_param.unbound.clone(),
1046
                default: ty_param.default.clone(),
1047
                span: ty_param.span,
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
            }
        })
    }

    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 {
1059 1060 1061 1062 1063 1064
                &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 已提交
1065 1066
                &ast::TraitTyParamBound(ref poly_tr) => {
                    let tr = &poly_tr.trait_ref;
1067 1068
                    let last_seg = tr.path.segments.last().unwrap();
                    let mut insert = Vec::new();
1069 1070
                    let lifetimes = last_seg.parameters.lifetimes();
                    for (i, lt) in lifetimes.iter().enumerate() {
1071 1072 1073 1074 1075 1076 1077
                        if region_names.contains(&lt.name) {
                            insert.push(i);
                        }
                    }
                    let rebuild_info = RebuildPathInfo {
                        path: &tr.path,
                        indexes: insert,
1078
                        expected: lifetimes.len(),
1079 1080 1081 1082
                        anon_nums: &HashSet::new(),
                        region_names: region_names
                    };
                    let new_path = self.rebuild_path(rebuild_info, lifetime);
N
Niko Matsakis 已提交
1083 1084 1085 1086 1087 1088
                    ast::TraitTyParamBound(ast::PolyTraitRef {
                        bound_lifetimes: poly_tr.bound_lifetimes.clone(),
                        trait_ref: ast::TraitRef {
                            path: new_path,
                            ref_id: tr.ref_id,
                        }
1089 1090 1091 1092 1093 1094
                    })
                }
            }
        })
    }

1095 1096 1097 1098 1099 1100 1101
    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 {
1102
            Some(ref expl_self) => match *expl_self {
1103
                ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
1104
                    Some(lt) => if region_names.contains(&lt.name) {
1105
                        return Some(ast::SelfRegion(Some(lifetime), muta, id));
1106 1107 1108 1109 1110 1111
                    },
                    None => {
                        let anon = self.cur_anon.get();
                        self.inc_and_offset_cur_anon(1);
                        if anon_nums.contains(&anon) {
                            self.track_anon(anon);
1112
                            return Some(ast::SelfRegion(Some(lifetime), muta, id));
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
                        }
                    }
                },
                _ => ()
            },
            None => ()
        }
        expl_self_opt
    }

1123 1124
    fn rebuild_generics(&self,
                        generics: &ast::Generics,
1125 1126
                        add: &Vec<ast::Lifetime>,
                        keep: &HashSet<ast::Name>,
1127
                        remove: &HashSet<ast::Name>,
1128 1129
                        ty_params: OwnedSlice<ast::TyParam>,
                        where_clause: ast::WhereClause)
1130 1131 1132
                        -> ast::Generics {
        let mut lifetimes = Vec::new();
        for lt in add.iter() {
1133 1134
            lifetimes.push(ast::LifetimeDef { lifetime: *lt,
                                              bounds: Vec::new() });
1135 1136
        }
        for lt in generics.lifetimes.iter() {
1137
            if keep.contains(&lt.lifetime.name) ||
1138
                !remove.contains(&lt.lifetime.name) {
1139 1140 1141 1142 1143
                lifetimes.push((*lt).clone());
            }
        }
        ast::Generics {
            lifetimes: lifetimes,
1144 1145
            ty_params: ty_params,
            where_clause: where_clause,
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
        }
    }

    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() {
1157
            let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime,
1158 1159 1160
                                                       anon_nums, region_names);
            let possibly_new_arg = ast::Arg {
                ty: new_ty,
1161
                pat: arg.pat.clone(),
1162 1163 1164 1165 1166 1167 1168
                id: arg.id
            };
            new_inputs.push(possibly_new_arg);
        }
        new_inputs
    }

1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
    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)
        }
    }

1181
    fn rebuild_arg_ty_or_output(&self,
1182
                                ty: &ast::Ty,
1183 1184 1185
                                lifetime: ast::Lifetime,
                                anon_nums: &HashSet<uint>,
                                region_names: &HashSet<ast::Name>)
1186 1187
                                -> P<ast::Ty> {
        let mut new_ty = P(ty.clone());
1188 1189
        let mut ty_queue = vec!(ty);
        while !ty_queue.is_empty() {
1190
            let cur_ty = ty_queue.remove(0).unwrap();
1191
            match cur_ty.node {
1192 1193 1194
                ast::TyRptr(lt_opt, ref mut_ty) => {
                    let rebuild = match lt_opt {
                        Some(lt) => region_names.contains(&lt.name),
1195 1196
                        None => {
                            let anon = self.cur_anon.get();
1197 1198
                            let rebuild = anon_nums.contains(&anon);
                            if rebuild {
1199 1200 1201
                                self.track_anon(anon);
                            }
                            self.inc_and_offset_cur_anon(1);
1202
                            rebuild
1203
                        }
1204 1205 1206 1207 1208 1209 1210 1211
                    };
                    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));
1212
                    }
1213
                    ty_queue.push(&*mut_ty.ty);
1214
                }
1215
                ast::TyPath(ref path, id) => {
1216
                    let a_def = match self.tcx.def_map.borrow().get(&id) {
1217 1218 1219 1220 1221
                        None => {
                            self.tcx
                                .sess
                                .fatal(format!(
                                        "unbound path {}",
1222
                                        pprust::path_to_string(path)).as_slice())
1223
                        }
1224 1225 1226
                        Some(&d) => d
                    };
                    match a_def {
1227
                        def::DefTy(did, _) | def::DefStruct(did) => {
1228
                            let generics = ty::lookup_item_type(self.tcx, did).generics;
1229

1230 1231 1232
                            let expected =
                                generics.regions.len(subst::TypeSpace);
                            let lifetimes =
1233
                                path.segments.last().unwrap().parameters.lifetimes();
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
                            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);
                                    }
                                }
                            }
1252 1253 1254 1255 1256 1257 1258
                            let rebuild_info = RebuildPathInfo {
                                path: path,
                                indexes: insert,
                                expected: expected,
                                anon_nums: anon_nums,
                                region_names: region_names
                            };
1259 1260 1261
                            let new_path = self.rebuild_path(rebuild_info, lifetime);
                            let to = ast::Ty {
                                id: cur_ty.id,
1262
                                node: ast::TyPath(new_path, id),
1263 1264 1265
                                span: cur_ty.span
                            };
                            new_ty = self.rebuild_ty(new_ty, P(to));
1266 1267 1268 1269 1270
                        }
                        _ => ()
                    }

                }
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280

                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)),
                _ => {}
1281 1282 1283 1284 1285 1286
            }
        }
        new_ty
    }

    fn rebuild_ty(&self,
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
                  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),
                        })
1304
                    }
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
                    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 已提交
1316
                        ast::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
1317 1318 1319 1320 1321 1322
                    }
                    ast::TyParen(typ) => ast::TyParen(build_to(typ, to)),
                    other => other
                };
                ast::Ty { id: id, node: new_node, span: span }
            })
1323 1324
        }

1325
        build_to(from, &mut Some(to))
1326 1327 1328
    }

    fn rebuild_path(&self,
1329
                    rebuild_info: RebuildPathInfo,
1330
                    lifetime: ast::Lifetime)
1331 1332
                    -> ast::Path
    {
1333
        let RebuildPathInfo {
1334 1335 1336 1337 1338
            path,
            indexes,
            expected,
            anon_nums,
            region_names,
1339 1340
        } = rebuild_info;

1341
        let last_seg = path.segments.last().unwrap();
1342 1343 1344
        let new_parameters = match last_seg.parameters {
            ast::ParenthesizedParameters(..) => {
                last_seg.parameters.clone()
1345
            }
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362

            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());
                            }
                        }
                    }
1363
                } else {
1364 1365 1366 1367 1368 1369 1370
                    for (i, lt) in data.lifetimes.iter().enumerate() {
                        if indexes.contains(&i) {
                            new_lts.push(lifetime);
                        } else {
                            new_lts.push(*lt);
                        }
                    }
1371
                }
1372 1373 1374
                let new_types = data.types.map(|t| {
                    self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
                });
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
                let new_bindings = data.bindings.map(|b| {
                    P(ast::TypeBinding {
                        id: b.id,
                        ident: b.ident,
                        ty: self.rebuild_arg_ty_or_output(&*b.ty,
                                                          lifetime,
                                                          anon_nums,
                                                          region_names),
                        span: b.span
                    })
                });
1386 1387
                ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
                    lifetimes: new_lts,
1388 1389 1390
                    types: new_types,
                    bindings: new_bindings,
               })
1391
            }
1392
        };
1393 1394
        let new_seg = ast::PathSegment {
            identifier: last_seg.identifier,
1395
            parameters: new_parameters
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
        };
        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
        }
    }
1406 1407
}

1408
impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
1409
    fn give_expl_lifetime_param(&self,
1410
                                decl: &ast::FnDecl,
N
Niko Matsakis 已提交
1411
                                unsafety: ast::Unsafety,
1412
                                ident: ast::Ident,
1413
                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
1414 1415
                                generics: &ast::Generics,
                                span: codemap::Span) {
N
Niko Matsakis 已提交
1416
        let suggested_fn = pprust::fun_to_string(decl, unsafety, ident,
1417
                                              opt_explicit_self, generics);
1418 1419
        let msg = format!("consider using an explicit lifetime \
                           parameter as shown: {}", suggested_fn);
P
P1start 已提交
1420
        self.tcx.sess.span_help(span, msg.as_slice());
1421 1422
    }

E
Eduard Burtescu 已提交
1423
    fn report_inference_failure(&self,
1424 1425
                                var_origin: RegionVariableOrigin) {
        let var_description = match var_origin {
1426 1427 1428 1429 1430 1431
            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(),
1432
            infer::LateBoundRegion(_, br, infer::FnCall) => {
1433
                format!(" for {}in function call",
1434
                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
1435
            }
1436 1437
            infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
                format!(" for {}in generic type",
1438
                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
1439
            }
1440
            infer::EarlyBoundRegion(_, name) => {
1441
                format!(" for lifetime parameter `{}`",
1442
                        token::get_name(name).get())
1443
            }
1444
            infer::BoundRegionInCoherence(name) => {
1445
                format!(" for lifetime parameter `{}` in coherence check",
1446
                        token::get_name(name).get())
1447
            }
1448 1449
            infer::UpvarRegion(ref upvar_id, _) => {
                format!(" for capture of `{}` by closure",
1450
                        ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_string())
1451
            }
1452 1453 1454 1455 1456 1457
        };

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

1461
    fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
1462
        match *origin {
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
            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(_) => {
1478 1479 1480 1481 1482
                        format!("self type matches impl self type")
                    }
                    infer::RelateOutputImplTypes(_) => {
                        format!("trait type parameters matches those \
                                 specified on the impl")
1483
                    }
1484
                    infer::MatchExpressionArm(_, _) => {
1485 1486 1487 1488 1489
                        format!("match arms have compatible types")
                    }
                    infer::IfExpression(_) => {
                        format!("if and else have compatible types")
                    }
1490 1491 1492
                    infer::IfExpressionWithNoElse(_) => {
                        format!("if may be missing an else clause")
                    }
1493 1494 1495
                    infer::EquatePredicate(_) => {
                        format!("equality where clause is satisfied")
                    }
1496 1497 1498 1499 1500 1501 1502
                };

                match self.values_str(&trace.values) {
                    Some(values_str) => {
                        self.tcx.sess.span_note(
                            trace.origin.span(),
                            format!("...so that {} ({})",
1503
                                    desc, values_str).as_slice());
1504 1505 1506 1507 1508 1509 1510 1511
                    }
                    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(),
1512
                            format!("...so that {}", desc).as_slice());
1513 1514 1515 1516 1517 1518
                    }
                }
            }
            infer::Reborrow(span) => {
                self.tcx.sess.span_note(
                    span,
1519
                    "...so that reference does not outlive \
1520 1521
                    borrowed content");
            }
1522 1523 1524
            infer::ReborrowUpvar(span, ref upvar_id) => {
                self.tcx.sess.span_note(
                    span,
1525 1526 1527 1528
                    format!(
                        "...so that closure can access `{}`",
                        ty::local_var_name_str(self.tcx, upvar_id.var_id)
                            .get()
1529
                            .to_string()).as_slice())
1530
            }
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
            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");
            }
1547
            infer::FreeVariable(span, id) => {
1548 1549
                self.tcx.sess.span_note(
                    span,
1550 1551
                    format!("...so that captured variable `{}` \
                            does not outlive the enclosing closure",
1552 1553
                            ty::local_var_name_str(
                                self.tcx,
1554
                                id).get().to_string()).as_slice());
1555 1556 1557 1558 1559 1560 1561 1562 1563
            }
            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,
1564 1565
                    "...so that it can be closed over into an object");
            }
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583
            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,
1584
                    "...so that reference is valid \
1585 1586 1587 1588 1589
                     at the time of borrow");
            }
            infer::AutoBorrow(span) => {
                self.tcx.sess.span_note(
                    span,
1590 1591
                    "...so that auto-reference is valid \
                     at the time of borrow");
1592
            }
1593 1594 1595 1596 1597 1598 1599
            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());
            }
1600 1601 1602 1603 1604
            infer::BindingTypeIsNotValidAtDecl(span) => {
                self.tcx.sess.span_note(
                    span,
                    "...so that variable is valid at time of its declaration");
            }
1605 1606 1607 1608 1609 1610 1611
            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());
            }
1612
            infer::RelateParamBound(span, t) => {
1613 1614
                self.tcx.sess.span_note(
                    span,
1615
                    format!("...so that the type `{}` \
1616
                             will meet the declared lifetime bounds",
1617 1618 1619 1620 1621 1622 1623
                            self.ty_to_string(t)).as_slice());
            }
            infer::RelateDefaultParamBound(span, t) => {
                self.tcx.sess.span_note(
                    span,
                    format!("...so that type parameter \
                             instantiated with `{}`, \
1624
                             will meet its declared lifetime bounds",
1625 1626 1627
                            self.ty_to_string(t)).as_slice());
            }
            infer::RelateRegionParamBound(span) => {
1628 1629
                self.tcx.sess.span_note(
                    span,
1630 1631
                    format!("...so that the declared lifetime parameter bounds \
                                are satisfied").as_slice());
1632 1633
            }
        }
1634 1635 1636
    }
}

1637 1638
pub trait Resolvable<'tcx> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Self;
1639
    fn contains_error(&self) -> bool;
J
Jakub Bukaj 已提交
1640 1641
}

1642 1643
impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Ty<'tcx> {
1644
        infcx.resolve_type_vars_if_possible(self)
J
Jakub Bukaj 已提交
1645 1646 1647 1648 1649 1650
    }
    fn contains_error(&self) -> bool {
        ty::type_is_error(*self)
    }
}

1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
                   -> Rc<ty::TraitRef<'tcx>> {
        Rc::new(infcx.resolve_type_vars_if_possible(&**self))
    }
    fn contains_error(&self) -> bool {
        ty::trait_ref_contains_error(&**self)
    }
}

1661
impl<'tcx> Resolvable<'tcx> for Rc<ty::PolyTraitRef<'tcx>> {
1662
    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
1663
                   -> Rc<ty::PolyTraitRef<'tcx>> {
1664
        Rc::new(infcx.resolve_type_vars_if_possible(&**self))
1665 1666
    }
    fn contains_error(&self) -> bool {
1667
        ty::trait_ref_contains_error(&self.0)
1668 1669 1670
    }
}

1671 1672
fn lifetimes_in_scope(tcx: &ty::ctxt,
                      scope_id: ast::NodeId)
1673
                      -> Vec<ast::LifetimeDef> {
1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
    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
            },
1685 1686
            ast_map::NodeImplItem(ii) => {
                match *ii {
1687
                    ast::MethodImplItem(ref m) => {
1688 1689 1690
                        taken.push_all(m.pe_generics().lifetimes.as_slice());
                        Some(m.id)
                    }
1691
                    ast::TypeImplItem(_) => None,
1692 1693
                }
            }
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
            _ => 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 {
1704
                    ast::ItemImpl(_, ref gen, _, _, _) => {
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
                        taken.push_all(gen.lifetimes.as_slice());
                    }
                    _ => ()
                },
                _ => ()
            },
            None => ()
        }
    }
    return taken;
}

1717 1718
// LifeGiver is responsible for generating fresh lifetime names
struct LifeGiver {
1719
    taken: HashSet<String>,
1720 1721 1722 1723 1724
    counter: Cell<uint>,
    generated: RefCell<Vec<ast::Lifetime>>,
}

impl LifeGiver {
1725
    fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
1726 1727
        let mut taken_ = HashSet::new();
        for lt in taken.iter() {
1728
            let lt_name = token::get_name(lt.lifetime.name).get().to_string();
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745
            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 {
1746
            let mut s = String::from_str("'");
1747
            s.push_str(num_to_string(self.counter.get()).as_slice());
1748 1749 1750
            if !self.taken.contains(&s) {
                lifetime = name_to_dummy_lifetime(
                                    token::str_to_ident(s.as_slice()).name);
1751
                self.generated.borrow_mut().push(lifetime);
1752 1753 1754 1755 1756 1757 1758 1759
                break;
            }
            self.inc_counter();
        }
        self.inc_counter();
        return lifetime;

        // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
1760
        fn num_to_string(counter: uint) -> String {
1761
            let mut s = String::new();
1762 1763 1764
            let (n, r) = (counter/26 + 1, counter % 26);
            let letter: char = from_u32((r+97) as u32).unwrap();
            for _ in range(0, n) {
1765
                s.push(letter);
1766
            }
1767
            s
1768 1769 1770 1771
        }
    }

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