diff options
Diffstat (limited to 'compiler/rustc_infer/src/infer/opaque_types.rs')
-rw-r--r-- | compiler/rustc_infer/src/infer/opaque_types.rs | 138 |
1 files changed, 68 insertions, 70 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 9d5ec228d..5927f79a1 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -33,9 +33,6 @@ pub struct OpaqueTypeDecl<'tcx> { /// There can be multiple, but they are all `lub`ed together at the end /// to obtain the canonical hidden type. pub hidden_type: OpaqueHiddenType<'tcx>, - - /// The origin of the opaque type. - pub origin: hir::OpaqueTyOrigin, } impl<'tcx> InferCtxt<'tcx> { @@ -49,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> InferOk<'tcx, T> { // We handle opaque types differently in the new solver. - if self.tcx.trait_solver_next() { + if self.next_trait_solver() { return InferOk { value, obligations: vec![] }; } @@ -108,7 +105,7 @@ impl<'tcx> InferCtxt<'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); - let origin = match self.defining_use_anchor { + match self.defining_use_anchor { DefiningAnchor::Bind(_) => { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose @@ -144,9 +141,11 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id)? + if self.opaque_type_origin(def_id).is_none() { + return None; + } } - DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id), + DefiningAnchor::Bubble => {} DefiningAnchor::Error => return None, }; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { @@ -170,7 +169,6 @@ impl<'tcx> InferCtxt<'tcx> { cause.clone(), param_env, b, - origin, a_is_expected, )) } @@ -380,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> { DefiningAnchor::Bind(bind) => bind, }; - let origin = self.opaque_type_origin_unchecked(def_id); + 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, @@ -397,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> { }; in_definition_scope.then_some(origin) } - - /// Returns the origin of the opaque type `def_id` even if we are not in its - /// defining scope. - #[instrument(skip(self), level = "trace", ret)] - fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin { - self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin - } } /// Visitor that requires that (almost) all regions in the type visited outlive @@ -482,17 +473,6 @@ where } } - ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { - // Skip lifetime parameters that are not captures. - let variances = self.tcx.variances_of(proj.def_id); - - for (v, s) in std::iter::zip(variances, proj.substs.iter()) { - if *v != ty::Variance::Bivariant { - s.visit_with(self); - } - } - } - _ => { ty.super_visit_with(self); } @@ -524,30 +504,22 @@ impl<'tcx> InferCtxt<'tcx> { cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, - origin: hir::OpaqueTyOrigin, a_is_expected: bool, ) -> InferResult<'tcx, ()> { - // Ideally, we'd get the span where *this specific `ty` came - // from*, but right now we just use the span from the overall - // value being folded. In simple cases like `-> impl Foo`, - // these are the same span, but not in cases like `-> (impl - // Foo, impl Bar)`. - let span = cause.span; - let prev = self.inner.borrow_mut().opaque_types().register( + let mut obligations = Vec::new(); + + self.insert_hidden_type( opaque_type_key, - OpaqueHiddenType { ty: hidden_ty, span }, - origin, - ); - let mut obligations = if let Some(prev) = prev { - self.at(&cause, param_env) - .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? - .obligations - } else { - Vec::new() - }; + &cause, + param_env, + hidden_ty, + a_is_expected, + &mut obligations, + )?; self.add_item_bounds_for_hidden_type( - opaque_type_key, + opaque_type_key.def_id.to_def_id(), + opaque_type_key.substs, cause, param_env, hidden_ty, @@ -557,32 +529,60 @@ impl<'tcx> InferCtxt<'tcx> { Ok(InferOk { value: (), obligations }) } - /// Registers an opaque's hidden type -- only should be used when the opaque - /// can be defined. For something more fallible -- checks the anchors, tries - /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`. - pub fn register_hidden_type_in_new_solver( + /// Insert a hidden type into the opaque type storage, equating it + /// with any previous entries if necessary. + /// + /// This **does not** add the item bounds of the opaque as nested + /// obligations. That is only necessary when normalizing the opaque + /// itself, not when getting the opaque type constraints from + /// somewhere else. + pub fn insert_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, + cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, - ) -> InferResult<'tcx, ()> { - assert!(self.tcx.trait_solver_next()); - let origin = self - .opaque_type_origin(opaque_type_key.def_id) - .expect("should be called for defining usages only"); - self.register_hidden_type( - opaque_type_key, - ObligationCause::dummy(), - param_env, - hidden_ty, - origin, - true, - ) + a_is_expected: bool, + obligations: &mut Vec<PredicateObligation<'tcx>>, + ) -> Result<(), TypeError<'tcx>> { + // Ideally, we'd get the span where *this specific `ty` came + // from*, but right now we just use the span from the overall + // value being folded. In simple cases like `-> impl Foo`, + // these are the same span, but not in cases like `-> (impl + // Foo, impl Bar)`. + let span = cause.span; + if self.intercrate { + // During intercrate we do not define opaque types but instead always + // force ambiguity unless the hidden type is known to not implement + // our trait. + obligations.push(traits::Obligation::new( + self.tcx, + cause.clone(), + param_env, + ty::PredicateKind::Ambiguous, + )) + } else { + let prev = self + .inner + .borrow_mut() + .opaque_types() + .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); + if let Some(prev) = prev { + obligations.extend( + self.at(&cause, param_env) + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? + .obligations, + ); + } + }; + + Ok(()) } pub fn add_item_bounds_for_hidden_type( &self, - OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, + def_id: DefId, + substs: ty::SubstsRef<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, @@ -602,7 +602,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::Alias(ty::Projection, projection_ty) if !projection_ty.has_escaping_bound_vars() && !tcx.is_impl_trait_in_trait(projection_ty.def_id) - && !tcx.trait_solver_next() => + && !self.next_trait_solver() => { self.infer_projection( param_env, @@ -615,7 +615,7 @@ impl<'tcx> InferCtxt<'tcx> { // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. }) - if def_id.to_def_id() == def_id2 && substs == substs2 => + if def_id == def_id2 && substs == substs2 => { hidden_ty } @@ -624,16 +624,14 @@ impl<'tcx> InferCtxt<'tcx> { ty::Alias( ty::Projection, ty::AliasTy { def_id: def_id2, substs: substs2, .. }, - ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty, + ) if def_id == def_id2 && substs == substs2 => hidden_ty, _ => ty, }, lt_op: |lt| lt, ct_op: |ct| ct, }); - if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() { if projection.term.references_error() { // No point on adding any obligations since there's a type error involved. obligations.clear(); |