Rollup merge of #92006 - oli-obk:welcome_opaque_types_into_the_fold, r=nikomatsakis
Welcome opaque types into the fold r? ```@nikomatsakis``` because idk who else to bug on the type_op changes The commits have explanations in them. The TLDR is that *5c46002273
stops the "recurse and replace" scheme that replaces opaque types with their canonical inference var by just doing that ahead of time *bdeeb07bf6
does not affect anything on master afaict, but since opaque types generate obligations when instantiated, and lazy TAIT instantiates opaque types *everywhere*, we need to properly handle obligations here instead of just hoping no problematic obligations ever come up.
This commit is contained in:
commit
b45a819bef
4 changed files with 61 additions and 80 deletions
|
@ -551,6 +551,22 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
let predicate = predicate.subst(tcx, substs);
|
||||
debug!(?predicate);
|
||||
|
||||
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||
tcx,
|
||||
ty_op: |ty| match *ty.kind() {
|
||||
// Replace all other mentions of the same opaque type with the hidden type,
|
||||
// as the bounds must hold on the hidden type after all.
|
||||
ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
|
||||
ty_var
|
||||
}
|
||||
// Instantiate nested instances of `impl Trait`.
|
||||
ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty),
|
||||
_ => ty,
|
||||
},
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct,
|
||||
});
|
||||
|
||||
// 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,
|
||||
|
@ -575,10 +591,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
|||
return tcx.ty_error();
|
||||
}
|
||||
}
|
||||
// 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`.
|
||||
let predicate = self.instantiate_opaque_types_in_map(predicate);
|
||||
|
||||
let cause =
|
||||
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
|
||||
|
|
|
@ -4,7 +4,9 @@ use crate::infer::canonical::{
|
|||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits::query::Fallible;
|
||||
use crate::traits::ObligationCause;
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::infer::canonical::{Canonical, Certainty};
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::PredicateObligations;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
|
||||
use std::fmt;
|
||||
|
@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
|
|||
pub mod normalize;
|
||||
pub mod outlives;
|
||||
pub mod prove_predicate;
|
||||
use self::prove_predicate::ProvePredicate;
|
||||
pub mod subtype;
|
||||
|
||||
pub use rustc_middle::traits::query::type_op::*;
|
||||
|
@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
|
|||
query_key: ParamEnvAnd<'tcx, Self>,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
|
||||
) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
|
||||
) -> Fallible<(
|
||||
Self::QueryResponse,
|
||||
Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
|
||||
PredicateObligations<'tcx>,
|
||||
Certainty,
|
||||
)> {
|
||||
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
|
||||
return Ok((result, None));
|
||||
return Ok((result, None, vec![], Certainty::Proven));
|
||||
}
|
||||
|
||||
// FIXME(#33684) -- We need to use
|
||||
|
@ -104,20 +110,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
|
|||
output_query_region_constraints,
|
||||
)?;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
// create obligations. However, in some cases there
|
||||
// are unresolved type variables, and unify them *can*
|
||||
// create obligations. In that case, we have to go
|
||||
// fulfill them. We do this via a (recursive) query.
|
||||
for obligation in obligations {
|
||||
let ((), _) = ProvePredicate::fully_perform_into(
|
||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||
infcx,
|
||||
output_query_region_constraints,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok((value, Some(canonical_self)))
|
||||
Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,9 +122,39 @@ where
|
|||
|
||||
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
|
||||
let mut region_constraints = QueryRegionConstraints::default();
|
||||
let (output, canonicalized_query) =
|
||||
let (output, canonicalized_query, mut obligations, _) =
|
||||
Q::fully_perform_into(self, infcx, &mut region_constraints)?;
|
||||
|
||||
// Typically, instantiating NLL query results does not
|
||||
// create obligations. However, in some cases there
|
||||
// are unresolved type variables, and unify them *can*
|
||||
// create obligations. In that case, we have to go
|
||||
// fulfill them. We do this via a (recursive) query.
|
||||
while !obligations.is_empty() {
|
||||
trace!("{:#?}", obligations);
|
||||
let mut progress = false;
|
||||
for obligation in std::mem::take(&mut obligations) {
|
||||
let obligation = infcx.resolve_vars_if_possible(obligation);
|
||||
match ProvePredicate::fully_perform_into(
|
||||
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
|
||||
infcx,
|
||||
&mut region_constraints,
|
||||
) {
|
||||
Ok(((), _, new, certainty)) => {
|
||||
obligations.extend(new);
|
||||
progress = true;
|
||||
if let Certainty::Ambiguous = certainty {
|
||||
obligations.push(obligation);
|
||||
}
|
||||
}
|
||||
Err(_) => obligations.push(obligation),
|
||||
}
|
||||
}
|
||||
if !progress {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
|
||||
// Promote the final query-region-constraints into a
|
||||
// (optional) ref-counted vector:
|
||||
let region_constraints =
|
||||
|
|
|
@ -15,9 +15,5 @@ impl<W> Trait<W> for () {}
|
|||
|
||||
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR non-defining opaque type use in defining scope
|
||||
//~| ERROR `T` is part of concrete type but not used in parameter list
|
||||
//~| ERROR `T` is part of concrete type but not used in parameter list
|
||||
()
|
||||
}
|
||||
|
|
|
@ -1,34 +1,8 @@
|
|||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/bound_reduction2.rs:16:60
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ____________________________________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | ()
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
--> $DIR/bound_reduction2.rs:16:60
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ____________________________________________________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | ()
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
--> $DIR/bound_reduction2.rs:16:46
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
|
@ -36,35 +10,11 @@ note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
|
|||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `_` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/bound_reduction2.rs:16:1
|
||||
|
|
||||
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: used non-generic type `_` for generic parameter
|
||||
--> $DIR/bound_reduction2.rs:9:10
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^
|
||||
|
||||
error: could not find defining uses
|
||||
--> $DIR/bound_reduction2.rs:9:15
|
||||
|
|
||||
LL | type Foo<V> = impl Trait<V>;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue