From: Niko Matsakis Date: Fri, 28 Apr 2017 13:41:01 +0000 (-0400) Subject: introduce `IntoKeyValues` trait to prepare for multi-queries X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3d1095c5bea7bbdc4b150425482ac4d526a4bb76;p=rust.git introduce `IntoKeyValues` trait to prepare for multi-queries The idea is that such queries will return `FxHashMap` --- diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index e653392e3fb..f2bfd23b189 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -24,8 +24,12 @@ use ty::subst::Substs; use util::nodemap::{DefIdSet, NodeSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::IndexVec; use std::cell::{RefCell, RefMut}; +use std::fmt::Debug; +use std::hash::Hash; +use std::iter::{self, Once}; use std::mem; use std::collections::BTreeMap; use std::ops::Deref; @@ -33,7 +37,7 @@ use syntax_pos::{Span, DUMMY_SP}; use syntax::symbol::Symbol; -trait Key: Clone { +trait Key: Clone + Hash + Eq + Debug { fn map_crate(&self) -> CrateNum; fn default_span(&self, tcx: TyCtxt) -> Span; } @@ -156,6 +160,33 @@ fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self { } } +trait IntoKeyValues { + type KeyValues: IntoIterator; + + fn into_key_values(tcx: TyCtxt, key: &K, value: Self) -> Self::KeyValues; +} + +impl IntoKeyValues for V { + type KeyValues = Once<(K, V)>; + + fn into_key_values(_: TyCtxt, key: &K, value: Self) -> Self::KeyValues { + iter::once((key.clone(), value)) + } +} + +impl IntoKeyValues for FxHashMap { + type KeyValues = Self; + + fn into_key_values(tcx: TyCtxt, key: &K, value: Self) -> Self { + if !value.contains_key(key) { + span_bug!(key.default_span(tcx), + "multi-generation function for `{:?}` did not generate a value for `{:?}`", + key, key) + } + value + } +} + pub struct CycleError<'a, 'tcx: 'a> { span: Span, cycle: RefMut<'a, [(Span, Query<'tcx>)]>, @@ -437,7 +468,14 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, provider(tcx.global_tcx(), key) })?; - Ok(f(&tcx.maps.$name.borrow_mut().entry(key).or_insert(result))) + { + let map = &mut *tcx.maps.$name.borrow_mut(); + for (k, v) in IntoKeyValues::<$K, $V>::into_key_values(tcx, &key, result) { + map.insert(k, v); + } + } + + Ok(f(tcx.maps.$name.borrow().get(&key).expect("value just generated"))) } pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)