From 34de78fd8131ac8149caab086c9696899d8d2bed Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 10 Aug 2021 11:45:32 +0000 Subject: [PATCH] Generate inference vars and obligations for projections in opaque types instead of trying to normalize them. --- .../rustc_trait_selection/src/opaque_types.rs | 41 +++++++++++-------- src/test/ui/impl-trait/issue-72911.rs | 1 + src/test/ui/impl-trait/issue-72911.stderr | 14 +++++-- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index c3c565cc08f..04ce0c56c2a 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,4 +1,3 @@ -use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -995,31 +994,37 @@ fn fold_opaque_ty( debug!("generated new type inference var {:?}", ty_var.kind()); let item_bounds = tcx.explicit_item_bounds(def_id); - debug!(?item_bounds); - let bounds: Vec<_> = - item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); - let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( - ObligationCause::misc(self.value_span, self.body_id), - param_env, - bounds, - ); - self.obligations.extend(obligations); + self.obligations.reserve(item_bounds.len()); + for (predicate, _) in item_bounds { + debug!(?predicate); + let predicate = predicate.subst(tcx, substs); + debug!(?predicate); - debug!(?bounds); + // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| match ty.kind() { + ty::Projection(projection_ty) => infcx.infer_projection( + self.param_env, + *projection_ty, + ObligationCause::misc(self.value_span, self.body_id), + 0, + &mut self.obligations, + ), + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + debug!(?predicate); - for predicate in &bounds { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. return ty_var; } } - } - - self.obligations.reserve(bounds.len()); - for predicate in bounds { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. // This also instantiates nested instances of `impl Trait`. @@ -1029,7 +1034,7 @@ fn fold_opaque_ty( traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. - debug!("instantiate_opaque_types: predicate={:?}", predicate); + debug!(?predicate); self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); } diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index dee5a41f6de..8761e4cf66a 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -16,6 +16,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator fn lint_files() -> impl Iterator { //~^ ERROR: failed to resolve + //~| ERROR: `()` is not an iterator unimplemented!() } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index 17748ae4277..6c6d9cbe23e 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -28,7 +28,15 @@ LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator impl Iterator { | -------------------------------------- returning this opaque type `FlatMap` -error: aborting due to 3 previous errors +error[E0277]: `()` is not an iterator + --> $DIR/issue-72911.rs:17:20 + | +LL | fn lint_files() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` -Some errors have detailed explanations: E0433, E0720. -For more information about an error, try `rustc --explain E0433`. +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0433, E0720. +For more information about an error, try `rustc --explain E0277`.