Split out make_ambiguous_response_no_constraints

This commit is contained in:
Michael Goulet 2023-04-26 22:33:33 +00:00
parent 5fa82092ae
commit ee8942138a
2 changed files with 52 additions and 29 deletions

View File

@ -70,25 +70,14 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
// into itself infinitely and any partial substitutions in the query // into itself infinitely and any partial substitutions in the query
// response are probably not useful anyways, so just return an empty // response are probably not useful anyways, so just return an empty
// query response. // query response.
Response { //
var_values: CanonicalVarValues { // This may prevent us from potentially useful inference, e.g.
var_values: self.tcx().mk_substs_from_iter( // 2 candidates, one ambiguous and one overflow, which both
self.var_values.var_values.iter().map(|arg| -> ty::GenericArg<'tcx> { // have the same inference constraints.
match arg.unpack() { //
GenericArgKind::Lifetime(_) => self.next_region_infer().into(), // Changing this to retain some constraints in the future
GenericArgKind::Type(_) => self.next_ty_infer().into(), // won't be a breaking change, so this is good enough for now.
GenericArgKind::Const(ct) => { return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
self.next_const_infer(ct.ty()).into()
}
}
}),
),
},
external_constraints: self
.tcx()
.mk_external_constraints(ExternalConstraintsData::default()),
certainty,
}
} }
}; };
@ -101,6 +90,40 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
Ok(canonical) Ok(canonical)
} }
/// Constructs a totally unconstrained, ambiguous response to a goal.
///
/// Take care when using this, since often it's useful to respond with
/// ambiguity but return constrained variables to guide inference.
pub(in crate::solve) fn make_ambiguous_response_no_constraints(
&self,
maybe_cause: MaybeCause,
) -> CanonicalResponse<'tcx> {
let unconstrained_response = Response {
var_values: CanonicalVarValues {
var_values: self.tcx().mk_substs_from_iter(self.var_values.var_values.iter().map(
|arg| -> ty::GenericArg<'tcx> {
match arg.unpack() {
GenericArgKind::Lifetime(_) => self.next_region_infer().into(),
GenericArgKind::Type(_) => self.next_ty_infer().into(),
GenericArgKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
}
},
)),
},
external_constraints: self
.tcx()
.mk_external_constraints(ExternalConstraintsData::default()),
certainty: Certainty::Maybe(maybe_cause),
};
Canonicalizer::canonicalize(
self.infcx,
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
&mut Default::default(),
unconstrained_response,
)
}
#[instrument(level = "debug", skip(self), ret)] #[instrument(level = "debug", skip(self), ret)]
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> { fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
// Cannot use `take_registered_region_obligations` as we may compute the response // Cannot use `take_registered_region_obligations` as we may compute the response

View File

@ -340,17 +340,17 @@ fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tc
if responses.is_empty() { if responses.is_empty() {
return Err(NoSolution); return Err(NoSolution);
} }
let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
certainty.unify_with(response.value.certainty)
});
let response = self.evaluate_added_goals_and_make_canonical_response(certainty); let Certainty::Maybe(maybe_cause) = responses.iter().fold(
if let Ok(response) = response { Certainty::AMBIGUOUS,
assert!(response.has_no_inference_or_external_constraints()); |certainty, response| {
Ok(response) certainty.unify_with(response.value.certainty)
} else { },
bug!("failed to make floundered response: {responses:?}"); ) else {
} bug!("expected flounder response to be ambiguous")
};
Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
} }
} }