Skip to content

Commit

Permalink
do not allow inference in pred_known_to_hold_modulo_regions
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed May 12, 2023
1 parent dbbb424 commit c06e611
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 23 deletions.
41 changes: 21 additions & 20 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,35 +142,36 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
pred: impl ToPredicate<'tcx>,
) -> bool {
let has_non_region_infer = pred.has_non_region_infer();
let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);

let result = infcx.evaluate_obligation_no_overflow(&obligation);
debug!(?result);

if result.must_apply_modulo_regions() && !has_non_region_infer {
if result.must_apply_modulo_regions() {
true
} else if result.may_apply() {
// Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm
// that guess. While imperfect, I believe this is sound.

// The handling of regions in this area of the code is terrible,
// see issue #29149. We should be able to improve on this with
// NLL.
let ocx = ObligationCtxt::new(infcx);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
match errors.as_slice() {
[] => true,
errors => {
debug!(?errors);
false
// Sometimes obligations are ambiguous because the recursive evaluator
// is not smart enough, so we fall back to fulfillment when we're not certain
// that an obligation holds or not. Even still, we must make sure that
// the we do no inference in the process of checking this obligation.
let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
infcx.probe(|_| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
ocx.register_obligation(obligation);

let errors = ocx.select_all_or_error();
match errors.as_slice() {
// Only known to hold if we did no inference.
[] => infcx.shallow_resolve(goal) == goal,

errors => {
debug!(?errors);
false
}
}
}
})
} else {
false
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
let goal =
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
let mut result = if this.tcx().trait_solver_next() {
this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
} else {
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/traits/copy-guessing.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// run-pass

#![allow(dead_code)]
#![allow(drop_copy)]

Expand All @@ -20,6 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}

fn main() {
let n = None;
//~^ ERROR type annotations needed for `Option<T>`
let e = S(&n);
let f = || {
// S being copy is critical for this to work
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/traits/copy-guessing.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0282]: type annotations needed for `Option<T>`
--> $DIR/copy-guessing.rs:20:9
|
LL | let n = None;
| ^
|
help: consider giving `n` an explicit type, where the type for type parameter `T` is specified
|
LL | let n: Option<T> = None;
| +++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.

0 comments on commit c06e611

Please sign in to comment.