From aa7024b0c7034c75d36ebe9048d12480c8d0bae2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 4 Jun 2021 10:05:27 -0300 Subject: [PATCH 01/18] Add VecMap to rustc_data_structures --- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_data_structures/src/vec_map.rs | 137 ++++++++++++++++++ .../src/vec_map/tests.rs | 48 ++++++ 3 files changed, 186 insertions(+) create mode 100644 compiler/rustc_data_structures/src/vec_map.rs create mode 100644 compiler/rustc_data_structures/src/vec_map/tests.rs diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index a8b9f479f1e9e..bbfe225e23ebf 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -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; diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs new file mode 100644 index 0000000000000..eca4ff212acae --- /dev/null +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -0,0 +1,137 @@ +use std::borrow::Borrow; +use std::iter::FromIterator; +use std::slice::{Iter, IterMut}; +use std::vec::IntoIter; + +use crate::stable_hasher::{HashStable, StableHasher}; + +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct VecMap(Vec<(K, V)>); + +impl VecMap +where + K: PartialEq, +{ + pub fn new() -> Self { + VecMap(Default::default()) + } + + pub fn insert(&mut self, k: K, v: V) -> Option { + 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 + } + } + + pub fn get(&self, k: &Q) -> Option<&V> + where + K: Borrow, + Q: Eq, + { + self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) + } + + pub fn contains_key(&self, k: &Q) -> bool + where + K: Borrow, + Q: Eq, + { + self.get(k).is_some() + } + + 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 Default for VecMap { + #[inline] + fn default() -> Self { + Self(Default::default()) + } +} + +impl From> for VecMap { + fn from(vec: Vec<(K, V)>) -> Self { + Self(vec) + } +} + +impl Into> for VecMap { + fn into(self) -> Vec<(K, V)> { + self.0 + } +} + +impl FromIterator<(K, V)> for VecMap { + fn from_iter>(iter: I) -> Self { + Self(iter.into_iter().collect()) + } +} + +impl<'a, K, V> IntoIterator for &'a VecMap { + 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 { + type Item = &'a mut (K, V); + type IntoIter = IterMut<'a, (K, V)>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.0.iter_mut() + } +} + +impl IntoIterator for VecMap { + type Item = (K, V); + type IntoIter = IntoIter<(K, V)>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl Extend<(K, V)> for VecMap { + fn extend>(&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 HashStable for VecMap +where + K: HashStable + Eq, + V: HashStable, +{ + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + self.0.hash_stable(hcx, hasher) + } +} + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/vec_map/tests.rs b/compiler/rustc_data_structures/src/vec_map/tests.rs new file mode 100644 index 0000000000000..9083de85982e7 --- /dev/null +++ b/compiler/rustc_data_structures/src/vec_map/tests.rs @@ -0,0 +1,48 @@ +use super::*; + +impl VecMap { + fn into_vec(self) -> Vec<(K, V)> { + self.0.into() + } +} + +#[test] +fn test_from_iterator() { + assert_eq!( + std::iter::empty().collect::>().into_vec(), + Vec::<(i32, bool)>::new() + ); + assert_eq!(std::iter::once((42, true)).collect::>().into_vec(), vec![(42, true)]); + assert_eq!( + vec![(1, true), (2, false)].into_iter().collect::>().into_vec(), + vec![(1, true), (2, false)] + ); +} + +#[test] +fn test_into_iterator_owned() { + assert_eq!(VecMap::new().into_iter().collect::>(), Vec::<(i32, bool)>::new()); + assert_eq!(VecMap::from(vec![(1, true)]).into_iter().collect::>(), vec![(1, true)]); + assert_eq!( + VecMap::from(vec![(1, true), (2, false)]).into_iter().collect::>(), + 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::>(); + assert_eq!(v.get(&1), Some(&true)); + assert_eq!(v.get(&2), Some(&false)); + assert_eq!(v.get(&3), None); +} From 2bc723fbcaa1c1136793dd92f1b4307335184007 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 4 Jun 2021 16:15:31 -0300 Subject: [PATCH 02/18] Change opaque type map to be a `VecMap` --- compiler/rustc_mir/src/borrow_check/type_check/mod.rs | 2 +- compiler/rustc_trait_selection/src/opaque_types.rs | 9 +++++---- compiler/rustc_typeck/src/check/inherited.rs | 5 +++-- compiler/rustc_typeck/src/check/writeback.rs | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index e294f128f2e14..4b9569b74b904 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1281,7 +1281,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .eq(output_ty, revealed_ty)?, ); - for (&opaque_def_id, opaque_decl) in &opaque_type_map { + for &(opaque_def_id, opaque_decl) in &opaque_type_map { let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty); let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { *def_id == opaque_def_id diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 163df26e9ffaf..2fdb267d0db8f 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -2,8 +2,9 @@ use crate::infer::InferCtxtExt as _; use crate::traits::{self, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::Node; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::free_regions::FreeRegionRelations; @@ -16,7 +17,7 @@ use rustc_span::Span; use std::ops::ControlFlow; -pub type OpaqueTypeMap<'tcx> = DefIdMap>; +pub type OpaqueTypeMap<'tcx> = VecMap>; /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that @@ -370,10 +371,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { debug!("constrain_opaque_types()"); - for (&def_id, opaque_defn) in opaque_types { + for &(def_id, opaque_defn) in opaque_types { self.constrain_opaque_type( def_id, - opaque_defn, + &opaque_defn, GenerateMemberConstraints::WhenRequired, free_region_relations, ); diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 1dacbade1bd32..0ff9bed749c75 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -2,8 +2,9 @@ use super::callee::DeferredCallResolution; use super::MaybeInProgressTables; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_hir::def_id::{DefIdMap, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; use rustc_infer::infer; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; @@ -58,7 +59,7 @@ pub struct Inherited<'a, 'tcx> { // associated fresh inference variable. Writeback resolves these // variables to get the concrete type, which can be used to // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions. - pub(super) opaque_types: RefCell>>, + pub(super) opaque_types: RefCell>>, /// A map from inference variables created from opaque /// type instantiations (`ty::Infer`) to the actual opaque diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index e472add6e80f3..685f81b3bd6a5 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -475,7 +475,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_opaque_types(&mut self, span: Span) { - for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { + for &(def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); From 3405725e0026dbea6dd3e8dccbcb44898511fa13 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 4 Jun 2021 17:02:48 -0300 Subject: [PATCH 03/18] Change concrete opaque type to be a `VecMap` --- compiler/rustc_middle/src/mir/query.rs | 4 ++-- compiler/rustc_middle/src/ty/context.rs | 3 ++- compiler/rustc_mir/src/borrow_check/mod.rs | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0edb79fdbc8e8..f6c8ed4cbab70 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -2,8 +2,8 @@ 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}; @@ -210,7 +210,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>, + pub concrete_opaque_types: VecMap>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 970e669c16f70..ee8fa4b647a8d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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}; @@ -424,7 +425,7 @@ pub struct TypeckResults<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. - pub concrete_opaque_types: FxHashMap>, + pub concrete_opaque_types: VecMap>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 36eb8a4baa830..5b2aaf56921b2 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -25,7 +26,7 @@ use either::Either; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; -use std::iter; +use std::iter::{self, FromIterator}; use std::mem; use std::rc::Rc; @@ -441,7 +442,7 @@ fn do_mir_borrowck<'a, 'tcx>( } let result = BorrowCheckResult { - concrete_opaque_types: opaque_type_values, + concrete_opaque_types: VecMap::from_iter(opaque_type_values.into_iter()), closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, }; From 7f8cad2019d3bee6f82b0394ed7d0d33d1db944a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 5 Jun 2021 15:08:35 -0300 Subject: [PATCH 04/18] Make OpaqueTypeKey the key of opaque types map --- compiler/rustc_middle/src/mir/query.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 6 + compiler/rustc_mir/src/borrow_check/mod.rs | 5 +- compiler/rustc_mir/src/borrow_check/nll.rs | 9 +- .../borrow_check/region_infer/opaque_types.rs | 18 +-- .../src/borrow_check/type_check/mod.rs | 30 ++-- .../rustc_trait_selection/src/opaque_types.rs | 10 +- compiler/rustc_typeck/src/check/writeback.rs | 10 +- compiler/rustc_typeck/src/collect/type_of.rs | 138 ++++++++++-------- 10 files changed, 134 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index f6c8ed4cbab70..9e61f5629ae02 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -9,6 +9,7 @@ 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; @@ -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: VecMap>, + pub concrete_opaque_types: VecMap, ty::ResolvedOpaqueTy<'tcx>>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ee8fa4b647a8d..d4433ebd350f1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -48,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}; @@ -425,7 +426,7 @@ pub struct TypeckResults<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. - pub concrete_opaque_types: VecMap>, + pub concrete_opaque_types: VecMap, ResolvedOpaqueTy<'tcx>>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b58c92b841517..268818b64e56e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 5b2aaf56921b2..36eb8a4baa830 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -26,7 +25,7 @@ use either::Either; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; -use std::iter::{self, FromIterator}; +use std::iter; use std::mem; use std::rc::Rc; @@ -442,7 +441,7 @@ fn do_mir_borrowck<'a, 'tcx>( } let result = BorrowCheckResult { - concrete_opaque_types: VecMap::from_iter(opaque_type_values.into_iter()), + concrete_opaque_types: opaque_type_values, closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, }; diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs index a0265b20d127b..fdc06ae303a07 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -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}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -47,7 +46,7 @@ crate type PoloniusOutput = Output; /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: FxHashMap>, + pub opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, pub polonius_output: Option>, pub opt_closure_req: Option>, pub nll_errors: RegionErrors<'tcx>, @@ -367,7 +366,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, - opaque_type_values: &FxHashMap>, + opaque_type_values: &VecMap, ty::ResolvedOpaqueTy<'tcx>>, errors_buffer: &mut Vec, ) { let tcx = infcx.tcx; diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs index 0d1d255104272..b1954e9938dd5 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs @@ -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, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -51,12 +50,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(in crate::borrow_check) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, - opaque_ty_decls: FxHashMap>, + opaque_ty_decls: VecMap, ty::ResolvedOpaqueTy<'tcx>>, span: Span, - ) -> FxHashMap> { + ) -> VecMap, ty::ResolvedOpaqueTy<'tcx>> { opaque_ty_decls .into_iter() - .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| { + .map(|(opaque_type_key, ty::ResolvedOpaqueTy { concrete_type, substs })| { debug!(?concrete_type, ?substs); let mut subst_regions = vec![self.universal_regions.fr_static]; @@ -110,14 +109,15 @@ 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, + opaque_type_key, ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs }, ) }) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 4b9569b74b904..26ae3f4b5c805 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -7,9 +7,10 @@ use either::Either; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; @@ -27,8 +28,8 @@ use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts}; use rustc_middle::ty::{ - self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPredicate, Ty, - TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, + self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, + ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, }; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; @@ -818,7 +819,7 @@ struct TypeChecker<'a, 'tcx> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, - opaque_type_values: FxHashMap>, + opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, } struct BorrowCheckContext<'a, 'tcx> { @@ -833,7 +834,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, pub(in crate::borrow_check) universal_region_relations: Frozen>, - crate opaque_type_values: FxHashMap>, + crate opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, } /// A collection of region constraints that must be satisfied for the @@ -978,7 +979,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, - opaque_type_values: FxHashMap::default(), + opaque_type_values: VecMap::default(), }; checker.check_user_type_annotations(); checker @@ -1240,7 +1241,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let param_env = self.param_env; let body = self.body; let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types; - let mut opaque_type_values = Vec::new(); + let mut opaque_type_values = VecMap::new(); debug!("eq_opaque_type_and_type: mir_def_id={:?}", body.source.def_id()); let opaque_type_map = self.fully_perform_op( @@ -1288,7 +1289,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } else { false }; - let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) { + + let opaque_type_key = + OpaqueTypeKey { def_id: opaque_def_id, substs: opaque_decl.substs }; + let opaque_defn_ty = match concrete_opaque_types + .iter() + .find(|(opaque_type_key, _)| opaque_type_key.def_id == opaque_def_id) + .map(|(_, resolved_opaque_ty)| resolved_opaque_ty) + { None => { if !concrete_is_opaque { tcx.sess.delay_span_bug( @@ -1322,13 +1330,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .at(&ObligationCause::dummy(), param_env) .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?, ); - opaque_type_values.push(( - opaque_def_id, + opaque_type_values.insert( + opaque_type_key, ty::ResolvedOpaqueTy { concrete_type: renumbered_opaque_defn_ty, substs: opaque_decl.substs, }, - )); + ); } else { // We're using an opaque `impl Trait` type without // 'revealing' it. For example, code like this: diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 2fdb267d0db8f..fc497755b3cb1 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -12,7 +12,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::Span; use std::ops::ControlFlow; @@ -143,8 +143,7 @@ pub trait InferCtxtExt<'tcx> { fn infer_opaque_definition_from_instantiation( &self, - def_id: DefId, - substs: SubstsRef<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, instantiated_ty: Ty<'tcx>, span: Span, ) -> Ty<'tcx>; @@ -573,11 +572,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// `opaque_defn.concrete_ty` fn infer_opaque_definition_from_instantiation( &self, - def_id: DefId, - substs: SubstsRef<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, instantiated_ty: Ty<'tcx>, span: Span, ) -> Ty<'tcx> { + let OpaqueTypeKey { def_id, substs } = opaque_type_key; + debug!( "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})", def_id, instantiated_ty diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 685f81b3bd6a5..ec940cb369326 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -493,9 +493,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // fn foo() -> Foo { .. } // ``` // figures out the concrete type with `U`, but the stored type is with `T`. + let opaque_type_key = OpaqueTypeKey { def_id, substs: opaque_defn.substs }; let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( - def_id, - opaque_defn.substs, + opaque_type_key, instantiated_ty, span, ); @@ -527,7 +527,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { substs: opaque_defn.substs, }; - let old = self.typeck_results.concrete_opaque_types.insert(def_id, new); + let opaque_type_key = OpaqueTypeKey { def_id, substs: opaque_defn.substs }; + let old = + self.typeck_results.concrete_opaque_types.insert(opaque_type_key, new); if let Some(old) = old { if old.concrete_type != definition_ty || old.substs != opaque_defn.substs { span_bug!( diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 19c35ebd011b1..b53ef070a458f 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,4 +1,5 @@ use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -9,7 +10,9 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ + self, DefIdTree, OpaqueTypeKey, ResolvedOpaqueTy, Ty, TyCtxt, TypeFoldable, +}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -346,36 +349,36 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } // Opaque types desugared from `impl Trait`. ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { - let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) - .concrete_opaque_types - .get(&def_id.to_def_id()) - .map(|opaque| opaque.concrete_type) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - owner, def_id, - ), - ); - if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors - { - // Some error in the - // owner fn prevented us from populating - // the `concrete_opaque_types` table. - tcx.ty_error() - } else { - // We failed to resolve the opaque type or it - // resolves to itself. Return the non-revealed - // type, which should result in E0720. - tcx.mk_opaque( - def_id.to_def_id(), - InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), - ) - } - }); + let concrete_ty = find_concrete_ty_from_def_id( + &tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types, + def_id.to_def_id(), + ) + .map(|opaque| opaque.concrete_type) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no opaque type for {:?} in its typeck results", + owner, def_id, + ), + ); + if let Some(ErrorReported) = + tcx.typeck(owner.expect_local()).tainted_by_errors + { + // Some error in the + // owner fn prevented us from populating + // the `concrete_opaque_types` table. + tcx.ty_error() + } else { + // We failed to resolve the opaque type or it + // resolves to itself. Return the non-revealed + // type, which should result in E0720. + tcx.mk_opaque( + def_id.to_def_id(), + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), + ) + } + }); debug!("concrete_ty = {:?}", concrete_ty); concrete_ty } @@ -515,7 +518,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. - if !self.tcx.typeck(def_id).concrete_opaque_types.contains_key(&self.def_id) { + if find_concrete_ty_from_def_id( + &self.tcx.typeck(def_id).concrete_opaque_types, + self.def_id, + ) + .is_none() + { debug!( "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", self.def_id, def_id, @@ -523,7 +531,10 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { return; } // Use borrowck to get the type with unerased regions. - let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id); + let ty = find_concrete_ty_from_def_id( + &self.tcx.mir_borrowck(def_id).concrete_opaque_types, + self.def_id, + ); if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty { debug!( "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", @@ -697,32 +708,31 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty let opaque_ty_def_id = opaque_ty_id.to_def_id(); let owner_typeck_results = tcx.typeck(scope_def_id); - let concrete_ty = owner_typeck_results - .concrete_opaque_types - .get(&opaque_ty_def_id) - .map(|opaque| opaque.concrete_type) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - scope_def_id, opaque_ty_id - ), - ); - if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors { - // Some error in the owner fn prevented us from populating the - // `concrete_opaque_types` table. - tcx.ty_error() - } else { - // We failed to resolve the opaque type or it resolves to - // itself. Return the non-revealed type, which should result in - // E0720. - tcx.mk_opaque( - opaque_ty_def_id, - InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), - ) - } - }); + let concrete_ty = + find_concrete_ty_from_def_id(&owner_typeck_results.concrete_opaque_types, opaque_ty_def_id) + .map(|opaque| opaque.concrete_type) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no opaque type for {:?} in its typeck results", + scope_def_id, opaque_ty_id + ), + ); + if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors { + // Some error in the owner fn prevented us from populating the + // `concrete_opaque_types` table. + tcx.ty_error() + } else { + // We failed to resolve the opaque type or it resolves to + // itself. Return the non-revealed type, which should result in + // E0720. + tcx.mk_opaque( + opaque_ty_def_id, + InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), + ) + } + }); debug!("concrete_ty = {:?}", concrete_ty); if concrete_ty.has_erased_regions() { // FIXME(impl_trait_in_bindings) Handle this case. @@ -796,3 +806,13 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { .emit(); } } + +fn find_concrete_ty_from_def_id<'tcx>( + concrete_opaque_types: &'tcx VecMap, ResolvedOpaqueTy<'tcx>>, + def_id: DefId, +) -> Option<&'tcx ResolvedOpaqueTy<'tcx>> { + concrete_opaque_types + .iter() + .find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) + .map(|(_, resolved_opaque_ty)| resolved_opaque_ty) +} From 7294f49d524772cceb96ee35ee85feec2a052076 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 14:40:47 -0300 Subject: [PATCH 05/18] Remove ResolvedOpaqueTy and just use Ty, SubstsRef is already there --- compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 13 +------- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_mir/src/borrow_check/nll.rs | 6 ++-- .../borrow_check/region_infer/opaque_types.rs | 14 ++++----- .../src/borrow_check/type_check/mod.rs | 25 ++++++---------- compiler/rustc_typeck/src/check/writeback.rs | 17 +++++------ compiler/rustc_typeck/src/collect/type_of.rs | 30 ++++++++----------- 8 files changed, 40 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 9e61f5629ae02..4fb737f463a86 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -211,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: VecMap, ty::ResolvedOpaqueTy<'tcx>>, + pub concrete_opaque_types: VecMap, Ty<'tcx>>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d4433ebd350f1..3c6c7f1b47bfa 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -288,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 = impl Bar; fn foo() -> Foo { .. }` - /// 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 @@ -426,7 +415,7 @@ pub struct TypeckResults<'tcx> { /// All the opaque types that are restricted to concrete types /// by this function. - pub concrete_opaque_types: VecMap, ResolvedOpaqueTy<'tcx>>, + pub concrete_opaque_types: VecMap, Ty<'tcx>>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 268818b64e56e..227aa8dc284e2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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; diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs index fdc06ae303a07..bfeafa33a91cf 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, OpaqueTypeKey, RegionKind, RegionVid}; +use rustc_middle::ty::{self, OpaqueTypeKey, RegionKind, RegionVid, Ty}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -46,7 +46,7 @@ crate type PoloniusOutput = Output; /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, + pub opaque_type_values: VecMap, Ty<'tcx>>, pub polonius_output: Option>, pub opt_closure_req: Option>, pub nll_errors: RegionErrors<'tcx>, @@ -366,7 +366,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, - opaque_type_values: &VecMap, ty::ResolvedOpaqueTy<'tcx>>, + opaque_type_values: &VecMap, Ty<'tcx>>, errors_buffer: &mut Vec, ) { let tcx = infcx.tcx; diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs index b1954e9938dd5..3ec24156f2237 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs @@ -1,6 +1,6 @@ use rustc_data_structures::vec_map::VecMap; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::{self, OpaqueTypeKey, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -50,12 +50,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(in crate::borrow_check) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, - opaque_ty_decls: VecMap, ty::ResolvedOpaqueTy<'tcx>>, + opaque_ty_decls: VecMap, Ty<'tcx>>, span: Span, - ) -> VecMap, ty::ResolvedOpaqueTy<'tcx>> { + ) -> VecMap, Ty<'tcx>> { opaque_ty_decls .into_iter() - .map(|(opaque_type_key, 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]; @@ -116,10 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { universal_concrete_type, span, ); - ( - opaque_type_key, - ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs }, - ) + (opaque_type_key, remapped_type) }) .collect() } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 26ae3f4b5c805..d08a335c7dae8 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -819,7 +819,7 @@ struct TypeChecker<'a, 'tcx> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, - opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, + opaque_type_values: VecMap, Ty<'tcx>>, } struct BorrowCheckContext<'a, 'tcx> { @@ -834,7 +834,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, pub(in crate::borrow_check) universal_region_relations: Frozen>, - crate opaque_type_values: VecMap, ty::ResolvedOpaqueTy<'tcx>>, + crate opaque_type_values: VecMap, Ty<'tcx>>, } /// A collection of region constraints that must be satisfied for the @@ -1292,10 +1292,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let opaque_type_key = OpaqueTypeKey { def_id: opaque_def_id, substs: opaque_decl.substs }; - let opaque_defn_ty = match concrete_opaque_types + let concrete_ty = match concrete_opaque_types .iter() .find(|(opaque_type_key, _)| opaque_type_key.def_id == opaque_def_id) - .map(|(_, resolved_opaque_ty)| resolved_opaque_ty) + .map(|(_, concrete_ty)| concrete_ty) { None => { if !concrete_is_opaque { @@ -1309,17 +1309,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } continue; } - Some(opaque_defn_ty) => opaque_defn_ty, + Some(concrete_ty) => concrete_ty, }; - debug!("opaque_defn_ty = {:?}", opaque_defn_ty); - let subst_opaque_defn_ty = - opaque_defn_ty.concrete_type.subst(tcx, opaque_decl.substs); + debug!("concrete_ty = {:?}", concrete_ty); + let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_decl.substs); let renumbered_opaque_defn_ty = renumber::renumber_regions(infcx, subst_opaque_defn_ty); debug!( "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}", - opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty, + concrete_ty, resolved_ty, renumbered_opaque_defn_ty, ); if !concrete_is_opaque { @@ -1330,13 +1329,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .at(&ObligationCause::dummy(), param_env) .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?, ); - opaque_type_values.insert( - opaque_type_key, - ty::ResolvedOpaqueTy { - concrete_type: renumbered_opaque_defn_ty, - substs: opaque_decl.substs, - }, - ); + opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty); } else { // We're using an opaque `impl Trait` type without // 'revealing' it. For example, code like this: diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index ec940cb369326..f0388444d6bfb 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -522,16 +522,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // in some other location, or we'll end up emitting an error due // to the lack of defining usage if !skip_add { - let new = ty::ResolvedOpaqueTy { - concrete_type: definition_ty, - substs: opaque_defn.substs, - }; - let opaque_type_key = OpaqueTypeKey { def_id, substs: opaque_defn.substs }; - let old = - self.typeck_results.concrete_opaque_types.insert(opaque_type_key, new); - if let Some(old) = old { - if old.concrete_type != definition_ty || old.substs != opaque_defn.substs { + let old_concrete_ty = self + .typeck_results + .concrete_opaque_types + .insert(opaque_type_key, definition_ty); + if let Some(old_concrete_ty) = old_concrete_ty { + if old_concrete_ty != definition_ty { span_bug!( span, "`visit_opaque_types` tried to write different types for the same \ @@ -539,7 +536,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { def_id, definition_ty, opaque_defn, - old, + old_concrete_ty, ); } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b53ef070a458f..032188b21211b 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -10,9 +10,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{ - self, DefIdTree, OpaqueTypeKey, ResolvedOpaqueTy, Ty, TyCtxt, TypeFoldable, -}; +use rustc_middle::ty::{self, DefIdTree, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -353,7 +351,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { &tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types, def_id.to_def_id(), ) - .map(|opaque| opaque.concrete_type) + .map(|&(_, concrete_ty)| concrete_ty) .unwrap_or_else(|| { tcx.sess.delay_span_bug( DUMMY_SP, @@ -531,14 +529,13 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { return; } // Use borrowck to get the type with unerased regions. - let ty = find_concrete_ty_from_def_id( - &self.tcx.mir_borrowck(def_id).concrete_opaque_types, - self.def_id, - ); - if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty { + let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; + if let Some((opaque_type_key, concrete_type)) = + find_concrete_ty_from_def_id(concrete_opaque_types, self.def_id) + { debug!( "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", - self.def_id, def_id, ty, + self.def_id, def_id, concrete_type, ); // FIXME(oli-obk): trace the actual span from inference to improve errors. @@ -549,7 +546,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // using `delay_span_bug`, just in case `wfcheck` slips up. let opaque_generics = self.tcx.generics_of(self.def_id); let mut used_params: FxHashSet<_> = FxHashSet::default(); - for (i, arg) in substs.iter().enumerate() { + for (i, arg) in opaque_type_key.substs.iter().enumerate() { let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), GenericArgKind::Lifetime(lt) => { @@ -710,7 +707,7 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty let owner_typeck_results = tcx.typeck(scope_def_id); let concrete_ty = find_concrete_ty_from_def_id(&owner_typeck_results.concrete_opaque_types, opaque_ty_def_id) - .map(|opaque| opaque.concrete_type) + .map(|&(_, concrete_ty)| concrete_ty) .unwrap_or_else(|| { tcx.sess.delay_span_bug( DUMMY_SP, @@ -808,11 +805,8 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { } fn find_concrete_ty_from_def_id<'tcx>( - concrete_opaque_types: &'tcx VecMap, ResolvedOpaqueTy<'tcx>>, + concrete_opaque_types: &'tcx VecMap, Ty<'tcx>>, def_id: DefId, -) -> Option<&'tcx ResolvedOpaqueTy<'tcx>> { - concrete_opaque_types - .iter() - .find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) - .map(|(_, resolved_opaque_ty)| resolved_opaque_ty) +) -> Option<&'tcx (OpaqueTypeKey<'tcx>, Ty<'tcx>)> { + concrete_opaque_types.iter().find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) } From 37ab718350453a328b1a925825d8d9bbea9fe9e6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 16:57:44 -0300 Subject: [PATCH 06/18] Make opaque type map key be of type OpaqueTypeKey --- .../rustc_mir/src/borrow_check/type_check/mod.rs | 6 ++++-- compiler/rustc_trait_selection/src/opaque_types.rs | 14 ++++++++++---- compiler/rustc_typeck/src/check/check.rs | 3 ++- compiler/rustc_typeck/src/check/inherited.rs | 6 +++--- compiler/rustc_typeck/src/check/writeback.rs | 3 ++- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index d08a335c7dae8..3476c94b797dd 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1282,7 +1282,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .eq(output_ty, revealed_ty)?, ); - for &(opaque_def_id, opaque_decl) in &opaque_type_map { + for &(opaque_type_key, opaque_decl) in &opaque_type_map { + let opaque_def_id = opaque_type_key.def_id; let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty); let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { *def_id == opaque_def_id @@ -1377,7 +1378,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // prove that `T: Iterator` where `T` is the type we // instantiated it with). if let Some(opaque_type_map) = opaque_type_map { - for (opaque_def_id, opaque_decl) in opaque_type_map { + for (opaque_type_key, opaque_decl) in opaque_type_map { + let opaque_def_id = opaque_type_key.def_id; self.fully_perform_op( locations, ConstraintCategory::OpaqueType, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index fc497755b3cb1..6137521c4c13e 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -17,7 +17,7 @@ use rustc_span::Span; use std::ops::ControlFlow; -pub type OpaqueTypeMap<'tcx> = VecMap>; +pub type OpaqueTypeMap<'tcx> = VecMap, OpaqueTypeDecl<'tcx>>; /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that @@ -370,7 +370,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { debug!("constrain_opaque_types()"); - for &(def_id, opaque_defn) in opaque_types { + for &(opaque_type_key, opaque_defn) in opaque_types { + let OpaqueTypeKey { def_id, substs: _ } = opaque_type_key; self.constrain_opaque_type( def_id, &opaque_defn, @@ -1041,7 +1042,12 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). - if let Some(opaque_defn) = self.opaque_types.get(&def_id) { + if let Some(opaque_defn) = self + .opaque_types + .iter() + .find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) + .map(|(_, opaque_defn)| opaque_defn) + { debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } @@ -1079,7 +1085,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let definition_span = self.value_span; self.opaque_types.insert( - def_id, + OpaqueTypeKey { def_id, substs }, OpaqueTypeDecl { opaque_type: ty, substs, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 166410731d291..e32561900de11 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -716,7 +716,8 @@ fn check_opaque_meets_bounds<'tcx>( infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span), ); - for (def_id, opaque_defn) in opaque_type_map { + for (opaque_type_key, opaque_defn) in opaque_type_map { + let def_id = opaque_type_key.def_id; match infcx .at(&misc_cause, param_env) .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs)) diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 0ff9bed749c75..2e9bef15f900a 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -4,12 +4,12 @@ use super::MaybeInProgressTables; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; +use rustc_hir::def_id::{DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; use rustc_infer::infer; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::{self, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::opaque_types::OpaqueTypeDecl; @@ -59,7 +59,7 @@ pub struct Inherited<'a, 'tcx> { // associated fresh inference variable. Writeback resolves these // variables to get the concrete type, which can be used to // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions. - pub(super) opaque_types: RefCell>>, + pub(super) opaque_types: RefCell, OpaqueTypeDecl<'tcx>>>, /// A map from inference variables created from opaque /// type instantiations (`ty::Infer`) to the actual opaque diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f0388444d6bfb..07c33d007cccd 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -475,7 +475,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_opaque_types(&mut self, span: Span) { - for &(def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { + for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() { + let OpaqueTypeKey { def_id, substs: _ } = opaque_type_key; let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); From 5dabd55d7dc3324bbc49a941584358e931b2cdd6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 17:34:36 -0300 Subject: [PATCH 07/18] Use substs from opaque type key instead of using it from opaque_decl --- .../src/borrow_check/type_check/mod.rs | 18 +++++++----------- .../rustc_trait_selection/src/opaque_types.rs | 3 +-- compiler/rustc_typeck/src/check/check.rs | 9 ++++----- compiler/rustc_typeck/src/check/writeback.rs | 14 ++++++-------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 3476c94b797dd..e03ae3869ef3c 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1283,20 +1283,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); for &(opaque_type_key, opaque_decl) in &opaque_type_map { - let opaque_def_id = opaque_type_key.def_id; let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty); let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() { - *def_id == opaque_def_id + *def_id == opaque_type_key.def_id } else { false }; - let opaque_type_key = - OpaqueTypeKey { def_id: opaque_def_id, substs: opaque_decl.substs }; let concrete_ty = match concrete_opaque_types .iter() - .find(|(opaque_type_key, _)| opaque_type_key.def_id == opaque_def_id) - .map(|(_, concrete_ty)| concrete_ty) + .find(|(key, _)| key.def_id == opaque_type_key.def_id) + .map(|(_, ty)| ty) { None => { if !concrete_is_opaque { @@ -1304,7 +1301,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body.span, &format!( "Non-defining use of {:?} with revealed type", - opaque_def_id, + opaque_type_key.def_id, ), ); } @@ -1313,7 +1310,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(concrete_ty) => concrete_ty, }; debug!("concrete_ty = {:?}", concrete_ty); - let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_decl.substs); + let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs); let renumbered_opaque_defn_ty = renumber::renumber_regions(infcx, subst_opaque_defn_ty); @@ -1353,7 +1350,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // gets 'revealed' into debug!( "eq_opaque_type_and_type: non-defining use of {:?}", - opaque_def_id, + opaque_type_key.def_id, ); } } @@ -1379,14 +1376,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // instantiated it with). if let Some(opaque_type_map) = opaque_type_map { for (opaque_type_key, opaque_decl) in opaque_type_map { - let opaque_def_id = opaque_type_key.def_id; self.fully_perform_op( locations, ConstraintCategory::OpaqueType, CustomTypeOp::new( |_cx| { infcx.constrain_opaque_type( - opaque_def_id, + opaque_type_key.def_id, &opaque_decl, GenerateMemberConstraints::IfNoStaticBound, universal_region_relations, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 6137521c4c13e..9bb08503712f3 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -371,9 +371,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { debug!("constrain_opaque_types()"); for &(opaque_type_key, opaque_defn) in opaque_types { - let OpaqueTypeKey { def_id, substs: _ } = opaque_type_key; self.constrain_opaque_type( - def_id, + opaque_type_key.def_id, &opaque_defn, GenerateMemberConstraints::WhenRequired, free_region_relations, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index e32561900de11..5df5fb7ea688c 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -717,11 +717,10 @@ fn check_opaque_meets_bounds<'tcx>( ); for (opaque_type_key, opaque_defn) in opaque_type_map { - let def_id = opaque_type_key.def_id; - match infcx - .at(&misc_cause, param_env) - .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs)) - { + match infcx.at(&misc_cause, param_env).eq( + opaque_defn.concrete_ty, + tcx.type_of(opaque_type_key.def_id).subst(tcx, opaque_defn.substs), + ) { Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), Err(ty_err) => tcx.sess.delay_span_bug( opaque_defn.definition_span, diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 07c33d007cccd..e8f606455f2af 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -476,8 +476,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self, span: Span) { for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() { - let OpaqueTypeKey { def_id, substs: _ } = opaque_type_key; - let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local()); + let hir_id = + self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -494,7 +494,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // fn foo() -> Foo { .. } // ``` // figures out the concrete type with `U`, but the stored type is with `T`. - let opaque_type_key = OpaqueTypeKey { def_id, substs: opaque_defn.substs }; let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( opaque_type_key, instantiated_ty, @@ -506,7 +505,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() { if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin { - if def_id == defin_ty_def_id { + if opaque_type_key.def_id == defin_ty_def_id { debug!( "skipping adding concrete definition for opaque type {:?} {:?}", opaque_defn, defin_ty_def_id @@ -516,14 +515,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - if !opaque_defn.substs.needs_infer() { + if !opaque_type_key.substs.needs_infer() { // We only want to add an entry into `concrete_opaque_types` // if we actually found a defining usage of this opaque type. // Otherwise, we do nothing - we'll either find a defining usage // in some other location, or we'll end up emitting an error due // to the lack of defining usage if !skip_add { - let opaque_type_key = OpaqueTypeKey { def_id, substs: opaque_defn.substs }; let old_concrete_ty = self .typeck_results .concrete_opaque_types @@ -534,7 +532,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { span, "`visit_opaque_types` tried to write different types for the same \ opaque type: {:?}, {:?}, {:?}, {:?}", - def_id, + opaque_type_key.def_id, definition_ty, opaque_defn, old_concrete_ty, From e3863735144095312ab6486191fc8666d7c54e4b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 17:53:09 -0300 Subject: [PATCH 08/18] Remove substs from OpaqueTypeDecl, use the one in OpaqueTypeKey --- .../src/borrow_check/type_check/mod.rs | 2 +- .../rustc_trait_selection/src/opaque_types.rs | 52 +++++++++---------- compiler/rustc_typeck/src/check/check.rs | 2 +- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index e03ae3869ef3c..60dd2e833e046 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1382,7 +1382,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CustomTypeOp::new( |_cx| { infcx.constrain_opaque_type( - opaque_type_key.def_id, + opaque_type_key, &opaque_decl, GenerateMemberConstraints::IfNoStaticBound, universal_region_relations, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 9bb08503712f3..8b864d6753608 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -27,19 +27,6 @@ pub struct OpaqueTypeDecl<'tcx> { /// The opaque type (`ty::Opaque`) for this declaration. pub opaque_type: Ty<'tcx>, - /// The substitutions that we apply to the opaque type that this - /// `impl Trait` desugars to. e.g., if: - /// - /// fn foo<'a, 'b, T>() -> impl Trait<'a> - /// - /// winds up desugared to: - /// - /// type Foo<'x, X> = impl Trait<'x> - /// fn foo<'a, 'b, T>() -> Foo<'a, T> - /// - /// then `substs` would be `['a, T]`. - pub substs: SubstsRef<'tcx>, - /// The span of this particular definition of the opaque type. So /// for example: /// @@ -126,7 +113,7 @@ pub trait InferCtxtExt<'tcx> { fn constrain_opaque_type>( &self, - def_id: DefId, + opaque_type_key: OpaqueTypeKey<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>, mode: GenerateMemberConstraints, free_region_relations: &FRR, @@ -137,7 +124,7 @@ pub trait InferCtxtExt<'tcx> { &self, concrete_ty: Ty<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>, - opaque_type_def_id: DefId, + opaque_type_key: OpaqueTypeKey<'tcx>, first_own_region_index: usize, ); @@ -372,7 +359,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { for &(opaque_type_key, opaque_defn) in opaque_types { self.constrain_opaque_type( - opaque_type_key.def_id, + opaque_type_key, &opaque_defn, GenerateMemberConstraints::WhenRequired, free_region_relations, @@ -383,11 +370,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// See `constrain_opaque_types` for documentation. fn constrain_opaque_type>( &self, - def_id: DefId, + opaque_type_key: OpaqueTypeKey<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>, mode: GenerateMemberConstraints, free_region_relations: &FRR, ) { + let def_id = opaque_type_key.def_id; + debug!("constrain_opaque_type()"); debug!("constrain_opaque_type: def_id={:?}", def_id); debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn); @@ -426,9 +415,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let bounds = tcx.explicit_item_bounds(def_id); debug!("constrain_opaque_type: predicates: {:#?}", bounds); let bounds: Vec<_> = - bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect(); + bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect(); debug!("constrain_opaque_type: bounds={:#?}", bounds); - let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); + let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs); let required_region_bounds = required_region_bounds(tcx, opaque_type, bounds.into_iter()); @@ -440,7 +429,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }); } if let GenerateMemberConstraints::IfNoStaticBound = mode { - self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region); + self.generate_member_constraint( + concrete_ty, + opaque_defn, + opaque_type_key, + first_own_region, + ); } return; } @@ -454,7 +448,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // second. let mut least_region = None; - for subst_arg in &opaque_defn.substs[first_own_region..] { + for subst_arg in &opaque_type_key.substs[first_own_region..] { let subst_region = match subst_arg.unpack() { GenericArgKind::Lifetime(r) => r, GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue, @@ -484,7 +478,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return self.generate_member_constraint( concrete_ty, opaque_defn, - def_id, + opaque_type_key, first_own_region, ); } @@ -497,7 +491,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let GenerateMemberConstraints::IfNoStaticBound = mode { if least_region != tcx.lifetimes.re_static { - self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region); + self.generate_member_constraint( + concrete_ty, + opaque_defn, + opaque_type_key, + first_own_region, + ); } } concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { @@ -517,14 +516,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, concrete_ty: Ty<'tcx>, opaque_defn: &OpaqueTypeDecl<'tcx>, - opaque_type_def_id: DefId, + opaque_type_key: OpaqueTypeKey<'tcx>, first_own_region: usize, ) { // Create the set of choice regions: each region in the hidden // type can be equal to any of the region parameters of the // opaque type definition. let choice_regions: Lrc>> = Lrc::new( - opaque_defn.substs[first_own_region..] + opaque_type_key.substs[first_own_region..] .iter() .filter_map(|arg| match arg.unpack() { GenericArgKind::Lifetime(r) => Some(r), @@ -537,7 +536,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { op: |r| { self.member_constraint( - opaque_type_def_id, + opaque_type_key.def_id, opaque_defn.definition_span, concrete_ty, r, @@ -1087,7 +1086,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { OpaqueTypeKey { def_id, substs }, OpaqueTypeDecl { opaque_type: ty, - substs, definition_span, concrete_ty: ty_var, has_required_region_bounds: !required_region_bounds.is_empty(), diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 5df5fb7ea688c..6b9ad128e2892 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -719,7 +719,7 @@ fn check_opaque_meets_bounds<'tcx>( for (opaque_type_key, opaque_defn) in opaque_type_map { match infcx.at(&misc_cause, param_env).eq( opaque_defn.concrete_ty, - tcx.type_of(opaque_type_key.def_id).subst(tcx, opaque_defn.substs), + tcx.type_of(opaque_type_key.def_id).subst(tcx, opaque_type_key.substs), ) { Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), Err(ty_err) => tcx.sess.delay_span_bug( From 9e547b446433d63e3fe99bacfdaedf97fed31a8a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 18:12:43 -0300 Subject: [PATCH 09/18] Differentiate different defining uses of taits when they reference distinct generic parameters --- .../rustc_trait_selection/src/opaque_types.rs | 17 +++++++---------- .../multiple-def-uses-in-one-fn.rs | 16 ++++++++++++++++ .../multiple-def-uses-in-one-fn.stderr | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 8b864d6753608..89ec211f2627b 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::free_regions::FreeRegionRelations; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::Span; @@ -1007,7 +1007,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ), }; if in_definition_scope { - return self.fold_opaque_ty(ty, def_id.to_def_id(), substs, origin); + let opaque_type_key = + OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; + return self.fold_opaque_ty(ty, opaque_type_key, origin); } debug!( @@ -1029,23 +1031,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, - def_id: DefId, - substs: SubstsRef<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, ) -> Ty<'tcx> { let infcx = self.infcx; let tcx = infcx.tcx; + let OpaqueTypeKey { def_id, substs } = opaque_type_key; debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs); // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). - if let Some(opaque_defn) = self - .opaque_types - .iter() - .find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) - .map(|(_, opaque_defn)| opaque_defn) - { + if let Some(opaque_defn) = self.opaque_types.get(&opaque_type_key) { debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs new file mode 100644 index 0000000000000..67351e2015993 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(min_type_alias_impl_trait)] + +type X = impl Into<&'static A>; +//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied + +fn f(a: &'static A, b: B) -> (X, X) { + (a, a) +} + +fn main() { + println!("{}", as Into<&String>>::into(f(&[1isize, 2, 3], String::new()).1)); +} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr new file mode 100644 index 0000000000000..731c6e2788dde --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied + --> $DIR/multiple-def-uses-in-one-fn.rs:7:16 + | +LL | type X = impl Into<&'static A>; + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | + = note: required because of the requirements on the impl of `Into<&'static B>` for `&A` +help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement + | +LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From c80d0620842968afdb327a039b42c3847d478cae Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 18:56:26 -0300 Subject: [PATCH 10/18] Add more TAIT multiple defining uses test cases --- .../multiple-def-uses-in-one-fn-pass.rs | 12 ++++++++++++ .../multiple-def-uses-in-one-fn2.rs | 16 ++++++++++++++++ .../multiple-def-uses-in-one-fn2.stderr | 8 ++++++++ .../multiple-def-uses-in-one-fn3.rs | 18 ++++++++++++++++++ .../multiple-def-uses-in-one-fn3.stderr | 18 ++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs new file mode 100644 index 0000000000000..ecad910f7d542 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(min_type_alias_impl_trait)] + +type X = impl ToString; + +fn f(a: A, b: B) -> (X, X) { + (a.clone(), a) +} + +fn main() { + println!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); +} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs new file mode 100644 index 0000000000000..38aa18fe40ee7 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(min_type_alias_impl_trait)] + +type X = impl ToString; +//~^ ERROR could not find defining uses + +fn f(a: A, b: B) -> (X, X) { + (a.clone(), a) +} + +fn main() { + println!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); +} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr new file mode 100644 index 0000000000000..c00973c0761b0 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -0,0 +1,8 @@ +error: could not find defining uses + --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52 + | +LL | type X = impl ToString; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs new file mode 100644 index 0000000000000..17e900058113d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(min_type_alias_impl_trait)] + +type X = impl ToString; + +fn f(a: A, b: B) -> (X, X) { + (a, b) +} + +fn g(a: A, b: B) -> (X, X) { + (a, b) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr new file mode 100644 index 0000000000000..bbe709dccab4e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 + | +LL | fn g(a: A, b: B) -> (X, X) { + | - - found type parameter + | | + | expected type parameter +LL | (a, b) + | ^ expected type parameter `A`, found type parameter `B` + | + = note: expected type parameter `A` + found type parameter `B` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From dd56ec653cec248fb532fc295e1c40271238cffc Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 09:40:58 -0300 Subject: [PATCH 11/18] Add VecMap::get_by(FnMut -> bool) --- compiler/rustc_data_structures/src/vec_map.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index eca4ff212acae..fef570c786b11 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -33,6 +33,13 @@ where self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) } + pub fn get_by

(&self, predicate: P) -> Option<&V> + where + for<'b> P: FnMut(&'b &(K, V)) -> bool, + { + self.0.iter().find(predicate).map(|elem| &elem.1) + } + pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, From 1278f3f29586e58a196772e8680df19045e9930e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 09:41:26 -0300 Subject: [PATCH 12/18] Simplify code by using VecMap::get_by --- .../src/borrow_check/type_check/mod.rs | 4 +- compiler/rustc_typeck/src/collect/type_of.rs | 134 +++++++++--------- 2 files changed, 65 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 60dd2e833e046..09cafddeeffde 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1291,9 +1291,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; let concrete_ty = match concrete_opaque_types - .iter() - .find(|(key, _)| key.def_id == opaque_type_key.def_id) - .map(|(_, ty)| ty) + .get_by(|(key, _)| key.def_id == opaque_type_key.def_id) { None => { if !concrete_is_opaque { diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 032188b21211b..29a87b18a9eb7 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,5 +1,4 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::vec_map::VecMap; use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -10,7 +9,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::map::Map; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -347,36 +346,36 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } // Opaque types desugared from `impl Trait`. ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { - let concrete_ty = find_concrete_ty_from_def_id( - &tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types, - def_id.to_def_id(), - ) - .map(|&(_, concrete_ty)| concrete_ty) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - owner, def_id, - ), - ); - if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors - { - // Some error in the - // owner fn prevented us from populating - // the `concrete_opaque_types` table. - tcx.ty_error() - } else { - // We failed to resolve the opaque type or it - // resolves to itself. Return the non-revealed - // type, which should result in E0720. - tcx.mk_opaque( - def_id.to_def_id(), - InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), - ) - } - }); + let concrete_ty = tcx + .mir_borrowck(owner.expect_local()) + .concrete_opaque_types + .get_by(|(key, _)| key.def_id == def_id.to_def_id()) + .map(|concrete_ty| *concrete_ty) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no opaque type for {:?} in its typeck results", + owner, def_id, + ), + ); + if let Some(ErrorReported) = + tcx.typeck(owner.expect_local()).tainted_by_errors + { + // Some error in the + // owner fn prevented us from populating + // the `concrete_opaque_types` table. + tcx.ty_error() + } else { + // We failed to resolve the opaque type or it + // resolves to itself. Return the non-revealed + // type, which should result in E0720. + tcx.mk_opaque( + def_id.to_def_id(), + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), + ) + } + }); debug!("concrete_ty = {:?}", concrete_ty); concrete_ty } @@ -516,11 +515,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { } // Calling `mir_borrowck` can lead to cycle errors through // const-checking, avoid calling it if we don't have to. - if find_concrete_ty_from_def_id( - &self.tcx.typeck(def_id).concrete_opaque_types, - self.def_id, - ) - .is_none() + if self + .tcx + .typeck(def_id) + .concrete_opaque_types + .get_by(|(key, _)| key.def_id == self.def_id) + .is_none() { debug!( "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", @@ -531,7 +531,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; if let Some((opaque_type_key, concrete_type)) = - find_concrete_ty_from_def_id(concrete_opaque_types, self.def_id) + concrete_opaque_types.iter().find(|(key, _)| key.def_id == self.def_id) { debug!( "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", @@ -705,31 +705,32 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty let opaque_ty_def_id = opaque_ty_id.to_def_id(); let owner_typeck_results = tcx.typeck(scope_def_id); - let concrete_ty = - find_concrete_ty_from_def_id(&owner_typeck_results.concrete_opaque_types, opaque_ty_def_id) - .map(|&(_, concrete_ty)| concrete_ty) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its typeck results", - scope_def_id, opaque_ty_id - ), - ); - if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors { - // Some error in the owner fn prevented us from populating the - // `concrete_opaque_types` table. - tcx.ty_error() - } else { - // We failed to resolve the opaque type or it resolves to - // itself. Return the non-revealed type, which should result in - // E0720. - tcx.mk_opaque( - opaque_ty_def_id, - InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), - ) - } - }); + let concrete_ty = owner_typeck_results + .concrete_opaque_types + .get_by(|(key, _)| key.def_id == opaque_ty_def_id) + .map(|concrete_ty| *concrete_ty) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no opaque type for {:?} in its typeck results", + scope_def_id, opaque_ty_id + ), + ); + if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors { + // Some error in the owner fn prevented us from populating the + // `concrete_opaque_types` table. + tcx.ty_error() + } else { + // We failed to resolve the opaque type or it resolves to + // itself. Return the non-revealed type, which should result in + // E0720. + tcx.mk_opaque( + opaque_ty_def_id, + InternalSubsts::identity_for_item(tcx, opaque_ty_def_id), + ) + } + }); debug!("concrete_ty = {:?}", concrete_ty); if concrete_ty.has_erased_regions() { // FIXME(impl_trait_in_bindings) Handle this case. @@ -803,10 +804,3 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { .emit(); } } - -fn find_concrete_ty_from_def_id<'tcx>( - concrete_opaque_types: &'tcx VecMap, Ty<'tcx>>, - def_id: DefId, -) -> Option<&'tcx (OpaqueTypeKey<'tcx>, Ty<'tcx>)> { - concrete_opaque_types.iter().find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) -} From f07412db4122023b76a02a5ddc31b17e49ed6cac Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 09:50:16 -0300 Subject: [PATCH 13/18] Destructure OpaqueTypeKey in certain cases to simplify code --- compiler/rustc_typeck/src/check/check.rs | 12 ++++++------ compiler/rustc_typeck/src/check/writeback.rs | 15 ++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 6b9ad128e2892..70d85796d002e 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::layout::MAX_SIMD_LANES; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt}; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; @@ -716,11 +716,11 @@ fn check_opaque_meets_bounds<'tcx>( infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span), ); - for (opaque_type_key, opaque_defn) in opaque_type_map { - match infcx.at(&misc_cause, param_env).eq( - opaque_defn.concrete_ty, - tcx.type_of(opaque_type_key.def_id).subst(tcx, opaque_type_key.substs), - ) { + for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map { + match infcx + .at(&misc_cause, param_env) + .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, substs)) + { Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), Err(ty_err) => tcx.sess.delay_span_bug( opaque_defn.definition_span, diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index e8f606455f2af..8754c8cd136a8 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -475,9 +475,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_opaque_types(&mut self, span: Span) { - for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() { - let hir_id = - self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local()); + for &(opaque_type_key @ OpaqueTypeKey { def_id, substs }, opaque_defn) in + self.fcx.opaque_types.borrow().iter() + { + let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -505,7 +506,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() { if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin { - if opaque_type_key.def_id == defin_ty_def_id { + if def_id == defin_ty_def_id { debug!( "skipping adding concrete definition for opaque type {:?} {:?}", opaque_defn, defin_ty_def_id @@ -515,7 +516,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - if !opaque_type_key.substs.needs_infer() { + if !substs.needs_infer() { // We only want to add an entry into `concrete_opaque_types` // if we actually found a defining usage of this opaque type. // Otherwise, we do nothing - we'll either find a defining usage @@ -532,7 +533,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { span, "`visit_opaque_types` tried to write different types for the same \ opaque type: {:?}, {:?}, {:?}, {:?}", - opaque_type_key.def_id, + def_id, definition_ty, opaque_defn, old_concrete_ty, From ecd78e985e7049d011e4de5e4fe04f5c9fe5af31 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 16:45:44 -0300 Subject: [PATCH 14/18] defin_ty_def_id -> definition_ty_def_id --- compiler/rustc_typeck/src/check/writeback.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 8754c8cd136a8..3984537a05687 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -503,13 +503,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut skip_add = false; - if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() { + if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() { if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin { - if def_id == defin_ty_def_id { + if def_id == definition_ty_def_id { debug!( "skipping adding concrete definition for opaque type {:?} {:?}", - opaque_defn, defin_ty_def_id + opaque_defn, def_id ); skip_add = true; } From 0ad09f938606b1a603300a93570da4a16cb7b5f2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 16:48:58 -0300 Subject: [PATCH 15/18] Do not deconstruct OpaqueTypeKey to make the code more clear --- compiler/rustc_typeck/src/check/writeback.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 3984537a05687..032cc7ee2334a 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -15,7 +15,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -475,10 +475,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_opaque_types(&mut self, span: Span) { - for &(opaque_type_key @ OpaqueTypeKey { def_id, substs }, opaque_defn) in - self.fcx.opaque_types.borrow().iter() - { - let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local()); + for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() { + let hir_id = + self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local()); let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -506,17 +505,17 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() { if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin { - if def_id == definition_ty_def_id { + if opaque_type_key.def_id == definition_ty_def_id { debug!( "skipping adding concrete definition for opaque type {:?} {:?}", - opaque_defn, def_id + opaque_defn, opaque_type_key.def_id ); skip_add = true; } } } - if !substs.needs_infer() { + if !opaque_type_key.substs.needs_infer() { // We only want to add an entry into `concrete_opaque_types` // if we actually found a defining usage of this opaque type. // Otherwise, we do nothing - we'll either find a defining usage @@ -533,7 +532,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { span, "`visit_opaque_types` tried to write different types for the same \ opaque type: {:?}, {:?}, {:?}, {:?}", - def_id, + opaque_type_key.def_id, definition_ty, opaque_defn, old_concrete_ty, From ed94da14ed19c20baf8912c69b427fe910bf5d5f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 16:50:33 -0300 Subject: [PATCH 16/18] Explicitly pass find arguments down the predicate so coercions can apply --- compiler/rustc_data_structures/src/vec_map.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index fef570c786b11..81d7fe3f6bd20 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -33,11 +33,11 @@ where self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) } - pub fn get_by

(&self, predicate: P) -> Option<&V> + pub fn get_by

(&self, mut predicate: P) -> Option<&V> where for<'b> P: FnMut(&'b &(K, V)) -> bool, { - self.0.iter().find(predicate).map(|elem| &elem.1) + self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1) } pub fn contains_key(&self, k: &Q) -> bool From cad762b1e24e350af3422b50b81e8b4e3b8393a0 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 16:52:33 -0300 Subject: [PATCH 17/18] Use impl FnMut directly as predicate type --- compiler/rustc_data_structures/src/vec_map.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 81d7fe3f6bd20..ceafdbbce2658 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -33,10 +33,7 @@ where self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1) } - pub fn get_by

(&self, mut predicate: P) -> Option<&V> - where - for<'b> P: FnMut(&'b &(K, V)) -> bool, - { + 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) } From 7b1e1c73330ca9ce7ad00f7a1d61ba393ea187b1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Jun 2021 17:16:05 -0300 Subject: [PATCH 18/18] add VecMap docs --- compiler/rustc_data_structures/src/vec_map.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index ceafdbbce2658..73b04d3329cb8 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -5,6 +5,8 @@ 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(Vec<(K, V)>); @@ -16,6 +18,7 @@ where 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 { if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) { Some(std::mem::replace(&mut elem.1, v)) @@ -25,6 +28,7 @@ where } } + /// Gets a reference to the value in the entry. pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, @@ -33,10 +37,19 @@ where 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(&self, k: &Q) -> bool where K: Borrow, @@ -45,6 +58,7 @@ where self.get(k).is_some() } + /// Returns `true` if the map contains no elements. pub fn is_empty(&self) -> bool { self.0.is_empty() }