Skip to content

Commit 3fab7f7

Browse files
committed
review + some small stuff
1 parent 2186847 commit 3fab7f7

File tree

7 files changed

+52
-14
lines changed

7 files changed

+52
-14
lines changed

compiler/rustc_middle/src/traits/solve.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,19 @@ pub enum Certainty {
5656
impl Certainty {
5757
pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
5858

59-
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
60-
/// use this function to unify the certainty of these goals
61-
pub fn unify_and(self, other: Certainty) -> Certainty {
59+
/// Use this function to merge the certainty of multiple nested subgoals.
60+
///
61+
/// Given an impl like `impl<T: Foo + Bar> Baz for T {}`, we have 2 nested
62+
/// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`.
63+
/// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in
64+
/// success, we merge these two responses. This results in ambiguity.
65+
///
66+
/// If we unify ambiguity with overflow, we return overflow. This doesn't matter
67+
/// inside of the solver as we distinguish ambiguity from overflow. It does
68+
/// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar`
69+
/// in ambiguity without changing the inference state, we still want to tell the
70+
/// user that `T: Baz` results in overflow.
71+
pub fn unify_with(self, other: Certainty) -> Certainty {
6272
match (self, other) {
6373
(Certainty::Yes, Certainty::Yes) => Certainty::Yes,
6474
(Certainty::Yes, Certainty::Maybe(_)) => other,

compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::solve::EvalCtxt;
1111
//
1212
// For types with an "existential" binder, i.e. generator witnesses, we also
1313
// instantiate the binder with placeholders eagerly.
14-
pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
14+
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
1515
ecx: &EvalCtxt<'_, 'tcx>,
1616
ty: Ty<'tcx>,
1717
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
@@ -87,7 +87,7 @@ pub(crate) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
8787
}
8888
}
8989

90-
pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
90+
pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
9191
tcx: TyCtxt<'tcx>,
9292
ty: Ty<'tcx>,
9393
) -> ty::Binder<'tcx, Ty<'tcx>> {
@@ -108,7 +108,7 @@ pub(crate) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
108108
ty::Binder::bind_with_vars(ty, bound_vars)
109109
}
110110

111-
pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
111+
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
112112
ecx: &EvalCtxt<'_, 'tcx>,
113113
ty: Ty<'tcx>,
114114
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
@@ -158,7 +158,7 @@ pub(crate) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
158158
}
159159
}
160160

161-
pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
161+
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
162162
ecx: &EvalCtxt<'_, 'tcx>,
163163
ty: Ty<'tcx>,
164164
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
@@ -224,7 +224,7 @@ pub(crate) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
224224
}
225225

226226
// Returns a binder of the tupled inputs types and output type from a builtin callable type.
227-
pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
227+
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
228228
tcx: TyCtxt<'tcx>,
229229
self_ty: Ty<'tcx>,
230230
goal_kind: ty::ClosureKind,
@@ -337,7 +337,13 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
337337
/// additional step of eagerly folding the associated types in the where
338338
/// clauses of the impl. In this example, that means replacing
339339
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
340-
pub(crate) fn predicates_for_object_candidate<'tcx>(
340+
///
341+
// FIXME: This is only necessary as `<Self as Trait>::Assoc: ItemBound`
342+
// bounds in impls are trivially proven using the item bound candidates.
343+
// This is unsound in general and once that is fixed, we don't need to
344+
// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
345+
// for more details.
346+
pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
341347
ecx: &EvalCtxt<'_, 'tcx>,
342348
param_env: ty::ParamEnv<'tcx>,
343349
trait_ref: ty::TraitRef<'tcx>,

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
357357
// deal with `has_changed` in the next iteration.
358358
new_goals.normalizes_to_hack_goal =
359359
Some(this.resolve_vars_if_possible(goal));
360-
has_changed = has_changed.map_err(|c| c.unify_and(certainty));
360+
has_changed = has_changed.map_err(|c| c.unify_with(certainty));
361361
}
362362
}
363363
}
@@ -378,7 +378,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
378378
Certainty::Yes => {}
379379
Certainty::Maybe(_) => {
380380
new_goals.goals.push(goal);
381-
has_changed = has_changed.map_err(|c| c.unify_and(certainty));
381+
has_changed = has_changed.map_err(|c| c.unify_with(certainty));
382382
}
383383
}
384384
}

compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
5050
certainty: Certainty,
5151
) -> QueryResult<'tcx> {
5252
let goals_certainty = self.try_evaluate_added_goals()?;
53-
let certainty = certainty.unify_and(goals_certainty);
53+
let certainty = certainty.unify_with(goals_certainty);
5454

5555
let external_constraints = self.compute_external_query_constraints()?;
5656

compiler/rustc_trait_selection/src/solve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
341341
return Err(NoSolution);
342342
}
343343
let certainty = responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
344-
certainty.unify_and(response.value.certainty)
344+
certainty.unify_with(response.value.certainty)
345345
});
346346

347347
let response = self.evaluate_added_goals_and_make_canonical_response(certainty);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/issue-95230.rs:9:13
3+
|
4+
LL | for<'a> &'a mut Self:;
5+
| ^^^^^^^^^^^^ cannot infer type for mutable reference `&'a mut Bar`
6+
|
7+
note: required by a bound in `Bar`
8+
--> $DIR/issue-95230.rs:9:13
9+
|
10+
LL | pub struct Bar
11+
| --- required by a bound in this struct
12+
LL | where
13+
LL | for<'a> &'a mut Self:;
14+
| ^^^^^^^^^^^^ required by this bound in `Bar`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0282`.

tests/ui/higher-rank-trait-bounds/issue-95230.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// check-pass
1+
// revisions: old new
2+
//[new] compile-flags: -Ztrait-solver=next
3+
//[old] check-pass
4+
//[new] known-bug: #109764
5+
26

37
pub struct Bar
48
where

0 commit comments

Comments
 (0)