Skip to content

Commit

Permalink
Split out make_ambiguous_response_no_constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Apr 26, 2023
1 parent 5fa8209 commit ee89421
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 30 deletions.
61 changes: 42 additions & 19 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,25 +70,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// into itself infinitely and any partial substitutions in the query
// response are probably not useful anyways, so just return an empty
// query 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,
}
//
// This may prevent us from potentially useful inference, e.g.
// 2 candidates, one ambiguous and one overflow, which both
// have the same inference constraints.
//
// Changing this to retain some constraints in the future
// won't be a breaking change, so this is good enough for now.
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow));
}
};

Expand All @@ -101,6 +90,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
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)]
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
// Cannot use `take_registered_region_obligations` as we may compute the response
Expand Down
22 changes: 11 additions & 11 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,17 +340,17 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if responses.is_empty() {
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);
if let Ok(response) = response {
assert!(response.has_no_inference_or_external_constraints());
Ok(response)
} else {
bug!("failed to make floundered response: {responses:?}");
}

let Certainty::Maybe(maybe_cause) = responses.iter().fold(
Certainty::AMBIGUOUS,
|certainty, response| {
certainty.unify_with(response.value.certainty)
},
) else {
bug!("expected flounder response to be ambiguous")
};

Ok(self.make_ambiguous_response_no_constraints(maybe_cause))
}
}

Expand Down

0 comments on commit ee89421

Please sign in to comment.