Skip to content

Commit 9b9e20b

Browse files
committed
Auto merge of rust-lang#120798 - compiler-errors:normalize-opaques, r=<try>
Normalize opaques to infer vars eagerly in AssocTypeNormalizer :forgor: r? `@ghost`
2 parents 1280928 + c353df0 commit 9b9e20b

File tree

8 files changed

+49
-134
lines changed

8 files changed

+49
-134
lines changed

compiler/rustc_hir_typeck/src/check.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,7 @@ pub(super) fn check_fn<'a, 'tcx>(
3838
let tcx = fcx.tcx;
3939
let hir = tcx.hir();
4040

41-
let declared_ret_ty = fn_sig.output();
42-
43-
let ret_ty =
44-
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
45-
declared_ret_ty,
46-
fn_def_id,
47-
decl.output.span(),
48-
fcx.param_env,
49-
));
41+
let ret_ty = fn_sig.output();
5042

5143
fcx.coroutine_types = coroutine_types;
5244
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
@@ -109,7 +101,7 @@ pub(super) fn check_fn<'a, 'tcx>(
109101
hir::FnRetTy::DefaultReturn(_) => body.value.span,
110102
hir::FnRetTy::Return(ty) => ty.span,
111103
};
112-
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
104+
fcx.require_type_is_sized(ret_ty, return_or_body_span, traits::SizedReturnType);
113105
fcx.is_whole_body.set(true);
114106
fcx.check_return_expr(body.value, false);
115107

@@ -120,7 +112,7 @@ pub(super) fn check_fn<'a, 'tcx>(
120112
let coercion = fcx.ret_coercion.take().unwrap().into_inner();
121113
let mut actual_return_ty = coercion.complete(fcx);
122114
debug!("actual_return_ty = {:?}", actual_return_ty);
123-
if let ty::Dynamic(..) = declared_ret_ty.kind() {
115+
if let ty::Dynamic(..) = ret_ty.kind() {
124116
// We have special-cased the case where the function is declared
125117
// `-> dyn Foo` and we don't actually relate it to the
126118
// `fcx.ret_coercion`, so just substitute a type variable.

compiler/rustc_hir_typeck/src/closure.rs

-11
Original file line numberDiff line numberDiff line change
@@ -879,17 +879,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
879879

880880
let output_ty = self.normalize(closure_span, output_ty);
881881

882-
// async fn that have opaque types in their return type need to redo the conversion to inference variables
883-
// as they fetch the still opaque version from the signature.
884-
let InferOk { value: output_ty, obligations } = self
885-
.replace_opaque_types_with_inference_vars(
886-
output_ty,
887-
body_def_id,
888-
closure_span,
889-
self.param_env,
890-
);
891-
self.register_predicates(obligations);
892-
893882
Some(output_ty)
894883
}
895884

compiler/rustc_infer/src/infer/opaque_types.rs

+1-56
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
21
use super::{DefineOpaqueTypes, InferResult};
32
use crate::errors::OpaqueHiddenTypeDiag;
43
use crate::infer::{InferCtxt, InferOk};
@@ -36,60 +35,6 @@ pub struct OpaqueTypeDecl<'tcx> {
3635
}
3736

3837
impl<'tcx> InferCtxt<'tcx> {
39-
/// This is a backwards compatibility hack to prevent breaking changes from
40-
/// lazy TAIT around RPIT handling.
41-
pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
42-
&self,
43-
value: T,
44-
body_id: LocalDefId,
45-
span: Span,
46-
param_env: ty::ParamEnv<'tcx>,
47-
) -> InferOk<'tcx, T> {
48-
// We handle opaque types differently in the new solver.
49-
if self.next_trait_solver() {
50-
return InferOk { value, obligations: vec![] };
51-
}
52-
53-
if !value.has_opaque_types() {
54-
return InferOk { value, obligations: vec![] };
55-
}
56-
57-
let mut obligations = vec![];
58-
let replace_opaque_type = |def_id: DefId| {
59-
def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
60-
};
61-
let value = value.fold_with(&mut BottomUpFolder {
62-
tcx: self.tcx,
63-
lt_op: |lt| lt,
64-
ct_op: |ct| ct,
65-
ty_op: |ty| match *ty.kind() {
66-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
67-
if replace_opaque_type(def_id) && !ty.has_escaping_bound_vars() =>
68-
{
69-
let def_span = self.tcx.def_span(def_id);
70-
let span = if span.contains(def_span) { def_span } else { span };
71-
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
72-
let cause = ObligationCause::new(span, body_id, code);
73-
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
74-
// for opaque types, and then use that kind to fix the spans for type errors
75-
// that we see later on.
76-
let ty_var = self.next_ty_var(TypeVariableOrigin {
77-
kind: TypeVariableOriginKind::OpaqueTypeInference(def_id),
78-
span,
79-
});
80-
obligations.extend(
81-
self.handle_opaque_type(ty, ty_var, true, &cause, param_env)
82-
.unwrap()
83-
.obligations,
84-
);
85-
ty_var
86-
}
87-
_ => ty,
88-
},
89-
});
90-
InferOk { value, obligations }
91-
}
92-
9338
pub fn handle_opaque_type(
9439
&self,
9540
a: Ty<'tcx>,
@@ -515,7 +460,7 @@ impl UseKind {
515460

516461
impl<'tcx> InferCtxt<'tcx> {
517462
#[instrument(skip(self), level = "debug")]
518-
fn register_hidden_type(
463+
pub fn register_hidden_type(
519464
&self,
520465
opaque_type_key: OpaqueTypeKey<'tcx>,
521466
cause: ObligationCause<'tcx>,

compiler/rustc_middle/src/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1004,14 +1004,14 @@ pub enum CodegenObligationError {
10041004
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
10051005
pub enum DefiningAnchor {
10061006
/// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
1007-
/// replace opaque types in `replace_opaque_types_with_inference_vars`.
1007+
/// replace opaque types in normalization.
10081008
Bind(LocalDefId),
10091009
/// In contexts where we don't currently know what opaques are allowed to be
10101010
/// defined, such as (old solver) canonical queries, we will simply allow
10111011
/// opaques to be defined, but "bubble" them up in the canonical response or
10121012
/// otherwise treat them to be handled later.
10131013
///
1014-
/// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
1014+
/// We do not eagerly replace opaque types in normalization,
10151015
/// which may affect what predicates pass and fail in the old trait solver.
10161016
Bubble,
10171017
/// Do not allow any opaques to be defined. This is used to catch type mismatch

compiler/rustc_trait_selection/src/solve/normalize.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::traits::error_reporting::TypeErrCtxtExt;
22
use crate::traits::query::evaluate_obligation::InferCtxtExt;
3-
use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
3+
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
44
use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_infer::infer::at::At;
66
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -205,10 +205,9 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
205205
}
206206

207207
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
208-
let reveal = self.at.param_env.reveal();
209208
let infcx = self.at.infcx;
210209
debug_assert_eq!(ct, infcx.shallow_resolve(ct));
211-
if !needs_normalization(&ct, reveal) {
210+
if !ct.has_projections() {
212211
return Ok(ct);
213212
}
214213

compiler/rustc_trait_selection/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use rustc_span::Span;
4040
use std::fmt::Debug;
4141
use std::ops::ControlFlow;
4242

43-
pub(crate) use self::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
43+
pub(crate) use self::project::{BoundVarReplacer, PlaceholderReplacer};
4444

4545
pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
4646
pub use self::coherence::{OrphanCheckErr, OverlapResult};

compiler/rustc_trait_selection/src/traits/project.rs

+35-45
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
2727
use rustc_errors::ErrorGuaranteed;
2828
use rustc_hir::def::DefKind;
2929
use rustc_hir::lang_items::LangItem;
30+
use rustc_hir::OpaqueTyOrigin;
3031
use rustc_infer::infer::at::At;
3132
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
3233
use rustc_infer::infer::DefineOpaqueTypes;
@@ -318,17 +319,6 @@ fn project_and_unify_type<'cx, 'tcx>(
318319
};
319320
debug!(?normalized, ?obligations, "project_and_unify_type result");
320321
let actual = obligation.predicate.term;
321-
// For an example where this is necessary see tests/ui/impl-trait/nested-return-type2.rs
322-
// This allows users to omit re-mentioning all bounds on an associated type and just use an
323-
// `impl Trait` for the assoc type to add more bounds.
324-
let InferOk { value: actual, obligations: new } =
325-
selcx.infcx.replace_opaque_types_with_inference_vars(
326-
actual,
327-
obligation.cause.body_id,
328-
obligation.cause.span,
329-
obligation.param_env,
330-
);
331-
obligations.extend(new);
332322

333323
// Need to define opaque types to support nested opaque types like `impl Fn() -> impl Trait`
334324
match infcx.at(&obligation.cause, obligation.param_env).eq(
@@ -409,25 +399,6 @@ where
409399
result
410400
}
411401

412-
pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
413-
value: &T,
414-
reveal: Reveal,
415-
) -> bool {
416-
match reveal {
417-
Reveal::UserFacing => value.has_type_flags(
418-
ty::TypeFlags::HAS_TY_PROJECTION
419-
| ty::TypeFlags::HAS_TY_INHERENT
420-
| ty::TypeFlags::HAS_CT_PROJECTION,
421-
),
422-
Reveal::All => value.has_type_flags(
423-
ty::TypeFlags::HAS_TY_PROJECTION
424-
| ty::TypeFlags::HAS_TY_INHERENT
425-
| ty::TypeFlags::HAS_TY_OPAQUE
426-
| ty::TypeFlags::HAS_CT_PROJECTION,
427-
),
428-
}
429-
}
430-
431402
struct AssocTypeNormalizer<'a, 'b, 'tcx> {
432403
selcx: &'a mut SelectionContext<'b, 'tcx>,
433404
param_env: ty::ParamEnv<'tcx>,
@@ -488,11 +459,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
488459
"Normalizing {value:?} without wrapping in a `Binder`"
489460
);
490461

491-
if !needs_normalization(&value, self.param_env.reveal()) {
492-
value
493-
} else {
494-
value.fold_with(self)
495-
}
462+
if !value.has_projections() { value } else { value.fold_with(self) }
496463
}
497464
}
498465

@@ -512,7 +479,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
512479
}
513480

514481
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
515-
if !needs_normalization(&ty, self.param_env.reveal()) {
482+
if !ty.has_projections() {
516483
return ty;
517484
}
518485

@@ -548,7 +515,36 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
548515
ty::Opaque => {
549516
// Only normalize `impl Trait` outside of type inference, usually in codegen.
550517
match self.param_env.reveal() {
551-
Reveal::UserFacing => ty.super_fold_with(self),
518+
Reveal::UserFacing => {
519+
if !data.has_escaping_bound_vars()
520+
&& let Some(def_id) = data.def_id.as_local()
521+
&& let Some(
522+
OpaqueTyOrigin::TyAlias { in_assoc_ty: true }
523+
| OpaqueTyOrigin::AsyncFn(_)
524+
| OpaqueTyOrigin::FnReturn(_),
525+
) = self.selcx.infcx.opaque_type_origin(def_id)
526+
{
527+
let infer = self.selcx.infcx.next_ty_var(TypeVariableOrigin {
528+
kind: TypeVariableOriginKind::OpaqueTypeInference(data.def_id),
529+
span: self.cause.span,
530+
});
531+
let InferOk { value: (), obligations } = self
532+
.selcx
533+
.infcx
534+
.register_hidden_type(
535+
ty::OpaqueTypeKey { def_id, args: data.args },
536+
self.cause.clone(),
537+
self.param_env,
538+
infer,
539+
true,
540+
)
541+
.expect("uwu");
542+
self.obligations.extend(obligations);
543+
self.selcx.infcx.resolve_vars_if_possible(infer)
544+
} else {
545+
ty.super_fold_with(self)
546+
}
547+
}
552548

553549
Reveal::All => {
554550
let recursion_limit = self.interner().recursion_limit();
@@ -752,9 +748,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
752748
#[instrument(skip(self), level = "debug")]
753749
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
754750
let tcx = self.selcx.tcx();
755-
if tcx.features().generic_const_exprs
756-
|| !needs_normalization(&constant, self.param_env.reveal())
757-
{
751+
if tcx.features().generic_const_exprs || !constant.has_projections() {
758752
constant
759753
} else {
760754
let constant = constant.super_fold_with(self);
@@ -770,11 +764,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
770764

771765
#[inline]
772766
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
773-
if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
774-
p.super_fold_with(self)
775-
} else {
776-
p
777-
}
767+
if p.allow_normalization() && p.has_projections() { p.super_fold_with(self) } else { p }
778768
}
779769
}
780770

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::infer::at::At;
66
use crate::infer::canonical::OriginalQueryValues;
77
use crate::infer::{InferCtxt, InferOk};
88
use crate::traits::error_reporting::TypeErrCtxtExt;
9-
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
9+
use crate::traits::project::{BoundVarReplacer, PlaceholderReplacer};
1010
use crate::traits::{ObligationCause, PredicateObligation, Reveal};
1111
use rustc_data_structures::sso::SsoHashMap;
1212
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -89,7 +89,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
8989
}
9090
}
9191

92-
if !needs_normalization(&value, self.param_env.reveal()) {
92+
if !value.has_projections() {
9393
return Ok(Normalized { value, obligations: vec![] });
9494
}
9595

@@ -198,7 +198,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
198198

199199
#[instrument(level = "debug", skip(self))]
200200
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
201-
if !needs_normalization(&ty, self.param_env.reveal()) {
201+
if !ty.has_projections() {
202202
return Ok(ty);
203203
}
204204

@@ -335,7 +335,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
335335
&mut self,
336336
constant: ty::Const<'tcx>,
337337
) -> Result<ty::Const<'tcx>, Self::Error> {
338-
if !needs_normalization(&constant, self.param_env.reveal()) {
338+
if !constant.has_projections() {
339339
return Ok(constant);
340340
}
341341

@@ -354,7 +354,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
354354
&mut self,
355355
p: ty::Predicate<'tcx>,
356356
) -> Result<ty::Predicate<'tcx>, Self::Error> {
357-
if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
357+
if p.allow_normalization() && p.has_projections() {
358358
p.try_super_fold_with(self)
359359
} else {
360360
Ok(p)

0 commit comments

Comments
 (0)