Skip to content

Create different inference variables for different defining uses of TAITs #86118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 9, 2021
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