about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs103
-rw-r--r--tests/ui/inference/issue-80409.no-compat.stderr2
2 files changed, 61 insertions, 44 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index faf218131b8..ae4cdb9258e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -159,53 +159,70 @@ where
             .0);
         }
 
+        let mut error_info = None;
         let mut region_constraints = QueryRegionConstraints::default();
-        let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
-                infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
-            })?;
-
-        // Typically, instantiating NLL query results does not
-        // create obligations. However, in some cases there
-        // are unresolved type variables, and unify them *can*
-        // create obligations. In that case, we have to go
-        // fulfill them. We do this via a (recursive) query.
-        while !obligations.is_empty() {
-            trace!("{:#?}", obligations);
-            let mut progress = false;
-            for obligation in std::mem::take(&mut obligations) {
-                let obligation = infcx.resolve_vars_if_possible(obligation);
-                match ProvePredicate::fully_perform_into(
-                    obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
-                    infcx,
-                    &mut region_constraints,
-                    span,
-                ) {
-                    Ok(((), _, new, certainty)) => {
-                        obligations.extend(new);
-                        progress = true;
-                        if let Certainty::Ambiguous = certainty {
-                            obligations.push(obligation);
+
+        // HACK(type_alias_impl_trait): When moving an opaque type to hidden type mapping from the query to the current inferctxt,
+        // we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
+        // hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
+        // collecting region constraints via `region_constraints`.
+        let (mut output, _) = scrape_region_constraints(
+            infcx,
+            |_ocx| {
+                let (output, ei, mut obligations, _) =
+                    Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
+                error_info = ei;
+
+                // Typically, instantiating NLL query results does not
+                // create obligations. However, in some cases there
+                // are unresolved type variables, and unify them *can*
+                // create obligations. In that case, we have to go
+                // fulfill them. We do this via a (recursive) query.
+                while !obligations.is_empty() {
+                    trace!("{:#?}", obligations);
+                    let mut progress = false;
+                    for obligation in std::mem::take(&mut obligations) {
+                        let obligation = infcx.resolve_vars_if_possible(obligation);
+                        match ProvePredicate::fully_perform_into(
+                            obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
+                            infcx,
+                            &mut region_constraints,
+                            span,
+                        ) {
+                            Ok(((), _, new, certainty)) => {
+                                obligations.extend(new);
+                                progress = true;
+                                if let Certainty::Ambiguous = certainty {
+                                    obligations.push(obligation);
+                                }
+                            }
+                            Err(_) => obligations.push(obligation),
                         }
                     }
-                    Err(_) => obligations.push(obligation),
+                    if !progress {
+                        infcx.dcx().span_bug(
+                            span,
+                            format!("ambiguity processing {obligations:?} from {self:?}"),
+                        );
+                    }
                 }
-            }
-            if !progress {
-                infcx
-                    .dcx()
-                    .span_bug(span, format!("ambiguity processing {obligations:?} from {self:?}"));
-            }
-        }
-
-        Ok(TypeOpOutput {
-            output,
-            constraints: if region_constraints.is_empty() {
-                None
-            } else {
-                Some(infcx.tcx.arena.alloc(region_constraints))
+                Ok(output)
             },
-            error_info,
-        })
+            "fully_perform",
+            span,
+        )?;
+        output.error_info = error_info;
+        if let Some(constraints) = output.constraints {
+            region_constraints
+                .member_constraints
+                .extend(constraints.member_constraints.iter().cloned());
+            region_constraints.outlives.extend(constraints.outlives.iter().cloned());
+        }
+        output.constraints = if region_constraints.is_empty() {
+            None
+        } else {
+            Some(infcx.tcx.arena.alloc(region_constraints))
+        };
+        Ok(output)
     }
 }
diff --git a/tests/ui/inference/issue-80409.no-compat.stderr b/tests/ui/inference/issue-80409.no-compat.stderr
index 523ca229b06..c772225be75 100644
--- a/tests/ui/inference/issue-80409.no-compat.stderr
+++ b/tests/ui/inference/issue-80409.no-compat.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } }
+error: internal compiler error: error performing operation: fully_perform
   --> $DIR/issue-80409.rs:49:30
    |
 LL |     builder.state().on_entry(|_| {});