Generate inference vars and obligations for projections in opaque types instead of trying to normalize them.

This commit is contained in:
Oli Scherer 2021-08-10 11:45:32 +00:00 committed by Oli Scherer
parent 5fb1a65215
commit 34de78fd81
3 changed files with 35 additions and 21 deletions

View file

@ -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 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
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 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
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));
}

View file

@ -16,6 +16,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint>
fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
//~^ ERROR: failed to resolve
//~| ERROR: `()` is not an iterator
unimplemented!()
}

View file

@ -28,7 +28,15 @@ LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = L
LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
| -------------------------------------- returning this opaque type `FlatMap<impl Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
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<Item = foo::MissingItem> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` 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`.