review + some small stuff
This commit is contained in:
parent
2186847f28
commit
3fab7f7c13
@ -56,9 +56,19 @@ pub enum Certainty {
|
|||||||
impl Certainty {
|
impl Certainty {
|
||||||
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
|
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
|
||||||
|
|
||||||
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
|
/// Use this function to merge the certainty of multiple nested subgoals.
|
||||||
/// use this function to unify the certainty of these goals
|
///
|
||||||
pub fn unify_and(self, other: Certainty) -> Certainty {
|
/// Given an impl like `impl<T: Foo + Bar> Baz for T {}`, we have 2 nested
|
||||||
|
/// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`.
|
||||||
|
/// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in
|
||||||
|
/// success, we merge these two responses. This results in ambiguity.
|
||||||
|
///
|
||||||
|
/// If we unify ambiguity with overflow, we return overflow. This doesn't matter
|
||||||
|
/// inside of the solver as we distinguish ambiguity from overflow. It does
|
||||||
|
/// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar`
|
||||||
|
/// in ambiguity without changing the inference state, we still want to tell the
|
||||||
|
/// user that `T: Baz` results in overflow.
|
||||||
|
pub fn unify_with(self, other: Certainty) -> Certainty {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
|
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
|
||||||
(Certainty::Yes, Certainty::Maybe(_)) => other,
|
(Certainty::Yes, Certainty::Maybe(_)) => other,
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
//
|
//
|
||||||
// For types with an "existential" binder, i.e. generator witnesses, we also
|
// For types with an "existential" binder, i.e. generator witnesses, we also
|
||||||
// instantiate the binder with placeholders eagerly.
|
// instantiate the binder with placeholders eagerly.
|
||||||
pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||||
ecx: &EvalCtxt<'_, 'tcx>,
|
ecx: &EvalCtxt<'_, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||||
@ -87,7 +87,7 @@ pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
|
pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> ty::Binder<'tcx, Ty<'tcx>> {
|
) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||||
@ -108,7 +108,7 @@ pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
|
|||||||
ty::Binder::bind_with_vars(ty, bound_vars)
|
ty::Binder::bind_with_vars(ty, bound_vars)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||||
ecx: &EvalCtxt<'_, 'tcx>,
|
ecx: &EvalCtxt<'_, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||||
@ -158,7 +158,7 @@ pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
||||||
ecx: &EvalCtxt<'_, 'tcx>,
|
ecx: &EvalCtxt<'_, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||||
@ -224,7 +224,7 @@ pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns a binder of the tupled inputs types and output type from a builtin callable type.
|
// Returns a binder of the tupled inputs types and output type from a builtin callable type.
|
||||||
pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
goal_kind: ty::ClosureKind,
|
goal_kind: ty::ClosureKind,
|
||||||
@ -337,7 +337,13 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
|||||||
/// additional step of eagerly folding the associated types in the where
|
/// additional step of eagerly folding the associated types in the where
|
||||||
/// clauses of the impl. In this example, that means replacing
|
/// clauses of the impl. In this example, that means replacing
|
||||||
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
|
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
|
||||||
pub(crate) fn predicates_for_object_candidate<'tcx>(
|
///
|
||||||
|
// FIXME: This is only necessary as `<Self as Trait>::Assoc: ItemBound`
|
||||||
|
// bounds in impls are trivially proven using the item bound candidates.
|
||||||
|
// This is unsound in general and once that is fixed, we don't need to
|
||||||
|
// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
|
||||||
|
// for more details.
|
||||||
|
pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
||||||
ecx: &EvalCtxt<'_, 'tcx>,
|
ecx: &EvalCtxt<'_, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
|
@ -357,7 +357,7 @@ pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolutio
|
|||||||
// deal with `has_changed` in the next iteration.
|
// deal with `has_changed` in the next iteration.
|
||||||
new_goals.normalizes_to_hack_goal =
|
new_goals.normalizes_to_hack_goal =
|
||||||
Some(this.resolve_vars_if_possible(goal));
|
Some(this.resolve_vars_if_possible(goal));
|
||||||
has_changed = has_changed.map_err(|c| c.unify_and(certainty));
|
has_changed = has_changed.map_err(|c| c.unify_with(certainty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolutio
|
|||||||
Certainty::Yes => {}
|
Certainty::Yes => {}
|
||||||
Certainty::Maybe(_) => {
|
Certainty::Maybe(_) => {
|
||||||
new_goals.goals.push(goal);
|
new_goals.goals.push(goal);
|
||||||
has_changed = has_changed.map_err(|c| c.unify_and(certainty));
|
has_changed = has_changed.map_err(|c| c.unify_with(certainty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
|
|||||||
certainty: Certainty,
|
certainty: Certainty,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let goals_certainty = self.try_evaluate_added_goals()?;
|
let goals_certainty = self.try_evaluate_added_goals()?;
|
||||||
let certainty = certainty.unify_and(goals_certainty);
|
let certainty = certainty.unify_with(goals_certainty);
|
||||||
|
|
||||||
let external_constraints = self.compute_external_query_constraints()?;
|
let external_constraints = self.compute_external_query_constraints()?;
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ fn flounder(&mut self, responses: &[CanonicalResponse<'tcx>]) -> QueryResult<'tc
|
|||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
|
let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
|
||||||
certainty.unify_and(response.value.certainty)
|
certainty.unify_with(response.value.certainty)
|
||||||
});
|
});
|
||||||
|
|
||||||
let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
|
let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
|
||||||
|
18
tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr
Normal file
18
tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/issue-95230.rs:9:13
|
||||||
|
|
|
||||||
|
LL | for<'a> &'a mut Self:;
|
||||||
|
| ^^^^^^^^^^^^ cannot infer type for mutable reference `&'a mut Bar`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Bar`
|
||||||
|
--> $DIR/issue-95230.rs:9:13
|
||||||
|
|
|
||||||
|
LL | pub struct Bar
|
||||||
|
| --- required by a bound in this struct
|
||||||
|
LL | where
|
||||||
|
LL | for<'a> &'a mut Self:;
|
||||||
|
| ^^^^^^^^^^^^ required by this bound in `Bar`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
@ -1,4 +1,8 @@
|
|||||||
// check-pass
|
// revisions: old new
|
||||||
|
//[new] compile-flags: -Ztrait-solver=next
|
||||||
|
//[old] check-pass
|
||||||
|
//[new] known-bug: #109764
|
||||||
|
|
||||||
|
|
||||||
pub struct Bar
|
pub struct Bar
|
||||||
where
|
where
|
||||||
|
Loading…
Reference in New Issue
Block a user