Skip to content

Commit

Permalink
review + some small stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Apr 10, 2023
1 parent 2186847 commit 3fab7f7
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 14 deletions.
16 changes: 13 additions & 3 deletions compiler/rustc_middle/src/traits/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,19 @@ pub enum Certainty {
impl Certainty {
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 unify the certainty of these goals
pub fn unify_and(self, other: Certainty) -> Certainty {
/// Use this function to merge the certainty of multiple nested subgoals.
///
/// 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) {
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
(Certainty::Yes, Certainty::Maybe(_)) => other,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::solve::EvalCtxt;
//
// For types with an "existential" binder, i.e. generator witnesses, we also
// 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>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
Expand Down Expand Up @@ -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>,
ty: Ty<'tcx>,
) -> ty::Binder<'tcx, Ty<'tcx>> {
Expand All @@ -108,7 +108,7 @@ pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
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>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
Expand Down Expand Up @@ -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>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
Expand Down Expand Up @@ -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.
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>,
self_ty: Ty<'tcx>,
goal_kind: ty::ClosureKind,
Expand Down Expand Up @@ -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
/// clauses of the impl. In this example, that means replacing
/// `<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>,
param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// deal with `has_changed` in the next iteration.
new_goals.normalizes_to_hack_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));
}
}
}
Expand All @@ -378,7 +378,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
Certainty::Yes => {}
Certainty::Maybe(_) => {
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));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
certainty: Certainty,
) -> QueryResult<'tcx> {
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()?;

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
return Err(NoSolution);
}
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);
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/higher-rank-trait-bounds/issue-95230.new.stderr
Original file line number Diff line number Diff line change
@@ -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`.
6 changes: 5 additions & 1 deletion tests/ui/higher-rank-trait-bounds/issue-95230.rs
Original file line number Diff line number Diff line change
@@ -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
where
Expand Down

0 comments on commit 3fab7f7

Please sign in to comment.