Skip to content

Commit e2b3676

Browse files
committed
Auto merge of rust-lang#114586 - oli-obk:patch_tait_rpit_order_check, r=lcnr,compiler-errors
Bubble up opaque <eq> opaque operations instead of picking an order In case we are in `Bubble` mode (meaning every opaque type that is defined in the current crate is treated as if it were in its defining scope), we don't try to register an opaque type as the hidden type of another opaque type, but instead bubble up an obligation to equate them at the query caller site. Usually that means we have a `DefiningAnchor::Bind` and thus can reliably figure out whether an opaque type is in its defining scope. Where we can't, we'll error out, so the default is sound. With this change we start using `AliasTyEq` predicates in the old solver, too. fixes rust-lang#108498 But also regresses `tests/ui/impl-trait/anon_scope_creep.rs`. Our use of `Bubble` for `check_opaque_type_well_formed` is going to keep biting us. r? `@lcnr` `@compiler-errors`
2 parents 0a199e4 + 930affa commit e2b3676

File tree

8 files changed

+128
-21
lines changed

8 files changed

+128
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ build/
5858
\#*
5959
\#*\#
6060
.#*
61+
rustc-ice-*.txt
6162

6263
## Tags
6364
tags

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;
@@ -1000,9 +1001,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10001001
}
10011002
}
10021003
}
1003-
ty::PredicateKind::AliasRelate(..) => {
1004-
bug!("AliasRelate is only used for new solver")
1004+
ty::PredicateKind::AliasRelate(..)
1005+
if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) =>
1006+
{
1007+
Ok(EvaluatedToAmbig)
10051008
}
1009+
ty::PredicateKind::AliasRelate(a, b, relate) => match relate {
1010+
ty::AliasRelationDirection::Equate => match self
1011+
.infcx
1012+
.at(&obligation.cause, obligation.param_env)
1013+
.eq(DefineOpaqueTypes::Yes, a, b)
1014+
{
1015+
Ok(inf_ok) => self.evaluate_predicates_recursively(
1016+
previous_stack,
1017+
inf_ok.into_obligations(),
1018+
),
1019+
Err(_) => Ok(EvaluatedToErr),
1020+
},
1021+
ty::AliasRelationDirection::Subtype => {
1022+
bug!("AliasRelate subtyping is only used for new solver")
1023+
}
1024+
},
10061025
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
10071026
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
10081027
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)