Skip to content

Commit 930affa

Browse files
committed
Bubble up opaque <eq> opaque operations instead of picking an order
1 parent ad4dd75 commit 930affa

File tree

7 files changed

+127
-21
lines changed

7 files changed

+127
-21
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -328,19 +328,26 @@ fn check_opaque_type_well_formed<'tcx>(
328328

329329
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
330330
// the bounds that the function supplies.
331-
let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args);
332-
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
333-
.map_err(|err| {
334-
infcx
335-
.err_ctxt()
336-
.report_mismatched_types(
337-
&ObligationCause::misc(definition_span, def_id),
338-
opaque_ty,
339-
definition_ty,
340-
err,
341-
)
342-
.emit()
343-
})?;
331+
let mut obligations = vec![];
332+
infcx
333+
.insert_hidden_type(
334+
OpaqueTypeKey { def_id, args: identity_args },
335+
&ObligationCause::misc(definition_span, def_id),
336+
param_env,
337+
definition_ty,
338+
true,
339+
&mut obligations,
340+
)
341+
.unwrap();
342+
infcx.add_item_bounds_for_hidden_type(
343+
def_id.to_def_id(),
344+
identity_args,
345+
ObligationCause::misc(definition_span, def_id),
346+
param_env,
347+
definition_ty,
348+
&mut obligations,
349+
);
350+
ocx.register_obligations(obligations);
344351

345352
// Require the hidden type to be well-formed with only the generics of the opaque type.
346353
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the

compiler/rustc_infer/src/infer/opaque_types.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,25 @@ impl<'tcx> InferCtxt<'tcx> {
145145
return None;
146146
}
147147
}
148-
DefiningAnchor::Bubble => {}
148+
DefiningAnchor::Bubble => {
149+
if let ty::Alias(ty::Opaque, _) = b.kind() {
150+
// In bubble mode we don't know which of the two opaque types is supposed to have the other
151+
// as a hidden type (both, none or either one of them could be in its defining scope).
152+
let predicate = ty::PredicateKind::AliasRelate(
153+
a.into(),
154+
b.into(),
155+
ty::AliasRelationDirection::Equate,
156+
);
157+
let obligation = traits::Obligation::new(
158+
self.tcx,
159+
cause.clone(),
160+
param_env,
161+
predicate,
162+
);
163+
let obligations = vec![obligation];
164+
return Some(Ok(InferOk { value: (), obligations }));
165+
}
166+
}
149167
DefiningAnchor::Error => return None,
150168
};
151169
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {

compiler/rustc_trait_selection/src/traits/fulfill.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_infer::infer::DefineOpaqueTypes;
66
use rustc_infer::traits::ProjectionCacheKey;
77
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
88
use rustc_middle::mir::interpret::ErrorHandled;
9+
use rustc_middle::traits::DefiningAnchor;
910
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
1011
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1112
use rustc_middle::ty::GenericArgsRef;
@@ -623,9 +624,27 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
623624
}
624625
}
625626
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
626-
ty::PredicateKind::AliasRelate(..) => {
627-
bug!("AliasRelate is only used for new solver")
627+
ty::PredicateKind::AliasRelate(..)
628+
if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
629+
{
630+
ProcessResult::Unchanged
628631
}
632+
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
633+
ty::AliasRelationDirection::Equate => match self
634+
.selcx
635+
.infcx
636+
.at(&obligation.cause, obligation.param_env)
637+
.eq(DefineOpaqueTypes::Yes, a, b)
638+
{
639+
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
640+
Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
641+
SelectionError::Unimplemented,
642+
)),
643+
},
644+
ty::AliasRelationDirection::Subtype => {
645+
bug!("AliasRelate with subtyping is only used for new solver")
646+
}
647+
},
629648
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
630649
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
631650
DefineOpaqueTypes::No,

compiler/rustc_trait_selection/src/traits/select/mod.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
3737
use rustc_infer::traits::TraitObligation;
3838
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
3939
use rustc_middle::mir::interpret::ErrorHandled;
40+
use rustc_middle::traits::DefiningAnchor;
4041
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
4142
use rustc_middle::ty::fold::BottomUpFolder;
4243
use rustc_middle::ty::relate::TypeRelation;
@@ -960,9 +961,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
960961
}
961962
}
962963
}
963-
ty::PredicateKind::AliasRelate(..) => {
964-
bug!("AliasRelate is only used for new solver")
964+
ty::PredicateKind::AliasRelate(..)
965+
if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
966+
{
967+
Ok(EvaluatedToAmbig)
965968
}
969+
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
970+
ty::AliasRelationDirection::Equate => match self
971+
.infcx
972+
.at(&obligation.cause, obligation.param_env)
973+
.eq(DefineOpaqueTypes::Yes, a, b)
974+
{
975+
Ok(inf_ok) => self.evaluate_predicates_recursively(
976+
previous_stack,
977+
inf_ok.into_obligations(),
978+
),
979+
Err(_) => Ok(EvaluatedToErr),
980+
},
981+
ty::AliasRelationDirection::Subtype => {
982+
bug!("AliasRelate subtyping is only used for new solver")
983+
}
984+
},
966985
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
967986
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
968987
match self.infcx.at(&obligation.cause, obligation.param_env).eq(

tests/ui/impl-trait/async_scope_creep.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(type_alias_impl_trait)]
22
// edition:2021
3-
// check-pass
3+
//[rpit] check-pass
4+
// revisions: tait rpit
45

56
struct Pending {}
67

@@ -12,15 +13,23 @@ impl AsyncRead for i32 {}
1213

1314
type PendingReader<'a> = impl AsyncRead + 'a;
1415

15-
type OpeningReadFuture<'a> =
16-
impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
16+
#[cfg(tait)]
17+
type OpeningReadFuture<'a> = impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
1718

1819
impl Pending {
1920
async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
2021
Ok(42)
2122
}
2223

24+
#[cfg(tait)]
2325
fn read_fut(&mut self) -> OpeningReadFuture<'_> {
26+
self.read() //[tait]~ ERROR: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
27+
}
28+
29+
#[cfg(rpit)]
30+
fn read_fut(
31+
&mut self,
32+
) -> impl std::future::Future<Output = Result<PendingReader<'_>, CantOpen>> {
2433
self.read()
2534
}
2635
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0284]: type annotations needed: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
2+
--> $DIR/async_scope_creep.rs:26:9
3+
|
4+
LL | self.read()
5+
| ^^^^^^^^^^^ cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0284`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! This tries to prove the APIT's bounds in a canonical query,
2+
//! which doesn't know anything about the defining scope of either
3+
//! opaque type and thus makes a random choice as to which opaque type
4+
//! becomes the hidden type of the other. When we leave the canonical
5+
//! query, we attempt to actually check the defining anchor, but now we
6+
//! have a situation where the RPIT gets constrained outside its anchor.
7+
8+
// revisions: current next
9+
//[next] compile-flags: -Ztrait-solver=next
10+
// check-pass
11+
12+
#![feature(type_alias_impl_trait)]
13+
14+
type Opaque = impl Sized;
15+
16+
fn get_rpit() -> impl Clone {}
17+
18+
fn query(_: impl FnOnce() -> Opaque) {}
19+
20+
fn test() -> Opaque {
21+
query(get_rpit);
22+
get_rpit()
23+
}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)