Skip to content

Commit c4b5406

Browse files
committed
Auto merge of #86118 - spastorino:tait-soundness-bug, r=nikomatsakis
Create different inference variables for different defining uses of TAITs Fixes #73481 r? `@nikomatsakis` cc `@oli-obk`
2 parents d45d205 + 7b1e1c7 commit c4b5406

File tree

21 files changed

+439
-132
lines changed

21 files changed

+439
-132
lines changed

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub mod thin_vec;
9696
pub mod tiny_list;
9797
pub mod transitive_relation;
9898
pub mod vec_linked_list;
99+
pub mod vec_map;
99100
pub mod work_queue;
100101
pub use atomic_ref::AtomicRef;
101102
pub mod frozen;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use std::borrow::Borrow;
2+
use std::iter::FromIterator;
3+
use std::slice::{Iter, IterMut};
4+
use std::vec::IntoIter;
5+
6+
use crate::stable_hasher::{HashStable, StableHasher};
7+
8+
/// A map type implemented as a vector of pairs `K` (key) and `V` (value).
9+
/// It currently provides a subset of all the map operations, the rest could be added as needed.
10+
#[derive(Clone, Encodable, Decodable, Debug)]
11+
pub struct VecMap<K, V>(Vec<(K, V)>);
12+
13+
impl<K, V> VecMap<K, V>
14+
where
15+
K: PartialEq,
16+
{
17+
pub fn new() -> Self {
18+
VecMap(Default::default())
19+
}
20+
21+
/// Sets the value of the entry, and returns the entry's old value.
22+
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
23+
if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) {
24+
Some(std::mem::replace(&mut elem.1, v))
25+
} else {
26+
self.0.push((k, v));
27+
None
28+
}
29+
}
30+
31+
/// Gets a reference to the value in the entry.
32+
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
33+
where
34+
K: Borrow<Q>,
35+
Q: Eq,
36+
{
37+
self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
38+
}
39+
40+
/// Returns the value corresponding to the supplied predicate filter.
41+
///
42+
/// The supplied predicate will be applied to each (key, value) pair and it will return a
43+
/// reference to the values where the predicate returns `true`.
44+
pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
45+
self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
46+
}
47+
48+
/// Returns `true` if the map contains a value for the specified key.
49+
///
50+
/// The key may be any borrowed form of the map's key type,
51+
/// [`Eq`] on the borrowed form *must* match those for
52+
/// the key type.
53+
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
54+
where
55+
K: Borrow<Q>,
56+
Q: Eq,
57+
{
58+
self.get(k).is_some()
59+
}
60+
61+
/// Returns `true` if the map contains no elements.
62+
pub fn is_empty(&self) -> bool {
63+
self.0.is_empty()
64+
}
65+
66+
pub fn iter(&self) -> Iter<'_, (K, V)> {
67+
self.into_iter()
68+
}
69+
70+
pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
71+
self.into_iter()
72+
}
73+
}
74+
75+
impl<K, V> Default for VecMap<K, V> {
76+
#[inline]
77+
fn default() -> Self {
78+
Self(Default::default())
79+
}
80+
}
81+
82+
impl<K, V> From<Vec<(K, V)>> for VecMap<K, V> {
83+
fn from(vec: Vec<(K, V)>) -> Self {
84+
Self(vec)
85+
}
86+
}
87+
88+
impl<K, V> Into<Vec<(K, V)>> for VecMap<K, V> {
89+
fn into(self) -> Vec<(K, V)> {
90+
self.0
91+
}
92+
}
93+
94+
impl<K, V> FromIterator<(K, V)> for VecMap<K, V> {
95+
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
96+
Self(iter.into_iter().collect())
97+
}
98+
}
99+
100+
impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
101+
type Item = &'a (K, V);
102+
type IntoIter = Iter<'a, (K, V)>;
103+
104+
#[inline]
105+
fn into_iter(self) -> Self::IntoIter {
106+
self.0.iter()
107+
}
108+
}
109+
110+
impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
111+
type Item = &'a mut (K, V);
112+
type IntoIter = IterMut<'a, (K, V)>;
113+
114+
#[inline]
115+
fn into_iter(self) -> Self::IntoIter {
116+
self.0.iter_mut()
117+
}
118+
}
119+
120+
impl<K, V> IntoIterator for VecMap<K, V> {
121+
type Item = (K, V);
122+
type IntoIter = IntoIter<(K, V)>;
123+
124+
#[inline]
125+
fn into_iter(self) -> Self::IntoIter {
126+
self.0.into_iter()
127+
}
128+
}
129+
130+
impl<K, V> Extend<(K, V)> for VecMap<K, V> {
131+
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
132+
self.0.extend(iter);
133+
}
134+
135+
fn extend_one(&mut self, item: (K, V)) {
136+
self.0.extend_one(item);
137+
}
138+
139+
fn extend_reserve(&mut self, additional: usize) {
140+
self.0.extend_reserve(additional);
141+
}
142+
}
143+
144+
impl<K, V, CTX> HashStable<CTX> for VecMap<K, V>
145+
where
146+
K: HashStable<CTX> + Eq,
147+
V: HashStable<CTX>,
148+
{
149+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
150+
self.0.hash_stable(hcx, hasher)
151+
}
152+
}
153+
154+
#[cfg(test)]
155+
mod tests;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use super::*;
2+
3+
impl<K, V> VecMap<K, V> {
4+
fn into_vec(self) -> Vec<(K, V)> {
5+
self.0.into()
6+
}
7+
}
8+
9+
#[test]
10+
fn test_from_iterator() {
11+
assert_eq!(
12+
std::iter::empty().collect::<VecMap<i32, bool>>().into_vec(),
13+
Vec::<(i32, bool)>::new()
14+
);
15+
assert_eq!(std::iter::once((42, true)).collect::<VecMap<_, _>>().into_vec(), vec![(42, true)]);
16+
assert_eq!(
17+
vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>().into_vec(),
18+
vec![(1, true), (2, false)]
19+
);
20+
}
21+
22+
#[test]
23+
fn test_into_iterator_owned() {
24+
assert_eq!(VecMap::new().into_iter().collect::<Vec<(i32, bool)>>(), Vec::<(i32, bool)>::new());
25+
assert_eq!(VecMap::from(vec![(1, true)]).into_iter().collect::<Vec<_>>(), vec![(1, true)]);
26+
assert_eq!(
27+
VecMap::from(vec![(1, true), (2, false)]).into_iter().collect::<Vec<_>>(),
28+
vec![(1, true), (2, false)]
29+
);
30+
}
31+
32+
#[test]
33+
fn test_insert() {
34+
let mut v = VecMap::new();
35+
assert_eq!(v.insert(1, true), None);
36+
assert_eq!(v.insert(2, false), None);
37+
assert_eq!(v.clone().into_vec(), vec![(1, true), (2, false)]);
38+
assert_eq!(v.insert(1, false), Some(true));
39+
assert_eq!(v.into_vec(), vec![(1, false), (2, false)]);
40+
}
41+
42+
#[test]
43+
fn test_get() {
44+
let v = vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>();
45+
assert_eq!(v.get(&1), Some(&true));
46+
assert_eq!(v.get(&2), Some(&false));
47+
assert_eq!(v.get(&3), None);
48+
}

compiler/rustc_middle/src/mir/query.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
33
use crate::mir::{abstract_const, Body, Promoted};
44
use crate::ty::{self, Ty, TyCtxt};
5-
use rustc_data_structures::fx::FxHashMap;
65
use rustc_data_structures::sync::Lrc;
6+
use rustc_data_structures::vec_map::VecMap;
77
use rustc_errors::ErrorReported;
88
use rustc_hir as hir;
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_index::bit_set::BitMatrix;
1111
use rustc_index::vec::IndexVec;
12+
use rustc_middle::ty::OpaqueTypeKey;
1213
use rustc_span::Span;
1314
use rustc_target::abi::VariantIdx;
1415
use smallvec::SmallVec;
@@ -210,7 +211,7 @@ pub struct BorrowCheckResult<'tcx> {
210211
/// All the opaque types that are restricted to concrete types
211212
/// by this function. Unlike the value in `TypeckResults`, this has
212213
/// unerased regions.
213-
pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
214+
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
214215
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
215216
pub used_mut_upvars: SmallVec<[Field; 8]>,
216217
}

compiler/rustc_middle/src/ty/context.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
3434
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3535
use rustc_data_structures::steal::Steal;
3636
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
37+
use rustc_data_structures::vec_map::VecMap;
3738
use rustc_errors::ErrorReported;
3839
use rustc_hir as hir;
3940
use rustc_hir::def::{DefKind, Res};
@@ -47,6 +48,7 @@ use rustc_hir::{
4748
use rustc_index::vec::{Idx, IndexVec};
4849
use rustc_macros::HashStable;
4950
use rustc_middle::mir::FakeReadCause;
51+
use rustc_middle::ty::OpaqueTypeKey;
5052
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
5153
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
5254
use rustc_session::lint::{Level, Lint};
@@ -286,17 +288,6 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
286288
}
287289
}
288290

289-
/// All information necessary to validate and reveal an `impl Trait`.
290-
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
291-
pub struct ResolvedOpaqueTy<'tcx> {
292-
/// The revealed type as seen by this function.
293-
pub concrete_type: Ty<'tcx>,
294-
/// Generic parameters on the opaque type as passed by this function.
295-
/// For `type Foo<A, B> = impl Bar<A, B>; fn foo<T, U>() -> Foo<T, U> { .. }`
296-
/// this is `[T, U]`, not `[A, B]`.
297-
pub substs: SubstsRef<'tcx>,
298-
}
299-
300291
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
301292
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
302293
/// captured types that can be useful for diagnostics. In particular, it stores the span that
@@ -424,7 +415,7 @@ pub struct TypeckResults<'tcx> {
424415

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

429420
/// Tracks the minimum captures required for a closure;
430421
/// see `MinCaptureInformationMap` for more details.

compiler/rustc_middle/src/ty/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval
5858
pub use self::context::{
5959
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
6060
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
61-
Lift, ResolvedOpaqueTy, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
61+
Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
6262
};
6363
pub use self::instance::{Instance, InstanceDef};
6464
pub use self::list::List;
@@ -835,6 +835,12 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
835835
}
836836
}
837837

838+
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
839+
pub struct OpaqueTypeKey<'tcx> {
840+
pub def_id: DefId,
841+
pub substs: SubstsRef<'tcx>,
842+
}
843+
838844
rustc_index::newtype_index! {
839845
/// "Universes" are used during type- and trait-checking in the
840846
/// presence of `for<..>` binders to control what sets of names are

compiler/rustc_mir/src/borrow_check/nll.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
//! The entry point of the NLL borrow checker.
22
3-
use rustc_data_structures::fx::FxHashMap;
3+
use rustc_data_structures::vec_map::VecMap;
44
use rustc_errors::Diagnostic;
5-
use rustc_hir::def_id::DefId;
65
use rustc_index::vec::IndexVec;
76
use rustc_infer::infer::InferCtxt;
87
use rustc_middle::mir::{
98
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
109
Promoted,
1110
};
12-
use rustc_middle::ty::{self, RegionKind, RegionVid};
11+
use rustc_middle::ty::{self, OpaqueTypeKey, RegionKind, RegionVid, Ty};
1312
use rustc_span::symbol::sym;
1413
use std::env;
1514
use std::fmt::Debug;
@@ -47,7 +46,7 @@ crate type PoloniusOutput = Output<RustcFacts>;
4746
/// closure requirements to propagate, and any generated errors.
4847
crate struct NllOutput<'tcx> {
4948
pub regioncx: RegionInferenceContext<'tcx>,
50-
pub opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
49+
pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
5150
pub polonius_output: Option<Rc<PoloniusOutput>>,
5251
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
5352
pub nll_errors: RegionErrors<'tcx>,
@@ -367,7 +366,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
367366
body: &Body<'tcx>,
368367
regioncx: &RegionInferenceContext<'tcx>,
369368
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
370-
opaque_type_values: &FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
369+
opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
371370
errors_buffer: &mut Vec<Diagnostic>,
372371
) {
373372
let tcx = infcx.tcx;

compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use rustc_data_structures::fx::FxHashMap;
2-
use rustc_hir::def_id::DefId;
1+
use rustc_data_structures::vec_map::VecMap;
32
use rustc_infer::infer::InferCtxt;
4-
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
3+
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
54
use rustc_span::Span;
65
use rustc_trait_selection::opaque_types::InferCtxtExt;
76

@@ -51,12 +50,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5150
pub(in crate::borrow_check) fn infer_opaque_types(
5251
&self,
5352
infcx: &InferCtxt<'_, 'tcx>,
54-
opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
53+
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
5554
span: Span,
56-
) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
55+
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
5756
opaque_ty_decls
5857
.into_iter()
59-
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
58+
.map(|(opaque_type_key, concrete_type)| {
59+
let substs = opaque_type_key.substs;
6060
debug!(?concrete_type, ?substs);
6161

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

111111
debug!(?universal_concrete_type, ?universal_substs);
112112

113+
let opaque_type_key =
114+
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
113115
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
114-
opaque_def_id,
115-
universal_substs,
116+
opaque_type_key,
116117
universal_concrete_type,
117118
span,
118119
);
119-
(
120-
opaque_def_id,
121-
ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
122-
)
120+
(opaque_type_key, remapped_type)
123121
})
124122
.collect()
125123
}

0 commit comments

Comments
 (0)