PageRenderTime 65ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/librustc/middle/infer/error_reporting.rs

http://github.com/eholk/rust
Rust | 1823 lines | 1627 code | 104 blank | 92 comment | 67 complexity | 78008ee460d254ebc62099fbacec4175 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-2-Clause, 0BSD, Apache-2.0, MIT, LGPL-2.0
  1. // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. //! Error Reporting Code for the inference engine
  11. //!
  12. //! Because of the way inference, and in particular region inference,
  13. //! works, it often happens that errors are not detected until far after
  14. //! the relevant line of code has been type-checked. Therefore, there is
  15. //! an elaborate system to track why a particular constraint in the
  16. //! inference graph arose so that we can explain to the user what gave
  17. //! rise to a particular error.
  18. //!
  19. //! The basis of the system are the "origin" types. An "origin" is the
  20. //! reason that a constraint or inference variable arose. There are
  21. //! different "origin" enums for different kinds of constraints/variables
  22. //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
  23. //! a span, but also more information so that we can generate a meaningful
  24. //! error message.
  25. //!
  26. //! Having a catalogue of all the different reasons an error can arise is
  27. //! also useful for other reasons, like cross-referencing FAQs etc, though
  28. //! we are not really taking advantage of this yet.
  29. //!
  30. //! # Region Inference
  31. //!
  32. //! Region inference is particularly tricky because it always succeeds "in
  33. //! the moment" and simply registers a constraint. Then, at the end, we
  34. //! can compute the full graph and report errors, so we need to be able to
  35. //! store and later report what gave rise to the conflicting constraints.
  36. //!
  37. //! # Subtype Trace
  38. //!
  39. //! Determining whether `T1 <: T2` often involves a number of subtypes and
  40. //! subconstraints along the way. A "TypeTrace" is an extended version
  41. //! of an origin that traces the types and other values that were being
  42. //! compared. It is not necessarily comprehensive (in fact, at the time of
  43. //! this writing it only tracks the root values being compared) but I'd
  44. //! like to extend it to include significant "waypoints". For example, if
  45. //! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
  46. //! <: T4` fails, I'd like the trace to include enough information to say
  47. //! "in the 2nd element of the tuple". Similarly, failures when comparing
  48. //! arguments or return types in fn types should be able to cite the
  49. //! specific position, etc.
  50. //!
  51. //! # Reality vs plan
  52. //!
  53. //! Of course, there is still a LOT of code in typeck that has yet to be
  54. //! ported to this system, and which relies on string concatenation at the
  55. //! time of error detection.
  56. use self::FreshOrKept::*;
  57. use super::InferCtxt;
  58. use super::TypeTrace;
  59. use super::SubregionOrigin;
  60. use super::RegionVariableOrigin;
  61. use super::ValuePairs;
  62. use super::region_inference::RegionResolutionError;
  63. use super::region_inference::ConcreteFailure;
  64. use super::region_inference::SubSupConflict;
  65. use super::region_inference::SupSupConflict;
  66. use super::region_inference::GenericBoundFailure;
  67. use super::region_inference::GenericKind;
  68. use super::region_inference::ProcessedErrors;
  69. use super::region_inference::SameRegions;
  70. use std::collections::HashSet;
  71. use middle::def;
  72. use middle::infer;
  73. use middle::subst;
  74. use middle::ty::{self, Ty};
  75. use middle::ty::{Region, ReFree};
  76. use std::cell::{Cell, RefCell};
  77. use std::char::from_u32;
  78. use std::rc::Rc;
  79. use std::string::String;
  80. use syntax::ast;
  81. use syntax::ast_map;
  82. use syntax::ast_util::name_to_dummy_lifetime;
  83. use syntax::owned_slice::OwnedSlice;
  84. use syntax::codemap;
  85. use syntax::parse::token;
  86. use syntax::print::pprust;
  87. use syntax::ptr::P;
  88. use util::ppaux::bound_region_to_string;
  89. use util::ppaux::note_and_explain_region;
  90. // Note: only import UserString, not Repr, since user-facing error
  91. // messages shouldn't include debug serializations.
  92. use util::ppaux::UserString;
  93. pub trait ErrorReporting<'tcx> {
  94. fn report_region_errors(&self,
  95. errors: &Vec<RegionResolutionError<'tcx>>);
  96. fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
  97. -> Vec<RegionResolutionError<'tcx>>;
  98. fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>);
  99. fn report_and_explain_type_error(&self,
  100. trace: TypeTrace<'tcx>,
  101. terr: &ty::type_err<'tcx>);
  102. fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
  103. fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
  104. &self,
  105. exp_found: &ty::expected_found<T>)
  106. -> Option<String>;
  107. fn report_concrete_failure(&self,
  108. origin: SubregionOrigin<'tcx>,
  109. sub: Region,
  110. sup: Region);
  111. fn report_generic_bound_failure(&self,
  112. origin: SubregionOrigin<'tcx>,
  113. kind: GenericKind<'tcx>,
  114. sub: Region,
  115. sups: Vec<Region>);
  116. fn report_sub_sup_conflict(&self,
  117. var_origin: RegionVariableOrigin,
  118. sub_origin: SubregionOrigin<'tcx>,
  119. sub_region: Region,
  120. sup_origin: SubregionOrigin<'tcx>,
  121. sup_region: Region);
  122. fn report_sup_sup_conflict(&self,
  123. var_origin: RegionVariableOrigin,
  124. origin1: SubregionOrigin<'tcx>,
  125. region1: Region,
  126. origin2: SubregionOrigin<'tcx>,
  127. region2: Region);
  128. fn report_processed_errors(&self,
  129. var_origin: &[RegionVariableOrigin],
  130. trace_origin: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
  131. same_regions: &[SameRegions]);
  132. fn give_suggestion(&self, same_regions: &[SameRegions]);
  133. }
  134. trait ErrorReportingHelpers<'tcx> {
  135. fn report_inference_failure(&self,
  136. var_origin: RegionVariableOrigin);
  137. fn note_region_origin(&self,
  138. origin: &SubregionOrigin<'tcx>);
  139. fn give_expl_lifetime_param(&self,
  140. decl: &ast::FnDecl,
  141. unsafety: ast::Unsafety,
  142. ident: ast::Ident,
  143. opt_explicit_self: Option<&ast::ExplicitSelf_>,
  144. generics: &ast::Generics,
  145. span: codemap::Span);
  146. }
  147. impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
  148. fn report_region_errors(&self,
  149. errors: &Vec<RegionResolutionError<'tcx>>) {
  150. let p_errors = self.process_errors(errors);
  151. let errors = if p_errors.is_empty() { errors } else { &p_errors };
  152. for error in errors {
  153. match error.clone() {
  154. ConcreteFailure(origin, sub, sup) => {
  155. self.report_concrete_failure(origin, sub, sup);
  156. }
  157. GenericBoundFailure(kind, param_ty, sub, sups) => {
  158. self.report_generic_bound_failure(kind, param_ty, sub, sups);
  159. }
  160. SubSupConflict(var_origin,
  161. sub_origin, sub_r,
  162. sup_origin, sup_r) => {
  163. self.report_sub_sup_conflict(var_origin,
  164. sub_origin, sub_r,
  165. sup_origin, sup_r);
  166. }
  167. SupSupConflict(var_origin,
  168. origin1, r1,
  169. origin2, r2) => {
  170. self.report_sup_sup_conflict(var_origin,
  171. origin1, r1,
  172. origin2, r2);
  173. }
  174. ProcessedErrors(ref var_origins,
  175. ref trace_origins,
  176. ref same_regions) => {
  177. if !same_regions.is_empty() {
  178. self.report_processed_errors(&var_origins[..],
  179. &trace_origins[..],
  180. &same_regions[..]);
  181. }
  182. }
  183. }
  184. }
  185. }
  186. // This method goes through all the errors and try to group certain types
  187. // of error together, for the purpose of suggesting explicit lifetime
  188. // parameters to the user. This is done so that we can have a more
  189. // complete view of what lifetimes should be the same.
  190. // If the return value is an empty vector, it means that processing
  191. // failed (so the return value of this method should not be used)
  192. fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
  193. -> Vec<RegionResolutionError<'tcx>> {
  194. debug!("process_errors()");
  195. let mut var_origins = Vec::new();
  196. let mut trace_origins = Vec::new();
  197. let mut same_regions = Vec::new();
  198. let mut processed_errors = Vec::new();
  199. for error in errors {
  200. match error.clone() {
  201. ConcreteFailure(origin, sub, sup) => {
  202. debug!("processing ConcreteFailure");
  203. let trace = match origin {
  204. infer::Subtype(trace) => Some(trace),
  205. _ => None,
  206. };
  207. match free_regions_from_same_fn(self.tcx, sub, sup) {
  208. Some(ref same_frs) if trace.is_some() => {
  209. let trace = trace.unwrap();
  210. let terr = ty::terr_regions_does_not_outlive(sup,
  211. sub);
  212. trace_origins.push((trace, terr));
  213. append_to_same_regions(&mut same_regions, same_frs);
  214. }
  215. _ => processed_errors.push((*error).clone()),
  216. }
  217. }
  218. SubSupConflict(var_origin, _, sub_r, _, sup_r) => {
  219. debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub_r, sup_r);
  220. match free_regions_from_same_fn(self.tcx, sub_r, sup_r) {
  221. Some(ref same_frs) => {
  222. var_origins.push(var_origin);
  223. append_to_same_regions(&mut same_regions, same_frs);
  224. }
  225. None => processed_errors.push((*error).clone()),
  226. }
  227. }
  228. SupSupConflict(..) => processed_errors.push((*error).clone()),
  229. _ => () // This shouldn't happen
  230. }
  231. }
  232. if !same_regions.is_empty() {
  233. let common_scope_id = same_regions[0].scope_id;
  234. for sr in &same_regions {
  235. // Since ProcessedErrors is used to reconstruct the function
  236. // declaration, we want to make sure that they are, in fact,
  237. // from the same scope
  238. if sr.scope_id != common_scope_id {
  239. debug!("returning empty result from process_errors because
  240. {} != {}", sr.scope_id, common_scope_id);
  241. return vec!();
  242. }
  243. }
  244. let pe = ProcessedErrors(var_origins, trace_origins, same_regions);
  245. debug!("errors processed: {:?}", pe);
  246. processed_errors.push(pe);
  247. }
  248. return processed_errors;
  249. struct FreeRegionsFromSameFn {
  250. sub_fr: ty::FreeRegion,
  251. sup_fr: ty::FreeRegion,
  252. scope_id: ast::NodeId
  253. }
  254. impl FreeRegionsFromSameFn {
  255. fn new(sub_fr: ty::FreeRegion,
  256. sup_fr: ty::FreeRegion,
  257. scope_id: ast::NodeId)
  258. -> FreeRegionsFromSameFn {
  259. FreeRegionsFromSameFn {
  260. sub_fr: sub_fr,
  261. sup_fr: sup_fr,
  262. scope_id: scope_id
  263. }
  264. }
  265. }
  266. fn free_regions_from_same_fn(tcx: &ty::ctxt,
  267. sub: Region,
  268. sup: Region)
  269. -> Option<FreeRegionsFromSameFn> {
  270. debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
  271. let (scope_id, fr1, fr2) = match (sub, sup) {
  272. (ReFree(fr1), ReFree(fr2)) => {
  273. if fr1.scope != fr2.scope {
  274. return None
  275. }
  276. assert!(fr1.scope == fr2.scope);
  277. (fr1.scope.node_id, fr1, fr2)
  278. },
  279. _ => return None
  280. };
  281. let parent = tcx.map.get_parent(scope_id);
  282. let parent_node = tcx.map.find(parent);
  283. match parent_node {
  284. Some(node) => match node {
  285. ast_map::NodeItem(item) => match item.node {
  286. ast::ItemFn(..) => {
  287. Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
  288. },
  289. _ => None
  290. },
  291. ast_map::NodeImplItem(..) |
  292. ast_map::NodeTraitItem(..) => {
  293. Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
  294. },
  295. _ => None
  296. },
  297. None => {
  298. debug!("no parent node of scope_id {}", scope_id);
  299. None
  300. }
  301. }
  302. }
  303. fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
  304. same_frs: &FreeRegionsFromSameFn) {
  305. let scope_id = same_frs.scope_id;
  306. let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr);
  307. for sr in &mut *same_regions {
  308. if sr.contains(&sup_fr.bound_region)
  309. && scope_id == sr.scope_id {
  310. sr.push(sub_fr.bound_region);
  311. return
  312. }
  313. }
  314. same_regions.push(SameRegions {
  315. scope_id: scope_id,
  316. regions: vec!(sub_fr.bound_region, sup_fr.bound_region)
  317. })
  318. }
  319. }
  320. fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>) {
  321. let expected_found_str = match self.values_str(&trace.values) {
  322. Some(v) => v,
  323. None => {
  324. return; /* derived error */
  325. }
  326. };
  327. let message_root_str = match trace.origin {
  328. infer::Misc(_) => "mismatched types",
  329. infer::MethodCompatCheck(_) => "method not compatible with trait",
  330. infer::ExprAssignable(_) => "mismatched types",
  331. infer::RelateTraitRefs(_) => "mismatched traits",
  332. infer::RelateSelfType(_) => "mismatched types",
  333. infer::RelateOutputImplTypes(_) => "mismatched types",
  334. infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
  335. infer::IfExpression(_) => "if and else have incompatible types",
  336. infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
  337. infer::RangeExpression(_) => "start and end of range have incompatible types",
  338. infer::EquatePredicate(_) => "equality predicate not satisfied",
  339. };
  340. span_err!(self.tcx.sess, trace.origin.span(), E0308,
  341. "{}: {} ({})",
  342. message_root_str,
  343. expected_found_str,
  344. ty::type_err_to_str(self.tcx, terr));
  345. match trace.origin {
  346. infer::MatchExpressionArm(_, arm_span) =>
  347. self.tcx.sess.span_note(arm_span, "match arm with an incompatible type"),
  348. _ => ()
  349. }
  350. }
  351. fn report_and_explain_type_error(&self,
  352. trace: TypeTrace<'tcx>,
  353. terr: &ty::type_err<'tcx>) {
  354. self.report_type_error(trace, terr);
  355. ty::note_and_explain_type_err(self.tcx, terr);
  356. }
  357. /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
  358. /// error.
  359. fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
  360. match *values {
  361. infer::Types(ref exp_found) => self.expected_found_str(exp_found),
  362. infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
  363. infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
  364. }
  365. }
  366. fn expected_found_str<T: UserString<'tcx> + Resolvable<'tcx>>(
  367. &self,
  368. exp_found: &ty::expected_found<T>)
  369. -> Option<String>
  370. {
  371. let expected = exp_found.expected.resolve(self);
  372. if expected.contains_error() {
  373. return None;
  374. }
  375. let found = exp_found.found.resolve(self);
  376. if found.contains_error() {
  377. return None;
  378. }
  379. Some(format!("expected `{}`, found `{}`",
  380. expected.user_string(self.tcx),
  381. found.user_string(self.tcx)))
  382. }
  383. fn report_generic_bound_failure(&self,
  384. origin: SubregionOrigin<'tcx>,
  385. bound_kind: GenericKind<'tcx>,
  386. sub: Region,
  387. _sups: Vec<Region>)
  388. {
  389. // FIXME: it would be better to report the first error message
  390. // with the span of the parameter itself, rather than the span
  391. // where the error was detected. But that span is not readily
  392. // accessible.
  393. let labeled_user_string = match bound_kind {
  394. GenericKind::Param(ref p) =>
  395. format!("the parameter type `{}`", p.user_string(self.tcx)),
  396. GenericKind::Projection(ref p) =>
  397. format!("the associated type `{}`", p.user_string(self.tcx)),
  398. };
  399. match sub {
  400. ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
  401. // Does the required lifetime have a nice name we can print?
  402. span_err!(self.tcx.sess, origin.span(), E0309,
  403. "{} may not live long enough", labeled_user_string);
  404. self.tcx.sess.fileline_help(
  405. origin.span(),
  406. &format!(
  407. "consider adding an explicit lifetime bound `{}: {}`...",
  408. bound_kind.user_string(self.tcx),
  409. sub.user_string(self.tcx)));
  410. }
  411. ty::ReStatic => {
  412. // Does the required lifetime have a nice name we can print?
  413. span_err!(self.tcx.sess, origin.span(), E0310,
  414. "{} may not live long enough", labeled_user_string);
  415. self.tcx.sess.fileline_help(
  416. origin.span(),
  417. &format!(
  418. "consider adding an explicit lifetime bound `{}: 'static`...",
  419. bound_kind.user_string(self.tcx)));
  420. }
  421. _ => {
  422. // If not, be less specific.
  423. span_err!(self.tcx.sess, origin.span(), E0311,
  424. "{} may not live long enough",
  425. labeled_user_string);
  426. self.tcx.sess.fileline_help(
  427. origin.span(),
  428. &format!(
  429. "consider adding an explicit lifetime bound for `{}`",
  430. bound_kind.user_string(self.tcx)));
  431. note_and_explain_region(
  432. self.tcx,
  433. &format!("{} must be valid for ", labeled_user_string),
  434. sub,
  435. "...");
  436. }
  437. }
  438. self.note_region_origin(&origin);
  439. }
  440. fn report_concrete_failure(&self,
  441. origin: SubregionOrigin<'tcx>,
  442. sub: Region,
  443. sup: Region) {
  444. match origin {
  445. infer::Subtype(trace) => {
  446. let terr = ty::terr_regions_does_not_outlive(sup, sub);
  447. self.report_and_explain_type_error(trace, &terr);
  448. }
  449. infer::Reborrow(span) => {
  450. span_err!(self.tcx.sess, span, E0312,
  451. "lifetime of reference outlines \
  452. lifetime of borrowed content...");
  453. note_and_explain_region(
  454. self.tcx,
  455. "...the reference is valid for ",
  456. sub,
  457. "...");
  458. note_and_explain_region(
  459. self.tcx,
  460. "...but the borrowed content is only valid for ",
  461. sup,
  462. "");
  463. }
  464. infer::ReborrowUpvar(span, ref upvar_id) => {
  465. span_err!(self.tcx.sess, span, E0313,
  466. "lifetime of borrowed pointer outlives \
  467. lifetime of captured variable `{}`...",
  468. ty::local_var_name_str(self.tcx,
  469. upvar_id.var_id)
  470. .to_string());
  471. note_and_explain_region(
  472. self.tcx,
  473. "...the borrowed pointer is valid for ",
  474. sub,
  475. "...");
  476. note_and_explain_region(
  477. self.tcx,
  478. &format!("...but `{}` is only valid for ",
  479. ty::local_var_name_str(self.tcx,
  480. upvar_id.var_id)
  481. .to_string()),
  482. sup,
  483. "");
  484. }
  485. infer::InfStackClosure(span) => {
  486. span_err!(self.tcx.sess, span, E0314,
  487. "closure outlives stack frame");
  488. note_and_explain_region(
  489. self.tcx,
  490. "...the closure must be valid for ",
  491. sub,
  492. "...");
  493. note_and_explain_region(
  494. self.tcx,
  495. "...but the closure's stack frame is only valid for ",
  496. sup,
  497. "");
  498. }
  499. infer::InvokeClosure(span) => {
  500. span_err!(self.tcx.sess, span, E0315,
  501. "cannot invoke closure outside of its lifetime");
  502. note_and_explain_region(
  503. self.tcx,
  504. "the closure is only valid for ",
  505. sup,
  506. "");
  507. }
  508. infer::DerefPointer(span) => {
  509. self.tcx.sess.span_err(
  510. span,
  511. "dereference of reference outside its lifetime");
  512. note_and_explain_region(
  513. self.tcx,
  514. "the reference is only valid for ",
  515. sup,
  516. "");
  517. }
  518. infer::FreeVariable(span, id) => {
  519. self.tcx.sess.span_err(
  520. span,
  521. &format!("captured variable `{}` does not \
  522. outlive the enclosing closure",
  523. ty::local_var_name_str(self.tcx,
  524. id).to_string()));
  525. note_and_explain_region(
  526. self.tcx,
  527. "captured variable is valid for ",
  528. sup,
  529. "");
  530. note_and_explain_region(
  531. self.tcx,
  532. "closure is valid for ",
  533. sub,
  534. "");
  535. }
  536. infer::IndexSlice(span) => {
  537. self.tcx.sess.span_err(span,
  538. "index of slice outside its lifetime");
  539. note_and_explain_region(
  540. self.tcx,
  541. "the slice is only valid for ",
  542. sup,
  543. "");
  544. }
  545. infer::RelateObjectBound(span) => {
  546. self.tcx.sess.span_err(
  547. span,
  548. "lifetime of the source pointer does not outlive \
  549. lifetime bound of the object type");
  550. note_and_explain_region(
  551. self.tcx,
  552. "object type is valid for ",
  553. sub,
  554. "");
  555. note_and_explain_region(
  556. self.tcx,
  557. "source pointer is only valid for ",
  558. sup,
  559. "");
  560. }
  561. infer::RelateParamBound(span, ty) => {
  562. self.tcx.sess.span_err(
  563. span,
  564. &format!("the type `{}` does not fulfill the \
  565. required lifetime",
  566. self.ty_to_string(ty)));
  567. note_and_explain_region(self.tcx,
  568. "type must outlive ",
  569. sub,
  570. "");
  571. }
  572. infer::RelateRegionParamBound(span) => {
  573. self.tcx.sess.span_err(
  574. span,
  575. "lifetime bound not satisfied");
  576. note_and_explain_region(
  577. self.tcx,
  578. "lifetime parameter instantiated with ",
  579. sup,
  580. "");
  581. note_and_explain_region(
  582. self.tcx,
  583. "but lifetime parameter must outlive ",
  584. sub,
  585. "");
  586. }
  587. infer::RelateDefaultParamBound(span, ty) => {
  588. self.tcx.sess.span_err(
  589. span,
  590. &format!("the type `{}` (provided as the value of \
  591. a type parameter) is not valid at this point",
  592. self.ty_to_string(ty)));
  593. note_and_explain_region(self.tcx,
  594. "type must outlive ",
  595. sub,
  596. "");
  597. }
  598. infer::CallRcvr(span) => {
  599. self.tcx.sess.span_err(
  600. span,
  601. "lifetime of method receiver does not outlive \
  602. the method call");
  603. note_and_explain_region(
  604. self.tcx,
  605. "the receiver is only valid for ",
  606. sup,
  607. "");
  608. }
  609. infer::CallArg(span) => {
  610. self.tcx.sess.span_err(
  611. span,
  612. "lifetime of function argument does not outlive \
  613. the function call");
  614. note_and_explain_region(
  615. self.tcx,
  616. "the function argument is only valid for ",
  617. sup,
  618. "");
  619. }
  620. infer::CallReturn(span) => {
  621. self.tcx.sess.span_err(
  622. span,
  623. "lifetime of return value does not outlive \
  624. the function call");
  625. note_and_explain_region(
  626. self.tcx,
  627. "the return value is only valid for ",
  628. sup,
  629. "");
  630. }
  631. infer::Operand(span) => {
  632. self.tcx.sess.span_err(
  633. span,
  634. "lifetime of operand does not outlive \
  635. the operation");
  636. note_and_explain_region(
  637. self.tcx,
  638. "the operand is only valid for ",
  639. sup,
  640. "");
  641. }
  642. infer::AddrOf(span) => {
  643. self.tcx.sess.span_err(
  644. span,
  645. "reference is not valid \
  646. at the time of borrow");
  647. note_and_explain_region(
  648. self.tcx,
  649. "the borrow is only valid for ",
  650. sup,
  651. "");
  652. }
  653. infer::AutoBorrow(span) => {
  654. self.tcx.sess.span_err(
  655. span,
  656. "automatically reference is not valid \
  657. at the time of borrow");
  658. note_and_explain_region(
  659. self.tcx,
  660. "the automatic borrow is only valid for ",
  661. sup,
  662. "");
  663. }
  664. infer::ExprTypeIsNotInScope(t, span) => {
  665. self.tcx.sess.span_err(
  666. span,
  667. &format!("type of expression contains references \
  668. that are not valid during the expression: `{}`",
  669. self.ty_to_string(t)));
  670. note_and_explain_region(
  671. self.tcx,
  672. "type is only valid for ",
  673. sup,
  674. "");
  675. }
  676. infer::SafeDestructor(span) => {
  677. self.tcx.sess.span_err(
  678. span,
  679. "unsafe use of destructor: destructor might be called \
  680. while references are dead");
  681. // FIXME (22171): terms "super/subregion" are suboptimal
  682. note_and_explain_region(
  683. self.tcx,
  684. "superregion: ",
  685. sup,
  686. "");
  687. note_and_explain_region(
  688. self.tcx,
  689. "subregion: ",
  690. sub,
  691. "");
  692. }
  693. infer::BindingTypeIsNotValidAtDecl(span) => {
  694. self.tcx.sess.span_err(
  695. span,
  696. "lifetime of variable does not enclose its declaration");
  697. note_and_explain_region(
  698. self.tcx,
  699. "the variable is only valid for ",
  700. sup,
  701. "");
  702. }
  703. infer::ReferenceOutlivesReferent(ty, span) => {
  704. self.tcx.sess.span_err(
  705. span,
  706. &format!("in type `{}`, reference has a longer lifetime \
  707. than the data it references",
  708. self.ty_to_string(ty)));
  709. note_and_explain_region(
  710. self.tcx,
  711. "the pointer is valid for ",
  712. sub,
  713. "");
  714. note_and_explain_region(
  715. self.tcx,
  716. "but the referenced data is only valid for ",
  717. sup,
  718. "");
  719. }
  720. }
  721. }
  722. fn report_sub_sup_conflict(&self,
  723. var_origin: RegionVariableOrigin,
  724. sub_origin: SubregionOrigin<'tcx>,
  725. sub_region: Region,
  726. sup_origin: SubregionOrigin<'tcx>,
  727. sup_region: Region) {
  728. self.report_inference_failure(var_origin);
  729. note_and_explain_region(
  730. self.tcx,
  731. "first, the lifetime cannot outlive ",
  732. sup_region,
  733. "...");
  734. self.note_region_origin(&sup_origin);
  735. note_and_explain_region(
  736. self.tcx,
  737. "but, the lifetime must be valid for ",
  738. sub_region,
  739. "...");
  740. self.note_region_origin(&sub_origin);
  741. }
  742. fn report_sup_sup_conflict(&self,
  743. var_origin: RegionVariableOrigin,
  744. origin1: SubregionOrigin<'tcx>,
  745. region1: Region,
  746. origin2: SubregionOrigin<'tcx>,
  747. region2: Region) {
  748. self.report_inference_failure(var_origin);
  749. note_and_explain_region(
  750. self.tcx,
  751. "first, the lifetime must be contained by ",
  752. region1,
  753. "...");
  754. self.note_region_origin(&origin1);
  755. note_and_explain_region(
  756. self.tcx,
  757. "but, the lifetime must also be contained by ",
  758. region2,
  759. "...");
  760. self.note_region_origin(&origin2);
  761. }
  762. fn report_processed_errors(&self,
  763. var_origins: &[RegionVariableOrigin],
  764. trace_origins: &[(TypeTrace<'tcx>, ty::type_err<'tcx>)],
  765. same_regions: &[SameRegions]) {
  766. for vo in var_origins {
  767. self.report_inference_failure(vo.clone());
  768. }
  769. self.give_suggestion(same_regions);
  770. for &(ref trace, terr) in trace_origins {
  771. self.report_type_error(trace.clone(), &terr);
  772. }
  773. }
  774. fn give_suggestion(&self, same_regions: &[SameRegions]) {
  775. let scope_id = same_regions[0].scope_id;
  776. let parent = self.tcx.map.get_parent(scope_id);
  777. let parent_node = self.tcx.map.find(parent);
  778. let taken = lifetimes_in_scope(self.tcx, scope_id);
  779. let life_giver = LifeGiver::with_taken(&taken[..]);
  780. let node_inner = match parent_node {
  781. Some(ref node) => match *node {
  782. ast_map::NodeItem(ref item) => {
  783. match item.node {
  784. ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => {
  785. Some((fn_decl, gen, pur, item.ident, None, item.span))
  786. },
  787. _ => None
  788. }
  789. }
  790. ast_map::NodeImplItem(item) => {
  791. match item.node {
  792. ast::MethodImplItem(ref sig, _) => {
  793. Some((&sig.decl,
  794. &sig.generics,
  795. sig.unsafety,
  796. item.ident,
  797. Some(&sig.explicit_self.node),
  798. item.span))
  799. }
  800. ast::TypeImplItem(_) => None,
  801. ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro")
  802. }
  803. },
  804. ast_map::NodeTraitItem(item) => {
  805. match item.node {
  806. ast::MethodTraitItem(ref sig, Some(_)) => {
  807. Some((&sig.decl,
  808. &sig.generics,
  809. sig.unsafety,
  810. item.ident,
  811. Some(&sig.explicit_self.node),
  812. item.span))
  813. }
  814. _ => None
  815. }
  816. }
  817. _ => None
  818. },
  819. None => None
  820. };
  821. let (fn_decl, generics, unsafety, ident, expl_self, span)
  822. = node_inner.expect("expect item fn");
  823. let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
  824. generics, same_regions, &life_giver);
  825. let (fn_decl, expl_self, generics) = rebuilder.rebuild();
  826. self.give_expl_lifetime_param(&fn_decl, unsafety, ident,
  827. expl_self.as_ref(), &generics, span);
  828. }
  829. }
  830. struct RebuildPathInfo<'a> {
  831. path: &'a ast::Path,
  832. // indexes to insert lifetime on path.lifetimes
  833. indexes: Vec<u32>,
  834. // number of lifetimes we expect to see on the type referred by `path`
  835. // (e.g., expected=1 for struct Foo<'a>)
  836. expected: u32,
  837. anon_nums: &'a HashSet<u32>,
  838. region_names: &'a HashSet<ast::Name>
  839. }
  840. struct Rebuilder<'a, 'tcx: 'a> {
  841. tcx: &'a ty::ctxt<'tcx>,
  842. fn_decl: &'a ast::FnDecl,
  843. expl_self_opt: Option<&'a ast::ExplicitSelf_>,
  844. generics: &'a ast::Generics,
  845. same_regions: &'a [SameRegions],
  846. life_giver: &'a LifeGiver,
  847. cur_anon: Cell<u32>,
  848. inserted_anons: RefCell<HashSet<u32>>,
  849. }
  850. enum FreshOrKept {
  851. Fresh,
  852. Kept
  853. }
  854. impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
  855. fn new(tcx: &'a ty::ctxt<'tcx>,
  856. fn_decl: &'a ast::FnDecl,
  857. expl_self_opt: Option<&'a ast::ExplicitSelf_>,
  858. generics: &'a ast::Generics,
  859. same_regions: &'a [SameRegions],
  860. life_giver: &'a LifeGiver)
  861. -> Rebuilder<'a, 'tcx> {
  862. Rebuilder {
  863. tcx: tcx,
  864. fn_decl: fn_decl,
  865. expl_self_opt: expl_self_opt,
  866. generics: generics,
  867. same_regions: same_regions,
  868. life_giver: life_giver,
  869. cur_anon: Cell::new(0),
  870. inserted_anons: RefCell::new(HashSet::new()),
  871. }
  872. }
  873. fn rebuild(&self)
  874. -> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
  875. let mut expl_self_opt = self.expl_self_opt.cloned();
  876. let mut inputs = self.fn_decl.inputs.clone();
  877. let mut output = self.fn_decl.output.clone();
  878. let mut ty_params = self.generics.ty_params.clone();
  879. let where_clause = self.generics.where_clause.clone();
  880. let mut kept_lifetimes = HashSet::new();
  881. for sr in self.same_regions {
  882. self.cur_anon.set(0);
  883. self.offset_cur_anon();
  884. let (anon_nums, region_names) =
  885. self.extract_anon_nums_and_names(sr);
  886. let (lifetime, fresh_or_kept) = self.pick_lifetime(&region_names);
  887. match fresh_or_kept {
  888. Kept => { kept_lifetimes.insert(lifetime.name); }
  889. _ => ()
  890. }
  891. expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime,
  892. &anon_nums, &region_names);
  893. inputs = self.rebuild_args_ty(&inputs[..], lifetime,
  894. &anon_nums, &region_names);
  895. output = self.rebuild_output(&output, lifetime, &anon_nums, &region_names);
  896. ty_params = self.rebuild_ty_params(ty_params, lifetime,
  897. &region_names);
  898. }
  899. let fresh_lifetimes = self.life_giver.get_generated_lifetimes();
  900. let all_region_names = self.extract_all_region_names();
  901. let generics = self.rebuild_generics(self.generics,
  902. &fresh_lifetimes,
  903. &kept_lifetimes,
  904. &all_region_names,
  905. ty_params,
  906. where_clause);
  907. let new_fn_decl = ast::FnDecl {
  908. inputs: inputs,
  909. output: output,
  910. variadic: self.fn_decl.variadic
  911. };
  912. (new_fn_decl, expl_self_opt, generics)
  913. }
  914. fn pick_lifetime(&self,
  915. region_names: &HashSet<ast::Name>)
  916. -> (ast::Lifetime, FreshOrKept) {
  917. if region_names.len() > 0 {
  918. // It's not necessary to convert the set of region names to a
  919. // vector of string and then sort them. However, it makes the
  920. // choice of lifetime name deterministic and thus easier to test.
  921. let mut names = Vec::new();
  922. for rn in region_names {
  923. let lt_name = token::get_name(*rn).to_string();
  924. names.push(lt_name);
  925. }
  926. names.sort();
  927. let name = token::str_to_ident(&names[0]).name;
  928. return (name_to_dummy_lifetime(name), Kept);
  929. }
  930. return (self.life_giver.give_lifetime(), Fresh);
  931. }
  932. fn extract_anon_nums_and_names(&self, same_regions: &SameRegions)
  933. -> (HashSet<u32>, HashSet<ast::Name>) {
  934. let mut anon_nums = HashSet::new();
  935. let mut region_names = HashSet::new();
  936. for br in &same_regions.regions {
  937. match *br {
  938. ty::BrAnon(i) => {
  939. anon_nums.insert(i);
  940. }
  941. ty::BrNamed(_, name) => {
  942. region_names.insert(name);
  943. }
  944. _ => ()
  945. }
  946. }
  947. (anon_nums, region_names)
  948. }
  949. fn extract_all_region_names(&self) -> HashSet<ast::Name> {
  950. let mut all_region_names = HashSet::new();
  951. for sr in self.same_regions {
  952. for br in &sr.regions {
  953. match *br {
  954. ty::BrNamed(_, name) => {
  955. all_region_names.insert(name);
  956. }
  957. _ => ()
  958. }
  959. }
  960. }
  961. all_region_names
  962. }
  963. fn inc_cur_anon(&self, n: u32) {
  964. let anon = self.cur_anon.get();
  965. self.cur_anon.set(anon+n);
  966. }
  967. fn offset_cur_anon(&self) {
  968. let mut anon = self.cur_anon.get();
  969. while self.inserted_anons.borrow().contains(&anon) {
  970. anon += 1;
  971. }
  972. self.cur_anon.set(anon);
  973. }
  974. fn inc_and_offset_cur_anon(&self, n: u32) {
  975. self.inc_cur_anon(n);
  976. self.offset_cur_anon();
  977. }
  978. fn track_anon(&self, anon: u32) {
  979. self.inserted_anons.borrow_mut().insert(anon);
  980. }
  981. fn rebuild_ty_params(&self,
  982. ty_params: OwnedSlice<ast::TyParam>,
  983. lifetime: ast::Lifetime,
  984. region_names: &HashSet<ast::Name>)
  985. -> OwnedSlice<ast::TyParam> {
  986. ty_params.map(|ty_param| {
  987. let bounds = self.rebuild_ty_param_bounds(ty_param.bounds.clone(),
  988. lifetime,
  989. region_names);
  990. ast::TyParam {
  991. ident: ty_param.ident,
  992. id: ty_param.id,
  993. bounds: bounds,
  994. default: ty_param.default.clone(),
  995. span: ty_param.span,
  996. }
  997. })
  998. }
  999. fn rebuild_ty_param_bounds(&self,
  1000. ty_param_bounds: OwnedSlice<ast::TyParamBound>,
  1001. lifetime: ast::Lifetime,
  1002. region_names: &HashSet<ast::Name>)
  1003. -> OwnedSlice<ast::TyParamBound> {
  1004. ty_param_bounds.map(|tpb| {
  1005. match tpb {
  1006. &ast::RegionTyParamBound(lt) => {
  1007. // FIXME -- it's unclear whether I'm supposed to
  1008. // substitute lifetime here. I suspect we need to
  1009. // be passing down a map.
  1010. ast::RegionTyParamBound(lt)
  1011. }
  1012. &ast::TraitTyParamBound(ref poly_tr, modifier) => {
  1013. let tr = &poly_tr.trait_ref;
  1014. let last_seg = tr.path.segments.last().unwrap();
  1015. let mut insert = Vec::new();
  1016. let lifetimes = last_seg.parameters.lifetimes();
  1017. for (i, lt) in lifetimes.iter().enumerate() {
  1018. if region_names.contains(&lt.name) {
  1019. insert.push(i as u32);
  1020. }
  1021. }
  1022. let rebuild_info = RebuildPathInfo {
  1023. path: &tr.path,
  1024. indexes: insert,
  1025. expected: lifetimes.len() as u32,
  1026. anon_nums: &HashSet::new(),
  1027. region_names: region_names
  1028. };
  1029. let new_path = self.rebuild_path(rebuild_info, lifetime);
  1030. ast::TraitTyParamBound(ast::PolyTraitRef {
  1031. bound_lifetimes: poly_tr.bound_lifetimes.clone(),
  1032. trait_ref: ast::TraitRef {
  1033. path: new_path,
  1034. ref_id: tr.ref_id,
  1035. },
  1036. span: poly_tr.span,
  1037. }, modifier)
  1038. }
  1039. }
  1040. })
  1041. }
  1042. fn rebuild_expl_self(&self,
  1043. expl_self_opt: Option<ast::ExplicitSelf_>,
  1044. lifetime: ast::Lifetime,
  1045. anon_nums: &HashSet<u32>,
  1046. region_names: &HashSet<ast::Name>)
  1047. -> Option<ast::ExplicitSelf_> {
  1048. match expl_self_opt {
  1049. Some(ref expl_self) => match *expl_self {
  1050. ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
  1051. Some(lt) => if region_names.contains(&lt.name) {
  1052. return Some(ast::SelfRegion(Some(lifetime), muta, id));
  1053. },
  1054. None => {
  1055. let anon = self.cur_anon.get();
  1056. self.inc_and_offset_cur_anon(1);
  1057. if anon_nums.contains(&anon) {
  1058. self.track_anon(anon);
  1059. return Some(ast::SelfRegion(Some(lifetime), muta, id));
  1060. }
  1061. }
  1062. },
  1063. _ => ()
  1064. },
  1065. None => ()
  1066. }
  1067. expl_self_opt
  1068. }
  1069. fn rebuild_generics(&self,
  1070. generics: &ast::Generics,
  1071. add: &Vec<ast::Lifetime>,
  1072. keep: &HashSet<ast::Name>,
  1073. remove: &HashSet<ast::Name>,
  1074. ty_params: OwnedSlice<ast::TyParam>,
  1075. where_clause: ast::WhereClause)
  1076. -> ast::Generics {
  1077. let mut lifetimes = Vec::new();
  1078. for lt in add {
  1079. lifetimes.push(ast::LifetimeDef { lifetime: *lt,
  1080. bounds: Vec::new() });
  1081. }
  1082. for lt in &generics.lifetimes {
  1083. if keep.contains(&lt.lifetime.name) ||
  1084. !remove.contains(&lt.lifetime.name) {
  1085. lifetimes.push((*lt).clone());
  1086. }
  1087. }
  1088. ast::Generics {
  1089. lifetimes: lifetimes,
  1090. ty_params: ty_params,
  1091. where_clause: where_clause,
  1092. }
  1093. }
  1094. fn rebuild_args_ty(&self,
  1095. inputs: &[ast::Arg],
  1096. lifetime: ast::Lifetime,
  1097. anon_nums: &HashSet<u32>,
  1098. region_names: &HashSet<ast::Name>)
  1099. -> Vec<ast::Arg> {
  1100. let mut new_inputs = Vec::new();
  1101. for arg in inputs {
  1102. let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime,
  1103. anon_nums, region_names);
  1104. let possibly_new_arg = ast::Arg {
  1105. ty: new_ty,
  1106. pat: arg.pat.clone(),
  1107. id: arg.id
  1108. };
  1109. new_inputs.push(possibly_new_arg);
  1110. }
  1111. new_inputs
  1112. }
  1113. fn rebuild_output(&self, ty: &ast::FunctionRetTy,
  1114. lifetime: ast::Lifetime,
  1115. anon_nums: &HashSet<u32>,
  1116. region_names: &HashSet<ast::Name>) -> ast::FunctionRetTy {
  1117. match *ty {
  1118. ast::Return(ref ret_ty) => ast::Return(
  1119. self.rebuild_arg_ty_or_output(&**ret_ty, lifetime, anon_nums, region_names)
  1120. ),
  1121. ast::DefaultReturn(span) => ast::DefaultReturn(span),
  1122. ast::NoReturn(span) => ast::NoReturn(span)
  1123. }
  1124. }
  1125. fn rebuild_arg_ty_or_output(&self,
  1126. ty: &ast::Ty,
  1127. lifetime: ast::Lifetime,
  1128. anon_nums: &HashSet<u32>,
  1129. region_names: &HashSet<ast::Name>)
  1130. -> P<ast::Ty> {
  1131. let mut new_ty = P(ty.clone());
  1132. let mut ty_queue = vec!(ty);
  1133. while !ty_queue.is_empty() {
  1134. let cur_ty = ty_queue.remove(0);
  1135. match cur_ty.node {
  1136. ast::TyRptr(lt_opt, ref mut_ty) => {
  1137. let rebuild = match lt_opt {
  1138. Some(lt) => region_names.contains(&lt.name),
  1139. None => {
  1140. let anon = self.cur_anon.get();
  1141. let rebuild = anon_nums.contains(&anon);
  1142. if rebuild {
  1143. self.track_anon(anon);
  1144. }
  1145. self.inc_and_offset_cur_anon(1);
  1146. rebuild
  1147. }
  1148. };
  1149. if rebuild {
  1150. let to = ast::Ty {
  1151. id: cur_ty.id,
  1152. node: ast::TyRptr(Some(lifetime), mut_ty.clone()),
  1153. span: cur_ty.span
  1154. };
  1155. new_ty = self.rebuild_ty(new_ty, P(to));
  1156. }
  1157. ty_queue.push(&*mut_ty.ty);
  1158. }
  1159. ast::TyPath(ref maybe_qself, ref path) => {
  1160. let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) {
  1161. None => {
  1162. self.tcx
  1163. .sess
  1164. .fatal(&format!(
  1165. "unbound path {}",
  1166. pprust::path_to_string(path)))
  1167. }
  1168. Some(d) => d.full_def()
  1169. };
  1170. match a_def {
  1171. def::DefTy(did, _) | def::DefStruct(did) => {
  1172. let generics = ty::lookup_item_type(self.tcx, did).generics;
  1173. let expected =
  1174. generics.regions.len(subst::TypeSpace) as u32;
  1175. let lifetimes =
  1176. path.segments.last().unwrap().parameters.lifetimes();
  1177. let mut insert = Vec::new();
  1178. if lifetimes.len() == 0 {
  1179. let anon = self.cur_anon.get();
  1180. for (i, a) in (anon..anon+expected).enumerate() {
  1181. if anon_nums.contains(&a) {
  1182. insert.push(i as u32);
  1183. }
  1184. self.track_anon(a);
  1185. }
  1186. self.inc_and_offset_cur_anon(expected);
  1187. } else {
  1188. for (i, lt) in lifetimes.iter().enumerate() {
  1189. if region_names.contains(&lt.name) {
  1190. insert.push(i as u32);
  1191. }
  1192. }
  1193. }
  1194. let rebuild_info = RebuildPathInfo {
  1195. path: path,
  1196. indexes: insert,
  1197. expected: expected,
  1198. anon_nums: anon_nums,
  1199. region_names: region_names
  1200. };
  1201. let new_path = self.rebuild_path(rebuild_info, lifetime);
  1202. let qself = maybe_qself.as_ref().map(|qself| {
  1203. ast::QSelf {
  1204. ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
  1205. anon_nums, region_names),
  1206. position: qself.position
  1207. }
  1208. });
  1209. let to = ast::Ty {
  1210. id: cur_ty.id,
  1211. node: ast::TyPath(qself, new_path),
  1212. span: cur_ty.span
  1213. };
  1214. new_ty = self.rebuild_ty(new_ty, P(to));
  1215. }
  1216. _ => ()
  1217. }
  1218. }
  1219. ast::TyPtr(ref mut_ty) => {
  1220. ty_queue.push(&*mut_ty.ty);
  1221. }
  1222. ast::TyVec(ref ty) |
  1223. ast::TyFixedLengthVec(ref ty, _) => {
  1224. ty_queue.push(&**ty);
  1225. }
  1226. ast::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
  1227. _ => {}
  1228. }
  1229. }
  1230. new_ty
  1231. }
  1232. fn rebuild_ty(&self,
  1233. from: P<ast::Ty>,
  1234. to: P<ast::Ty>)
  1235. -> P<ast::Ty> {
  1236. fn build_to(from: P<ast::Ty>,
  1237. to: &mut Option<P<ast::Ty>>)
  1238. -> P<ast::Ty> {
  1239. if Some(from.id) == to.as_ref().map(|ty| ty.id) {
  1240. return to.take().expect("`to` type found more than once during rebuild");
  1241. }
  1242. from.map(|ast::Ty {id, node, span}| {
  1243. let new_node = match node {
  1244. ast::TyRptr(lifetime, mut_ty) => {
  1245. ast::TyRptr(lifetime, ast::MutTy {
  1246. mutbl: mut_ty.mutbl,
  1247. ty: build_to(mut_ty.ty, to),
  1248. })
  1249. }
  1250. ast::TyPtr(mut_ty) => {
  1251. ast::TyPtr(ast::MutTy {
  1252. mutbl: mut_ty.mutbl,
  1253. ty: build_to(mut_ty.ty, to),
  1254. })
  1255. }
  1256. ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
  1257. ast::TyFixedLengthVec(ty, e) => {
  1258. ast::TyFixedLengthVec(build_to(ty, to), e)
  1259. }
  1260. ast::TyTup(tys) => {
  1261. ast::TyTup(tys.into_iter().map(|ty| build_to(ty, to)).collect())
  1262. }
  1263. ast::TyParen(typ) => ast::TyParen(build_to(typ, to)),
  1264. other => other
  1265. };
  1266. ast::Ty { id: id, node: new_node, span: span }
  1267. })
  1268. }
  1269. build_to(from, &mut Some(to))
  1270. }
  1271. fn rebuild_path(&self,
  1272. rebuild_info: RebuildPathInfo,
  1273. lifetime: ast::Lifetime)
  1274. -> ast::Path
  1275. {
  1276. let RebuildPathInfo {
  1277. path,
  1278. indexes,
  1279. expected,
  1280. anon_nums,
  1281. region_names,
  1282. } = rebuild_info;
  1283. let last_seg = path.segments.last().unwrap();
  1284. let new_parameters = match last_seg.parameters {
  1285. ast::ParenthesizedParameters(..) => {
  1286. last_seg.parameters.clone()
  1287. }
  1288. ast::AngleBracketedParameters(ref data) => {
  1289. let mut new_lts = Vec::new();
  1290. if data.lifetimes.len() == 0 {
  1291. // traverse once to see if there's a need to insert lifetime
  1292. let need_insert = (0..expected).any(|i| {
  1293. indexes.contains(&i)
  1294. });
  1295. if need_insert {
  1296. for i in 0..expected {
  1297. if indexes.contains(&i) {
  1298. new_lts.push(lifetime);
  1299. } else {
  1300. new_lts.push(self.life_giver.give_lifetime());
  1301. }
  1302. }
  1303. }
  1304. } else {
  1305. for (i, lt) in data.lifetimes.iter().enumerate() {
  1306. if indexes.contains(&(i as u32)) {
  1307. new_lts.push(lifetime);
  1308. } else {
  1309. new_lts.push(*lt);
  1310. }
  1311. }
  1312. }
  1313. let new_types = data.types.map(|t| {
  1314. self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
  1315. });
  1316. let new_bindings = data.bindings.map(|b| {
  1317. P(ast::TypeBinding {
  1318. id: b.id,
  1319. ident: b.ident,
  1320. ty: self.rebuild_arg_ty_or_output(&*b.ty,
  1321. lifetime,
  1322. anon_nums,
  1323. region_names),
  1324. span: b.span
  1325. })
  1326. });
  1327. ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
  1328. lifetimes: new_lts,
  1329. types: new_types,
  1330. bindings: new_bindings,
  1331. })
  1332. }
  1333. };
  1334. let new_seg = ast::PathSegment {
  1335. identifier: last_seg.identifier,
  1336. parameters: new_parameters
  1337. };
  1338. let mut new_segs = Vec::new();
  1339. new_segs.push_all(path.segments.init());
  1340. new_segs.push(new_seg);
  1341. ast::Path {
  1342. span: path.span,
  1343. global: path.global,
  1344. segments: new_segs
  1345. }
  1346. }
  1347. }
  1348. impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
  1349. fn give_expl_lifetime_param(&self,
  1350. decl: &ast::FnDecl,
  1351. unsafety: ast::Unsafety,
  1352. ident: ast::Ident,
  1353. opt_explicit_self: Option<&ast::ExplicitSelf_>,
  1354. generics: &ast::Generics,
  1355. span: codemap::Span) {
  1356. let suggested_fn = pprust::fun_to_string(decl, unsafety, ident,
  1357. opt_explicit_self, generics);
  1358. let msg = format!("consider using an explicit lifetime \
  1359. parameter as shown: {}", suggested_fn);
  1360. self.tcx.sess.span_help(span, &msg[..]);
  1361. }
  1362. fn report_inference_failure(&self,
  1363. var_origin: RegionVariableOrigin) {
  1364. let var_description = match var_origin {
  1365. infer::MiscVariable(_) => "".to_string(),
  1366. infer::PatternRegion(_) => " for pattern".to_string(),
  1367. infer::AddrOfRegion(_) => " for borrow expression".to_string(),
  1368. infer::Autoref(_) => " for autoref".to_string(),
  1369. infer::Coercion(_) => " for automatic coercion".to_string(),
  1370. infer::LateBoundRegion(_, br, infer::FnCall) => {
  1371. format!(" for {}in function call",
  1372. bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
  1373. }
  1374. infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
  1375. format!(" for {}in generic type",
  1376. bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
  1377. }
  1378. infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
  1379. format!(" for {}in trait containing associated type `{}`",
  1380. bound_region_to_string(self.tcx, "lifetime parameter ", true, br),
  1381. token::get_name(type_name))
  1382. }
  1383. infer::EarlyBoundRegion(_, name) => {
  1384. format!(" for lifetime parameter `{}`",
  1385. &token::get_name(name))
  1386. }
  1387. infer::BoundRegionInCoherence(name) => {
  1388. format!(" for lifetime parameter `{}` in coherence check",
  1389. &token::get_name(name))
  1390. }
  1391. infer::UpvarRegion(ref upvar_id, _) => {
  1392. format!(" for capture of `{}` by closure",
  1393. ty::local_var_name_str(self.tcx, upvar_id.var_id).to_string())
  1394. }
  1395. };
  1396. self.tcx.sess.span_err(
  1397. var_origin.span(),
  1398. &format!("cannot infer an appropriate lifetime{} \
  1399. due to conflicting requirements",
  1400. var_description));
  1401. }
  1402. fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
  1403. match *origin {
  1404. infer::Subtype(ref trace) => {
  1405. let desc = match trace.origin {
  1406. infer::Misc(_) => {
  1407. format!("types are compatible")
  1408. }
  1409. infer::MethodCompatCheck(_) => {
  1410. format!("method type is compatible with trait")
  1411. }
  1412. infer::ExprAssignable(_) => {
  1413. format!("expression is assignable")
  1414. }
  1415. infer::RelateTraitRefs(_) => {
  1416. format!("traits are compatible")
  1417. }
  1418. infer::RelateSelfType(_) => {
  1419. format!("self type matches impl self type")
  1420. }
  1421. infer::RelateOutputImplTypes(_) => {
  1422. format!("trait type parameters matches those \
  1423. specified on the impl")
  1424. }
  1425. infer::MatchExpressionArm(_, _) => {
  1426. format!("match arms have compatible types")
  1427. }
  1428. infer::IfExpression(_) => {
  1429. format!("if and else have compatible types")
  1430. }
  1431. infer::IfExpressionWithNoElse(_) => {
  1432. format!("if may be missing an else clause")
  1433. }
  1434. infer::RangeExpression(_) => {
  1435. format!("start and end of range have compatible types")
  1436. }
  1437. infer::EquatePredicate(_) => {
  1438. format!("equality where clause is satisfied")
  1439. }
  1440. };
  1441. match self.values_str(&trace.values) {
  1442. Some(values_str) => {
  1443. self.tcx.sess.span_note(
  1444. trace.origin.span(),
  1445. &format!("...so that {} ({})",
  1446. desc, values_str));
  1447. }
  1448. None => {
  1449. // Really should avoid printing this error at
  1450. // all, since it is derived, but that would
  1451. // require more refactoring than I feel like
  1452. // doing right now. - nmatsakis
  1453. self.tcx.sess.span_note(
  1454. trace.origin.span(),
  1455. &format!("...so that {}", desc));
  1456. }
  1457. }
  1458. }
  1459. infer::Reborrow(span) => {
  1460. self.tcx.sess.span_note(
  1461. span,
  1462. "...so that reference does not outlive \
  1463. borrowed content");
  1464. }
  1465. infer::ReborrowUpvar(span, ref upvar_id) => {
  1466. self.tcx.sess.span_note(
  1467. span,
  1468. &format!(
  1469. "...so that closure can access `{}`",
  1470. ty::local_var_name_str(self.tcx, upvar_id.var_id)
  1471. .to_string()))
  1472. }
  1473. infer::InfStackClosure(span) => {
  1474. self.tcx.sess.span_note(
  1475. span,
  1476. "...so that closure does not outlive its stack frame");
  1477. }
  1478. infer::InvokeClosure(span) => {
  1479. self.tcx.sess.span_note(
  1480. span,
  1481. "...so that closure is not invoked outside its lifetime");
  1482. }
  1483. infer::DerefPointer(span) => {
  1484. self.tcx.sess.span_note(
  1485. span,
  1486. "...so that pointer is not dereferenced \
  1487. outside its lifetime");
  1488. }
  1489. infer::FreeVariable(span, id) => {
  1490. self.tcx.sess.span_note(
  1491. span,
  1492. &format!("...so that captured variable `{}` \
  1493. does not outlive the enclosing closure",
  1494. ty::local_var_name_str(
  1495. self.tcx,
  1496. id).to_string()));
  1497. }
  1498. infer::IndexSlice(span) => {
  1499. self.tcx.sess.span_note(
  1500. span,
  1501. "...so that slice is not indexed outside the lifetime");
  1502. }
  1503. infer::RelateObjectBound(span) => {
  1504. self.tcx.sess.span_note(
  1505. span,
  1506. "...so that it can be closed over into an object");
  1507. }
  1508. infer::CallRcvr(span) => {
  1509. self.tcx.sess.span_note(
  1510. span,
  1511. "...so that method receiver is valid for the method call");
  1512. }
  1513. infer::CallArg(span) => {
  1514. self.tcx.sess.span_note(
  1515. span,
  1516. "...so that argument is valid for the call");
  1517. }
  1518. infer::CallReturn(span) => {
  1519. self.tcx.sess.span_note(
  1520. span,
  1521. "...so that return value is valid for the call");
  1522. }
  1523. infer::Operand(span) => {
  1524. self.tcx.sess.span_err(
  1525. span,
  1526. "...so that operand is valid for operation");
  1527. }
  1528. infer::AddrOf(span) => {
  1529. self.tcx.sess.span_note(
  1530. span,
  1531. "...so that reference is valid \
  1532. at the time of borrow");
  1533. }
  1534. infer::AutoBorrow(span) => {
  1535. self.tcx.sess.span_note(
  1536. span,
  1537. "...so that auto-reference is valid \
  1538. at the time of borrow");
  1539. }
  1540. infer::ExprTypeIsNotInScope(t, span) => {
  1541. self.tcx.sess.span_note(
  1542. span,
  1543. &format!("...so type `{}` of expression is valid during the \
  1544. expression",
  1545. self.ty_to_string(t)));
  1546. }
  1547. infer::BindingTypeIsNotValidAtDecl(span) => {
  1548. self.tcx.sess.span_note(
  1549. span,
  1550. "...so that variable is valid at time of its declaration");
  1551. }
  1552. infer::ReferenceOutlivesReferent(ty, span) => {
  1553. self.tcx.sess.span_note(
  1554. span,
  1555. &format!("...so that the reference type `{}` \
  1556. does not outlive the data it points at",
  1557. self.ty_to_string(ty)));
  1558. }
  1559. infer::RelateParamBound(span, t) => {
  1560. self.tcx.sess.span_note(
  1561. span,
  1562. &format!("...so that the type `{}` \
  1563. will meet its required lifetime bounds",
  1564. self.ty_to_string(t)));
  1565. }
  1566. infer::RelateDefaultParamBound(span, t) => {
  1567. self.tcx.sess.span_note(
  1568. span,
  1569. &format!("...so that type parameter \
  1570. instantiated with `{}`, \
  1571. will meet its declared lifetime bounds",
  1572. self.ty_to_string(t)));
  1573. }
  1574. infer::RelateRegionParamBound(span) => {
  1575. self.tcx.sess.span_note(
  1576. span,
  1577. &format!("...so that the declared lifetime parameter bounds \
  1578. are satisfied"));
  1579. }
  1580. infer::SafeDestructor(span) => {
  1581. self.tcx.sess.span_note(
  1582. span,
  1583. "...so that references are valid when the destructor \
  1584. runs")
  1585. }
  1586. }
  1587. }
  1588. }
  1589. pub trait Resolvable<'tcx> {
  1590. fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Self;
  1591. fn contains_error(&self) -> bool;
  1592. }
  1593. impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
  1594. fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Ty<'tcx> {
  1595. infcx.resolve_type_vars_if_possible(self)
  1596. }
  1597. fn contains_error(&self) -> bool {
  1598. ty::type_is_error(*self)
  1599. }
  1600. }
  1601. impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
  1602. fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
  1603. -> Rc<ty::TraitRef<'tcx>> {
  1604. Rc::new(infcx.resolve_type_vars_if_possible(&**self))
  1605. }
  1606. fn contains_error(&self) -> bool {
  1607. ty::trait_ref_contains_error(&**self)
  1608. }
  1609. }
  1610. impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
  1611. fn resolve<'a>(&self,
  1612. infcx: &InferCtxt<'a, 'tcx>)
  1613. -> ty::PolyTraitRef<'tcx>
  1614. {
  1615. infcx.resolve_type_vars_if_possible(self)
  1616. }
  1617. fn contains_error(&self) -> bool {
  1618. ty::trait_ref_contains_error(&*self.0)
  1619. }
  1620. }
  1621. fn lifetimes_in_scope(tcx: &ty::ctxt,
  1622. scope_id: ast::NodeId)
  1623. -> Vec<ast::LifetimeDef> {
  1624. let mut taken = Vec::new();
  1625. let parent = tcx.map.get_parent(scope_id);
  1626. let method_id_opt = match tcx.map.find(parent) {
  1627. Some(node) => match node {
  1628. ast_map::NodeItem(item) => match item.node {
  1629. ast::ItemFn(_, _, _, ref gen, _) => {
  1630. taken.push_all(&gen.lifetimes);
  1631. None
  1632. },
  1633. _ => None
  1634. },
  1635. ast_map::NodeImplItem(ii) => {
  1636. match ii.node {
  1637. ast::MethodImplItem(ref sig, _) => {
  1638. taken.push_all(&sig.generics.lifetimes);
  1639. Some(ii.id)
  1640. }
  1641. ast::TypeImplItem(_) => None,
  1642. ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro")
  1643. }
  1644. }
  1645. _ => None
  1646. },
  1647. None => None
  1648. };
  1649. if method_id_opt.is_some() {
  1650. let method_id = method_id_opt.unwrap();
  1651. let parent = tcx.map.get_parent(method_id);
  1652. match tcx.map.find(parent) {
  1653. Some(node) => match node {
  1654. ast_map::NodeItem(item) => match item.node {
  1655. ast::ItemImpl(_, _, ref gen, _, _, _) => {
  1656. taken.push_all(&gen.lifetimes);
  1657. }
  1658. _ => ()
  1659. },
  1660. _ => ()
  1661. },
  1662. None => ()
  1663. }
  1664. }
  1665. return taken;
  1666. }
  1667. // LifeGiver is responsible for generating fresh lifetime names
  1668. struct LifeGiver {
  1669. taken: HashSet<String>,
  1670. counter: Cell<uint>,
  1671. generated: RefCell<Vec<ast::Lifetime>>,
  1672. }
  1673. impl LifeGiver {
  1674. fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
  1675. let mut taken_ = HashSet::new();
  1676. for lt in taken {
  1677. let lt_name = token::get_name(lt.lifetime.name).to_string();
  1678. taken_.insert(lt_name);
  1679. }
  1680. LifeGiver {
  1681. taken: taken_,
  1682. counter: Cell::new(0),
  1683. generated: RefCell::new(Vec::new()),
  1684. }
  1685. }
  1686. fn inc_counter(&self) {
  1687. let c = self.counter.get();
  1688. self.counter.set(c+1);
  1689. }
  1690. fn give_lifetime(&self) -> ast::Lifetime {
  1691. let mut lifetime;
  1692. loop {
  1693. let mut s = String::from_str("'");
  1694. s.push_str(&num_to_string(self.counter.get()));
  1695. if !self.taken.contains(&s) {
  1696. lifetime = name_to_dummy_lifetime(
  1697. token::str_to_ident(&s[..]).name);
  1698. self.generated.borrow_mut().push(lifetime);
  1699. break;
  1700. }
  1701. self.inc_counter();
  1702. }
  1703. self.inc_counter();
  1704. return lifetime;
  1705. // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on
  1706. fn num_to_string(counter: uint) -> String {
  1707. let mut s = String::new();
  1708. let (n, r) = (counter/26 + 1, counter % 26);
  1709. let letter: char = from_u32((r+97) as u32).unwrap();
  1710. for _ in 0..n {
  1711. s.push(letter);
  1712. }
  1713. s
  1714. }
  1715. }
  1716. fn get_generated_lifetimes(&self) -> Vec<ast::Lifetime> {
  1717. self.generated.borrow().clone()
  1718. }
  1719. }