Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub mod thin_vec;
pub mod tiny_list;
pub mod transitive_relation;
pub mod vec_linked_list;
pub mod vec_map;
pub mod work_queue;
pub use atomic_ref::AtomicRef;
pub mod frozen;
Expand Down
155 changes: 155 additions & 0 deletions compiler/rustc_data_structures/src/vec_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use std::borrow::Borrow;
use std::iter::FromIterator;
use std::slice::{Iter, IterMut};
use std::vec::IntoIter;

use crate::stable_hasher::{HashStable, StableHasher};

/// A map type implemented as a vector of pairs `K` (key) and `V` (value).
/// It currently provides a subset of all the map operations, the rest could be added as needed.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct VecMap<K, V>(Vec<(K, V)>);

impl<K, V> VecMap<K, V>
where
K: PartialEq,
{
pub fn new() -> Self {
VecMap(Default::default())
}

/// Sets the value of the entry, and returns the entry's old value.
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) {
Some(std::mem::replace(&mut elem.1, v))
} else {
self.0.push((k, v));
None
}
}

/// Gets a reference to the value in the entry.
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Eq,
{
self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
}

/// Returns the value corresponding to the supplied predicate filter.
///
/// The supplied predicate will be applied to each (key, value) pair and it will return a
/// reference to the values where the predicate returns `true`.
pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
}

/// Returns `true` if the map contains a value for the specified key.
///
/// The key may be any borrowed form of the map's key type,
/// [`Eq`] on the borrowed form *must* match those for
/// the key type.
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Eq,
{
self.get(k).is_some()
}

/// Returns `true` if the map contains no elements.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub fn iter(&self) -> Iter<'_, (K, V)> {
self.into_iter()
}

pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
self.into_iter()
}
}

impl<K, V> Default for VecMap<K, V> {
#[inline]
fn default() -> Self {
Self(Default::default())
}
}

impl<K, V> From<Vec<(K, V)>> for VecMap<K, V> {
fn from(vec: Vec<(K, V)>) -> Self {
Self(vec)
}
}

impl<K, V> Into<Vec<(K, V)>> for VecMap<K, V> {
fn into(self) -> Vec<(K, V)> {
self.0
}
}

impl<K, V> FromIterator<(K, V)> for VecMap<K, V> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}

impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
type Item = &'a (K, V);
type IntoIter = Iter<'a, (K, V)>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
type Item = &'a mut (K, V);
type IntoIter = IterMut<'a, (K, V)>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}

impl<K, V> IntoIterator for VecMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<(K, V)>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

impl<K, V> Extend<(K, V)> for VecMap<K, V> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
self.0.extend(iter);
}

fn extend_one(&mut self, item: (K, V)) {
self.0.extend_one(item);
}

fn extend_reserve(&mut self, additional: usize) {
self.0.extend_reserve(additional);
}
}

impl<K, V, CTX> HashStable<CTX> for VecMap<K, V>
where
K: HashStable<CTX> + Eq,
V: HashStable<CTX>,
{
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
self.0.hash_stable(hcx, hasher)
}
}

#[cfg(test)]
mod tests;
48 changes: 48 additions & 0 deletions compiler/rustc_data_structures/src/vec_map/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use super::*;

impl<K, V> VecMap<K, V> {
fn into_vec(self) -> Vec<(K, V)> {
self.0.into()
}
}

#[test]
fn test_from_iterator() {
assert_eq!(
std::iter::empty().collect::<VecMap<i32, bool>>().into_vec(),
Vec::<(i32, bool)>::new()
);
assert_eq!(std::iter::once((42, true)).collect::<VecMap<_, _>>().into_vec(), vec![(42, true)]);
assert_eq!(
vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>().into_vec(),
vec![(1, true), (2, false)]
);
}

#[test]
fn test_into_iterator_owned() {
assert_eq!(VecMap::new().into_iter().collect::<Vec<(i32, bool)>>(), Vec::<(i32, bool)>::new());
assert_eq!(VecMap::from(vec![(1, true)]).into_iter().collect::<Vec<_>>(), vec![(1, true)]);
assert_eq!(
VecMap::from(vec![(1, true), (2, false)]).into_iter().collect::<Vec<_>>(),
vec![(1, true), (2, false)]
);
}

#[test]
fn test_insert() {
let mut v = VecMap::new();
assert_eq!(v.insert(1, true), None);
assert_eq!(v.insert(2, false), None);
assert_eq!(v.clone().into_vec(), vec![(1, true), (2, false)]);
assert_eq!(v.insert(1, false), Some(true));
assert_eq!(v.into_vec(), vec![(1, false), (2, false)]);
}

#[test]
fn test_get() {
let v = vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>();
assert_eq!(v.get(&1), Some(&true));
assert_eq!(v.get(&2), Some(&false));
assert_eq!(v.get(&3), None);
}
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

use crate::mir::{abstract_const, Body, Promoted};
use crate::ty::{self, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::OpaqueTypeKey;
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
Expand Down Expand Up @@ -210,7 +211,7 @@ pub struct BorrowCheckResult<'tcx> {
/// All the opaque types that are restricted to concrete types
/// by this function. Unlike the value in `TypeckResults`, this has
/// unerased regions.
pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
pub used_mut_upvars: SmallVec<[Field; 8]>,
}
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
Expand All @@ -47,6 +48,7 @@ use rustc_hir::{
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::OpaqueTypeKey;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint};
Expand Down Expand Up @@ -286,17 +288,6 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
}
}

/// All information necessary to validate and reveal an `impl Trait`.
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
pub struct ResolvedOpaqueTy<'tcx> {
/// The revealed type as seen by this function.
pub concrete_type: Ty<'tcx>,
/// Generic parameters on the opaque type as passed by this function.
/// For `type Foo<A, B> = impl Bar<A, B>; fn foo<T, U>() -> Foo<T, U> { .. }`
/// this is `[T, U]`, not `[A, B]`.
pub substs: SubstsRef<'tcx>,
}

/// Whenever a value may be live across a generator yield, the type of that value winds up in the
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
/// captured types that can be useful for diagnostics. In particular, it stores the span that
Expand Down Expand Up @@ -424,7 +415,7 @@ pub struct TypeckResults<'tcx> {

/// All the opaque types that are restricted to concrete types
/// by this function.
pub concrete_opaque_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,

/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
Lift, ResolvedOpaqueTy, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
};
pub use self::instance::{Instance, InstanceDef};
pub use self::list::List;
Expand Down Expand Up @@ -835,6 +835,12 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
pub struct OpaqueTypeKey<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
}

rustc_index::newtype_index! {
/// "Universes" are used during type- and trait-checking in the
/// presence of `for<..>` binders to control what sets of names are
Expand Down
9 changes: 4 additions & 5 deletions compiler/rustc_mir/src/borrow_check/nll.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
//! The entry point of the NLL borrow checker.

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::DefId;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::{
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
Promoted,
};
use rustc_middle::ty::{self, RegionKind, RegionVid};
use rustc_middle::ty::{self, OpaqueTypeKey, RegionKind, RegionVid, Ty};
use rustc_span::symbol::sym;
use std::env;
use std::fmt::Debug;
Expand Down Expand Up @@ -47,7 +46,7 @@ crate type PoloniusOutput = Output<RustcFacts>;
/// closure requirements to propagate, and any generated errors.
crate struct NllOutput<'tcx> {
pub regioncx: RegionInferenceContext<'tcx>,
pub opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
pub polonius_output: Option<Rc<PoloniusOutput>>,
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
pub nll_errors: RegionErrors<'tcx>,
Expand Down Expand Up @@ -367,7 +366,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
opaque_type_values: &FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
errors_buffer: &mut Vec<Diagnostic>,
) {
let tcx = infcx.tcx;
Expand Down
22 changes: 10 additions & 12 deletions compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_data_structures::vec_map::VecMap;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::opaque_types::InferCtxtExt;

Expand Down Expand Up @@ -51,12 +50,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(in crate::borrow_check) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
span: Span,
) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
opaque_ty_decls
.into_iter()
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
.map(|(opaque_type_key, concrete_type)| {
let substs = opaque_type_key.substs;
debug!(?concrete_type, ?substs);

let mut subst_regions = vec![self.universal_regions.fr_static];
Expand Down Expand Up @@ -110,16 +110,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {

debug!(?universal_concrete_type, ?universal_substs);

let opaque_type_key =
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
opaque_def_id,
universal_substs,
opaque_type_key,
universal_concrete_type,
span,
);
(
opaque_def_id,
ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
)
(opaque_type_key, remapped_type)
})
.collect()
}
Expand Down
Loading