Generate inference vars and obligations for projections in opaque types instead of trying to normalize them.
This commit is contained in:
parent
5fb1a65215
commit
34de78fd81
3 changed files with 35 additions and 21 deletions
|
@ -1,4 +1,3 @@
|
||||||
use crate::infer::InferCtxtExt as _;
|
|
||||||
use crate::traits::{self, ObligationCause, PredicateObligation};
|
use crate::traits::{self, ObligationCause, PredicateObligation};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::Lrc;
|
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());
|
debug!("generated new type inference var {:?}", ty_var.kind());
|
||||||
|
|
||||||
let item_bounds = tcx.explicit_item_bounds(def_id);
|
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);
|
self.obligations.reserve(item_bounds.len());
|
||||||
let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
|
for (predicate, _) in item_bounds {
|
||||||
ObligationCause::misc(self.value_span, self.body_id),
|
debug!(?predicate);
|
||||||
param_env,
|
let predicate = predicate.subst(tcx, substs);
|
||||||
bounds,
|
debug!(?predicate);
|
||||||
);
|
|
||||||
self.obligations.extend(obligations);
|
|
||||||
|
|
||||||
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 let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
|
||||||
if projection.ty.references_error() {
|
if projection.ty.references_error() {
|
||||||
// No point on adding these obligations since there's a type error involved.
|
// No point on adding these obligations since there's a type error involved.
|
||||||
return ty_var;
|
return ty_var;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.obligations.reserve(bounds.len());
|
|
||||||
for predicate in bounds {
|
|
||||||
// Change the predicate to refer to the type variable,
|
// Change the predicate to refer to the type variable,
|
||||||
// which will be the concrete type instead of the opaque type.
|
// which will be the concrete type instead of the opaque type.
|
||||||
// This also instantiates nested instances of `impl Trait`.
|
// 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);
|
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
|
||||||
|
|
||||||
// Require that the predicate holds for the concrete type.
|
// 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));
|
self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint>
|
||||||
|
|
||||||
fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
|
fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
|
||||||
//~^ ERROR: failed to resolve
|
//~^ ERROR: failed to resolve
|
||||||
|
//~| ERROR: `()` is not an iterator
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
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]>`
|
| -------------------------------------- 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.
|
error: aborting due to 4 previous errors
|
||||||
For more information about an error, try `rustc --explain E0433`.
|
|
||||||
|
Some errors have detailed explanations: E0277, E0433, E0720.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue