Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Rollup merge of #92006 - oli-obk:welcome_opaque_types_into_th… #92928

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 4 additions & 16 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,22 +555,6 @@ 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,
Expand All @@ -595,6 +579,10 @@ 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);
Expand Down
61 changes: 19 additions & 42 deletions compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use crate::infer::canonical::{
use crate::infer::{InferCtxt, InferOk};
use crate::traits::query::Fallible;
use crate::traits::ObligationCause;
use rustc_infer::infer::canonical::{Canonical, Certainty};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::PredicateObligations;
use rustc_infer::infer::canonical::Canonical;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use std::fmt;
Expand All @@ -19,6 +17,7 @@ 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::*;
Expand Down Expand Up @@ -81,14 +80,9 @@ 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>>>,
PredicateObligations<'tcx>,
Certainty,
)> {
) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok((result, None, vec![], Certainty::Proven));
return Ok((result, None));
}

// FIXME(#33684) -- We need to use
Expand All @@ -110,7 +104,20 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
output_query_region_constraints,
)?;

Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty))
// 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)))
}
}

Expand All @@ -122,39 +129,9 @@ where

fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let mut region_constraints = QueryRegionConstraints::default();
let (output, canonicalized_query, mut obligations, _) =
let (output, canonicalized_query) =
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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this hurts perf. We create a new Vec when we take, so we have to reallocate when new obligations are pushed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying this out in #93007

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 =
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/type-alias-impl-trait/bound_reduction2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ 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
()
}
56 changes: 53 additions & 3 deletions src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,70 @@
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:46
--> $DIR/bound_reduction2.rs:16:1
|
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
|
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 2 previous errors
error: aborting due to 6 previous errors