diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ac6b0924ab572..b2d7ff29e5e72 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -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() { @@ -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 @@ -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 { - 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. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 150e917c73988..6a5ad37152a31 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -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(), @@ -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 { diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs index b33e7b8d68cf9..444be126db8d4 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/inherited.rs @@ -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; @@ -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; @@ -33,6 +33,8 @@ pub struct Inherited<'tcx> { pub(super) fulfillment_cx: RefCell>>, + pub(super) root_obligations: RefCell>>, + /// 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. @@ -119,6 +121,7 @@ impl<'tcx> Inherited<'tcx> { typeck_results, infcx, fulfillment_cx: RefCell::new(>::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()), @@ -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); } diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index d3519f4b37b82..5042612c07ca6 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -41,8 +41,6 @@ pub trait TraitEngine<'tcx>: 'tcx { fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; - fn pending_obligations(&self) -> Vec>; - fn relationships(&mut self) -> &mut FxHashMap; } diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index e988c77a064f6..038912ab796cb 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -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; @@ -138,14 +139,16 @@ 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 = >::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 = >::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 @@ -153,7 +156,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { 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); diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index e88950523537f..6fffc92a397f0 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -151,10 +151,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { errors } - fn pending_obligations(&self) -> Vec> { - self.obligations.iter().cloned().collect() - } - fn relationships(&mut self) -> &mut FxHashMap { &mut self.relationships } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 76a755ed9e09d..4ed544be15ba4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -161,10 +161,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.select(selcx) } - fn pending_obligations(&self) -> Vec> { - self.predicates.map_pending_obligations(|o| o.obligation.clone()) - } - fn relationships(&mut self) -> &mut FxHashMap { &mut self.relationships } diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.rs b/src/test/ui/higher-rank-trait-bounds/issue-30786.rs index e5f46f711c2fb..93ca4b7802f7e 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.rs +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.rs @@ -116,7 +116,6 @@ fn variant1() { // guess. let map = source.mapx(|x: &_| x); let filter = map.filterx(|x: &_| true); - //~^ ERROR the method } fn variant2() { diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr index 0458d2535f2f5..a8916b034bb80 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -1,26 +1,5 @@ -error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied - --> $DIR/issue-30786.rs:118:22 - | -LL | pub struct Map { - | -------------------- - | | - | method `filterx` not found for this struct - | doesn't satisfy `_: StreamExt` -... -LL | let filter = map.filterx(|x: &_| true); - | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds - | -note: the following trait bounds were not satisfied: - `&'a mut &Map: Stream` - `&'a mut &mut Map: Stream` - `&'a mut Map: Stream` - --> $DIR/issue-30786.rs:96:50 - | -LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | --------- - ^^^^^^ unsatisfied trait bound introduced here - -error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied - --> $DIR/issue-30786.rs:130:24 +error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@issue-30786.rs:128:30]>`, but its trait bounds were not satisfied + --> $DIR/issue-30786.rs:129:24 | LL | pub struct Filter { | ----------------------- @@ -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 fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` - `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` - `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream` + `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream` + `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:128:30: 128:37]>: Stream` --> $DIR/issue-30786.rs:96:50 | LL | impl 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`. diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs index ad3cc7c2524b9..cf5b7a4822809 100644 --- a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -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)] diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr new file mode 100644 index 0000000000000..52c2d015fd87e --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr @@ -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`. diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index be9c643b2d881..63f4898f4306b 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -5,7 +5,6 @@ pub struct Lint {} impl Lint {} pub fn gather_all() -> impl Iterator { - //~^ ERROR type annotations needed lint_files().flat_map(|f| gather_from_file(&f)) } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index fc7200c75c226..0e86561aa2779 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -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 { | ^^^ 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 { | ^^^ 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 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`.