Skip to content

[experiment] Get rid of pending_obligations #106073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions compiler/rustc_hir_typeck/src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
/// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
/// if fallback has occurred.
pub(super) fn type_inference_fallback(&self) {
debug!(
"type-inference-fallback start obligations: {:#?}",
self.fulfillment_cx.borrow_mut().pending_obligations()
);

// All type checking constraints were added, try to fallback unsolved variables.
self.select_obligations_where_possible(|_| {});

debug!(
"type-inference-fallback post selection obligations: {:#?}",
self.fulfillment_cx.borrow_mut().pending_obligations()
);

// Check if we have any unsolved variables. If not, no need for fallback.
let unsolved_variables = self.unsolved_variables();
if unsolved_variables.is_empty() {
Expand Down Expand Up @@ -281,8 +271,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
roots_reachable_from_non_diverging,
);

debug!("inherited: {:#?}", self.inh.fulfillment_cx.borrow_mut().pending_obligations());
debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations());
debug!("root obligations: {:#?}", self.root_obligations.borrow());
debug!("relationships: {:#?}", relationships);

// For each diverging variable, figure out whether it can
Expand Down Expand Up @@ -348,10 +337,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
/// Returns a graph whose nodes are (unresolved) inference variables and where
/// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
fn create_coercion_graph(&self) -> VecGraph<ty::TyVid> {
let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations();
debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations);
let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations
.into_iter()
let root_obligations = self.root_obligations.borrow();
debug!("create_coercion_graph: pending_obligations={:?}", root_obligations);
let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = root_obligations
.iter()
.filter_map(|obligation| {
// The predicates we are looking for look like `Coerce(?A -> ?B)`.
// They will have no bound variables.
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,10 +611,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: consider using `sub_root_var` here so we
// can see through subtyping.
let ty_var_root = self.root_var(self_ty);
trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations());
trace!("root_obligations = {:#?}", self.root_obligations.borrow());

self.fulfillment_cx.borrow().pending_obligations().into_iter().filter_map(
move |obligation| match &obligation.predicate.kind().skip_binder() {
self.root_obligations.borrow().clone().into_iter().filter_map(move |obligation| {
match &obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(data))
if self.self_type_matches_expected_vid(
data.projection_ty.self_ty(),
Expand Down Expand Up @@ -650,8 +650,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
},
)
}
})
}

pub(in super::super) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool {
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_typeck/src/inherited.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::callee::DeferredCallResolution;

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
Expand All @@ -10,7 +10,7 @@ use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap;
use rustc_span::{self, Span};
use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};

use std::cell::RefCell;
use std::ops::Deref;
Expand All @@ -33,6 +33,8 @@ pub struct Inherited<'tcx> {

pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,

pub(super) root_obligations: RefCell<FxIndexSet<PredicateObligation<'tcx>>>,

/// Some additional `Sized` obligations badly affect type inference.
/// These obligations are added in a later stage of typeck.
/// Removing these may also cause additional complications, see #101066.
Expand Down Expand Up @@ -119,6 +121,7 @@ impl<'tcx> Inherited<'tcx> {
typeck_results,
infcx,
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(tcx)),
root_obligations: RefCell::new(Default::default()),
locals: RefCell::new(Default::default()),
deferred_sized_obligations: RefCell::new(Vec::new()),
deferred_call_resolutions: RefCell::new(Default::default()),
Expand All @@ -136,6 +139,7 @@ impl<'tcx> Inherited<'tcx> {
if obligation.has_escaping_bound_vars() {
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
}
self.root_obligations.borrow_mut().insert(obligation.clone());
self.fulfillment_cx.borrow_mut().register_predicate_obligation(self, obligation);
}

Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_infer/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ pub trait TraitEngine<'tcx>: 'tcx {

fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;

fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;

fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships>;
}

Expand Down
17 changes: 10 additions & 7 deletions compiler/rustc_trait_selection/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::NormalizeExt;
use crate::traits::{self, TraitEngine, TraitEngineExt};
use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::{InferCtxt, InferOk};
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Limit;
Expand Down Expand Up @@ -138,22 +139,24 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}

let normalized_ty = self
let InferOk { value: normalized_ty, obligations } = self
.infcx
.at(&cause, self.param_env)
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
let normalized_ty =
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
let errors = fulfillcx.select_where_possible(&self.infcx);

// HACK(compiler-errors): We must *select* here so we *affect* inference...
// This can probably be moved to method_autoderef_steps or something instead.
let mut fulfill_cx = <dyn TraitEngine<'_>>::new_in_snapshot(tcx);
fulfill_cx.register_predicate_obligations(&self.infcx, obligations.clone());
let errors = fulfill_cx.select_where_possible(&self.infcx);
if !errors.is_empty() {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
return None;
}
let obligations = fulfillcx.pending_obligations();

debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
errors
}

fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.obligations.iter().cloned().collect()
}

fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
&mut self.relationships
}
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.select(selcx)
}

fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.predicates.map_pending_obligations(|o| o.obligation.clone())
}

fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
&mut self.relationships
}
Expand Down
1 change: 0 additions & 1 deletion src/test/ui/higher-rank-trait-bounds/issue-30786.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ fn variant1() {
// guess.
let map = source.mapx(|x: &_| x);
let filter = map.filterx(|x: &_| true);
//~^ ERROR the method
}

fn variant2() {
Expand Down
33 changes: 6 additions & 27 deletions src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
error[E0599]: the method `filterx` exists for struct `Map<Repeat, [[email protected]:117:27]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:118:22
|
LL | pub struct Map<S, F> {
| --------------------
| |
| method `filterx` not found for this struct
| doesn't satisfy `_: StreamExt`
...
LL | let filter = map.filterx(|x: &_| true);
| ^^^^^^^ method cannot be called on `Map<Repeat, [[email protected]:117:27]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
`&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
`&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
--> $DIR/issue-30786.rs:96:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here

error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [[email protected]:129:30]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:130:24
error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [[email protected]:128:30]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:129:24
|
LL | pub struct Filter<S, F> {
| -----------------------
Expand All @@ -32,14 +11,14 @@ LL | let count = filter.countx();
| ^^^^^^ method cannot be called due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
`&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
`&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
`&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream`
`&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream`
`&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream`
--> $DIR/issue-30786.rs:96:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
5 changes: 4 additions & 1 deletion src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// check-pass
// edition:2021

// known-bug: unknown
// This is broken bc we don't normalize the obligations we get back from InferOk...
// I'll have to think how best to do that later.

#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]

Expand Down
33 changes: 33 additions & 0 deletions src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
error: non-defining opaque type use in defining scope
--> $DIR/default-body-with-rpit.rs:13:39
|
LL | async fn baz(&self) -> impl Debug {
| _______________________________________^
LL | | ""
LL | | }
| |_____^ lifetime `'_` is part of concrete type but not used in parameter list of the `impl Trait` type alias

error: concrete type differs from previous defining opaque type use
--> $DIR/default-body-with-rpit.rs:14:9
|
LL | ""
| ^^ expected `impl Debug`, got `&'static str`
|
note: previous use here
--> $DIR/default-body-with-rpit.rs:13:39
|
LL | async fn baz(&self) -> impl Debug {
| _______________________________________^
LL | | ""
LL | | }
| |_____^

error[E0720]: cannot resolve opaque type
--> $DIR/default-body-with-rpit.rs:13:28
|
LL | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ cannot resolve opaque type

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0720`.
1 change: 0 additions & 1 deletion src/test/ui/impl-trait/issue-72911.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub struct Lint {}
impl Lint {}

pub fn gather_all() -> impl Iterator<Item = Lint> {
//~^ ERROR type annotations needed
lint_files().flat_map(|f| gather_from_file(&f))
}

Expand Down
15 changes: 4 additions & 11 deletions src/test/ui/impl-trait/issue-72911.stderr
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
error[E0433]: failed to resolve: use of undeclared crate or module `foo`
--> $DIR/issue-72911.rs:12:33
--> $DIR/issue-72911.rs:11:33
|
LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
| ^^^ use of undeclared crate or module `foo`

error[E0433]: failed to resolve: use of undeclared crate or module `foo`
--> $DIR/issue-72911.rs:17:41
--> $DIR/issue-72911.rs:16:41
|
LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
| ^^^ use of undeclared crate or module `foo`

error[E0282]: type annotations needed
--> $DIR/issue-72911.rs:7:24
|
LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0433.
For more information about an error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0433`.