Skip to content

Commit

Permalink
Fixed rust-lang#30.
Browse files Browse the repository at this point in the history
A stack overflow was caused by circular references in analyzed item
types, since mismatch computation didn't keep track of item pairs
*currently being matched*. This is now fixed using two sets of old and
new types.
  • Loading branch information
ibabushkin committed Oct 4, 2017
1 parent 32cb8fa commit c7a0687
Showing 1 changed file with 17 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/semcheck/mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc::ty::subst::Substs;

use semcheck::mapping::IdMapping;

use std::collections::{HashMap, VecDeque};
use std::collections::{HashMap, HashSet, VecDeque};

/// A relation searching for items appearing at the same spot in a type.
///
Expand All @@ -27,6 +27,10 @@ pub struct MismatchRelation<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
item_queue: VecDeque<(DefId, DefId)>,
/// The id mapping to use.
id_mapping: &'a mut IdMapping,
/// Type cache holding all old types currently being processed to avoid loops.
current_old_types: HashSet<Ty<'tcx>>,
/// Type cache holding all new types currently being processed to avoid loops.
current_new_types: HashSet<Ty<'tcx>>,
}

impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> {
Expand All @@ -37,6 +41,8 @@ impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> MismatchRelation<'a, 'gcx, 'tcx> {
tcx: tcx,
item_queue: id_mapping.toplevel_queue(),
id_mapping: id_mapping,
current_old_types: Default::default(),
current_new_types: Default::default(),
}
}

Expand Down Expand Up @@ -100,6 +106,13 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx,
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
use rustc::ty::TypeVariants::*;

if self.current_old_types.contains(a) || self.current_new_types.contains(b) {
return Ok(self.tcx.types.err);
}

self.current_old_types.insert(a);
self.current_new_types.insert(b);

debug!("tys: mismatch relation: a: {:?}, b: {:?}", a, b);
let matching = match (&a.sty, &b.sty) {
(&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) => {
Expand Down Expand Up @@ -193,6 +206,9 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for MismatchRelation<'a, 'gcx,
_ => None,
};

self.current_old_types.remove(a);
self.current_new_types.remove(b);

if let Some((old_def_id, new_def_id)) = matching {
if !self.id_mapping.contains_old_id(old_def_id) &&
self.id_mapping.in_old_crate(old_def_id) {
Expand Down

0 comments on commit c7a0687

Please sign in to comment.