Skip to content

Commit dd72bf9

Browse files
committed
Scrape extraneous regions from instantiate_nll_query_response_and_region_obligations
1 parent 08e25e4 commit dd72bf9

File tree

2 files changed

+61
-44
lines changed

2 files changed

+61
-44
lines changed

compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

+60-43
Original file line numberDiff line numberDiff line change
@@ -159,53 +159,70 @@ where
159159
.0);
160160
}
161161

162+
let mut error_info = None;
162163
let mut region_constraints = QueryRegionConstraints::default();
163-
let (output, error_info, mut obligations, _) =
164-
Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
165-
infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
166-
})?;
167-
168-
// Typically, instantiating NLL query results does not
169-
// create obligations. However, in some cases there
170-
// are unresolved type variables, and unify them *can*
171-
// create obligations. In that case, we have to go
172-
// fulfill them. We do this via a (recursive) query.
173-
while !obligations.is_empty() {
174-
trace!("{:#?}", obligations);
175-
let mut progress = false;
176-
for obligation in std::mem::take(&mut obligations) {
177-
let obligation = infcx.resolve_vars_if_possible(obligation);
178-
match ProvePredicate::fully_perform_into(
179-
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
180-
infcx,
181-
&mut region_constraints,
182-
span,
183-
) {
184-
Ok(((), _, new, certainty)) => {
185-
obligations.extend(new);
186-
progress = true;
187-
if let Certainty::Ambiguous = certainty {
188-
obligations.push(obligation);
164+
165+
// HACK(type_alias_impl_trait): When moving an opaque type to hidden type mapping from the query to the current inferctxt,
166+
// we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
167+
// hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
168+
// collecting region constraints via `region_constraints`.
169+
let (mut output, _) = scrape_region_constraints(
170+
infcx,
171+
|_ocx| {
172+
let (output, ei, mut obligations, _) =
173+
Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
174+
error_info = ei;
175+
176+
// Typically, instantiating NLL query results does not
177+
// create obligations. However, in some cases there
178+
// are unresolved type variables, and unify them *can*
179+
// create obligations. In that case, we have to go
180+
// fulfill them. We do this via a (recursive) query.
181+
while !obligations.is_empty() {
182+
trace!("{:#?}", obligations);
183+
let mut progress = false;
184+
for obligation in std::mem::take(&mut obligations) {
185+
let obligation = infcx.resolve_vars_if_possible(obligation);
186+
match ProvePredicate::fully_perform_into(
187+
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
188+
infcx,
189+
&mut region_constraints,
190+
span,
191+
) {
192+
Ok(((), _, new, certainty)) => {
193+
obligations.extend(new);
194+
progress = true;
195+
if let Certainty::Ambiguous = certainty {
196+
obligations.push(obligation);
197+
}
198+
}
199+
Err(_) => obligations.push(obligation),
189200
}
190201
}
191-
Err(_) => obligations.push(obligation),
202+
if !progress {
203+
infcx.dcx().span_bug(
204+
span,
205+
format!("ambiguity processing {obligations:?} from {self:?}"),
206+
);
207+
}
192208
}
193-
}
194-
if !progress {
195-
infcx
196-
.dcx()
197-
.span_bug(span, format!("ambiguity processing {obligations:?} from {self:?}"));
198-
}
199-
}
200-
201-
Ok(TypeOpOutput {
202-
output,
203-
constraints: if region_constraints.is_empty() {
204-
None
205-
} else {
206-
Some(infcx.tcx.arena.alloc(region_constraints))
209+
Ok(output)
207210
},
208-
error_info,
209-
})
211+
"fully_perform",
212+
span,
213+
)?;
214+
output.error_info = error_info;
215+
if let Some(constraints) = output.constraints {
216+
region_constraints
217+
.member_constraints
218+
.extend(constraints.member_constraints.iter().cloned());
219+
region_constraints.outlives.extend(constraints.outlives.iter().cloned());
220+
}
221+
output.constraints = if region_constraints.is_empty() {
222+
None
223+
} else {
224+
Some(infcx.tcx.arena.alloc(region_constraints))
225+
};
226+
Ok(output)
210227
}
211228
}

tests/ui/inference/issue-80409.no-compat.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } }
1+
error: internal compiler error: error performing operation: fully_perform
22
--> $DIR/issue-80409.rs:49:30
33
|
44
LL | builder.state().on_entry(|_| {});

0 commit comments

Comments
 (0)