diff options
| author | bors <bors@rust-lang.org> | 2024-03-11 19:01:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-11 19:01:15 +0000 |
| commit | 4ccbb7dc95596c7fc0c5756fdc47a17a56c085d3 (patch) | |
| tree | b36a408d7aff94b9359528d7e50ffebef00a66c5 /compiler | |
| parent | 6554a5645a13e4d9331fd028960d69be91d7492d (diff) | |
| parent | b0328c20ce75a56879bda08235242c21c1a451a1 (diff) | |
| download | rust-4ccbb7dc95596c7fc0c5756fdc47a17a56c085d3.tar.gz rust-4ccbb7dc95596c7fc0c5756fdc47a17a56c085d3.zip | |
Auto merge of #121796 - oli-obk:eager_opaque_checks3, r=lcnr
Make `DefiningAnchor::Bind` only store the opaque types that may be constrained, instead of the current infcx root item. This makes `Bind` almost always be empty, so we can start forwarding it to queries, allowing us to remove `Bubble` entirely (not done in this PR) The only behaviour change is in diagnostics. r? `@lcnr` `@compiler-errors`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_borrowck/src/consumers.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/lib.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/inherited.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/mod.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/opaque_types/mod.rs | 65 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/type_foldable.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/traits/mod.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/traits/solve.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/codec.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/opaque_types.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/sig_types.rs | 14 |
16 files changed, 105 insertions, 111 deletions
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index a58fe2b7447..31307ef1410 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -106,7 +106,7 @@ pub fn get_body_with_borrowck_facts( options: ConsumerOptions, ) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap() diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8dcfe014b65..415ba095a1b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -126,10 +126,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let hir_owner = tcx.local_def_id_to_hir_id(def).owner; - - let infcx = - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 12b02c7fcfa..8a172233037 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -311,13 +311,13 @@ fn check_opaque_type_well_formed<'tcx>( parent_def_id = tcx.local_parent(parent_def_id); } - // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Error` + // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])` // and prepopulate this `InferCtxt` with known opaque values, rather than // using the `Bind` anchor here. For now it's fine. let infcx = tcx .infer_ctxt() .with_next_trait_solver(next_trait_solver) - .with_opaque_type_inference(DefiningAnchor::Bind(parent_def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id)) .build(); let ocx = ObligationCtxt::new(&infcx); let identity_args = GenericArgs::identity_for_item(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1b24c2b61fd..cb739ac48a8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -347,7 +347,7 @@ fn check_opaque_meets_bounds<'tcx>( let infcx = tcx .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor)) .build(); let ocx = ObligationCtxt::new(&infcx); @@ -1558,7 +1558,7 @@ pub(super) fn check_coroutine_obligations( .ignoring_regions() // Bind opaque types to type checking root, as they should have been checked by borrowck, // but may show up in some cases, like when (root) obligations are stalled in the new solver. - .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id)) .build(); let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx); diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index 4ad46845f0b..b0950ed2800 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -79,7 +79,7 @@ impl<'tcx> Inherited<'tcx> { let infcx = tcx .infer_ctxt() .ignoring_regions() - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) + .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id)) .build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 15cdd6a910e..89e4e88b3df 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -242,9 +242,10 @@ pub struct InferCtxt<'tcx> { /// short lived InferCtxt within queries. The opaque type obligations are forwarded /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. /// - /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that + /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined. + /// This way it is easier to catch errors that /// might come up during inference or typeck. - pub defining_use_anchor: DefiningAnchor, + pub defining_use_anchor: DefiningAnchor<'tcx>, /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during hir typeck as region @@ -605,7 +606,7 @@ impl fmt::Display for FixupError { /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, - defining_use_anchor: DefiningAnchor, + defining_use_anchor: DefiningAnchor<'tcx>, considering_regions: bool, skip_leak_check: bool, /// Whether we are in coherence mode. @@ -620,7 +621,7 @@ impl<'tcx> TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, - defining_use_anchor: DefiningAnchor::Error, + defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()), considering_regions: true, skip_leak_check: false, intercrate: false, @@ -636,7 +637,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// It is only meant to be called in two places, for typeck /// (via `Inherited::build`) and for the inference context used /// in mir borrowck. - pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self { + pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self { self.defining_use_anchor = defining_use_anchor; self } @@ -1208,13 +1209,11 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self), ret)] pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error); std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types) } #[instrument(level = "debug", skip(self), ret)] pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> { - debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error); self.inner.borrow().opaque_type_storage.opaque_types.clone() } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 3d6829ba657..a6f8115c27e 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -150,9 +150,6 @@ impl<'tcx> InferCtxt<'tcx> { } } DefiningAnchor::Bubble => {} - DefiningAnchor::Error => { - return None; - } } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, and we don't @@ -378,28 +375,14 @@ impl<'tcx> InferCtxt<'tcx> { /// in its defining scope. #[instrument(skip(self), level = "trace", ret)] pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> { - let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id); - let parent_def_id = match self.defining_use_anchor { - DefiningAnchor::Bubble | DefiningAnchor::Error => return None, + let defined_opaque_types = match self.defining_use_anchor { + DefiningAnchor::Bubble => return None, DefiningAnchor::Bind(bind) => bind, }; let origin = self.tcx.opaque_type_origin(def_id); - let in_definition_scope = match origin { - // Async `impl Trait` - hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, - // Anonymous `impl Trait` - hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, - // Named `type Foo = impl Bar;` - hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => { - if in_assoc_ty { - self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id) - } else { - may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id) - } - } - }; - in_definition_scope.then_some(origin) + + defined_opaque_types.contains(&def_id).then_some(origin) } } @@ -656,43 +639,3 @@ impl<'tcx> InferCtxt<'tcx> { } } } - -/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`. -/// -/// Example: -/// ```ignore UNSOLVED (is this a bug?) -/// # #![feature(type_alias_impl_trait)] -/// pub mod foo { -/// pub mod bar { -/// pub trait Bar { /* ... */ } -/// pub type Baz = impl Bar; -/// -/// # impl Bar for () {} -/// fn f1() -> Baz { /* ... */ } -/// } -/// fn f2() -> bar::Baz { /* ... */ } -/// } -/// ``` -/// -/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`), -/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`. -/// For the above example, this function returns `true` for `f1` and `false` for `f2`. -fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool { - let mut hir_id = tcx.local_def_id_to_hir_id(def_id); - - // Named opaque types can be defined by any siblings or children of siblings. - let scope = tcx.hir().get_defining_scope(opaque_hir_id); - // We walk up the node tree until we hit the root or the scope of the opaque type. - while hir_id != scope && hir_id != hir::CRATE_HIR_ID { - hir_id = tcx.hir().get_parent_item(hir_id).into(); - } - // Syntactically, we are allowed to define the concrete type if: - let res = hir_id == scope; - trace!( - "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.hir_node(hir_id), - tcx.hir_node(opaque_hir_id), - res - ); - res -} diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 93a9bbf64c9..b798f078800 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,6 +1,7 @@ //! `TypeFoldable` implementations for MIR types use rustc_ast::InlineAsmTemplatePiece; +use rustc_hir::def_id::LocalDefId; use super::*; @@ -44,6 +45,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] { } } +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + _folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self) + } +} + impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a6e4702d819..aea58653351 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -12,8 +12,8 @@ pub mod util; use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; -use crate::ty::GenericArgsRef; use crate::ty::{self, AdtKind, Ty}; +use crate::ty::{GenericArgsRef, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diag, EmissionGuarantee}; @@ -1001,10 +1001,14 @@ pub enum CodegenObligationError { /// opaques are replaced with inference vars eagerly in the old solver (e.g. /// in projection, and in the signature during function type-checking). #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] -pub enum DefiningAnchor { - /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly - /// replace opaque types in `replace_opaque_types_with_inference_vars`. - Bind(LocalDefId), +pub enum DefiningAnchor<'tcx> { + /// Define opaques which are in-scope of the current item being analyzed. + /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`. + /// + /// If the list is empty, do not allow any opaques to be defined. This is used to catch type mismatch + /// errors when handling opaque types, and also should be used when we would + /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). + Bind(&'tcx ty::List<LocalDefId>), /// In contexts where we don't currently know what opaques are allowed to be /// defined, such as (old solver) canonical queries, we will simply allow /// opaques to be defined, but "bubble" them up in the canonical response or @@ -1013,8 +1017,10 @@ pub enum DefiningAnchor { /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`, /// which may affect what predicates pass and fail in the old trait solver. Bubble, - /// Do not allow any opaques to be defined. This is used to catch type mismatch - /// errors when handling opaque types, and also should be used when we would - /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode). - Error, +} + +impl<'tcx> DefiningAnchor<'tcx> { + pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { + Self::Bind(tcx.opaque_types_defined_by(item)) + } } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 95139b50cb8..dc4cd203415 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -114,7 +114,7 @@ impl MaybeCause { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct QueryInput<'tcx, T> { pub goal: Goal<'tcx, T>, - pub anchor: DefiningAnchor, + pub anchor: DefiningAnchor<'tcx>, pub predefined_opaques_in_body: PredefinedOpaques<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 69ae05ca820..ddbc0bffaed 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -17,6 +17,7 @@ use crate::traits; use crate::ty::GenericArgsRef; use crate::ty::{self, AdtDef, Ty}; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; @@ -431,6 +432,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi } } +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<LocalDefId> { + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.interner().mk_local_def_ids_from_iter( + (0..len).map::<LocalDefId, _>(|_| Decodable::decode(decoder)), + ) + } +} + impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<(VariantIdx, FieldIdx)> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b08e5df30ef..c415c06c21b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2014,6 +2014,14 @@ impl<'tcx> TyCtxt<'tcx> { self.intern_local_def_ids(clauses) } + pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<LocalDefId, &'tcx List<LocalDefId>>, + { + T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs)) + } + pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 22f52c27362..3b858cb449f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -16,7 +16,7 @@ use rustc_middle::traits::solve::{ CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, PredefinedOpaques, PredefinedOpaquesData, QueryResult, }; -use rustc_middle::traits::{specialization_graph, DefiningAnchor}; +use rustc_middle::traits::specialization_graph; use rustc_middle::ty::{ self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, @@ -258,10 +258,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // instead of taking them. This would cause an ICE here, since we have // assertions against dropping an `InferCtxt` without taking opaques. // FIXME: Once we remove support for the old impl we can remove this. - if input.anchor != DefiningAnchor::Error { - // This seems ok, but fragile. - let _ = infcx.take_opaque_types(); - } + let _ = infcx.take_opaque_types(); result } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 71fcc47dba3..ad5b7debad7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -32,7 +32,7 @@ use rustc_hir::{GenericParam, Item, Node}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; -use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData}; +use rustc_middle::traits::SignatureMismatchData; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; @@ -3390,19 +3390,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { obligation.cause.span, format!("cannot check whether the hidden type of {name} satisfies auto traits"), ); + + err.note( + "fetching the hidden types of an opaque inside of the defining scope is not supported. \ + You can try moving the opaque type and the item that actually registers a hidden type into a new submodule", + ); err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); - match self.defining_use_anchor { - DefiningAnchor::Bubble | DefiningAnchor::Error => {} - DefiningAnchor::Bind(bind) => { - err.span_note( - self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)), - "this item depends on auto traits of the hidden type, \ - but may also be registering the hidden type. \ - This is not supported right now. \ - You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(), - ); - } - }; self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 3dcc8382289..4a1064b29f6 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { self.span = old; } - fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> { + fn parent_impl_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> { let parent = self.parent()?; if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()) @@ -210,6 +210,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { self.visit_opaque_ty(alias_ty); } + // Skips type aliases, as they are meant to be transparent. ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => { self.tcx .type_of(alias_ty.def_id) @@ -220,11 +221,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { // This avoids having to do normalization of `Self::AssocTy` by only // supporting the case of a method defining opaque types from assoc types // in the same impl block. - if let Some(parent_trait_ref) = self.parent_trait_ref() { + if let Some(impl_trait_ref) = self.parent_impl_trait_ref() { // If the trait ref of the associated item and the impl differs, // then we can't use the impl's identity args below, so // just skip. - if alias_ty.trait_ref(self.tcx) == parent_trait_ref { + if alias_ty.trait_ref(self.tcx) == impl_trait_ref { let parent = self.parent().expect("we should have a parent here"); for &assoc in self.tcx.associated_items(parent).in_definition_order() { @@ -241,7 +242,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { let impl_args = alias_ty.args.rebase_onto( self.tcx, - parent_trait_ref.def_id, + impl_trait_ref.def_id, ty::GenericArgs::identity_for_item(self.tcx, parent), ); @@ -259,6 +260,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { } } } + } else if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = + self.tcx.opt_rpitit_info(alias_ty.def_id) + && fn_def_id == self.item.into() + { + // RPITIT in trait definitions get desugared to an associated type. For + // default methods we also create an opaque type this associated type + // normalizes to. The associated type is only known to normalize to the + // opaque if it is fully concrete. There could otherwise be an impl + // overwriting the default method. + // + // However, we have to be able to normalize the associated type while inside + // of the default method. This is normally handled by adding an unchecked + // `Projection(<Self as Trait>::synthetic_assoc_ty, trait_def::opaque)` + // assumption to the `param_env` of the default method. We also separately + // rely on that assumption here. + let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args); + let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") }; + self.visit_opaque_ty(alias_ty); } } ty::Adt(def, _) if def.did().is_local() => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 5527d853e30..72fcc95c3b3 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -23,8 +23,14 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( match kind { // Walk over the signature of the function DefKind::AssocFn | DefKind::Fn => { - let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap(); + // If the type of the item uses `_`, we're gonna error out anyway, but + // typeck (which type_of invokes below), will call back into opaque_types_defined_by + // causing a cycle. So we just bail out in this case. + if hir_sig.output.get_infer_ret_ty().is_some() { + return V::Result::output(); + } + let ty_sig = tcx.fn_sig(item).instantiate_identity(); // Walk over the inputs and outputs manually in order to get good spans for them. try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output())); for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { @@ -39,6 +45,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Walk over the type of the item DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { + // If the type of the item uses `_`, we're gonna error out anyway, but + // typeck (which type_of invokes below), will call back into opaque_types_defined_by + // causing a cycle. So we just bail out in this case. + if ty.is_suggestable_infer_ty() { + return V::Result::output(); + } // Associated types in traits don't necessarily have a type that we can visit try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } |
