Skip to content

Commit

Permalink
Scrape extraneous regions from instantiate_nll_query_response_and_reg…
Browse files Browse the repository at this point in the history
…ion_obligations
  • Loading branch information
oli-obk committed Apr 8, 2024
1 parent 08e25e4 commit dd72bf9
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 44 deletions.
103 changes: 60 additions & 43 deletions compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
2 changes: 1 addition & 1 deletion tests/ui/inference/issue-80409.no-compat.stderr
Original file line number Diff line number Diff line change
@@ -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(|_| {});
Expand Down

0 comments on commit dd72bf9

Please sign in to comment.