Skip to content

Commit ccfcf42

Browse files
authored
Rollup merge of rust-lang#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 * 5c46002 stops the "recurse and replace" scheme that replaces opaque types with their canonical inference var by just doing that ahead of time * bdeeb07 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.
2 parents 9bcfb54 + bdeeb07 commit ccfcf42

File tree

4 files changed

+61
-80
lines changed

4 files changed

+61
-80
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,22 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
551551
let predicate = predicate.subst(tcx, substs);
552552
debug!(?predicate);
553553

554+
let predicate = predicate.fold_with(&mut BottomUpFolder {
555+
tcx,
556+
ty_op: |ty| match *ty.kind() {
557+
// Replace all other mentions of the same opaque type with the hidden type,
558+
// as the bounds must hold on the hidden type after all.
559+
ty::Opaque(def_id2, substs2) if def_id == def_id2 && substs == substs2 => {
560+
ty_var
561+
}
562+
// Instantiate nested instances of `impl Trait`.
563+
ty::Opaque(..) => self.instantiate_opaque_types_in_map(ty),
564+
_ => ty,
565+
},
566+
lt_op: |lt| lt,
567+
ct_op: |ct| ct,
568+
});
569+
554570
// We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
555571
let predicate = predicate.fold_with(&mut BottomUpFolder {
556572
tcx,
@@ -575,10 +591,6 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
575591
return tcx.ty_error();
576592
}
577593
}
578-
// Change the predicate to refer to the type variable,
579-
// which will be the concrete type instead of the opaque type.
580-
// This also instantiates nested instances of `impl Trait`.
581-
let predicate = self.instantiate_opaque_types_in_map(predicate);
582594

583595
let cause =
584596
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);

compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

+42-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use crate::infer::canonical::{
44
use crate::infer::{InferCtxt, InferOk};
55
use crate::traits::query::Fallible;
66
use crate::traits::ObligationCause;
7-
use rustc_infer::infer::canonical::Canonical;
7+
use rustc_infer::infer::canonical::{Canonical, Certainty};
8+
use rustc_infer::traits::query::NoSolution;
9+
use rustc_infer::traits::PredicateObligations;
810
use rustc_middle::ty::fold::TypeFoldable;
911
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
1012
use std::fmt;
@@ -17,7 +19,6 @@ pub mod implied_outlives_bounds;
1719
pub mod normalize;
1820
pub mod outlives;
1921
pub mod prove_predicate;
20-
use self::prove_predicate::ProvePredicate;
2122
pub mod subtype;
2223

2324
pub use rustc_middle::traits::query::type_op::*;
@@ -80,9 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
8081
query_key: ParamEnvAnd<'tcx, Self>,
8182
infcx: &InferCtxt<'_, 'tcx>,
8283
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
83-
) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
84+
) -> Fallible<(
85+
Self::QueryResponse,
86+
Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
87+
PredicateObligations<'tcx>,
88+
Certainty,
89+
)> {
8490
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
85-
return Ok((result, None));
91+
return Ok((result, None, vec![], Certainty::Proven));
8692
}
8793

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

107-
// Typically, instantiating NLL query results does not
108-
// create obligations. However, in some cases there
109-
// are unresolved type variables, and unify them *can*
110-
// create obligations. In that case, we have to go
111-
// fulfill them. We do this via a (recursive) query.
112-
for obligation in obligations {
113-
let ((), _) = ProvePredicate::fully_perform_into(
114-
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
115-
infcx,
116-
output_query_region_constraints,
117-
)?;
118-
}
119-
120-
Ok((value, Some(canonical_self)))
113+
Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty))
121114
}
122115
}
123116

@@ -129,9 +122,39 @@ where
129122

130123
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
131124
let mut region_constraints = QueryRegionConstraints::default();
132-
let (output, canonicalized_query) =
125+
let (output, canonicalized_query, mut obligations, _) =
133126
Q::fully_perform_into(self, infcx, &mut region_constraints)?;
134127

128+
// Typically, instantiating NLL query results does not
129+
// create obligations. However, in some cases there
130+
// are unresolved type variables, and unify them *can*
131+
// create obligations. In that case, we have to go
132+
// fulfill them. We do this via a (recursive) query.
133+
while !obligations.is_empty() {
134+
trace!("{:#?}", obligations);
135+
let mut progress = false;
136+
for obligation in std::mem::take(&mut obligations) {
137+
let obligation = infcx.resolve_vars_if_possible(obligation);
138+
match ProvePredicate::fully_perform_into(
139+
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
140+
infcx,
141+
&mut region_constraints,
142+
) {
143+
Ok(((), _, new, certainty)) => {
144+
obligations.extend(new);
145+
progress = true;
146+
if let Certainty::Ambiguous = certainty {
147+
obligations.push(obligation);
148+
}
149+
}
150+
Err(_) => obligations.push(obligation),
151+
}
152+
}
153+
if !progress {
154+
return Err(NoSolution);
155+
}
156+
}
157+
135158
// Promote the final query-region-constraints into a
136159
// (optional) ref-counted vector:
137160
let region_constraints =

src/test/ui/type-alias-impl-trait/bound_reduction2.rs

-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,5 @@ impl<W> Trait<W> for () {}
1515

1616
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
1717
//~^ ERROR non-defining opaque type use in defining scope
18-
//~| ERROR non-defining opaque type use in defining scope
19-
//~| ERROR non-defining opaque type use in defining scope
20-
//~| ERROR `T` is part of concrete type but not used in parameter list
21-
//~| ERROR `T` is part of concrete type but not used in parameter list
2218
()
2319
}
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,20 @@
1-
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
2-
--> $DIR/bound_reduction2.rs:16:60
3-
|
4-
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
5-
| ____________________________________________________________^
6-
LL | |
7-
LL | |
8-
LL | |
9-
... |
10-
LL | | ()
11-
LL | | }
12-
| |_^
13-
14-
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
15-
--> $DIR/bound_reduction2.rs:16:60
16-
|
17-
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
18-
| ____________________________________________________________^
19-
LL | |
20-
LL | |
21-
LL | |
22-
... |
23-
LL | | ()
24-
LL | | }
25-
| |_^
26-
271
error: non-defining opaque type use in defining scope
28-
--> $DIR/bound_reduction2.rs:16:1
2+
--> $DIR/bound_reduction2.rs:16:46
293
|
304
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^
326
|
337
note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
348
--> $DIR/bound_reduction2.rs:9:10
359
|
3610
LL | type Foo<V> = impl Trait<V>;
3711
| ^
3812

39-
error: non-defining opaque type use in defining scope
40-
--> $DIR/bound_reduction2.rs:16:1
41-
|
42-
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44-
|
45-
note: used non-generic type `_` for generic parameter
46-
--> $DIR/bound_reduction2.rs:9:10
47-
|
48-
LL | type Foo<V> = impl Trait<V>;
49-
| ^
50-
51-
error: non-defining opaque type use in defining scope
52-
--> $DIR/bound_reduction2.rs:16:1
53-
|
54-
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
55-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56-
|
57-
note: used non-generic type `_` for generic parameter
58-
--> $DIR/bound_reduction2.rs:9:10
59-
|
60-
LL | type Foo<V> = impl Trait<V>;
61-
| ^
62-
6313
error: could not find defining uses
6414
--> $DIR/bound_reduction2.rs:9:15
6515
|
6616
LL | type Foo<V> = impl Trait<V>;
6717
| ^^^^^^^^^^^^^
6818

69-
error: aborting due to 6 previous errors
19+
error: aborting due to 2 previous errors
7020

0 commit comments

Comments
 (0)