diff --git a/.gitignore b/.gitignore index 485968d9c56ff..4c8d1a0376426 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ build/ \#* \#*\# .#* +rustc-ice-*.txt ## Tags tags diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4da7b60257186..b7da15af6dc31 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -328,19 +328,26 @@ fn check_opaque_type_well_formed<'tcx>( // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); - ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) - .map_err(|err| { - infcx - .err_ctxt() - .report_mismatched_types( - &ObligationCause::misc(definition_span, def_id), - opaque_ty, - definition_ty, - err, - ) - .emit() - })?; + let mut obligations = vec![]; + infcx + .insert_hidden_type( + OpaqueTypeKey { def_id, args: identity_args }, + &ObligationCause::misc(definition_span, def_id), + param_env, + definition_ty, + true, + &mut obligations, + ) + .unwrap(); + infcx.add_item_bounds_for_hidden_type( + def_id.to_def_id(), + identity_args, + ObligationCause::misc(definition_span, def_id), + param_env, + definition_ty, + &mut obligations, + ); + ocx.register_obligations(obligations); // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 1c3a5c3607650..09df93fcc2fde 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -145,7 +145,25 @@ impl<'tcx> InferCtxt<'tcx> { return None; } } - DefiningAnchor::Bubble => {} + DefiningAnchor::Bubble => { + if let ty::Alias(ty::Opaque, _) = b.kind() { + // In bubble mode we don't know which of the two opaque types is supposed to have the other + // as a hidden type (both, none or either one of them could be in its defining scope). + let predicate = ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ); + let obligation = traits::Obligation::new( + self.tcx, + cause.clone(), + param_env, + predicate, + ); + let obligations = vec![obligation]; + return Some(Ok(InferOk { value: (), obligations })); + } + } DefiningAnchor::Error => return None, }; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3ebf1246a4141..f1779451bc5ca 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::GenericArgsRef; @@ -623,9 +624,27 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, - ty::PredicateKind::AliasRelate(..) => { - bug!("AliasRelate is only used for new solver") + ty::PredicateKind::AliasRelate(..) + if matches!(self.selcx.infcx.defining_use_anchor, DefiningAnchor::Bubble) => + { + ProcessResult::Unchanged } + ty::PredicateKind::AliasRelate(a, b, relate) => match relate { + ty::AliasRelationDirection::Equate => match self + .selcx + .infcx + .at(&obligation.cause, obligation.param_env) + .eq(DefineOpaqueTypes::Yes, a, b) + { + Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError( + SelectionError::Unimplemented, + )), + }, + ty::AliasRelationDirection::Subtype => { + bug!("AliasRelate with subtyping is only used for new solver") + } + }, ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( DefineOpaqueTypes::No, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7e4d926dc8dad..0d84fee83091f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -37,6 +37,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::relate::TypeRelation; @@ -1000,9 +1001,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } - ty::PredicateKind::AliasRelate(..) => { - bug!("AliasRelate is only used for new solver") + ty::PredicateKind::AliasRelate(..) + if matches!(self.infcx.defining_use_anchor, DefiningAnchor::Bubble) => + { + Ok(EvaluatedToAmbig) } + ty::PredicateKind::AliasRelate(a, b, relate) => match relate { + ty::AliasRelationDirection::Equate => match self + .infcx + .at(&obligation.cause, obligation.param_env) + .eq(DefineOpaqueTypes::Yes, a, b) + { + Ok(inf_ok) => self.evaluate_predicates_recursively( + previous_stack, + inf_ok.into_obligations(), + ), + Err(_) => Ok(EvaluatedToErr), + }, + ty::AliasRelationDirection::Subtype => { + bug!("AliasRelate subtyping is only used for new solver") + } + }, ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { match self.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/tests/ui/impl-trait/async_scope_creep.rs b/tests/ui/impl-trait/async_scope_creep.rs index 7a9d64d339feb..9a8831a299ee1 100644 --- a/tests/ui/impl-trait/async_scope_creep.rs +++ b/tests/ui/impl-trait/async_scope_creep.rs @@ -1,6 +1,7 @@ #![feature(type_alias_impl_trait)] // edition:2021 -// check-pass +//[rpit] check-pass +// revisions: tait rpit struct Pending {} @@ -12,15 +13,23 @@ impl AsyncRead for i32 {} type PendingReader<'a> = impl AsyncRead + 'a; -type OpeningReadFuture<'a> = - impl std::future::Future, CantOpen>>; +#[cfg(tait)] +type OpeningReadFuture<'a> = impl std::future::Future, CantOpen>>; impl Pending { async fn read(&mut self) -> Result { Ok(42) } + #[cfg(tait)] fn read_fut(&mut self) -> OpeningReadFuture<'_> { + self.read() //[tait]~ ERROR: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>` + } + + #[cfg(rpit)] + fn read_fut( + &mut self, + ) -> impl std::future::Future, CantOpen>> { self.read() } } diff --git a/tests/ui/impl-trait/async_scope_creep.tait.stderr b/tests/ui/impl-trait/async_scope_creep.tait.stderr new file mode 100644 index 0000000000000..165096a05743f --- /dev/null +++ b/tests/ui/impl-trait/async_scope_creep.tait.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>` + --> $DIR/async_scope_creep.rs:26:9 + | +LL | self.read() + | ^^^^^^^^^^^ cannot satisfy `impl AsyncRead + 'a == PendingReader<'a>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs new file mode 100644 index 0000000000000..eefe333da4511 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -0,0 +1,25 @@ +//! This tries to prove the APIT's bounds in a canonical query, +//! which doesn't know anything about the defining scope of either +//! opaque type and thus makes a random choice as to which opaque type +//! becomes the hidden type of the other. When we leave the canonical +//! query, we attempt to actually check the defining anchor, but now we +//! have a situation where the RPIT gets constrained outside its anchor. + +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(type_alias_impl_trait)] + +type Opaque = impl Sized; + +fn get_rpit() -> impl Clone {} + +fn query(_: impl FnOnce() -> Opaque) {} + +fn test() -> Opaque { + query(get_rpit); + get_rpit() +} + +fn main() {}