summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/opaque_types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer/opaque_types.rs')
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs138
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();